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’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ICU expression (plural) does not work with angular and HTML tags, since angular 9 #38588

Closed
rygoebel opened this issue Aug 26, 2020 · 9 comments

Comments

@rygoebel
Copy link

rygoebel commented Aug 26, 2020

🐞 bug report

Affected Package

The issue is caused by package @angular/localize ?

Is this a regression?

Yes, the previous version in which this bug was not present was: 8.3.29

Description

After update to Angular 9 (and similarly for Angular 10), ICU expression does not render component or HTML tags inside ICU expression (in this case - plural expression). There is no error in browser or console, only "One " and "Other " strings are displayed without buttons (included in expressions). It worked fine for Angular 8 (both buttons were displayed):
<ng-container i18n="Plurals example">{
  pluralsValue, plural,
    one {One <ng-container *ngTemplateOutlet="myTemplate"></ng-container>}
    other {Other <button>button_other</button>}
}</ng-container>

<ng-template #myTemplate>
  <button>button_one</button>
</ng-template>

🔬 Minimal Reproduction

Angular 8 (working):

https://stackblitz.com/edit/angular-plurals-angular8
Angular 9 (not working, regression):
https://stackblitz.com/edit/angular-plurals-angular9

🔥 Exception or Error





🌍 Your Environment

Angular Version:

Angular 9+



Anything else relevant?

@ngbot ngbot bot added this to the needsTriage milestone Aug 26, 2020
@rygoebel rygoebel changed the title ICU expression (plural) does not work with component and HTML tags, since angular 9 ICU expression (plural) does not work with angular and HTML tags, since angular 9 Aug 26, 2020
@petebacondarwin
Copy link
Member

@rygoebel thanks for the excellent reproductions of this problem. I can confirm that this is a regression.
@mhevery is currently reworking some of the ICU handling in Ivy and so this may be related.

@petebacondarwin
Copy link
Member

petebacondarwin commented Aug 26, 2020

The relevant section of the generated Ivy instructions are:

        i0.ɵɵelementContainerStart(7);
        i0.ɵɵi18n(8, I18N_0);
        i0.ɵɵelementContainerEnd();

But what is strange is the post-processing of the I18N_0 variable:

I18N_0 = i0.ɵɵi18nPostprocess(I18N_0, {
  "VAR_PLURAL": "\uFFFD0\uFFFD",
  "START_TAG_NG_CONTAINER": "<ng-container *ngTemplateOutlet=\"myTemplate\">",
  "CLOSE_TAG_NG_CONTAINER": "</ng-container>",
  "START_TAG_BUTTON": "<button>",
  "CLOSE_TAG_BUTTON": "</button>"
});

I would have expected a "sub-template" block marker in there (i.e. something like �*3:2�).

@mhevery
Copy link
Contributor

mhevery commented Aug 26, 2020

Actually this is intended regression and is documented here: https://angular.io/guide/ivy-compatibility

ICU parsing happens at runtime, so only text, HTML tags and text bindings are allowed inside ICU cases (previously, directives were also permitted inside ICUs).

So this is a side-effect of the fact that i18n is now runtime.

I am going to close this as working as intended.

@mhevery mhevery closed this as completed Aug 26, 2020
@petebacondarwin
Copy link
Member

The workaround for this case is to use ngPlural directives instead of ICUs: https://stackblitz.com/edit/angular-plurals-angular9-mgccwr?file=src/app/app.component.html

@lqc
Copy link

lqc commented Aug 27, 2020

@petebacondarwin It's a very poor workaround because the extracted in XLIFF is very unfriendly to the translator. While some I18N tools handle ICU well, there are no tools for handling the code generated from ngPlural and no easy way to convert it back to ICU.

@lqc
Copy link

lqc commented Aug 27, 2020

@mhevery First time I hear about something like "indented regression". It is a major backward-incompatible change that was not communicated in a good way. I understand the reason behind it, but could be documented better.

@rygoebel
Copy link
Author

@mhevery The example I provided suggests that HTML tags inside ICU expressions do not work - e.g. button doesn't (and they should work, according to cited part from "Ivy compatibility guide"). So maybe you could change documentation to be more accurate?

@petebacondarwin Thank you for adding workaround with ngPlurals and attaching stackblitz working solution. I've tried it, but I have problem that after translation process ngPluralCase value (like e.g. 0, 1, other) is not included in final .xliff translation file (as opposite to ICU expression, that passed this information directly into translation files). So do you know maybe if there is possibility to have this information (plurality) in translated .xliff files also for ngPlural solution?

@petebacondarwin
Copy link
Member

The new ivy extraction ought to be able to provide a bit better information about the original context of the placeholders, although currently I see it is rather broken:

<x id="START_TAG_NG_TEMPLATE" equiv-text="iner&gt; &lt;/ng-templ"/>
  One
  <x id="START_TAG_NG_CONTAINER" equiv-text="se=&quot;other&quot;&gt;Other &lt;button&gt;button_ot"/>
  <x id="CLOSE_TAG_NG_CONTAINER" equiv-text="&lt;/ng-container&gt;&lt;ng-template #myTem"/>
<x id="CLOSE_TAG_NG_TEMPLATE"/>
<x id="START_TAG_NG_TEMPLATE_1"/>
  Other
  <x id="START_TAG_BUTTON"/>button_other<x id="CLOSE_TAG_BUTTON"/>
<x id="CLOSE_TAG_NG_TEMPLATE"/>

I would expect it to be more like:

<x id="START_TAG_NG_TEMPLATE" equiv-text="&lt;ng-template ngPluralCase=&quot;one&quot;&gt;"/>
  One
  <x id="START_TAG_NG_CONTAINER" equiv-text="&lt;ng-container *ngTemplateOutlet=&quot;myTemplate&quot;&gt;"/>
  <x id="CLOSE_TAG_NG_CONTAINER" equiv-text="&lt;/ng-container&gt;"/>
<x id="CLOSE_TAG_NG_TEMPLATE" equiv-text="&lt;/ng-template&gt;/>
<x id="START_TAG_NG_TEMPLATE_1" equiv-text="&lt;ng-template ngPluralCase=&quot;other&quot&gt;"/>
  Other
  <x id="START_TAG_BUTTON" equiv-text="&lt;button&gt;"/>button_other<x id="CLOSE_TAG_BUTTON" equiv-text="&lt;/button&gt;"/>
<x id="CLOSE_TAG_NG_TEMPLATE" equiv-text="&lt;/ng-template&gt;/>

I will work on some fixes for this...

petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Aug 31, 2020
Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See angular#38588 (comment)
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Aug 31, 2020
Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See angular#38588 (comment)
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Aug 31, 2020
Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See angular#38588 (comment)
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Aug 31, 2020
Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See angular#38588 (comment)
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Sep 3, 2020
Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See angular#38588 (comment)
atscott pushed a commit that referenced this issue Sep 8, 2020
)

Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See #38588 (comment)

PR Close #38645
petebacondarwin added a commit to petebacondarwin/angular that referenced this issue Sep 8, 2020
Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See angular#38588 (comment)
atscott pushed a commit that referenced this issue Sep 8, 2020
)

Previously, localized strings had very limited or incorrect source-mapping
information available.

Now the i18n AST nodes and related output AST nodes include source-span
information about message-parts and placeholders - including closing tag
placeholders.

This information is then used when generating the final localized string
ASTs to ensure that the correct source-mapping is rendered.

See #38588 (comment)

PR Close #38747
@angular-automatic-lock-bot
Copy link

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 Sep 28, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

5 participants