3

Using angular 8.x i18n I've come across an issue with a very obscure error message (as all i18n error messages tend to be; looking at you, https://github.com/angular/angular-cli/issues/7555#issuecomment-394228634).

The message states: ERROR in src/app/***.component.html(1,2): : Property 'VAR_PLURAL' does not exist on type '***Component'.

That error only says correctly which file is impacted, but the line indicator is nonsensical. Using a binary search, commenting half of the i18n plural occurrences, I managed to pinpoint the troublemaker:

<ng-container i18n="@@playerCardinality">
  {singleTournament.tournament.teamSize.max, plural, =1 {player} other {players}}
</ng-container>

At first I thought the issue might be different var name, since this @@playerCardinality is used on multiple places throughout the app:

<ng-container i18n="@@playerCardinality">{ tournamentScreen.tournament.teamSize.max, plural, =1 {player} other {players} }</ng-container>
<ng-container i18n="@@playerCardinality">{ ladderScreen.ladder.teamSizeMax, plural, =1 {player} other {players} }</ng-container>

but other don't have the same variable name either and it posed no problem so far.

Commenting out those other occurrences also fixed the issue so it must be some kind of interaction related issue between those.

Must be some banal issue since apparently no one else ever had a similar issue (based on google results)...

crollywood
  • 523
  • 1
  • 6
  • 17

2 Answers2

1

Found the answer, to whom it may concern, the issue was in the formating, when I deleted newlines it worked. So basically all translations with the same id must be of the same format as well as the same content.

These are working translations:

<ng-container i18n="@@playerCardinality">{ singleTournament.tournament.teamSize.max, plural, =1 {player} other {players} }</ng-container>
<ng-container i18n="@@playerCardinality">{ tournamentScreen.tournament.teamSize.max, plural, =1 {player} other {players} }</ng-container>
<ng-container i18n="@@playerCardinality">{ ladderScreen.ladder.teamSizeMax, plural, =1 {player} other {players} }</ng-container>

crollywood
  • 523
  • 1
  • 6
  • 17
1

I know the author has found a solution for themselves, but I am going to elaborate and lay out a few more scenarios where this error can occur and how to fix them. Also this fix applies to VAR_SELECT as well as VAR_PLURAL. So if you are seeing this error: ERROR in src/app/app.component.html(1,2): Property 'VAR_SELECT' does not exist on type 'AppComponent'. The following fixes should also help you.

If you have the following translation:

<trans-unit id="PLURAL_TEST" datatype="html">
  <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago} }</source>
  <target>{VAR_PLURAL, plural, =0 {à l'instantt} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>
</trans-unit>

And want to use it in your html, you would do something like this:

<p i18n="@@PLURAL_TEST">{minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago} }</p>

However, if you have some characters before or after the {minutes, plural ...} } part of the html, it will fail and you will see this error: ERROR in src/app/app.component.html(1,8): Property 'VAR_PLURAL' does not exist on type 'AppComponent'.

This means that all the following html values will fail:

<p i18n="@@PLURAL_TEST"> {minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago} }</p>
<p i18n="@@PLURAL_TEST">{minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago} } </p>
<p i18n="@@PLURAL_TEST">
{minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago} }
</p>

The first one has a space at the start, the second one has a space at the end, the third one has a newline character. The third one is an example of the original poster did. You can replace whitespace with any characters, words, interpolation etc, it will always fail. Even if you change the translations in the .xlf files to match the html, it will still fail. So for example:

xlf:

<trans-unit id="PLURAL_TEST" datatype="html">
  <source> {VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago} }</source>
  <target> {VAR_PLURAL, plural, =0 {à l'instantt} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>
</trans-unit>

html:

<p i18n="@@PLURAL_TEST"> {minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago} }</p>

Will still fail. Even though the leading space is present in the translations and the html.

If you do want to nest the VAR_PLURAL or VAR_SELECT translation inside another translation, then you should use the <x id="ICU" /> tag to achieve this.

So if I wanted this in my html:

<p>Hello, {minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago} }</p>

I would need to define two translations, one for the VAR_PLURAL or VAR_SELECT part of the text. We will call this the inner translation. And we will also need another translation for the rest of the text (in this case it is the Hello, part), which will be the outer translation. So my translations file will look like this:

<trans-unit id="PLURAL_TEST_OUTER" datatype="html">
  <source>Hello, <x id="ICU" /></source>
  <target>Bonjour, <x id="ICU" /></target>
</trans-unit>

<trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" datatype="html">
  <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" /> minutes ago} }</source>
  <target>{VAR_PLURAL, plural, =0 {à l'instantt} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>
</trans-unit>

Note that the trans-id of the inner expression must be auto generated (See more in https://github.com/angular/angular/issues/26379).

My html will look like this:

<p i18n="@@PLURAL_TEST_OUTER">Hello, {minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago} }</p>

You can find more information on nesting translations here - https://angular.io/guide/i18n#translate-a-nested-expression

So in conclusion, if you are seeing this issue:

  1. Check for whitespace, characters or interpolation before or after your VAR_PLURAL or VAR_SELECT statements in your html. Delete it if it isn't supposed to be there.
  2. If it is supposed to be there, make sure you are correctly nesting your translations in the .xlf files.
Fapskey
  • 31
  • 7