loclapp / locl

Internationalization (i18n) tools suite for Angular
https://www.locl.app
GNU Affero General Public License v3.0
92 stars 16 forks source link

Regular expressions for plurals improper extraction #32

Open rayita opened 4 years ago

rayita commented 4 years ago

We are having problems with extracting plural expression, initially we thought it was a problem of the converter to JSON as it gave the following error:

    else throw err
           ^
Unexpected character "EOF" (Do you have an unescaped "{" in your template? Use "{{ '{' }}") to escape it.) ("e>{VAR_PLURAL, plural, =0 {no recipients found} =1 {1 recipient} other {{INTERPOLATION} recipients}}[ERROR ->]</source>
        <target>{VAR_PLURAL, plural, =0 {no recipients found} =1 {1 recipient} other {{INTE"): F:/Projects/n4t.car/n4t.fleet-admin/src/locale/messages.en-GB.xlf@79:114
Invalid ICU message. Missing '}'. ("tatype="html">
        <source>{VAR_PLURAL, plural, =0 {no recipients found} =1 {1 recipient} other [ERROR ->]{{INTERPOLATION} recipients}}</source>
        <target>{VAR_PLURAL, plural, =0 {no recipients found} "): F:/Projects/n4t.car/n4t.fleet-admin/src/locale/messages.en-GB.xlf@79:85
(Use `node --trace-uncaught ...` to show where the exception was thrown)

But finally the problem seems to be in the extraction, because with the angle extraction they work correctly and the JSON converter does its job well.

This is the extraction extracted by angular extractor:

  <trans-unit id="Recipients_Footer_Recipients_Count_Text" datatype="html">
    <source>{VAR_PLURAL, plural, =0 {no recipients found} =1 {1 recipient} other {<x id="INTERPOLATION" equiv-text="{{recipientDataSource.filteredData.length}}"/> recipients} }</source>
    <context-group purpose="location">
      <context context-type="sourcefile">src/app/features/administration/recipients/recipients.component.html</context>
      <context context-type="linenumber">107</context>
    </context-group>
    <note priority="1" from="description">Recipients, footer recipient count text</note>
  </trans-unit>

and this is the one extracted by locl extract:

  <trans-unit id="Recipients_Footer_Recipients_Count_Text" datatype="html">
    <source>{VAR_PLURAL, plural, =0 {no recipients found} =1 {1 recipient} other {{INTERPOLATION} recipients}}</source>
    <target>{VAR_PLURAL, plural, =0 {no recipients found} =1 {1 recipient} other {{INTERPOLATION} recipients}}</target>
    <note priority="1" from="description">Recipients, footer recipient count text</note>
  </trans-unit>

The first one is converted into JSON correctly by locl convert, while the second one generates the above mentioned error.

Thanks.

ocombe commented 4 years ago

Could you give me the content of the template? It would be easier to reproduce, thanks!

rayita commented 4 years ago

Well is pretty simple:

<span i18n="Description@@CustomId">{itemCount, plural, =0 {no items} =1 {1 item} other {{{itemCount}} items}}</span>

This is how angular extract it:

      <trans-unit id="CustomId" datatype="html">
        <source>{VAR_PLURAL, plural, =0 {no items} =1 {1 item} other {<x id="INTERPOLATION" equiv-text="{{itemCount}}"/> items} }</source>
        <context-group purpose="location">
          <context context-type="sourcefile">src/app/features/administration/recipients/recipients.component.html</context>
          <context context-type="linenumber">111</context>
        </context-group>
        <note priority="1" from="description">Description</note>
      </trans-unit>

This is how locl estract it:

      <trans-unit id="CustomId" datatype="html">
        <source>{VAR_PLURAL, plural, =0 {no items} =1 {1 item} other {{INTERPOLATION} items}}</source>
        <target>{VAR_PLURAL, plural, =0 {no items} =1 {1 item} other {{INTERPOLATION} items}}</target>
        <note priority="1" from="description">Description</note>
      </trans-unit>

As I said locl can convert angular version but cannot convert locl version.

Cheers.

abierbaum commented 4 years ago

@rayita @ocombe Any workaround for this? It is keeping me from using locl right now.

andreybuzin commented 4 years ago

@ocombe same problem

SaschaPWittwer commented 4 years ago

While not perfect I found a workaround to use plurals with the locl tooling.

Instead of using the plural expression directly in the template, I discovered that using the i18nPlural pipe can provide a workaround for using plurals with the locl tooling.

In the template instead of writing

{itemCount, plural, =0 {no items} =1 {1 item} other {{{itemCount}} items}}

use this

{{ itemCount | i18nPlural: itemCountTranslationMap }}

and define the translation map in your component like this

itemCountTranslationMap: { [k: string]: string } = { '=0': 'no items', '=1': $localize`:@@itemSingular:1 item`, other: $localize`:@@itemPlural:# items` };

When extracting with the locl cli, we now will have simple translations for both $localize calls (In this case itemSingular and itemPlural) instead of the complex plural translation.

Maybe this helps someone 😄

Estevete commented 4 years ago

I have this code in my html:

<span i18n="@@itemHeaderNewName">
    {{item.get('itemId')?.value ? "*" : "New item"}}
</span>

Do you know if it's possible to translate "*" and "New item"? This is how the locl converts it: @@itemHeaderNewName: "{$INTERPOLATION}"