In-context mode issue with angular interpolation


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).

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!

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:
(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 ?

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!

The project name is 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">
        <context-group purpose="location">
          <context context-type="sourcefile">dist/projects/project/[...]/my.component.ts</context>
          <context context-type="linenumber">14,15</context>
        <target state="needs-translation">Hello</target>

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>
        <target state="needs-translation">Hello <x id="INTERPOLATION" equiv-text="{{ value }}"/>!</target>

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)

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

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


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).

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

Hi Wykks,

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

1 Like


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)



Happy to hear this!