Angular and PrimeNG i18n using ng2-translate

The internationalization(i18n) support place a significant role in the web applications to improve the user base from different regions and languages. “Internationalization is the process of designing a software application so that it can potentially be adapted to various languages and regions without engineering changes”. Officially, Angular team supports this internationalization using i18n tools.Internally it uses ngx-i18n tools for the template translationThe entire process involves four phases:

  1. Identify the messages: Initially mark the static text messages in your component templates.
  2. Generate standard translation files: Extracts the marked messages into an industry standard translation source file(XLIFF and XMB formats).
  3. Translating the messages: Translating the extracted text messages into the target language by Translator tool.
  4. Complete the translation files: Angular compiler imports the compiled translation files and replace the original text with translation text files. Finally it creates translation files based target language.

There are many other libraries exists as an alternative. Among all those libraries, ngx-translate is the most popular one.

What makes ngx-translate library as better option?

As stated above, the official process (https://angular.io/guide/i18n) involves too many steps with the deep learning curve. The complexity grows with the number of features. The ngx-i18n tools are created especially for professional translators. It uses XLIFF (XML Localization Interchange File Format) and XMB (XML Message Bundle) standard ICU file formats which represents in the form of old clumsy XML format. Where as ngx-translator creates the translations in the most used JSON format. Apart from this, the i18n tools has some issues with Angular-CLI and AOT support (fixed in the later releases). Due to these reasons, many developers are still trying to explore other alternatives. Among them ngx-Translate is the popular one and used by many Angular developers.

Let’s start on how to use ngx-translate in Angular and PrimeNG application for internationalization support.

Getting started with ngx-translate

The library basically consists of 3 main modules

1. Core module
2. Loader module
3. Extractor module

Core library: NGX-Translate is extremely modular.The Core module is the heart of this library. We can use this library in standalone but it is recommended to use with other modules. We will explain more about this module in later sections. The Github URL for this module is available here .
Loader module: The loader module is used to load the translation files using different loader options.It supports three kinds of loaders.

  • Http Loader: Load JSON translation files using http (Github Link).
  • Angular Universal Loader: Load JSON translation files with fs instead of http (Github Link).
  • Po Loader: Load .po files with http (Github Link).

Extractor: This  module is useful to extract translatable (ngx-translate) strings from your code and save it as a JSON or Gettext pot file. It merges with existing strings if the output file already exists. The github URL is available  here.

How to setup ngx-Translate

Let’s first add below 3 packages(one for each module) inside your package.json file of angular’s application,

npm install @ngx-translate/core --save
npm install @ngx-translate/http-loader --save
npm install @biesbjerg/ngx-translate-extract --save-dev
In the Next step, we need to define TranslationModule which refers to particular loader(e.g, HttpLoader) inside global AppModule as below,
exportfunctioncreateHomeTranslateLoader(http:Http){
  returnnewTranslateHttpLoader(http,'./assets/i18n/','.json');
}
@NgModule({
  declarations:[...],
  imports:[...,
    TranslateModule.forRoot({
      loader:{
        provide:TranslateLoader,
        useFactory:createHomeTranslateLoader,
        deps:[Http]
      }
    })
  ],
  providers:[...],
  bootstrap:[AppComponent]
})
After that we need to active the TranslationService in your AppComponent as below. The .use method enables translation language as target. (In our demo example, the language is dynamically changed using select dropdown and reflected through routing navigations).
export class AppComponent {
    constructor(private translate: TranslateService) {
       translate.addLangs(["en", "es", "de"]);
       translate.setDefaultLang('en');
       translate.use('de');
     // let browserLang = translate.getBrowserLang();
     //translate.use(browserLang.match(/en|es|de/) ? browserLang : 'en');
}
}
Finally you need to apply translation for each label using translate pipe(|) symbol. The translate pipe refers the translations based on TranslationService language configuration.
 
<label style="float:right">{{ 'HOME.SELECT' | translate:param }}
     <select #langSelect (change)="translate.use(langSelect.value)">
          <option *ngFor="let lang of translate.getLangs()" [value]="lang" [selected]="lang ===                        translate.currentLang">{{ lang }}</option>
     </select>
</label> 

and define param property in component class as follows

param: any = {value: '3'};

You can either use the TranslateService, the TranslatePipe or the TranslateDirective to get your translation values.

If you opt service, it looks like this in component class:

translate.get('HOME.SELECT', {value: '3'}).subscribe((res: string) => {
    console.log(res);
    //=> 'Select Language(3)'
});

and the same with directive would be as below:

<div [translate]="'HOME.SELECT'" [translateParams]="{value: '3'}"></div>

Extracting the translation content

The manual process of creating JSON files and define key-value pairs would be difficult and time consuming process. This kind of process is error-prone too.  At this point, ngx-translate-extract module comes into the rescue. It will extract the translate labels from each file and creates the language specific( for example, en, es and de) JSON files. 
 
The below script command need to be executed to generate the files. Let’s park it as script command inside package.json file considering many options.
 
"i18n": "ngx-translate-extract --input ./src/app/ --patterns /app*.html
             --output ./src/assets/i18n/{en,es,de}.json --clean --sort --format namespaced-json" 
The command extracts the files from specified folder (denoted with –input option) and generates the JSON files (denoted with –output option) which needs to be edited with translations at a later point of time.
 

How to handle multiple modules?

In real-time angular applications, the entire project will be created as multi modular system. i.e, The specific functionalities or use cases grouped as one entity. In our demo example, we created registration and summary separate modules for employee system project. Due to these reasons, it should generate translation files specific to module.
 
The extraction command for multi modules would be as follows
"i18n_1": "ngx-translate-extract --input ./src/app/shared/registration
                 --output  ./src/assets/i18n/registration/{en,es,de}.json --clean --sort --format namespaced-json",
"i18n_2": "ngx-translate-extract --input ./src/app/shared/summary
                 --output ./src/assets/i18n/summary/{en,es,de}.json --clean --sort --format namespaced-json",
"extract": "npm run i18n_1 && npm run i18n_2" 
 So you can execute above scripts using npm run extract command.
After that, we have to declare TranslationModule and loaders for each component module. For example, the translation module for registration component would be as follows.
exportfunctioncreateRegistrationTranslateLoader(http:Http){
  returnnewTranslateHttpLoader(http,'../../../assets/i18n/registration/','.json');
}
@NgModule({
  declarations:[...],
  imports:[...,
    TranslateModule.forRoot({
      loader:{
        provide:TranslateLoader,
        useFactory:createRegistrationTranslateLoader,
        deps:[Http]
      }
    })
  ],
  providers:[...],
  bootstrap:[AppComponent]
}) 

Note: In the above example, we used forChild instead forRoot.This is because “When you use lazy loading for modules, you should use the forChild static method to import the TranslateModule".

It is time to showcase the demo (npm start command). The landing page navigates to registration screen. Let’s change the language option to ‘de’ from default option ‘en’ and then click registration or summary links to change the translation.The registration screen looks as below,

and the employee’s summary screen appears as below

What needs to be improved?

Even though ngx-translate is matured and popular in the Angular community it needs to be improved in different areas.
1. It is still need to support singular and plurals. (Where as i18x tools provides this feature)
2. More number of file formats will give flexible options to the developers(rather only JSON format).
3. The documentation need to be improved instead of relying on Github documentation.

Conclusion:

Both i18n and ngx-translate provides great features for internationalization support. It is totally developer’s choice to opt any one of the library. But ngx-translate is a best option for angular’s community who are looking for alternatives of Angular’s i18n, simplicity and fast development.
 
I will make an another detailed post on how to work with Angular’s official i18n tools. Cheers Geekos 🙂
 
 

Leave a Reply

Your email address will not be published. Required fields are marked *