Skip to content

Enabling Angular i18n native

Iskandar Najmuddin edited this page Oct 2, 2017 · 14 revisions

Using Angular i18n native module can be tricky. This guide intends to help you enable i18n with the seed and deal with common problems related to internationalization in Angular.

  1. Uncomment src/client/app/i18n.providers.

  2. Enable i18n in the seed

Open main.ts located at src/client/app and uncomment the following lines :

import { TranslationProviders } from './i18n.providers';

...

let TP = new TranslationProviders();
TP.getTranslationFile().then((providers: any) => {
   const options: any = { providers };
   platformBrowserDynamic().bootstrapModule(AppModule, options);
});

NOTE: Be sure to uncomment options so it is passed as the second parameter to bootstrapModule().

  1. The i18n attribute

The i18n attribute is the way Angular determines what content is to translate. It also helps the compiler-cli to generate the XLF file. For example:

<h1>Howdy!</h1>

<!-- becomes -->

<h1 i18n>Howdy!</h1>

WARNING: translatable fields are ids based. Since the ids is based on the content of the element (formatting and text), make sure to avoid any breaking returns, empty lines, etc. If so, the translation will break when the application is mangled for production.

  1. In order to allow ng-xi18n find the application, in tools/tasks/project create file called: app.through.ts with the following content:

    import '../../../src/client/app/main';
  2. Generate your XLF base file

In the command line, run the following command:

$ npm run i18n

NOTE: Errors may show when running the command. If the messages.xlf has been generated, the process was successful.

This will generate a messages.en.xlf in the dist/locale/ directory. Move this file to your locale folder (default folder is set to src/client/assets/locale. Copy it and rename it such as messages.fr.xlf for french, messages.de.xlf for german, etc.

By convention, we respect the ISO 3166-1 alpha-2 2 letter country code names.

  1. Manage the application language from the client

Open i18n.providers.ts located at src/client/app, this is where you will set the way you want to deal with languages, there is no default but a noProviders callback is local language is undefined.

The seed lets you manage languages the way you want. Here is working example for you to try:

Replace the following lines from the i18n.providers.ts files:

...

// Define a way to retrieve the local information
let locale: string;
try {
      locale = localStorage.getItem('lang') || 'en-US';
} catch (e) {
      // Handle any errors (e.g. "SecurityError: The operation is insecure." if client blocks cookies.)
      locale = 'en-US';
}
...

To create the localStorage record, open navbar.component.ts located at src/client/app/shared/navbar and update the component such as:

export class NavbarComponent {
   public lang: string;

   public constructor () {
     try {
       this.lang = localStorage.getItem('lang') || 'en-US';
     } catch (e) {
       // Handle any errors (e.g. "SecurityError: The operation is insecure." if client blocks cookies.)
       this.lang = 'en-US';
     }
   }

   public selectLanguage = (lang: string) => {
     try {
       localStorage.setItem('lang', lang);
     } catch (e) {
       // Handle any errors (e.g. "SecurityError: The operation is insecure." if client blocks cookies.)
     }
     window.location.href = '/';
   }
}

Finally, edit navbar.component.html and add the following lines in the <nav> element:

<a (click)="selectLanguage('fr')" *ngIf="lang !== 'fr'">Français</a>
<a (click)="selectLanguage('en-US')" *ngIf="lang !== 'en-US'">English</a>
  1. Compiling for AoT

While JiT does not require any action to compile a multilingual application, AoT is different. One needs to generate one package per language using the following command (example for french) :

$ npm run build.prod.exp -- --lang fr

At the moment, the compiler will only recognize files stored in src/client/assets/locale/messages.xx.xlf.

  1. Known issues

A. Translation break at runtime in production environment

Issue: When the compiler scans for i18n elements, it also gives a specific id to the translatable field. This id is based on the content and the formatting of the field. When building, the build.prod task will mangle the text nodes which result in creating different ids between dev and prod environment. This issue should disappear with AoT.

Solution: Make sure to keep your text inline.

B. The language won't change

Issue: The language file cannot be found or the Translation for id="xxx" cannot be found.

Solution: Make sure i18n.providers.ts data is correct (translation filenames and translations folder).

More information about I18nSelectPipe and I18nPluralPipe to come.

That's all folks. This guide helped through the process of enabling i18n native.