This days I’m learning angular2 and ionic2. My first impression was bad. Too many new things: angular2, typescript, new project architecture, … but after passing those bad moments I started to like angular2. One of the first things that I want to work with is internationalization. There’re several i18n providers for angular2. For example ng2-translate, but I want to build something similar to a angular i18n provider that I’d created time ago.
The idea is first configure the service
import {Component} from "@angular/core"; import {Platform, ionicBootstrap} from "ionic-angular"; import {StatusBar} from "ionic-native"; import {HomePage} from "./pages/home/home"; import {I18nService} from "./services/i18n/I18nService"; import {lang} from "./conf/conf"; @Component({ template: '<ion-nav [root]="rootPage"></ion-nav>' }) export class MyApp { rootPage:any = HomePage; constructor(platform:Platform, i18n:I18nService) { platform.ready().then(() => { i18n.init(lang); StatusBar.styleDefault(); }); } } ionicBootstrap(MyApp, [I18nService]);
We can see that we’re using one configuration from conf/conf.ts
var lang = { availableLangs: { en: 'English' }, defaultLang: 'en', lang: { "true": { en: "True", es: "Verdadero" }, "false": { en: "False", es: "Falso" }, } }; export {lang};
Now we can translate texts using:
import {Component} from "@angular/core"; import {I18nService} from "../../services/i18n/I18nService"; @Component({ templateUrl: 'build/pages/home/home.html' }) export class HomePage { constructor(private i18n:I18nService) { } label1:string = this.i18n.translate('true'); label2:string = 'true'; ngOnInit() { setInterval(() => { this.label2 = this.i18n.translate(this.label2 == 'false' ? 'true' : 'false'); }, 2000); } }
We also need a Pipe to use i18n within templates
{{ "true" | i18n }}
This is the service:
import {Injectable, Pipe} from "@angular/core"; @Injectable() export class I18nService { private conf:any; private userLang:string; private lang:any; setUserLang(lang:string):void { this.userLang = lang; } init(lang:any):void { this.conf = lang; this.setUserLang(lang.defaultLang); } translate(key:string):string { if (typeof this.conf.lang !== 'undefined' && this.conf.lang.hasOwnProperty(key)) { return this.conf.lang[key][this.userLang] || key; } else { return key; } } } @Pipe({ name: 'i18n', pure: false }) export class I18nPipe { constructor(private i18n:I18nService) { } transform(key:string) { return this.i18n.translate(key); } }
The code is in my github account. I also have tried to created a npm package and install it using
npm install angular2-i18n --save
I don’t know why it doesn’t work when I use the npm installed package and I works like a charm when I use the code in my project directory
import {I18nService} from "./services/i18n/I18nService"; // works import {I18nService} from "angular2-i18n/src/I18nService"; // don't work
I also have problems with unit tests. It works when I run the tests locally (it works on my machine 🙂 ) but it doesn’t work when I run them in travis. Any help with those two problems would be appreciated.
I have a feeling it doesn’t work after installing the package because your module system can’t find the package directory angular2-i18n. You need to either tell system.js where to look in the map section of the config or you need to tell webpack that there is an external location it needs to use to find the package. If you are just using typescript then you need typings or it also needs to be able to find the package using it’s own version of the config. You will need typescript 1.9 or greater for that config to work.
txs. I need to master a little bit system.js and webpack. There are a lot of “new” stuff here for me yet 🙂