In-context mode issue with angular interpolation

Hi,

There is an issue when using in-context mode with angular official translation system.
When translating text with some angular template interpolation, crowdin add the brackets inside the translation target :worried:

So if I have this in an angular template:
<span i18n>Hello {{ value }}!</span>

Then in the xlf file generated for in-context translation, we get something like this :
<target>crwdns8303:0{{ value }}crwdne8303:0</target>

Which make angular crash with the following error:

Unable to parse ICU expression in ā€œcrwdns8303:0{{ value }}crwdne8303:0ā€ message.

Is there any way to fix this?
(excluding the interpolation from the translation is not a solution, because sometimes, we may want to reorder the words).

1 Like

Hi Wykks,

Weā€™d be glad to help!

Our developers recommended setting up an automatic change of the strings via angular once they will be processed by the in-context. Could you please let us know whether there is any chance such an option might work for you?

Additionally, you may use the parameters listed here:

For example, the ā€œbefore_dom_insertā€ option should help in such case.

Could you please give it a try, and let us know of the results?

Weā€™d be glad to help with any further questions!

1 Like

Thanks for your help!
Iā€™m not sure to understand your solution. The issue is that, angular itself is unable to read ā€œtargetā€ with {} in the xlf file, therefore ā€œbefore_dom_insertā€ cannot help here.

We may be able to run a script to edit the xlf before building the application, but what kind of change would work with crowdin ?

Maybe removing the content with bracket from this:
<target>crwdns8303:0{{ value }}crwdne8303:0</target>
To this:
<target>crwdns8303:0crwdne8303:0</target>
(I havenā€™t tested yet, because I donā€™t really like the idea that we would have to do this kind of processingā€¦)

But if something like this actually works, why crowdin actually add brackets in the first place, if itā€™s not necessary for the whole thing to work ?

1 Like

Could you please share with us the project name youā€™re working with In-context?

Also, could you please share any string example from the project where you noticed an issue with the crash (I mean the strings that make the angular crash)?

Weā€™d pass the details to our developers and double-check everything for you

Any additional details will be much appreciated!

1 Like

The project name is netwo-app (https://crowdin.com/project/netwo-app).

Itā€™s quite easy to reproduce (as long as you have a crowdin in-context setup working with angular).
With the official @angular/localize, you can do this:

<span i18n>Hello</span>

Which, after running ng extract-i18n will generate xlf files with something like this:

      <trans-unit id="112233445566" datatype="html">
        <source>Hello</source>
        <context-group purpose="location">
          <context context-type="sourcefile">dist/projects/project/[...]/my.component.ts</context>
          <context context-type="linenumber">14,15</context>
        </context-group>
        <target state="needs-translation">Hello</target>
      </trans-unit>

But if you are using an interpolation for dynamic content like this:
<span i18n>Hello {{ value }}!</span>

Then you get this:

      <trans-unit id="112233445566" datatype="html">
        <source>Hello <x id="INTERPOLATION" equiv-text="{{ value }}"/>!</source>
        <context-group purpose="location">
          <context context-type="sourcefile">dist/projects/project/[...]/my.component.ts</context>
          <context context-type="linenumber">14,15</context>
        </context-group>
        <target state="needs-translation">Hello <x id="INTERPOLATION" equiv-text="{{ value }}"/>!</target>
      </trans-unit>

When crowdin generate a translation for this item, in <target>, we get:

<target>crwdns10593:0{{ value }}crwdne10593:0</target>

Which result in an error when Angular read this at runtime.
Looks like brackets must be inside x id="INTERPOLATION" blocks to work properly in <target> blocks.

Also, when there is multiple brackets inside one trans-unit, Angular add a counter to INTERPOLATION, because itā€™s an id.
For example:
<div i18n>Stuff {{ a }} - {{ b }}</div>

Give us this:

<source>Stuff <x id="INTERPOLATION" equiv-text="{{ a }}"/> - <x id="INTERPOLATION_1" equiv-text="{{ b }}"/></source>`
[...]
`<target state="needs-translation">Stuff <x id="INTERPOLATION" equiv-text="{{ a }}"/> - <x id="INTERPOLATION_1" equiv-text="{{ b }}"/></target>

And currently with crowdin in-context:

<target>crwdns11335:0{{ a }}crwdnd11335:0{{ b }}crwdne11335:0</target>

(crwdns11335 is real if you want to check in the netwo-app project)

1 Like

Hi Wykks,

Thanks so much for such a detailed clarification!

Weā€™ve passed everything to our devs, and once they check everything - weā€™ll let you know right away

1 Like

Hi Wykks,

Our developers are still checking everything, but they have one additional question for you:

Could you please let us know whether itā€™d be possible for you to first let Crowdin process the string with its own script, and then start the angular script to process the string and avoid the issue with brackets?

In case that is not an option, weā€™ll create a task for our developers to check the possible changes for processing such strings with brackets on our side

1 Like

Hi,

Iā€™m not sure where this kind of processing should take place.

Currently we have:

  1. dev write the angular template
  2. run ng extract-i18n
  3. crowdin generate localized xlf files plus itā€™s own special in-context data to one specific xlf file.
  4. ng build
  5. crash when running with in-context translations.

Between step 1 and 2 looks super difficult (automatic template source code modification, very hard to do properly, no idea what kind of change could be done here), after step 2 itā€™s already crowdin turn, and after step 4 itā€™s not possible either (and I donā€™t know what could be done after step 4 that could not be done after step 2).

1 Like

Hi Wykks,

Thanks for the clarification!

Weā€™ll create a task for our developers to investigate the possible solutions

Weā€™ll keep you updated on any comments/news

1 Like

Hi Wykks,

Our developers have fixed the issue. Could you please check on your side if all works as expected now?

2 Likes

Hi,

The issue is indeed solved, many thanks! Thereā€™s still a small issue: the value is not rendered, but we can deal with it.
(ā€œhello {{ name }}ā€ => render "hello " in in-context mode)

2 Likes

Hi,

Happy to hear this!

1 Like

Hi,

I have recently tried adding In-Context Localization to an Angular project myself, and Iā€™m running into the same issue. In the pseudo-language package, the interpolation values still show up with the double brackets. Which results into an error when showing a page that contains those strings.
Error: Unable to parse ICU expression in "crwdns782:0{{ value }}crwdne782:0" message.

The situation seems the same as Wykksā€™ detailed description.

Is there any way to resolve this?

1 Like

Hello @Joren

Iā€™d like to assist you with this, but I need a project ID in order to check everything from my side. Canā€™t find any project owned own by your account. Please provide me with an ID here or in a private conversation (direct message), in case the project is not public available.

1 Like

Hi Dima,

Thanks for responding, I donā€™t see a DM button anywhere here or on anyoneā€™s profile.
But anyways, the project name is ā€œfarmdeskā€ with ID: 502394

2 Likes

Hi Joren, Iā€™ve done some magic from my side, kindly check your project now :slightly_smiling_face:

2 Likes

Thank you Dima.
The pages using interpolation are actually loading now.
Although, similar to Wykks, the value of the variable isnā€™t being rendered.

In the now fixed pseudo-language file:

<trans-unit id="8fbb34dd65417e82cd0abd96aba6979315441c58" datatype="html">
    <source>/<x id="INTERPOLATION" equiv-text="{{ animalTypeTranslationSingular }}"/>/day</source>
    <context-group purpose="location">
        <context context-type="sourcefile">src/app/containers/dashboard/dashboard.component.html</context>
        <context context-type="linenumber">35</context>
    </context-group>
    <target>crwdns768:0<x id="INTERPOLATION" equiv-text="{{ animalTypeTranslationSingular }}"/>crwdne768:0</target>
</trans-unit>

Renders as:
per_cow_per_day

Here, in case of Dutch, the expected result would be ā€œ/koe/dagā€.

Itā€™s great that both strings are revealed when clicking the translation icon, but I imagine it might be confusing for the translators if they donā€™t see that full string on the actual webpage.

Is displaying it like that something that could be fixed from Crowdinā€™s side or is that not within Crowdinā€™s control?

1 Like

Hello Joren. Magic was exactly the same as that was done for Wykks project. I assume itā€™s the default behavior, but for sure I can double-check with the team. How do you wish it to be like? Please provide me with a full vision so I can discuss internally whether itā€™s possible to implement or not.

1 Like

Sure, Iā€™ll use my post above for the example.

Iā€™m interpolating the animal variable:
<span i18n>/{{ animal }}/day</span>

Which can render on the webpage as /cow/day, /goat/day, or /sheep/day for the type of animal that the user has.

After extracting this string to a source file, and translating it, it will show up in the translated files like this (Dutch):

<trans-unit id="8fbb34dd65417e82cd0abd96aba6979315441c58" datatype="html">
    <source>/<x id="INTERPOLATION" equiv-text="{{ animal }}"/>/day</source>
    ...
    <target>/<x id="INTERPOLATION" equiv-text="{{ animal }}"/>/dag</target>
</trans-unit>

This is then rendered on the webpage as /koe/dag, /geit/dag/, or /shaap/dag.

Now, going to the In-Context Translation,
in the psuedo language file, it shows up like this:

<trans-unit id="8fbb34dd65417e82cd0abd96aba6979315441c58" datatype="html">
    <source>/<x id="INTERPOLATION" equiv-text="{{ animal }}"/>/day</source>
    ...
    <target>crwdns768:0<x id="INTERPOLATION" equiv-text="{{ animal }}"/>crwdne768:0</target>
</trans-unit>

But on the webpage it renders as //day for English, or //dag for Dutch.
The text for the animal is missing.

image

It would be ideal if the content from interpolated variables is also rendered on the In-Context webpages.
I hope that clarifies the situation a little. :sweat_smile:

2 Likes

Thanks, now things are more clear to me. Iā€™m going to check whether itā€™s possible to do something form our side.

1 Like