Angular Localization and Internationalization

angular localization i18n cover image | The Phrase Blog

Learn how to easily implement Angular localization with built-in or external libraries. This tutorial will show you how to work with both angular-i18n and ngx-translate.

When it comes to translating Angular-based apps, there are several decisions you need to make before diving into the tiniest of details of both internationalization (i18n) and localization (l10n).

To give you a helping hand, this guide will provide an in-depth overview of Angular i18n and l10n options available, highlight both their pros and cons, as well as provide some practical Angular localization examples.

Preparing the Ground for Angular Localization

First things first, you need to be able to answer the following question: Should I use the built-in tools or a third-party library for Angular i18n? Please note that the built-in tools are not finished yet so there are some missing features that we will point out further down as well.

Have you decided to go with built-in tools for your Angular localization, there is a second decision to make: Do you want to use the ahead-of-time (AOT) compiler or the just-in-time (JIT) compiler? With AOT, your application can be served fast, and your users profit from a better performance. As a disadvantage, you need to serve an application for each locale because all information, including the content, is built-in when compiling the app.

The decision of which language should be shown to your users needs to happen with serverside logic or by URL parameters. If you go with JIT, translations are dynamic, but you need to take care of providing the translations in your application. However, keep in mind that, in this case, performance might decrease.

There is also the option to choose a third-party library for internationalization. As an example, we will pick ngx-translate, one of the most popular libraries. The library can be used for both the JIT and AOT compiled versions of your app.

Angular Localization with Built-In I18n

First, we will take a closer look at the built-in tools of Angular. We will show you how to set up your Angular localization and how to actually translate content. Then we will look at issues like pluralization and placeholders in your content. Last but not least, we will present a basic workflow of how to integrate Phrase into your development flow.


With AOT there is nothing to set up for starting internationalization within your app. The only thing for testing different locales is starting your app with the locale code as a parameter. Here is an example if you want to test the German translations using the locale code de:

ng serve --aot --locale de

If you are using JIT you need to define your LOCALE_ID provider in your main module:

import { LOCALE_ID, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from '../src/app/app.component';

      imports: [ BrowserModule ],
        declarations: [ AppComponent ],
        providers: [ { provide: LOCALE_ID, useValue: 'de' } ],
        bootstrap: [ AppComponent ]
export class AppModule { }

That’s all you need for getting started with internationalization in your Angular app using the built-in tools.

Extract Your Unlocalized Content

In most cases, you already have an app that now needs to be translated into several languages. Extracting every existing translation can be very annoying.

Angular’s CLI provides a command that exports every content that is marked with the i18n attribute (you will read about that in the next section). Unfortunately, you need to mark every content yourself. Once this is done you can generate a file that includes every source translation with:

ng x18n

By default, this will generate a message.xlf XLIFF 1.2 file. With this file, you can start translating the content into multiple languages.

Best practice is to create a directory where every content that needs localization is located e.g. ./locale. Now copy your generated file into the new folder and include the locale information into the filename. For example, messages.en.xlfif the content is English or if it’s German content.

Translate your content

For translating the content the type of the built-in compiler doesn’t matter. Both options are using the same syntax.

<h1 i18n>My Headline<h1>

The attribute i18n will take care of the localization of this content. We highly recommend to add an ID for the translation otherwise it will be generated by angular which results in a random ID.

<h1 i18n="@@my_meaningful_id">My Headline<h1>

You can also add a description for your translation which could help your translators understanding the context:

<h1 i18n="This is a very good description@@my_meaningful_id">My Headline<h1>

In a few cases, you need to localize an image for example. You can do this by localizing the src attribute of the image tag:

<img [src]="a localized images" i18n-title title="the localized title of the image" i18n-x="@@meaningful_id" />

This works with any attribute of any element.

Unfortunately, localizing content somewhere other than in an html-file is not possible yet. There is already an open issue on github but it seems to be quite tricky so it might take a while until this is implemented. If you need this feature, we recommend taking a closer look at the ngx-translate library.

Use Pluralization and Placeholders in Your Content

Angular uses the ICU message format by default. With this format, you can almost implement every constellation of pluralization and placeholders you can imagine. Here’s a basic example followed by an advanced one:

<h1>Hello {{ name }}</h1>
<span i18n>
    Updated: {minutes, plural,
    =0 {just now}
    =1 {one minute ago}
    other {{{minutes}} minutes ago by {gender, select, m {male} f {female} o {other}}}}

The first one simply says hello to the given name. The second example will print different content based on the value of minutes. If the minutes are unequal 0 and 1 the content of the other case will be taken where the content is dependent on the gender of a person. ICU message format is really powerful but also a bit complicated for users that are not used to it. You can read more about the format here.

Sidenote: Fortunately, Phrase supports some highlighting and simplification for the ICU message format.

Angular Localization with ngx-translate

🗒 Note » This is just a short and sweet intro to internationalizing with ngx-translate. For more insights on how to use ngx like a pro, make sure to stop by our Deep Dive on Angular I18n with ngx-translate.

ngx-translate is an internationalization library for angular which tries to close the gap between the missing features of the built-in internationalization functionalities.


For setting it up you first need to install the library

npm install @ngx-translate/core --save

After that, you need to configure the TranslateModule for loading the i18n files where the translated content is located.

import {NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {HttpClientModule, HttpClient} from '@angular/common/http';
import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
import {AppComponent} from './app';

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

        imports: [
                            loader: {
                                        provide: TranslateLoader,
                                        useFactory: HttpLoaderFactory,
                                        deps: [HttpClient]
            bootstrap: [AppComponent]
export class AppModule { }

This would load the translations from /assets/i18n/<locale-code>.json<locale-code> is the placeholder for all the languages you provide.

The next step initializes the TranslationService. Here, you have to tell the app what the default language should be. The default language will be used in cases where no translation in the target language exists.

 export class AppComponent {
         param = {value: 'world'};

             constructor(translate: TranslateService) {

Your app is now ready for i18n. You can also setup ngx-translate for working with AOT. For more details please visit the official page where some more informations about the setup are shown.

Extract Your Unlocalized Content

ngx-translate can’t export your content automatically. But there is a plugin that can extract every translatable content and save it as JSON or Gettext pot files.
Visit the github page for more information and a basic integration.

Translate the Content

ngx-translate provides three ways to localize the content. You can either use the TranslationService, the TranslatePipe or the TranslateDirective to get your localized content.
Use theTranslationService if you need to localize content in one of your services or controllers.

translate.get('my_meaningful_id').subscribe((res: string) => { ... });

For translating content in your html files you can use the TranslatePipe:

<h1>{{ 'my_meaningful_id' | translate }}

In addition to the pipe you can use the TranslateDirective to translate the content in your view:

<div translate>my_meaningful_id</div>

Localizing single attributes of an HTML-Tag is not possible. Therefore you need to set up the whole tag as a translation which is no problem at all. You only need to use the innerHTML-Attribute and it should work out of the box:

<h1 [innerHTML]="'key_id_with_html_content' | translate"></h1>

Use pluralization and placeholders in your content

Placeholders can be filled in by simply passing a hash when inserting. Here the examples of the above-mentioned ways:

translate.get('my_meaningful_id', { placeholder_name: value }).subscribe((res: string) => {
# in your component
params = { placeholder_name: value }
#in your view
<h1>{{ 'my_meaningful_id' | translate:params }}
<div translate="my_meaningful_id" translateParams="{ placeholder_name: value }">my_meaningful_id</div>

Pluralization doesn’t work out of the box. You need to use the i18nPluralPipe from the Angular API to solve this.
Here you can find more information about that:

There is also a plugin for using the ICU message format:

Automate Your Angular Localization Workflow

It’s very easy to integrate Phrase into your yarn/npm build flow. You can simply add the phraseapp pull command into your scripts in the package.json.

Here is an example of how your scripts can look like:

"scripts": { 
  "ng": "ng", 
  "start": "ng serve",
  "build": "phraseapp pull && ng build", 
  "localize": "phraseapp push", 
  "test": "ng test", 
  "lint": "ng lint", 
  "e2e": "ng e2e" 

There are two actions we implement. First one is yarn localize / npm localize. This will push all translations to Phrase where the content can be translated by your translators or you can order translations. The second action is yarn build / npm build. Here we added phraseapp pull in order to have the translation always up to date before releasing a new version.
To use this configuration you only need to install our CLI Tool and create a config in your project.


For your Angular l10n & i18n, ngx-translate seems to be more feature complete and usable as the built-in tools. The plugins for ngx-translate are adding most of the missing features like ICU message format and extracting the content for an easy start. But we think that Angular has done some very good work on their i18n tools. The easy setup is one of the biggest advantages of Angular’s i18n feature, especially if you only use translation in your view files.