internationalizationangular-i18n

Angular i18n $localize - template literal with expressions


I am having so much trouble getting this syntax to translate - Angular 13.0.02 .

My two resources are:

https://angular.io/api/localize/init/$localize
https://lokalise.com/blog/angular-i18n/

As per the Angular docs:

Naming placeholders

 If the template literal string contains expressions, then the expressions will be automatically associated with placeholder names for you.

For example:

  $localize `Hi ${name}! There are ${items.length} items.`;

  will generate a message-source of Hi {$PH}! There are {$PH_1} items.`

And providing meaning, descrip, and ID:

$localize`:meaning|description@@id:source message text`;

$localize`:meaning|:source message text`;
$localize`:description:source message text`;
$localize`:@@id:source message text`;

This example from lokalise.com works:

const company = "Google";
const created_by = $localize`Created by ${company}`;

in my XLIF translation file:

   <trans-unit id="3990133897753911565" datatype="html">
     <source>Created by <x id="PH"/></source>
     <target>Creado por... <x id="PH"/></target>
   </trans-unit>

enter image description here

This DOESN'T WQRK:

Yet when I try to reproduce the same syntax with another i18 term - it DOESN'T WORK. It only pulls the English phrase, not the Spanish one.

 const company = "Google";
 const createdByCompany = $localize`Created by this person ${company}`;

<trans-unit id="spanishTest123" datatype="html">
    <source>Created by this person <x id="PH"/></source>
    <target>Creado por esta persona <x id="PH"/></target>
</trans-unit>

enter image description here

FYI: for the example that does work, if I REMOVE id="3990133897753911565", then it does NOT pull that translation. So clearly this id makes it happen - yet in my 2nd example I cannot get it to work.

*** UPDATE ***

Using the Angular extract tool produces the XLF file in the required xml format (it parses all i18n tags in your html temples, and the $localize calls in your component code). Run in your app's root dir as follows ng extract-i18n --output-path src/locale - then check the messages.xlf file in the locale folder.


Solution

  • So as per the docs, the "pre-pending it with a colon" syntax did work - https://angular.io/api/localize/init/$localize

    const msg = $localize`:Password Reset Modal|Min num of chars@@passwordNumChars:Must be at least ${setting.SettingValue}:minLen: characters long.`;
    

    Notice how I updated the trans-unit "id" attrib in the xlf - i.e. my custom ID is "passwordNumChars".

    <trans-unit id="passwordNumChars" datatype="html">
        <source>Must be at least <x id="minLen" equiv-text="setting.SettingValue"/> characters long.</source>
        <target>Debe contener al menos <x id="minLen" equiv-text="setting.SettingValue"/> caracteres.</target>
        <note priority="1" from="meaning">password edit modal</note>
    </trans-unit>

    One final note: if you have the $localize function setup in your ts code - but you can't figure out the xlf format - you can use ng extract-i18n --output-path src/locale from a cmd line to generate the appropriate xlf file.

    Then just copy/paste the section you need into your locale file; also perhaps into whatever translation software you're using as the source of truth (i.e. poedit.com to store all i18n terms).