In-depth Guides
Internationalization

Work with translation files

After you prepare a component for translation, use the extract-i18n Angular CLI command to extract the marked text in the component into a source language file.

The marked text includes text marked with i18n, attributes marked with i18n-attribute, and text tagged with $localize as described in Prepare component for translation.

Complete the following steps to create and update translation files for your project.

  1. Extract the source language file.
    1. Optionally, change the location, format, and name.
  2. Copy the source language file to create a translation file for each language.
  3. Translate each translation file.
  4. Translate plurals and alternate expressions separately.
    1. Translate plurals.
    2. Translate alternate expressions.
    3. Translate nested expressions.

Extract the source language file

To extract the source language file, complete the following actions.

  1. Open a terminal window.
  2. Change to the root directory of your project.
  3. Run the following CLI command.
          
    ng add @angular/localizeng extract-i18nng extract-i18n --output-path src/localeng extract-i18n --format=xlfng extract-i18n --format=xlf2ng extract-i18n --format=xmbng extract-i18n --format=jsonng extract-i18n --format=arbng extract-i18n --out-file source.xlfng build --localizeng serve --configuration=frng build --configuration=production,fr

The extract-i18n command creates a source language file named messages.xlf in the root directory of your project. For more information about the XML Localization Interchange File Format (XLIFF, version 1.2), see XLIFF.

Use the following extract-i18n command options to change the source language file location, format, and file name.

Command option Details
--format Set the format of the output file
--out-file Set the name of the output file
--output-path Set the path of the output directory

Change the source language file location

To create a file in the src/locale directory, specify the output path as an option.

extract-i18n --output-path example

The following example specifies the output path as an option.

      
ng add @angular/localizeng extract-i18nng extract-i18n --output-path src/localeng extract-i18n --format=xlfng extract-i18n --format=xlf2ng extract-i18n --format=xmbng extract-i18n --format=jsonng extract-i18n --format=arbng extract-i18n --out-file source.xlfng build --localizeng serve --configuration=frng build --configuration=production,fr

Change the source language file format

The extract-i18n command creates files in the following translation formats.

Specify the translation format explicitly with the --format command option.

HELPFUL: The XMB format generates .xmb source language files, but uses.xtb translation files.

extract-i18n --format example

The following example demonstrates several translation formats.

      
ng add @angular/localizeng extract-i18nng extract-i18n --output-path src/localeng extract-i18n --format=xlfng extract-i18n --format=xlf2ng extract-i18n --format=xmbng extract-i18n --format=jsonng extract-i18n --format=arbng extract-i18n --out-file source.xlfng build --localizeng serve --configuration=frng build --configuration=production,fr

Change the source language file name

To change the name of the source language file generated by the extraction tool, use the --out-file command option.

extract-i18n --out-file example

The following example demonstrates naming the output file.

      
ng add @angular/localizeng extract-i18nng extract-i18n --output-path src/localeng extract-i18n --format=xlfng extract-i18n --format=xlf2ng extract-i18n --format=xmbng extract-i18n --format=jsonng extract-i18n --format=arbng extract-i18n --out-file source.xlfng build --localizeng serve --configuration=frng build --configuration=production,fr

Create a translation file for each language

To create a translation file for a locale or language, complete the following actions.

  1. Extract the source language file.

  2. Make a copy of the source language file to create a translation file for each language.

  3. Rename the translation file to add the locale.

          messages.xlf --> messages.{locale}.xlf
        
  4. Create a new directory at your project root named locale.

          src/locale
        
  5. Move the translation file to the new directory.

  6. Send the translation file to your translator.

  7. Repeat the above steps for each language you want to add to your application.

extract-i18n example for French

For example, to create a French translation file, complete the following actions.

  1. Run the extract-i18n command.
  2. Make a copy of the messages.xlf source language file.
  3. Rename the copy to messages.fr.xlf for the French language (fr) translation.
  4. Move the fr translation file to the src/locale directory.
  5. Send the fr translation file to the translator.

Translate each translation file

Unless you are fluent in the language and have the time to edit translations, you will likely complete the following steps.

  1. Send each translation file to a translator.
  2. The translator uses an XLIFF file editor to complete the following actions.
    1. Create the translation.
    2. Edit the translation.

Translation process example for French

To demonstrate the process, review the messages.fr.xlf file in the Example Angular Internationalization application. The Example Angular Internationalization application includes a French translation for you to edit without a special XLIFF editor or knowledge of French.

The following actions describe the translation process for French.

  1. Open messages.fr.xlf and find the first <trans-unit> element. This is a translation unit, also known as a text node, that represents the translation of the <h1> greeting tag that was previously marked with the i18n attribute.

    src/locale/messages.fr.xlf ()

          
    <!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

    The id="introductionHeader" is a custom ID, but without the @@ prefix required in the source HTML.

  2. Duplicate the <source>... </source> element in the text node, rename it to target, and then replace the content with the French text.

    src/locale/messages.fr.xlf (, after translation)

          
    <!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

    In a more complex translation, the information and context in the description and meaning elements help you choose the right words for translation.

  3. Translate the other text nodes. The following example displays the way to translate.

    src/locale/messages.fr.xlf ()

          
    <!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

IMPORTANT: Don't change the IDs for translation units. Each id attribute is generated by Angular and depends on the content of the component text and the assigned meaning.

If you change either the text or the meaning, then the id attribute changes. For more about managing text updates and IDs, see custom IDs.

Translate plurals

Add or remove plural cases as needed for each language.

HELPFUL: For language plural rules, see CLDR plural rules.

minute plural example

To translate a plural, translate the ICU format match values.

  • just now
  • one minute ago
  • <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago

The following example displays the way to translate.

src/locale/messages.fr.xlf ()

      
<!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

Translate alternate expressions

Angular also extracts alternate select ICU expressions as separate translation units.

gender select example

The following example displays a select ICU expression in the component template.

src/app/app.component.html

      
<h1 i18n="User welcome|An introduction header for this sample@@introductionHeader">  Hello i18n!</h1><ng-container i18n>I don't output any element</ng-container><br /><img [src]="logo" i18n-title title="Angular logo" alt="Angular logo"/><br><button type="button" (click)="inc(1)">+</button> <button type="button" (click)="inc(-1)">-</button><span i18n>Updated {minutes, plural, =0 {just now} =1 {one minute ago} other {{{ minutes }} minutes ago}}</span>({{ minutes }})<br><br><button type="button" (click)="male()">♂</button><button type="button" (click)="female()">♀</button><button type="button" (click)="other()">⚧</button><span i18n>The author is {gender, select, male {male} female {female} other {other}}</span><br><br><span i18n>Updated: {minutes, plural,  =0 {just now}  =1 {one minute ago}  other {{{ minutes }} minutes ago by {gender, select, male {male} female {female} other {other}}}}</span><br><br><button type="button" (click)="toggleDisplay()">Toggle</button><div i18n [attr.aria-label]="toggleAriaLabel()">{{toggle()}}</div>

In this example, Angular extracts the expression into two translation units. The first contains the text outside of the select clause, and uses a placeholder for select (<x id="ICU">):

src/locale/messages.fr.xlf ()

      
<!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

IMPORTANT: When you translate the text, move the placeholder if necessary, but don't remove it. If you remove the placeholder, the ICU expression is removed from your translated application.

The following example displays the second translation unit that contains the select clause.

src/locale/messages.fr.xlf ()

      
<!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

The following example displays both translation units after translation is complete.

src/locale/messages.fr.xlf ()

      
<!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

Translate nested expressions

Angular treats a nested expression in the same manner as an alternate expression. Angular extracts the expression into two translation units.

Nested plural example

The following example displays the first translation unit that contains the text outside of the nested expression.

src/locale/messages.fr.xlf ()

      
<!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

The following example displays the second translation unit that contains the complete nested expression.

src/locale/messages.fr.xlf ()

      
<!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

The following example displays both translation units after translating.

src/locale/messages.fr.xlf ()

      
<!-- The `messages.fr.xlf` after translation for documentation purposes --><?xml version="1.0" encoding="UTF-8" ?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2">  <file source-language="en" datatype="plaintext" original="ng2.template">    <body>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="introductionHeader" datatype="html">        <source>Hello i18n!</source>        <target>Bonjour i18n !</target>        <note priority="1" from="description">An introduction header for this sample</note>        <note priority="1" from="meaning">User welcome</note>      </trans-unit>      <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">        <source>I don't output any element</source>        <target>Je n'affiche aucun élément</target>      </trans-unit>      <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">        <source>Angular logo</source>        <target>Logo d'Angular</target>      </trans-unit>      <trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" 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'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>      </trans-unit>      <trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">        <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>        <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">        <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>        <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>      </trans-unit>      <trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">        <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>        <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>      </trans-unit>      <trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">        <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>        <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>      </trans-unit>      <trans-unit id="myId" datatype="html">        <source>Hello</source>        <target state="new">Bonjour</target>      </trans-unit>    </body>  </file></xliff>

What's next