June 6, 2016
Ionic2 & Angular2 Translate – Internationalize and Localize Your App
Setting up Ionic 2 with angular2-translate is pretty simple. But since there were a lot of changes in the recent time and most of the code examples provided in other blogs is already outdated i decided to describe the latest working approach. Currently i’m using angular2rc.1. Since Anuglar has reached RC status there should be no more breaking API changes and this approach stays valid. Ionic2 on the other hand is still in Beta. Im working with “ionic-angular”: “2.0.0-beta.7” update 2.0.0.beta.8 update (you can get this information from package.json). I’m working with TypeScript and you should too!
The code of the example is available here – every step is also available as separat commit, see readme:
https://github.com/CanKattwinkel/ionic2-translate-example
Lets get started. Setup an empty project or use an existing one:
1 |
ionic start ionic2-translate tutorial --v2 --ts |
now add angular2-translate:
1 2 |
cd ionic2-translate npm install ng2-translate --save |
In Ionic 2 your assets belong in the www/ folder. So create your localization files in www/assets/i18n/:
1 2 3 4 |
www/assets/i18n/de.json www/assets/i18n/en.json www/assets/i18n/es.json ... |
Each JSON file should look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
// en.json: { "key" : "Translation for Key", "nested": { "user": "User", "signIn": "Sign In", "signUp": "Sign Up" } } // de.json: { "key" : "Übersetzung für Key", "nested": { "user": "Benutzer", "signIn": "Einloggen", "signUp": "Registrieren" } } // es.json: { "key" : "Traducción Key", "nested": { "user": "Usuario", "signIn": "Entrar", "signUp": "Registrarse" } } |
Go to your app.ts and setup the required configuration. First of all the required imports:
1 2 3 |
import {provide} from '@angular/core'; import {Http, HTTP_PROVIDERS} from '@angular/http'; import {TranslateService, TranslatePipe, TranslateLoader, TranslateStaticLoader} from 'ng2-translate/ng2-translate'; |
Now add provider and pipe to ionicBootstrap method (previous of beta 8, set this in @app{providers: XXX}
:
1 2 3 4 5 6 |
ionicBootstrap(MyApp, [[provide(TranslateLoader, { useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'), deps: [Http] }), TranslateService]], { }); |
(If your path deviates, change it in row 2)
now add the translate service to your constructor:
1 2 3 4 5 6 7 8 9 10 11 12 |
class MyApp { @ViewChild(Nav) nav: Nav; // make HelloIonicPage the root (or first) page rootPage: any = HelloIonicPage; pages: Array<{title: string, component: any}>; constructor( private platform: Platform, private menu: MenuController, private translate: TranslateService ) { |
in the class MyApp create a method called translateConfig and make sure all your languages are present in the regex in line 3:
1 2 3 4 5 6 7 8 9 10 |
translateConfig() { var userLang = navigator.language.split('-')[0]; // use navigator lang if available userLang = /(de|en|es)/gi.test(userLang) ? userLang : 'en'; // this language will be used as a fallback when a translation isn't found in the current language this.translate.setDefaultLang('en'); // the lang to use, if the lang isn't available, it will use the current loader to get them this.translate.use(userLang); } |
and then call it in your constructor:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
constructor( private platform: Platform, private menu: MenuController, private translate: TranslateService ) { this.initializeApp(); // set our app's pages this.pages = [ { title: 'Hello Ionic', component: HelloIonicPage }, { title: 'My First List', component: ListPage } ]; this.translateConfig(); } |
The whole app.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 |
import {ViewChild, Component} from '@angular/core'; import {ionicBootstrap, Platform, MenuController, Nav} from 'ionic-angular'; import {StatusBar} from 'ionic-native'; import {HelloIonicPage} from './pages/hello-ionic/hello-ionic'; import {ListPage} from './pages/list/list'; import {provide} from '@angular/core'; import {Http, HTTP_PROVIDERS} from '@angular/http'; import {TranslateService, TranslatePipe, TranslateLoader, TranslateStaticLoader} from 'ng2-translate/ng2-translate'; @Component({ templateUrl: 'build/app.html', pipes: [TranslatePipe] }) class MyApp { @ViewChild(Nav) nav: Nav; // make HelloIonicPage the root (or first) page rootPage: any = HelloIonicPage; pages: Array<{title: string, component: any}>; constructor( private platform: Platform, private menu: MenuController, private translate: TranslateService ) { this.initializeApp(); // set our app's pages this.pages = [ { title: 'Hello Ionic', component: HelloIonicPage }, { title: 'My First List', component: ListPage } ]; this.translateConfig(); } initializeApp() { this.platform.ready().then(() => { // Okay, so the platform is ready and our plugins are available. // Here you can do any higher level native things you might need. StatusBar.styleDefault(); }); } translateConfig() { var userLang = navigator.language.split('-')[0]; // use navigator lang if available userLang = /(fr|en|de)/gi.test(userLang) ? userLang : 'en'; // this language will be used as a fallback when a translation isn't found in the current language this.translate.setDefaultLang('en'); // the lang to use, if the lang isn't available, it will use the current loader to get them this.translate.use(userLang); } openPage(page) { // close the menu when clicking a link from the menu this.menu.close(); // navigate to the new page if it is not the current page this.nav.setRoot(page.component); } } ionicBootstrap(MyApp, [[provide(TranslateLoader, { useFactory: (http: Http) => new TranslateStaticLoader(http, 'assets/i18n', '.json'), deps: [Http] }), TranslateService]], { }); |
Thats it – ng2 translate is now ready to use. Lets add it to home view – which is hello-ionic.html in my example.
app/pages/hello-ionic.html:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
<ion-navbar *navbar> <button menuToggle> <ion-icon name="menu"></ion-icon> </button> <ion-title>Hello Ionic</ion-title> </ion-navbar> <ion-content padding class="getting-started"> <h3>Welcome to your first Ionic app!</h3> <p> This starter project is our way of helping you get a functional app running in record time. </p> <p> Follow along on the tutorial section of the Ionic docs! </p> <p> <button primary menuToggle>Toggle Menu</button> </p> {{ "key" | translate }}<br> {{ "nested.user" | translate }}<br> {{ "nested.signIn" | translate }}<br> {{ "nested.signUp" | translate }}<br> </ion-content> |
The last step is to add the pipe to the component. It is required for every component with usage of ng2 translate. If you miss it Angular will throw The pipe 'translate' could not be found.
app/pages/hello-ionic.ts:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import {TranslatePipe} from "ng2-translate/ng2-translate"; import {Component} from "@angular/core"; @Component({ templateUrl: 'build/pages/hello-ionic/hello-ionic.html', pipes: [TranslatePipe] }) export class HelloIonicPage { constructor() { } } |
See the result:
Its working for App page(lef menu. bottom tabs) for me … but not for subsequent pages. So when I open a.g. AboutPage, it doesnt know anything about selected language and I have to do setup once again which is not nice. It seems to me that ‘TranslateService’ is created as a fresh object for every page so I’m loosing the setup and current language info I made for App. Any hint?
Hello David,
you are totally right. I’ve updated the example repository from Ionic beta 7 tobBeta 8 and solved the issue by referencing the provider in the ionicBootstrap method. See end of app.ts in the github repo.
https://github.com/CanKattwinkel/ionic2-translate-example/blob/master/app/app.ts
I’ll update the blogpost tomorrow.
Good Luck!
Thanks, is there a way how to access the shared version of TranslateService on others pages in case I have to make translation inside code not using translate pipe? When I insert Translation service using provider definition is gets me fresh copy with not current language info…
Just fixed this. Everything is working as expected. I just read the Angular2 docs about the shared services topic …
can you please help me to convert these to javascript? i am not using typescript for my ionic2 project
Hi Kevin, i’d really advise you to use typescript. Almost all of the Angular2 and Ionic2 stuff is made with TypeScript. It might be hard to dive into on your own but it is definitely worth it.
This can be done with JavaScript as well and is not so different to the TypeScript Code. I’d recommend you take a look at the GitHub repo of the code.
https://github.com/CanKattwinkel/ionic2-translate-example
Go trough the steps mentioned in the readme file. You’ll find where to put the code in JavaScript. 🙂
hi
first thanks.
i go throw steps, every thing fine for “en” but i cant change the language.
i think the browser use its default language.
how i can fix this?
Hello Armin,
make sure to include the language in the following line:
userLang = /(de|en|es)/gi.test(userLang) ? userLang : ‘en’;
Does this help?
Hello,
Very useful post : as an Ionic beginner, it’s hard to find tutorials about internationalization of Ionic apps…
Two questions :
– I read somewhere that angular 2 will have its own translation system, which has not yet been published. Does it worth to implement ng2-translate if the integrated solution comes with the final release (this summer ???)?
– Instead having one big translation file by language, which is hard to maintain, I’d like to have one translation file by page. Is it possible and how to do it?
Thanks in advance.
Hey Patrick,
i’m not too familiar with the angular 2 i18n module but i think it is included since RC2. See node_modules/@angular/compiler/src/i18n/ in a updated project or visit the Angular2 GitHub Repository. So I’d recommend to wait if this is possible. I’ll think about writing an article about angular 2 i18n as soon as the docs are better.
Having a translation file per page is not so good since it would become redundant quickly. Like button labels etc. So this is really not recommended! But there are tools that you can set on top of your workflow to manage i18n JSON generation, most of them require a monthly fee.
Hello! You can try https://poeditor.com/ to easily translate your app or other piece of software into other languages. It has a simple and intuitive work interface, and many useful features: API, translation memory, WordPress plugin, Bitbucket and GitHub integration.
Thanks for the nice tutorial.
Could you, please, provide a license to your code?
I am getting peer dependency error when I am trying to install ng2-translate.
How can I solve it?
Ionic version: 2.0.0.11.Beta
Hello sathyesh,
this is because the current ionic versions (beta 11) relies on Angular RC 4 while the latest ng2-translate version already runs with RC 5.
So to fix the ng2-translate UNMET PEER DEPENDENCY issue simply install version 2.2.2 of ng2-translate:
npm install ng2-translate@2.2.2 –save
You can update ng2-translate when the Ionic Beta is on RC 5.
Good Luck!
Hi sathyesh,
working great, thanks for the tutorial. how would you translate text directly in the controller instead of view (for an alert for example)?
thanks for your help,
martin
Hello Martin,
this can simply be achieved by using the provided observable:
translate.get(‘welcome-greeting’).subscribe((res: string) => {
// res will be sth. like: “Herzlich Willkommen”
});
Hi it’s very useful , a lot of thanks .
But if there any update on this tutorial for ionic 2.0.1 :/
Hi I take below mistake , Can you help me .
C:\Projects\Vipas\VipasIon\node_modules\ng2-translate\ng2-translate.js:1
export * from ‘./index’;
^
ParseError: ‘import’ and ‘export’ may appear only with ‘sourceType: module’