Tips

How to create a multilingual NativeScript app with Angular 4?

If you created a multilingual app following "How to create a multilingual NativeScript app?" go to the instructions in "Upgrade multilingual NativeScript app to Angular 4" to upgrade it to Angular 4.

For an app project (recently upgraded to Angular 4) I needed a solution to switch from Dutch to English in real-time for our non-Dutch customers.

The best internationalization (i18n) solution out there is ngx-translate, a project by Olivier Combe.

You can follow the steps below or clone the sample project NSNL_Multilingual4 from Github.

1. Create a new NativeScript project with Angular

With the following commands we create a new project and add the Android and iOS platforms.


tns create projectname --ng
cd projectname
tns platform add android
tns platform add ios

2. Install ngx-translate/core

ngx-translate/core is a npm package and can be installed with the following command.


npm install @ngx-translate/core --save

3. Install ngx-translate/http-loader

ngx-translate/core is a npm package and can be installed with the following command.


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

4. Create language files

Create the folder i18n in the app directory and add the files nl.json and en.json.

nl.json


{
    "EXAMPLE": {
        "TITLE": "Hallo wereld!",
        "TEXT": "Dit is een zin in het Nederlands.",
        "BACK": "Terug"
    }
}

en.json


{
    "EXAMPLE": {
    "TITLE": "Hello world!",
    "TEXT": "This is a sentence in English.",
    "BACK": "Back"
    }
}

5. Edit app.module.ts

We need to import the following modules.


import {NativeScriptHttpModule} from "nativescript-angular/http";
import {TranslateModule, TranslateLoader} from "@ngx-translate/core";
import {TranslateHttpLoader} from "@ngx-translate/http-loader";
import {Http} from "@angular/http";

NativeScript uses Ahead-of-time compilation, so we need to export a function that returns the TranslateHttpLoader.


// for AoT compilation
export function translateLoaderFactory(http: Http) {
    return new TranslateHttpLoader(http, "/i18n/", ".json");
};

And we also need to extend the @NgModule imports.


NativeScriptHttpModule,
TranslateModule.forRoot({
    loader: {
        provide: TranslateLoader,
        deps: [Http],
        useFactory: (translateLoaderFactory)
    }
})

6. Edit items.component.html

The default NativeScript Angular template is a master-detail example at the moment.
For this multilingual example, we are going to ignore that completely :-)

The files item.ts, item.service.ts, item-detail.component.ts and item-detail.component.html remain in the project, but aren't really used now.

Replace the contents of items.component.html with the markup below.

This way we bind EXAMPLE.TITLE to the ActionBar label and the Label in the StackLayout. We also bind EXAMPLE.TEXT to the TextView.

And we have buttons available to switch between Dutch (Nederlands) and English. These buttons will fire the function changeLanguage when tapped.


<ActionBar [title]="'EXAMPLE.TITLE' | translate"></ActionBar>
<ScrollView>
    <StackLayout>
        <Label [text]="'EXAMPLE.TITLE' | translate"></Label>
        <TextView editable="false" [text]="'EXAMPLE.TEXT' | translate"></TextView>
        <Button text="Nederlands" (tap)="changeLanguage('nl')"></Button>
        <Button text="English" (tap)="changeLanguage('en')"></Button>
    </StackLayout>
</ScrollView>

7. Edit items.component.ts

We need to import the following modules.


import * as Platform from "platform";
import {TranslateService} from "@ngx-translate/core";

In the constructor we set the default language to Dutch.
After that we set the language based on the preferred language of the device. In case we don't have a JSON file in that language, ng2-translate will fallback to the default language. Replace the current constructor with the one below.


constructor(private translate: TranslateService) {
    this.translate.setDefaultLang("nl");
    this.translate.use(Platform.device.language);
}

Because we don't inject the itemService into our constructor anymore, you have to comment out the call in ngOnInit. Otherwise the app won't run and display an error in the console like error TS2339: Property 'itemService' does not exist on type 'ItemsComponent'.


ngOnInit(): void {
    // this.items = this.itemService.getItems();
}

And we need a function to switch the language in real-time.


public changeLanguage(lang: string) {
    this.translate.use(lang);
}

And we're done! In only seven steps you have built a multilingual NativeScript app with Angular 4!

Please don't forget to check out the sample project NSNL_Multilingual4 (see animation at the top of this article) on Github, which is a more extensive example.