Creating a multi-language Ionic translation app with ngx-translate

July 14, 2018, 8:18 pm Categories:

Categories

As 21st Century citizens we might well live in the global village thanks to relatively inexpensive and widely available transport links, immigration and a digital window on the world courtesy of the internet but language can still be a tricky hurdle to navigate.

This is especially true when developing websites/applications for multinational corporations who MUST target the demographics of their user base according to their native language (in addition to other relevant factors).

Over the course of this tutorial we'll explore how we can develop Ionic applications that make use of multi-language features by leveraging the impressive NGX-Translate library for Angular.

What we'll be developing

We'll make use of the NGX-Translate library to create a relatively simple Single Page Application that allows the user to display the same page text in the following 4 languages:

  • English
  • French
  • German
  • Spanish

English will be the default language that the applications loads/displays the page texts with.

Our choice of page text will centre on the Hello World theme that is so beloved by developers in their tutorials - albeit with a slight twist:

As you can see a quite simple but effective language switching App courtesy of Ionic & NGX-Translate (any issues with translation lay them at Google Translate's doorstep!)

Okay, now we know what we'll be developing let's get started!

First steps

Using the Ionic CLI (after having navigated to a location on your computer's hard drive where you store your projects) create the following Ionic project:

ionic start ionic-babeliser blank

If you're using Ionic 4 select Angular from the menu prompt followed by entering N for Cordova integration (we won't be developing for mobile platforms as the application will simply be running within the desktop browser courtesy of ionic serve).

Finally, once the project has been generated from the CLI change into the ionic-babeliser directory:

cd ionic-babeliser

And install the NGX-Translate library:

npm install --save @ngx-translate/core

So far, so good - now we need to configure the NGX-Translate library integration.

Configuration

Now we need to perform the following steps:

  • Import the NgX-Translate library into the application's root module
  • Import the @ngx-translate/http-loader module (this will load translation files via Angular's HttpClient module)
  • Define the loader to be used within the application's root module

We'll start by installing the TranslateHttpLoader module:

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

We'll also need to define the following function for loading the language translation files stored within the application:

export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
}

This function simply uses the HTTP protocol to load JSON files from the following directory within the application:

  • ionic-babeliser/src/assets/i18n/

You'll need to manually create this directory as, no surprises for guessing, this is where we will be storing the different language translation files for the page texts to be displayed within the application.

Next we move onto the application's root module - ionic-babeliser/src/app/app.module.ts - and put all of the above together by importing the NGX-Translate library and TranslateHttpLoader modules as well as defining the function for loading language translation files stored within the app:

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 { ErrorHandler, NgModule } from '@angular/core';
import { IonicApp, IonicErrorHandler, IonicModule } from 'ionic-angular';

import { MyApp } from './app.component';
import { HomePage } from '../pages/home/home';


// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
    return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
}


@NgModule({
  declarations: [
    MyApp,
    HomePage
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    TranslateModule.forRoot({
        loader: {
            provide: TranslateLoader,
            useFactory: HttpLoaderFactory,
            deps: [HttpClient]
        }
    }),
    IonicModule.forRoot(MyApp)
  ],
  bootstrap: [IonicApp],
  entryComponents: [
    MyApp,
    HomePage
  ],
  providers: [
    StatusBar,
    SplashScreen,
    {provide: ErrorHandler, useClass: IonicErrorHandler}
  ]
})
export class AppModule {}

Now we need to configure the application's root component file - ionic-babeliser/src/app/app.component.ts - to initialise the NGX-Translate library and allow the application to implement the language translation functionality when initialising.

Import the TranslateService module into the root component file like so:

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

Follow this by adding the following snippet towards the bottom of the root component file:

private _initTranslate() 
  {
     // Set the default language for translation strings, and the current language.
     this._translate.setDefaultLang('en');


     if (this._translate.getBrowserLang() !== undefined) 
     {
         this._translate.use(this._translate.getBrowserLang());
     } 
     else 
     {
         this._translate.use('en'); // Set your language here
     }
  }

With these in place your completed ionic-babeliser/src/app/app.component.ts file should now look like this:

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

import { HomePage } from '../pages/home/home';


@Component({
  templateUrl: 'app.html'
})
export class MyApp {
  rootPage:any = HomePage;

  constructor(private _platform          : Platform, 
              private _translate         : TranslateService) 
  {
     this._platform
     .ready()
     .then(() => 
     {
        this._initTranslate();
     });
  }



  private _initTranslate() 
  {
     // Set the default language for translation strings, and the current language.
     this._translate.setDefaultLang('en');


     if (this._translate.getBrowserLang() !== undefined) 
     {
         this._translate.use(this._translate.getBrowserLang());
     } 
     else 
     {
         this._translate.use('en'); // Set your language here
     }
  }

}

Now we'll move onto creating the language translation files to be used within the application.

Language files

The following JSON files will contain the respective translations for each language offered within the application:

  • src/assets/i18n/en.json
  • src/assets/i18n/es.json
  • src/assets/i18n/fr.json
  • src/assets/i18n/de.json

Our first file - src/assets/i18n/en.json - will consist of the default English language text for the application:

// src/assets/i18n/en.json
{
	"home" : {
		"heading" 		: "Hello world",
		"description" 	: "Oh no....Not the hello world tutorial demonstration again!" 
	}
}

This follows a very simple key/value structure identified by the page name that the text will be displayed on followed by the heading and description values for the page text. If we wanted to add further page sections and define their text content we could always extend this JSON file to accommodate those.

The remaining language files follow the same structure albeit with different translations:

// src/assets/i18n/de.json
{
	"home" : {
		"heading" 		: "Hallo Welt",
		"description" 	: "Oh nein .... Nicht die Hallo Welt Tutorial Demo noch einmal!" 
	}
}
// src/assets/i18n/es.json
{
	"home" : {
		"heading" 		: "Hola Mundo",
		"description" 	: "Oh no ... ¡No es la demostración del tutorial hello world otra vez!" 
	}
}
// src/assets/i18n/fr.json
{
	"home" : {
		"heading" 		: "Bonjour le monde",
		"description" 	: "Oh non .... Pas encore la démonstration du tutoriel Hello!" 
	}
}

With the language translation files in place we can now focus our attention on developing the logic/templating for the application.

Application logic

Our component class will handle the following requirements for implementing the language translations within the application:

  • Defining the initial page text values based on the default language (English)
  • Import the NGX-Translate TranslateService library module to facilitate language translation functionality
  • Allow the page text to be converted into and displayed in different languages

This is simpler than it might sound as demonstrated with the following code covered in the ionic-babeliser/src/pages/home/home.ts component class:

import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
import { TranslateService } from '@ngx-translate/core';


@Component({
  selector: 'page-home',
  templateUrl: 'home.html'
})
export class HomePage {


  /**
   * @name title
   * @type {string}
   * @public
   * @description     		Property that stores the page heading value
   */
  public title : string;




  /**
   * @name description
   * @type {string}
   * @public
   * @description     		Property that stores the page description value
   */
  public description : string;




  /**
   * @name language
   * @type {string}
   * @public
   * @description     		Property that stores the selected language value from the  component
   */
  public language : string;




  constructor(private _platform       : Platform, 
              public navCtrl 		  : NavController,
              private _translate 	  : TranslateService) 
  {  }




  /**
   * Implement translation of page text once view has completed loading
   *
   * @public
   * @method ionViewDidLoad
   * @return {none}
   */
  public ionViewDidLoad() : void
  {
     this._initialiseTranslation();
  }




  /**
   * Capture the selected language from the  component
   *
   * @public
   * @method changeLanguage
   * @return {none}
   */
  public changeLanguage() : void
  {
     this._translateLanguage();
  }




  /**
   * Implement the selected language via the Translate service
   *
   * @private
   * @method _translateLanguage
   * @return {none}
   */
  private _translateLanguage() : void
  {
     this._translate.use(this.language);
     this._initialiseTranslation();    
  }




  /**
   * Translate the page texts to the selected language value
   *
   * @private
   * @method _initialiseTranslation
   * @return {none}
   */
  private _initialiseTranslation() : void
  {
     setTimeout(() => 
     {
        this.title 			  = this._translate.instant("home.heading");
        this.description 	= this._translate.instant("home.description");
     }, 250);
  }

}

Notice that the _initialiseTranslation method wraps the language translations within a setTimeout function?

This helps ensure that the translations are not loaded before the template view is ready as I couldn't find another way to overcome this particular issue (if anyone reading this knows of another, more efficient way then let everyone know in the comments section below).

The class simply uses the language property as a model to detect and retrieve the selected language on the template's <ion-select> component when an ionChange event is fired (we'll cover this in the templating section below).

This model value is then supplied to the use method of the TranslateService module to instruct the application that the language should now be set to that value.

The _initialiseTranslation method then updates the title and description view properties with the selected values from the chosen language file.

Pretty straightforward huh?

Now let's round out the development with the required markup for the template.

Templating the application

Our ionic-babeliser/src/pages/home/home.html component markup structure is quite simple and consists of the following elements:

  • An <ion-select> component that uses the language property within an NgModel directive and an ionChange event to change/set the language value for that property
  • A simple <ion-card> component to display the translated page text

All of which is structured as follows:

<ion-header>
  <ion-navbar>
    <ion-title>
      Ionic Babeliser
    </ion-title>
  </ion-navbar>
</ion-header>

<ion-content padding>


  <ion-item>
  	<ion-select [(ngModel)]="language" (ionChange)="changeLanguage()">
  	   <ion-option value="en" selected="true">English</ion-option>
  	   <ion-option value="de">German</ion-option>
  	   <ion-option value="es">Spanish</ion-option>
  	   <ion-option value="fr">French</ion-option>
  	</ion-select>
  </ion-item>


  
  <ion-card padding>
    <h1>{{ title }}</h1>
    <p>{{ description }}</p>
  </ion-card>
</ion-content>

Notice how the <ion-option> values consist of the country code for each language? This matches the title of each language translation file for those countries. Don't mis-spell these or the translations won't load!

With our component logic and templating in place, and the application fully configured, we can test that this works in the browser by running the following command from the Ionic CLI:

ionic serve

All things being well (I.e. no transpilation errors or code bugs) then you should see the app being run within your browser and start being able to interact with that like so:

In summary

The NGX-Translate library makes the process of creating multi-lingual apps far easier to accomplish.

The only limitation of using the library is that you will need to define your language content for the texts on each page of your application beforehand - which will be stored as country code titled JSON files (I.e. en.json, jp.json, it.json etc) within the src/assets/i18n/ sub-directory. You can't dynamically generate the language translation on the fly using this library so if you require that type of functionality you'll need to look into using the Google Translate API (or similar) instead.

If you've enjoyed what you've read and/or found this helpful please feel free to share your comments, thoughts and suggestions in the comments area below.

I explore different aspects of working with the Ionic framework in my e-book featured below and if you're interested in learning more about further articles and e-books that I'm writing please sign up to my FREE mailing list.

Tags

Categories

Post a comment

All comments are welcome and the rules are simple - be nice and do NOT engage in trolling, spamming, abusiveness or illegal behaviour. If you fail to observe these rules you will be permanently banned from being able to comment.

Top