Internationalize Your Angular App with ngx-translate

Seth Gwartney

At some point, your web application may require serving a multilingual user base. Internationalization, or i18n for short, is the process by which you make your app usable for those with a different native language. While Angular has some built-in i18n functionality, ngx-translate is a third-party package which makes the process dead simple.

🐊 Alligator.io recommends

Our recommended Angular courses

Getting Started

You know the drill. Fire up your terminal and run the following command to add the package to your application.

$ npm i @ngx-translate/core --save

Now import the TranslateModule in your AppModule.

...
@NgModule({
  imports: [
    BrowserModule,
    TranslateModule.forRoot()
  ],
  bootstrap: [AppComponent]
})
...

This is basically all you need to do to have access to the core of the translate service, pipe, and directives. However, unless you plan on adding each and every translation yourself manually via code, you will probably want to add a little bit of configuration at this stage in order to make loading your translations a little easier.

Loaders

Probably the most common way to load translations is to include your translation files as assets, and load them via the TranslateHttpLoader, which is available in a separate npm package.

$ npm install @ngx-translate/http-loader --save
// ...
export function createTranslateLoader(http: HttpClient) {
	return new TranslateHttpLoader(http);
}

@NgModule({
  imports: [
    BrowserModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
          useFactory: createHttpLoader, // exported factory function needed for AoT compilation
          deps: [HttpClient]
      }
    })
  ],
  bootstrap: [AppComponent]
})

// ...

You are free to create your own loader - just implement the TranslateLoader interface and provide it in your module like above.

Translation Files

Creating the translation loader in this way expects you to have a file in your project under an /assets/i18n/ folder, called {lang}.json, where {lang} is the language of the file you are using for translations. For English, this file may be en.json, for example. You can change the default path and file extension by providing extra parameters to the new TranslateHttpLoader() constructor.

The translation file is just a JSON object of key-value pairs, where the key describes the text that is translated, and the value is the actual text in the language specified by the file. The value may also be another object, which allows you to group your translations however you’d like.

In the text of your translation value, you can also include double curly braces around a variable name, which will later allow you to interpolate strings dynamically into your translations.

en.json

{
  "welcomeMessage": "Thanks for joining, {{ firstName }}! It's great to have you!",
  "login": {
    "username": "Enter your user name",
    "password": "Password here",
  }
}

Accessing Translations

Before you can access these translations in your application, you have to initialize some properties in the TranslateService. Probably the best place to do this is in your bootstrapped AppComponent.

app.component.ts

import {Component} from '@angular/core';
import {TranslateService} from '@ngx-translate/core';

@Component({
  selector:  'my-app',
  templateUrl:  './app.component.html',
  styleUrls:  [  './app.component.css'  ]
})
export class AppComponent {
  constructor(translate: TranslateService) {
    translate.addLangs(['en', 'klingon'])
    translate.setDefaultLang('en');
    translate.use('en');
  }
}

First of all translate.addLangs([]) tells the service which languages are available to use for translations. The method translate.setDefaultLang('en') allows you to specify a fallback set of translations to use in case there are missing translations for the current language. translate.use('en') tells the service which is the current language to use for translations. The parameter for all of these is the language you want to pull translations from - these should match the names of the JSON files that define the translations for those languages.

With that set up, you have three ways to access the translations. Which one you use at any given time will be up to your needs and preferences.

TranslateService

Using the service, there are two methods to get your translations. The first, and recommended, method is to use get(key: string|Array<string>, interpolateParams?: Object). This returns an Observable, and as such, is asynchronous, which guarantees that the translation file will be loaded before using the value. This Observable then completes as soon as the value is retrieved. The second method is to use instant(key: string|Array<string>, interpolateParams?: Object), which is synchronous. If the translation file isn’t finished loading at the time you use this method, you won’t get a translation at all.

Remember, we told the service to use en as the current lang, so all translation results will come from en.json initially. You can implement your own method in your application to switch between languages - however you do it, whether through a select box, URL route, or some other method, wherever you are, just call the use(lang: string) method on the TranslateService to set the current language.

// ...
user: { firstName: string, lastName: string };
welcome: string;
usernameLabel: string;
passwordLabel: string;
constructor(private translate: TranslateService) { }

ngOnInit() {
  // synchronous. Also interpolate the 'firstName' parameter with a value
  this.welcome = this.translate.instant('welcomeMessage', { firstName: this.user.firstName });
  // asynchronous - gets translations then completes.
  this.translate.get(['login.username', 'login.password'])
    .subscribe(translations => {
      this.usernameLabel = translations['login.username'];
      this.passwordLabel = translations['login.password'];
    });
}

TranslatePipe

You can use the translate pipe much like you’d use any other pipe in Angular. The input into the pipe is the key of the translation you need. The optional parameter is an object which defines any interpolation strings that the translation is expecting. In the example below, the component has a user object, with a property of firstName. This matches the interpolation that is expected by the value of welcomeMessage.

<p>{{ 'welcomeMessage' | translate:user }}</p>
<input type="password" placeholder="{{ 'login.password' | translate }}">

TranslateDirective

You can also place a directive on any HTML element to get translations. There are a couple of different ways to do this.

<label translate='login.username'></label>

You can also set the key of the translation as the content of the element.

<p translate [translateParams]="{ firstName: user.firstName }">welcomeMessage</p>

Further Reading

  Tweet It

πŸ•΅ Search Results

πŸ”Ž Searching...

Sponsored by #native_company# β€” Learn More
#native_title# #native_desc#
#native_cta#