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

A9 - IE11 mixes up i18n units when lazy loaded #36229

Open
pburkindine opened this issue Mar 24, 2020 · 11 comments
Open

A9 - IE11 mixes up i18n units when lazy loaded #36229

pburkindine opened this issue Mar 24, 2020 · 11 comments
Labels
Milestone

Comments

@pburkindine
Copy link

@pburkindine pburkindine commented Mar 24, 2020

馃悶 bug report

Affected Package

@angular/localize? (still unclear what the culprit is)

Is this a regression?

Yes, this was working in A8

Description

We are experiencing a regression in IE11 after upgrade to A9. A somewhat complex page consisting of factoried components is showing completely-mixed-up i18n units. (This doesn't happen in evergreen browsers). We have temporarily worked around it by turning off lazy-loading for this page (if anyone can suggest a way to conditionally eager-load only in es5 compilation and not for evergreen, that would serve as a workaround for our purposes).

We have seen several errors, all related to i18nStartFirstPass as seen here or getBindingMask (which errors on .length on undefined .values in this line for (var i = 0; i < icuExpression.values.length; i++) {)

Since the i18n compile goes fine, and this works in evergreen browsers, we're not thinking there's a problem with any of our ICUs?

Here are some screenshots of the real app, as well as the stack trace, relevant code and messages.xlf for the unit it's currently choking on (which, as you can see, is uninteresting).

Chrome:

Chrome

IE11:

IE11

Stack trace

"Error: Unable to parse ICU expression in "{VAR_SELECT, select, MIPS_GRP_113_overall {Screening for colorectal (colon or rectum) cancer}}" message.
   at i18nStartFirstPass (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:151562:17)
   at 傻傻i18nStart (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:151423:9)
   at 傻傻i18n (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:152485:7)
   at ProviderDetailsNursingHomeOverviewComponent_Template (http://10.0.0.132:8080/2-es5.e3644e6c21e2fdb0ea5c.js:12859:13)
   at executeTemplate (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:124580:9)
   at renderView (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:124289:11)
   at renderComponent (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:126255:7)
   at renderChildComponents (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:124023:9)
   at renderView (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:124327:11)
   at create (http://10.0.0.132:8080/main-es5.7959501"

Template code & messages.xlf

Template:
(complete template available in real-problem-screenshots in repro repo)

<span
  content-type="measure-label"
  i18n="@@ProviderMeasuresGroupPracticePerformance__cancer-screening__measure-label"
>{measure.measureId, select,
  MIPS_GRP_113_overall {Screening for colorectal (colon or rectum) cancer}}</span
>

messages.xlf:

<trans-unit id="ProviderMeasuresGroupPracticePerformance__cancer-screening__measure-label" datatype="html">
<source>{VAR_SELECT, select, MIPS_GRP_113_overall {Screening for colorectal (colon or rectum) cancer} }</source>
<context-group purpose="location">
  <context context-type="sourcefile">../../libs/features/provider-measures/src/lib/components/group-practice/performance/performance.component.html</context>
  <context context-type="linenumber">128</context>
</context-group>
</trans-unit>

馃敩 Minimal Reproduction

Unfortunately our efforts to create a minimal repro by throwing a large amount of factoried data components from multiple modules at the screen did not succeed; here is that code:

https://github.com/pburkindine/angular9-ie11-i18n

The real-problem-screenshots folder in the repo has all the real app details provided here

馃敟 Exception or Error

"Error: Unable to parse ICU expression in "{VAR_SELECT, select, MIPS_GRP_113_overall {Screening for colorectal (colon or rectum) cancer}}" message.
   at i18nStartFirstPass (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:151562:17)
   at 傻傻i18nStart (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:151423:9)
   at 傻傻i18n (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:152485:7)
   at ProviderDetailsNursingHomeOverviewComponent_Template (http://10.0.0.132:8080/2-es5.e3644e6c21e2fdb0ea5c.js:12859:13)
   at executeTemplate (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:124580:9)
   at renderView (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:124289:11)
   at renderComponent (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:126255:7)
   at renderChildComponents (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:124023:9)
   at renderView (http://10.0.0.132:8080/main-es5.795950121ed4b72ff95a.js:124327:11)
   at create (http://10.0.0.132:8080/main-es5.7959501"

馃實 Your Environment

Angular Version:




Angular CLI: 9.0.7
Node: 12.13.1
OS: darwin x64

Angular: 9.0.7
... animations, cli, common, compiler, compiler-cli, core, forms
... language-service, localize, platform-browser
... platform-browser-dynamic, router, service-worker
Ivy Workspace: Yes

Package                           Version
-----------------------------------------------------------
@angular-devkit/architect         0.900.7
@angular-devkit/build-angular     0.900.7
@angular-devkit/build-optimizer   0.900.7
@angular-devkit/build-webpack     0.900.7
@angular-devkit/core              9.0.7
@angular-devkit/schematics        9.0.7
@angular/cdk                      9.1.3
@angular/material                 9.1.3
@ngtools/webpack                  9.0.7
@schematics/angular               9.0.7
@schematics/update                0.900.7
rxjs                              6.5.4
typescript                        3.7.5
webpack                           4.41.2
@ngbot ngbot bot added this to the needsTriage milestone Mar 24, 2020
@AndrewKushnir

This comment has been minimized.

Copy link
Contributor

@AndrewKushnir AndrewKushnir commented Mar 24, 2020

Hi @pburkindine, thanks for reporting the issue.

Based on the error message that you provided, it looks like the i18nPostProcess function (that is generated by the compiler and should be present in the compiled output) is not getting called in the scenario that you described, as a result, the runtime logic is not able to parse an ICU.

I looked at the repro repository and the template that causes the problem. The template is relatively big, so I'd like to ask if you could help find the minimum possible content in that template that would trigger the problem (for ex. by removing part of the template and checking if the problem still exists)?

Also, could you please let us know if you use some specific way of loading translations or the problem happens with bare templates (without actually loading translations)?

Thank you.

@pburkindine

This comment has been minimized.

Copy link
Author

@pburkindine pburkindine commented Mar 24, 2020

@AndrewKushnir Thanks for the reply!

Completely emptying that template just shifted the error into a different template. Here is the new template. What's worth noting is that these are both 1-case ICUs? (We set them up this way for consistency with other use cases and for future extensibility.)

template:

<span
  content-type="measure-label"
  i18n="@@HomeHealth__payment-value-of-care__measure-label"
  >{measureData.measureId, select,
  AMT_MEDICARE_SPENDS_EPISODE_COMPARED {How much Medicare spends on an episode of care at this agency, compared to Medicare spending across all agencies nationally}}</span
              >

So I removed this one as well - and the error messages dried up - but the problem remains :/ I cannot figure out how I was seeing the getBindingMask errors, but I believe the problem might lie there?

(By the way, that template and the new one are not part of the screen being displayed; they are components in a different module that get loaded into an A2M modal via action buttons on this screen, although not this particular factoried variant of the screen.)

Regarding the loading of the translations - we create them with ng xi18n --output-path src/locale, but this is actually the english site. We don't do anything during the compile to reference the english messages.xlf file, nor are there locales, translations set up to reference it in angular.json. Looking at a fresh site, I don't see any reference to the messages.xlf file there either?

So I am not sure how to do "bare" templates, if you can advise I'll give it a try

@AndrewKushnir

This comment has been minimized.

Copy link
Contributor

@AndrewKushnir AndrewKushnir commented Mar 25, 2020

Thanks for additional information @pburkindine, please see replies below.

What's worth noting is that these are both 1-case ICUs? (We set them up this way for consistency with other use cases and for future extensibility.

I think it should not matter, but it'd be great if you could double check whether adding more conditions into an ICU makes the problem go away.

So I removed this one as well - and the error messages dried up - but the problem remains :/

Sorry, I'm a bit unclear on this. Could you please let us know what happens after you remove that ICU from a template (and what's the expected behavior)?

I cannot figure out how I was seeing the getBindingMask errors, but I believe the problem might lie there?

There was a change made recently in PR #35923 that handles the situation when runtime logic is unable to parse an ICU. Prior to that change the error was thrown from the getBindingMask function as you pointed out.

My current assumption is that the i18nPostprocess function is not getting generated/called for some reasons, thus leading to raw ICU expression being passed to the runtime code.

(By the way, that template and the new one are not part of the screen being displayed; they are components in a different module that get loaded into an A2M modal via action buttons on this screen, although not this particular factoried variant of the screen.)

Could you please point us to that code (if it's a part of a repro), so that we can have a look?

So I am not sure how to do "bare" templates, if you can advise I'll give it a try

I was wondering if translations were loaded at all or the problem is reproduced with the default locale and just the code in the template.

@pburkindine

This comment has been minimized.

Copy link
Author

@pburkindine pburkindine commented Mar 25, 2020

@AndrewKushnir thanks for the reply

I think it should not matter, but it'd be great if you could double check whether adding more conditions into an ICU makes the problem go away.

So I removed this one as well - and the error messages dried up - but the problem remains :/

Sorry, I'm a bit unclear on this. Could you please let us know what happens
after you remove that ICU from a template (and what's the expected behavior)?

Sorry if this wasn't clear. Completely removing both the 1-item ICUs did not fix the problem (the template is still completely mixed up). Unfortunately it did solve the final error message I can report back; there is nothing in the console (this is with production: false and our error handler set to log everything to console)

(By the way, that template and the new one are not part of the screen being displayed; they are components in a different module that get loaded into an A2M modal via action buttons on this screen, although not this particular factoried variant of the screen.)

Could you please point us to that code (if it's a part of a repro), so that we can have a look?

If you have procedures in place for working with teams on proprietary/production code, we would be happy to work with you to try to provide a copy (need to talk to legal). We were unable to reproduce the error in our repro attempt.

So I am not sure how to do "bare" templates, if you can advise I'll give it a try

I was wondering if translations were loaded at all or the problem is reproduced with the default locale and just the code in the template.

Yes, just the default locale and the code in the template here.

It's probably worth mentioning that what is shown in each spot is not (for example) another entry in the correct ICU. It's just some arbitrary entry from the messages.xlf file (not necessarily an ICU).

@pburkindine

This comment has been minimized.

Copy link
Author

@pburkindine pburkindine commented Mar 25, 2020

@AndrewKushnir

(By the way, that template and the new one are not part of the screen being displayed; they are components in a different module that get loaded into an A2M modal via action buttons on this screen, although not this particular factoried variant of the screen.)

Could you please point us to that code (if it's a part of a repro), so that we can have a look?

The setup is the same as the one shown here, although this didn't reproduce the issue:

https://github.com/pburkindine/angular9-ie11-i18n/blob/master/libs/module1/src/lib/components/routable1/routable1.component.ts

@pburkindine

This comment has been minimized.

Copy link
Author

@pburkindine pburkindine commented Mar 26, 2020

@AndrewKushnir perhaps we could investigate via Zoom screenshare or similar?

@AndrewKushnir

This comment has been minimized.

Copy link
Contributor

@AndrewKushnir AndrewKushnir commented Mar 26, 2020

Hi @pburkindine,

perhaps we could investigate via Zoom screenshare or similar?

I don't think we have a process for this, but I can provide a couple suggestions on what to look for during the debugging:

  • leave the minimum possible template(s) locally to repro the problem
  • compile an app in dev mode (to have the code non-minified)
  • examine compiled output (in dist folder or via browser dev tools) for the component that is causing problems and check how the i18n message is represented there (search using ICU content). There should also be i18nPostprocess function generated that takes care of initial replacements of placeholders with the values that Ivy runtime understands (it looks like this is not happening).
  • put a breakpoint in browser dev tools in the i18nPostprocess function and see/log the content of the message and replacements arguments.
  • put a breakpoint in browser dev tools in the i18nStart function and see/log the content of the message argument.

What should happen is that the i18nPostprocess function is called first and i18nStart after that for a given ICU. Please compare the sequence of calls and the content of the mentioned arguments in IE11 (where the problem exists) and in a browser when everything works as expected.

Thank you.

@pburkindine

This comment has been minimized.

Copy link
Author

@pburkindine pburkindine commented Mar 29, 2020

@AndrewKushnir Thanks for the debugging tips

The results were quite surprising:

  • 傻傻i18nPostprocess is present but is indeed not called at all (as you predicted)... however - this is true in both es2015/Chrome and in es5/IE11!

  • Completely clearing the page-level template and replacing the contents with this:

<span i18n="@@General__national-average">National average</span>

... still reproduces the problem! (unit is replaced with another seemingly-random unit)

(Leaving any 1 factoried component from the real page also reproduces it)

What is going on! Oy! :D

@AndrewKushnir

This comment has been minimized.

Copy link
Contributor

@AndrewKushnir AndrewKushnir commented Mar 30, 2020

Thanks for further debugging and sharing results @pburkindine!

傻傻i18nPostprocess is present but is indeed not called at all (as you predicted)... however - this is true in both es2015/Chrome and in es5/IE11!

But it still works in Chrome or you experience the same issue?

Just want to mention that in this case:

<span i18n="@@General__national-average">National average</span>

The 傻傻i18nPostprocess will not be generated at all (since the content is pretty simple, and there are no ICUs, interpolations or HTML tags).

(Leaving any 1 factoried component from the real page also reproduces it)

It's good to know, I hope that brings us closer to better understanding of a scenario in which the problem happens and having a repro that I can also help investigate. It looks like you're on the right track to simplify the app to a minimum set of components/configuration needed to repro the problem 馃憤 Looking forward to further investigation results.

Thank you.

@pburkindine

This comment has been minimized.

Copy link
Author

@pburkindine pburkindine commented Mar 30, 2020

Thanks for further debugging and sharing results @pburkindine!

傻傻i18nPostprocess is present but is indeed not called at all (as you predicted)... however - this is true in both es2015/Chrome and in es5/IE11!

But it still works in Chrome or you experience the same issue?

Yes, everything works fine in Chrome

Just want to mention that in this case:

<span i18n="@@General__national-average">National average</span>

The 傻傻i18nPostprocess will not be generated at all (since the content is pretty simple, and there are no ICUs, interpolations or HTML tags).

Interesting... Still being replaced with the wrong unit, though? Which I thought would mean Postprocess is getting called with the wrong replacement unit?

(Leaving any 1 factoried component from the real page also reproduces it)

It's good to know, I hope that brings us closer to better understanding of a scenario in which the problem happens and having a repro that I can also help investigate. It looks like you're on the right track to simplify the app to a minimum set of components/configuration needed to repro the problem 馃憤 Looking forward to further investigation results.

Thank you.

The next (only?) thing I can think to try is to remove all the other components from the module? Any other suggestions?

@AndrewKushnir

This comment has been minimized.

Copy link
Contributor

@AndrewKushnir AndrewKushnir commented Mar 30, 2020

Interesting... Still being replaced with the wrong unit, though? Which I thought would mean Postprocess is getting called with the wrong replacement unit?

Could you please expand this question a bit?

I just wanted to mention (in my original comment) that the i18nPostprocess function is generated only in certain cases when the translation content requires some additional processing, for example in case of ICUs. If it's just a plan text (like in your example), the i18nPostprocess will not be generated at all (and that's expected). If the same problem exists with simple text messages - that's a good finding, because that should simplify the repro case.

The next (only?) thing I can think to try is to remove all the other components from the module? Any other suggestions?

I'd propose to keep removing components until it's clear in which circumstances the problem happens. Ideally it'd be just a couple components with minimum possible templates to repro the issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked pull requests

Successfully merging a pull request may close this issue.

None yet
2 participants
You can鈥檛 perform that action at this time.