TypeError: $localize is not a function => library components not translated
Which @angular/* package(s) are the source of the bug?
localize
Is this a regression?
Yes
Description
Hello,
I just migrated from 11 to 14. (had difficulties to do intermediate migrations so I made a fresh install)
My localized production builds fail to start with this error stack : ERROR Error: Uncaught (in promise): TypeError: $localize is not a function consts@http://localhost/en/player/main.e48ad9d7ec515188.js:3:1262797
Build is done with: ng build application --conifguration=production --localize
generated main.js starts with : var $localize=Object.assign(void 0===$localize?{}:$localize,{locale:"en"});
If build without localize option, I'm getting a slightly different error : $localize is not defined and the main.js does not contain the same first line
main.js contains this for each label to translate :
$localize:@@button.logOut␟bb694b49d408265c91c62799c2b3a7e3151c824d␟3797778920049399855:Logout
Clearly, translation is not done.
I tried to recreate my messages files but I get errors with extract-i18n :
_Error: Module build failed (from ./node_modules/@angular-devkit/build-angular/src/builders/extract-i18n/ivy-extract-loader.js):
TypeError: Cannot create property 'message' on string 'dist\bg-common\fesm2020\bg-common.mjs: Unexpected messageParts for $localize (expected an array of strings).
4968 | i18n_0 = MSG_EXTERNAL_buttonYes$$LIB_BG_CORE_COMPONENTS_DIALOG_COMPONENT_TS__1;
4969 | } else {
4970 | i18n_0 = $localize(_t2 || (_t2 =
:@@buttonYes␟4f20f2d5a6882190892e58b85f6ccbedfa737952␟2807800733729323332:Yes)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 4971 | }
I was using $localize function in a few typescript componenst but I removed it and now I have only i18n attributes in HTML templates.
Development built works fine.
Regards
Please provide a link to a minimal reproduction of the bug
No response
Please provide the exception or error you saw
_ERROR Error: Uncaught (in promise): TypeError: $localize is not a function
Please provide the environment you discovered this bug in (run ng version)
Angular CLI: 14.0.2
Node: 16.15.1
Package Manager: npm 8.11.0
OS: win32 x64
Angular: 14.0.2
... animations, cdk, cli, common, compiler, compiler-cli, core
... forms, localize, material, platform-browser
... platform-browser-dynamic, router
Package Version
---------------------------------------------------------
@angular-devkit/architect 0.1400.2
@angular-devkit/build-angular 14.0.2
@angular-devkit/core 14.0.2
@angular-devkit/schematics 14.0.2
@schematics/angular 14.0.2
rxjs 7.5.5
typescript 4.7.3
package.json :
"dependencies": {
"@angular/animations": "^14.0.0",
"@angular/cdk": "^14.0.2",
"@angular/common": "^14.0.0",
"@angular/compiler": "^14.0.0",
"@angular/core": "^14.0.0",
"@angular/forms": "^14.0.0",
"@angular/material": "^14.0.2",
"@angular/platform-browser": "^14.0.0",
"@angular/platform-browser-dynamic": "^14.0.0",
"@angular/router": "^14.0.0",
"js-sha256": "^0.9.0",
"ng-recaptcha": "^9.0.0",
"ng2-charts": "^3.0.11",
"ngx-image-cropper": "^6.1.0",
"ngx-quill": "^17.0.0",
"quill": "^1.3.7",
"quill-better-table": "^1.2.10",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"uuid": "^8.3.2",
"zone.js": "~0.11.4"
},
"devDependencies": {
"@angular-devkit/build-angular": "^14.0.2",
"@angular/cli": "^14.0.2",
"@angular/compiler-cli": "^14.0.0",
"@angular/localize": "^14.0.2",
"@types/jasmine": "~4.0.0",
"jasmine-core": "~4.1.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.7.2"
}
Anything else?
No response
There was a fix for extract-i18n in CLI 14.0.3.
I don't know enough about the i18n pipeline to tell why the $localize calls are not translated during build time. A reproduction would help, as I suspect this is some issue with your configuration.
My config was fine with Angular 11. There are probably adaptations to be done but I could not find which. I'm trying the fix on extract-i18n to check or any progress
thanks for the tip on extract-i18n, 14.0.3 fixed it
Recreating messages dit not help anyway
I downloaded the sample i18n from https://angular.io/guide/i18n-example I aligned my project configuration (localize : true as default, false for development). Still getting the error.
I will try to run the sample app
The sample app runs with translated versions
Seems that only library messages are not translated, I can find my main app own messages properly translated in main.js.
(Though messages from library components were properly extracted)
Could be related to https://github.com/angular/angular/issues/34056
Unfortunately without a reproduction we will not be able to look into this any further.
What do you need as reproduction ? An example project that you can run by yourself ?
Correct.
A good way to make a minimal repro is to create a new app via ng new repro-app and adding the minimum possible code to show the problem. Then you can push this repository to github and link it here.
Right. I will start from the i18n sample app coming from Angular site and will add consumption of a home made library ;)
Created an i18napp and i18nlib. So far I Cannot reproduce but I found out that output-path on extract-i18n is no longer project relative but root directory relative. And "sourceFile" context-type property in messages.xlf are therefore root related. Though it seems that this sourceFile is only .. informative. I can put any values in it, translation still works.
I'm analysing differences between the sample app and my main project...
I have compared and aligned : dependencies in package.json, projects structures in angular.json, tsconfig, etc... between working project and not working one. No sucess so far.
Before I try to rebuild my app from fresh and clean install, are they any leads that I can follow regarding the translation of library i8n labels ? a compiler flag ?
I find some differences in commands output : ng extract-i18n gives warning for duplicate label ids in my main project, not for the sample project in which I have added duplicates too. I therefore still have differences in my configuration
Seems that compile-time inlining is not applied for library. Is there a specific parameter for that ?
inlining of all $localize including those in libraries calls happens during the application build.
ok but seems not to go into some components
Probably not related but my main.js bundle contains references to library components which module is not imported
@my-jupiler I had the same issue - turns out this was caused by the library patching the $localize function. I'd suggest you reach out to the library that causes this.
Hello Daniel, what do you mean patching ? overriding the method ? I have removed all references to the $localize function in typescript components in my own library, I now have only "i18n" attributes. Could it be that I'm including an external library that is messing with the localize ?
@my-jupiler yes, I thought we were always talking about "external libraries" (such as ng-bootstrap etc.)
my non angular libs are : "js-sha256": "^0.9.0", "ng2-charts": "^3.0.11", "ngx-image-cropper": "^6.1.0"
(removed quills)
Yes indeed I'm talking about my library package inside my projects in which I have 8 modules whose components are not translated in production build
But your suggestion is interesting. compile-time inlining is not working but runtime translation should work as $localize function is referenced in the main.js bundle.
@alan-agius4 @JoostK found how to reproduce this:
Add ios_saf 12.2-12.6 (note that this is contained e.g. in > 0.5%) to .browserslist.
Then adding components from library that are localized and running the production build reproduce the issue.
(@my-jupiler This is of course as well a workaround: just remove older browsers..)
@daniel-sc You are a winner ! Just reproduced it in my sample app.
https://github.com/my-jupiler/i18nExample.git
And my main app works now, thanks a lot !
Workaround is fine for me, I consider it as part of version upgrade browserlist should be included in migration process , feature to add maybe ?
the browserslist that makes the bug :
> 0.5%
last 2 versions
Firefox ESR
not dead
not IE 9-11 # For IE 9-11 support, remove 'not'.
I have this same issue and browserlist with not ios_saf 12.2-12.6 fix it. Waiting for proper solution.
@alan-agius4 There's a reproduction here. Can you take a look? WDYT?
Hi @my-jupiler,
I tried to reproduce the issue using the reproduction provided above, however the build is not erroring.
~/cli-reproductions/i18nExample/i18nExample main ± ng b --localize
✔ Browser application bundle generation complete.
✔ Localized bundle generation complete.
✔ Copying assets complete.
✔ Index html generation complete.
Initial Chunk Files | Names | Raw Size | Estimated Transfer Size
main.eb9d52cf9adad779.js | main | 117.92 kB | 35.21 kB
polyfills.9f899a06b2dfdf4f.js | polyfills | 33.11 kB | 10.70 kB
runtime.7e37e778064d7986.js | runtime | 1.05 kB | 599 bytes
styles.ef46db3751d8e999.css | styles | 0 bytes | -
| Initial Total | 152.08 kB | 46.50 kB
Build at: 2022-08-22T13:36:51.109Z - Hash: 4f67f49b836f3ffe - Time: 19437ms