Angular i18n

Angular has support for internationalisation with the @ngx-translate/core module. This and a needed loader can be installed via

npm install @ngx-translate/core --save
npm install @ngx-translate/http-loader --save

With this done you need to create a folder src/assets/i18n and place your language json file like en.json in it.

Now the translation module and service needs to be configured. Open your app.module.ts file and add the follwing to your imports:

import { TranslateModule, TranslateLoader, TranslateService } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { HttpClientModule, HttpClient } from '@angular/common/http';
TranslateModule.forRoot({
  defaultLanguage: DEFAULT_LANG,
  loader: {
    provide: TranslateLoader,
    useFactory: httpLoaderFactory,
    deps: [HttpClient],
  },
})

Where DEFAULT_LANG is set as a const to ‘en’. httpLoaderFactory is a function defined above:

export function httpLoaderFactory(http: HttpClient): TranslateHttpLoader {
  return new TranslateHttpLoader(http);
}

To get it running I further added an app initialiser under providers:

import { APP_INITIALIZER, NgModule } from '@angular/core';
{
  provide: APP_INITIALIZER,
  useFactory: initialise,
  deps: [TranslateService],
  multi: true,
}

Where initialise is a method again:

export function initialise(translate: TranslateService): any {
  return async () => {
    translate.setDefaultLang(DEFAULT_LANG);
    translate.use(DEFAULT_LANG);

    const translatePromise = new Promise<void>((resolve) => {
      translate.onLangChange.subscribe(() => {
        resolve();
      });
    });

    return Promise.all([translatePromise]);
  };
}

Usage

Your translation files in assets/i18n are simple json structures that can be nested. Here an example:

{
  "MAIN": {
    "TITLE": "Hello",
    "TEXT": "world!"
  }
}

You can access this in your html files by using

{{ 'MAIN.TITLE' | translate }}

which would get the text Hello.

If you need to access translations in your typescript files you can do so by injecting the TranslateService and then asynchronously fetch translations like this:

title: string;
constructor(private translate: TranslateService) {
  translate.get('MAIN.TITLE').subscribe((text: string) => (this.title = text));
}

This will set the class variable title to the text from translation and you can access it like a normal variable in Angular.

HTML

If you need to include html in your translations you can use innerHtml like here:

<p class="lead" [innerHtml]="'MAIN.TEXT' | translate"></p>