Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Ivy] [i18n] Translated messages are not loaded for library components #34056

Closed
tsvetomir opened this issue Nov 26, 2019 · 6 comments 路 May be fixed by #34202
Closed

[Ivy] [i18n] Translated messages are not loaded for library components #34056

tsvetomir opened this issue Nov 26, 2019 · 6 comments 路 May be fixed by #34202

Comments

@tsvetomir
Copy link

@tsvetomir tsvetomir commented Nov 26, 2019

馃悶 bug report

Is this a regression?

Yes, the translated messages are picked up by Angular 6-8 and in Angular 9 with Ivy disabled.

Description

Messages for third-party components are extracted successfully when running ng xi18n, but the compiler fails to locate the translated strings during compilation.

Possibly related: #32311, #32881

馃敩 Minimal Reproduction

  1. Clone https://github.com/tsvetomir/ivy-i18n-messages
  2. Run npm ci
  3. Run ng serve --configuration=es or ng serve --configuration=es,production

Result:

  • None of the messages declared in CalendarModule are translated.
  • The message declared in the application ("Hello, World!") is translated.
  • If enableIvy is set to false in tsconfig.json messages are translated normally.

馃敟 Exception or Error

No run-time errors.

馃實 Your Environment

Angular Version:


Angular CLI: 9.0.0-rc.3
Node: 12.13.1
OS: darwin x64
Angular: 9.0.0-rc.3
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, platform-browser, platform-browser-dynamic
... router

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.0-rc.3
@angular-devkit/build-angular     0.900.0-rc.3
@angular-devkit/build-optimizer   0.900.0-rc.3
@angular-devkit/build-webpack     0.900.0-rc.3
@angular-devkit/core              9.0.0-rc.3
@angular-devkit/schematics        9.0.0-rc.3
@angular/localize                 9.0.0-rc.0
@ngtools/webpack                  9.0.0-rc.3
@schematics/angular               9.0.0-rc.3
@schematics/update                0.900.0-rc.3
rxjs                              6.5.3
typescript                        3.6.4
webpack                           4.41.2
@ngbot ngbot bot modified the milestone: needsTriage Nov 27, 2019
@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 27, 2019

I think I know what is going on here...

This is what the warnings look like:

No translation found for "826701167553276328" ("TODAY" - "kendo.calendar.today").
No translation found for "589112377451589685" ("Increase value" - "kendo.dateinput.increment").
No translation found for "6980524091606682769" ("Decrease value" - "kendo.dateinput.decrement").

Note that the message IDs are not XLIFF 1.2 format, which is the format that the translation file is using.


Normally when compiling we convert the IDs to use the appropriate message ID format for XLIFF 1.2 (aka i18nLegacyMessageIdFormat) which would mean that the compiled template uses the correct message ids.

The problem here is that these templates are being compiled by ngcc, which doesn't know to use the i18nLegacyMessageIdFormat, so it is just using the regular message id format for these templates.

I think we should be able to get the CLI to tell ngcc what format to use...

mhevery added a commit to mhevery/angular that referenced this issue Nov 28, 2019
Fixes angular#34056

Add support for interpolation in styles as shown:
```
<div style="color: {{exp1}}; width: {{exp2}};">
```
@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 28, 2019

Some background...

The "legacy message id format" (used for XLIFF 1.2) has message ids that can only be computed from the original template source. By the time we have compiled a component to ivy there is not enough information left to compute these ids.

The code generated by the Angular compiler (which is used by ngcc) looks like:

I18N_0 = $localize(傻ngcc5.__makeTemplateObject(
    [
      ":kendo.calendar.today|The label for the today button in the calendar header:TODAY"
    ],
    [
      ":kendo.calendar.today|The label for the today button in the calendar header:TODAY"
    ]
));

We can compute "non-legacy" message ids from the information in this generated code, but not legacy message ids. The workaround is that we can tell the Angular compiler that we want to use legacy message ids, and so it will compute them from the template and add them to the generated code. Resulting in code that looks like:

I18N_0 = $localize(傻ngcc5.__makeTemplateObject(
    [
      ":kendo.calendar.today|The label for the today button in the calendar header@@2df64767cd895a8fabe3e18b94b5b6b6f9e2e3f0:TODAY"
    ],
    [
      ":kendo.calendar.today|The label for the today button in the calendar header@@2df64767cd895a8fabe3e18b94b5b6b6f9e2e3f0:TODAY"
    ]
));

Note the addition of @@2df64767cd895a8fabe3e18b94b5b6b6f9e2e3f0, which is the legacy message id.

For this to happen the Angular compiler needs to know that legacy ids are required, ahead of the actual translation merging, which will happen much later in the build pipeline (at the end, in fact).

Currently ngcc has no way to know that the final application is expecting legacy message ids and so is not telling the Angular compiler to add them.

@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 28, 2019

One solution is to expose an option on ngcc that tells it to generate these legacy-message ids. There are currently three scenarios where ngcc is triggered:

  1. Standalone command line (e.g. ngcc) - in this case it would be necessary to have a new command line option (e.g. ngcc --i18n-legacy-message-id) which tells ngcc to use legacy message id format for all i18n tags it finds when compiling component templates in libraries.
  2. Angular CLI (e.g. ng build) - the CLI calls ngcc programmatically from inside webpack. The CLI already knows whether legacy message ids are required and it already passes this information through to ngtsc (the ivy compiler) when building the app; we should also enable the CLI to pass this knowledge through to ngcc.
  3. ng-packagr - ???
@petebacondarwin

This comment has been minimized.

Copy link
Member

@petebacondarwin petebacondarwin commented Nov 28, 2019

An alternative solution is to always add legacy message ids on ngcc built code, using a new syntax that does not conflict with custom message ids (as it does at the moment), then the compile-time merging can choose which id to use based on the format of the translation file.

petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Nov 28, 2019
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Nov 28, 2019
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Nov 28, 2019
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Nov 28, 2019
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Nov 28, 2019
@tsvetomir

This comment has been minimized.

Copy link
Author

@tsvetomir tsvetomir commented Nov 29, 2019

This is a great insight into i18n and how it interacts with ngcc, thanks @petebacondarwin! Also, a nice read on the separator control characters 馃憮

Including the legacy IDs as additional metadata seems like the right thing to do 馃憤

petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Nov 29, 2019
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Nov 29, 2019
By ensuring that legacy i18n message ids are rendered into the templates
of components for packages processed by ngcc, we ensure that these packages
can be used in an application that may provide translations in a legacy
format.

Fixes angular#34056
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Dec 2, 2019
By ensuring that legacy i18n message ids are rendered into the templates
of components for packages processed by ngcc, we ensure that these packages
can be used in an application that may provide translations in a legacy
format.

Fixes angular#34056
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Dec 3, 2019
By ensuring that legacy i18n message ids are rendered into the templates
of components for packages processed by ngcc, we ensure that these packages
can be used in an application that may provide translations in a legacy
format.

Fixes angular#34056
@mhevery mhevery closed this in f16f6a2 Dec 3, 2019
mhevery added a commit that referenced this issue Dec 3, 2019
By ensuring that legacy i18n message ids are rendered into the templates
of components for packages processed by ngcc, we ensure that these packages
can be used in an application that may provide translations in a legacy
format.

Fixes #34056

PR Close #34135
@angular-automatic-lock-bot

This comment has been minimized.

Copy link

@angular-automatic-lock-bot angular-automatic-lock-bot bot commented Jan 3, 2020

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jan 3, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
3 participants
You can鈥檛 perform that action at this time.