背景
最近基於angular 4.4.3和ionic 3.7.1寫了一個lazyload的小程序,做i18n的一些實踐整理。
框架
[email protected], [email protected], @ngx-translate/[email protected], @ngx-translate/[email protected]
導入
非懶加載模塊部分
可以在AppModule或者自定義的公共組件模塊中去加載TranslateModule。
比如:
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {TranslateModule} from '@ngx-translate/core';
@NgModule({
imports: [
BrowserModule,
TranslateModule.forRoot()
],
bootstrap: [AppComponent]
})
export class AppModule { }
或者:
@NgModule({
exports: [
CommonModule,
TranslateModule
]
})
export class SharedModule { }
這裏要注意點:在AppModule中導入的時候,使用了forRoot()方法,但是在公共模塊SharedModule中導入的時候,不能使用TranslateModule.forRoot()方法。這樣可能會使得整個依賴注入樹中存在多個TranslateModule的實例。如果有必要的話,倒是可以使用TranslateModule.forChild()方法.
懶加載模塊中
在懶加載的模塊中,我們需要使用下面的方式:
@NgModule({
imports: [
TranslateModule.forChild({
loader: {provide: TranslateLoader, useClass: CustomLoader},
compiler: {provide: TranslateCompiler, useClass: CustomCompiler},
parser: {provide: TranslateParser, useClass: CustomParser},
missingTranslationHandler: {provide: MissingTranslationHandler, useClass: CustomHandler},
isolate: true
})
]
})
export class LazyLoadedModule { }
因爲懶加載模塊可以使用獨立的loader,compiler,parser,所以可以在這裏進行額外配置,甚至可以使用isolate:true來要求創建一個獨立的TranslateModule的實例。當然,也可以放棄這些特性,使用公共的實例。
配置TranslateModule
因爲我們使用了ionic,所以需要在導入TranslateModule的時候做一些配置。
import {HttpClientModule, HttpClient} from '@angular/common/http';
import {TranslateModule, TranslateLoader} from '@ngx-translate/core';
import {TranslateHttpLoader} from '@ngx-translate/http-loader';
/**
*// AoT like ionic requires an exported function for factories
*/
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, './assets/i18n/', '.json');
}
@NgModule({
imports: [
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [HttpClient]
}
})
],
bootstrap: [AppComponent]
})
export class AppModule { }
其中./assets/i18n/
路徑下有着一些json格式的國際化映射關係。
比如:有一箇中文映射集:zh.json
{
"sudoku": "數 獨",
"Game Center": "遊戲中心",
"Level": "等級",
"Kindergarten": "幼兒園",
"Pupil": "小學生",
"Junior": "初中生",
"Senior": "高中生",
"Bachelor": "學士",
"Master": "碩士",
"Doctor": "博士",
"Genius": "天才",
"Godlike": "半神",
"Legendary": "傳說",
"Change": "換 題",
"Check": "檢 查",
"Peek": "提 示",
"Congratulations":"恭 喜",
"Congratulations_MSG":"恭喜完成此道數獨,你很棒棒喲^_^",
"Sorry":"抱 歉",
"Sorry_MSG":"你還沒有正確地完成此道數獨,要不再試試?XD",
"TryHarder":"下一難度",
"TryMore":"再來一題",
"Cancel":"取消",
"OK":"確認"
}
初始化TranslateService
可以以依賴注入的方式獲取到TranslateService的實例,進行初始化之後就可以直接當作管道使用。
初始化:
constructor(public translate:TranslateService){
let browserLang = translate.getBrowserLang();
translate.use(browserLang.match(/en|zh/) ? browserLang : 'en');
// translate.use('en');
}
當管道使用:
<ion-header>
<ion-navbar color="primary">
<ion-title >
<span class="lsp1px">{{'Game Center'|translate}}</span>
</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-list>
<ion-card *ngFor="let item of games" (click)="gotoGame(item.page)">
<img class="game-icon" [src]="item.img">
<button ion-button full color="secondary"><span class="lsp1px">{{item.name|translate}}</span></button>
</ion-card>
</ion-list>
</ion-content>
直接調用API進行轉化:
check() {
if (SudokuChecker.checkMatrix(this.matrix)) {
this.uiService.presentAlert({
title: this.translate.instant("Congratulations"),
message: this.translate.instant("Congratulations_MSG"),
buttons: [
{
text: this.translate.instant("TryHarder"),
handler: () => {
this.level++;
this.initPuzzle();
}
},{
text: this.translate.instant("TryMore"),
handler: () => {
this.initPuzzle();
}
}, {
text: this.translate.instant("Cancel"),
handler: () => {
return;
}
}
]
});
} else {
this.uiService.presentAlert({
title: this.translate.instant("Sorry"),
message: this.translate.instant("Sorry_MSG"),
});
}
}
這裏調用了instant()方法。
附錄
完整項目代碼:
https://github.com/ACEsLegendary/sudoku
項目演示:
https://aceslegendary.github.io/sudoku-demo
ngx-translate資源:
https://github.com/ngx-translate/core