在日常开发过程中,某些项目会要求支持国际化。对于使用 Angular 框架的项目来说,我们可以利用以下第三方库,快速支持国际化:
- ngx-translate/core
- ngx-translate/http-loader
- ngx-translate-extract
环境配置
本文将基于上述三个库,简单的介绍一下国际化的处理流程。首先我们来使用 Angular CLI 创建一个新的项目:
代码语言:javascript复制$ ng new ngx-translate-demo
当前环境: Angular CLI: 6.1.4、Node: 9.11.0、OS: darwin x64
然后我们来安装上面的三个库:
代码语言:javascript复制$ npm install @ngx-translate/core @ngx-translate/http-loader --save
$ npm install @biesbjerg/ngx-translate-extract --save-dev
ngx-translate 应用
安装完上述的库之后,接下来我们在根模块 AppModule 中导入 TranslateModule 模块:
代码语言:javascript复制import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { HttpClient, HttpClientModule } from "@angular/common/http";
import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { AppComponent } from "./app.component";
// 支持AOT
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
}
@NgModule({
declarations: [AppComponent],
imports: [
BrowserModule,
HttpClientModule,
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient]
}
})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
在导入 TranslateModule 模块之后,我们需要在根组件 AppComponent 中初始化 TranslateService 服务:
代码语言:javascript复制import { Component } from "@angular/core";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "app-root",
template: "./app.component.html",
styleUrls: ["./app.component.css"]
})
export class AppComponent {
title = "ngx-translate-demo";
constructor(translate: TranslateService) {
// 设置默认的语言
translate.setDefaultLang("zh-cn");
translate.use("zh-cn");
}
}
之后我们就可以在 app.component.html 模板中使用 TranslateModule 模块内提供的管道:
代码语言:javascript复制<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<p>{{"home" | translate}}</p>
</div>
ngx-translate-extract 应用
接下来我们来使用 ngx-translate-extract 这个库实现自动抽取模板中使用 TranslatePipe 转换的键。为了方便后续操作,我们可以定义一个 npm script:
代码语言:javascript复制"extract": "ngx-translate-extract --input ./src/app --output ./src/assets/i18n/{zh-cn,zh-hk,en}.json --sort --format namespaced-json --format-indentation ' '",
上述 ngx-translate-extract 命令中所使用的参数:
- –input:抽取字符串的目录;
- –output:抽取结果的输出目录;
- –sort:保存输出文件时, 按照字母顺序对键进行排序;
- –format:指定输出的文件格式,支持 json、namespaced-json 及 pot,默认为 json;
- –format-indentation:设置输出的缩进格式,默认为
t
。
在定义完 extract 脚本之后,我们可以运行下面的命令执行自动抽取任务:
代码语言:javascript复制$ npm run extract
命令成功执行后,在 src/assets
目录下会生成 3 个 JSON 文件:
└── i18n
├── en.json
├── zh-cn.json
└── zh-hk.json
接下来我们来分别更新一下 3 个文件:
- zh-cn.json
{"home": "首页"}
- zh-hk.json
{"home": "首頁"}
- en.json
{"home": "Home"}
更新完上述的文件,我们就可以运行 npm start
启动应用了。这时候因为我们默认使用的简体中文,所以以下的模板的显示结果为 “首页”:
<p>{{"home" | translate}}</p>
前面我们已经生成了 zh-cn.json
、zh-hk.json
和 en.json
三个语言文件,下面我们来看一下如何切换语言,首先更新一下模板,新增三个按钮:
<p>
<button (click)="useZhCn()">中文简体</button>
<button (click)="useZhHk()">中文繁体</button>
<button (click)="useEn()">英语</button>
</p>
然后更新一下 app.component.ts 文件,添加对应的方法:
代码语言:javascript复制useZhCn() {
this.translate.use("zh-cn");
}
useZhHk() {
this.translate.use("zh-hk");
}
useEn() {
this.translate.use("en");
}
ngx-translate-extract 这个库,除了能自动抽取模板中的使用 TranslatePipe 的字段之外,也可以抽取项目中应用TranslateDirective 和 TranslateService 进行国际化处理的字段。
- TranslateService 使用示例
translate.get('HELLO', {value: 'world'}).subscribe((res: string) => {
console.log(res);
//=> 'hello world'
});
- TranslateDirective 使用示例:
<div [translate]="'HELLO'" [translateParams]="{value: 'world'}"></div>
下面我们来验证项目中使用 TranslateService 服务,能否正常抽取对应的字段。先更新一下 app.component.ts 文件,新增一个 init() 方法:
代码语言:javascript复制init() {
this.translate
.get("hello", { value: "world" })
.subscribe((res: string) => {
console.log(res); //=> 'hello world'
});
}
上面示例中,我们演示了 TranslateService 服务支持模板参数的特性。接下来,我们再次执行抽取操作:
代码语言:javascript复制$ npm run extract
命令运行成功后,原先生成的 3 个 JSON 文件都会新增一个新的属性,这里以 zh-cn.json
文件为例:
{
"hello": "",
"home": "首页"
}
接着我们需要分别更新 zh-cn.json、zh-hk.json 和 en.json 文件:
代码语言:javascript复制{
"hello": "hello {{value}}",
"home": "首页"
}
最后我们在介绍如何在懒加载的模块中启用国际化。
懒加载模块国际化
假设我们已经定义了一个 UserModule 懒加载模块,该模块内包含一个 UserComponent 组件,具体如下:
user.module.ts
代码语言:javascript复制import { NgModule } from "@angular/core";
import { CommonModule } from "@angular/common";
import { RouterModule, Route } from "@angular/router";
import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
import { HttpClient } from "@angular/common/http";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { UserComponent } from "./user.component";
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, "./assets/i18n/user/", ".json");
}
const routes: Route[] = [
{
path: "",
component: UserComponent
}
];
@NgModule({
imports: [
CommonModule,
RouterModule.forChild(routes),
TranslateModule.forChild({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient]
},
isolate: true
})
],
declarations: [UserComponent]
})
export class UserModule {}
与 RouterModule 模块类似,TranslateModule 模块也为我们提供了 forChild()
方法,用于懒加载模块的使用。设置 isolate: true
参数,表示我们希望使用完全独立的服务实例。
user.component.ts
代码语言:javascript复制import { Component } from "@angular/core";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "app-user",
template: `
<div>
<h3>User Module</h3>
<p>{{"myNameIs" | translate}} semlinker</p>
<button (click)="useZhCn()">中文简体</button>
<button (click)="useEn()">英语</button>
</div>
`
})
export class UserComponent {
constructor(public translate: TranslateService) {}
useZhCn() {
this.translate.use("zh-cn");
}
useEn() {
this.translate.use("en");
}
}
定义完 UserModule 懒加载模块,我们可以使用 ngx-translate-extract 这个库,单独抽取该模块内的国际化配置信息。这里我们也同样在 npm scripts 中定义一个新的任务:
代码语言:javascript复制"extract-user": "ngx-translate-extract --input ./src/app/user --output ./src/assets/i18n/user/{zh-cn,zh-hk,en}.json --sort --format namespaced-json --format-indentation ' '",
这里需要注意的是 ngx-translate-extract 除了支持上述的参数外,还支持 --replace
、--clean
和 --verbose
等参数,有兴趣的同学可以阅读 ngx-translate-extract 说明文档。最后我们再来浏览一下根模块的相关文件:
app.module.ts
代码语言:javascript复制import { BrowserModule } from "@angular/platform-browser";
import { NgModule } from "@angular/core";
import { RouterModule, Route } from "@angular/router";
import { HttpClient, HttpClientModule } from "@angular/common/http";
import { TranslateModule, TranslateLoader } from "@ngx-translate/core";
import { TranslateHttpLoader } from "@ngx-translate/http-loader";
import { AppComponent } from "./app.component";
import { HomeComponent } from "./home.component";
const routes: Route[] = [
{
path: "",
pathMatch: "full",
redirectTo: "home"
},
{
path: "home",
component: HomeComponent
},
{
path: "user",
loadChildren: "./user/user.module#UserModule"
}
];
// 支持AOT
export function createTranslateLoader(http: HttpClient) {
return new TranslateHttpLoader(http, "./assets/i18n/", ".json");
}
@NgModule({
declarations: [AppComponent, HomeComponent],
imports: [
BrowserModule,
HttpClientModule,
RouterModule.forRoot(routes),
TranslateModule.forRoot({
loader: {
provide: TranslateLoader,
useFactory: createTranslateLoader,
deps: [HttpClient]
}
})
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule {}
app.component.ts
代码语言:javascript复制import { Component } from "@angular/core";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "app-root",
template: `
<div class="app">
<nav>
<a routerLink="/">首页</a>
<a routerLink="/user">我的</a>
</nav>
<router-outlet></router-outlet>
</div>
`,
styleUrls: ["./app.component.css"]
})
export class AppComponent {
title = "ngx-translate-demo";
}
home.component.ts
代码语言:javascript复制import { Component, OnInit } from "@angular/core";
import { TranslateService } from "@ngx-translate/core";
@Component({
selector: "app-home",
template: `
<div style="text-align:center">
<h1>
Welcome to {{ title }}!
</h1>
<p>{{"home" | translate}}</p>
<p>
<button (click)="useZhCn()">中文简体</button>
<button (click)="useZhHk()">中文繁体</button>
<button (click)="useEn()">英语</button>
</p>
</div>
`
})
export class HomeComponent implements OnInit {
title = "ngx-translate-demo";
constructor(public translate: TranslateService) {
// 设置默认的语言
translate.setDefaultLang("zh-cn");
translate.use("zh-cn");
}
ngOnInit() {
this.translate.get("hello", { value: "world" }).subscribe((res: string) => {
console.log(res); //=> 'hello world'
});
}
useZhCn() {
this.translate.use("zh-cn");
}
useZhHk() {
this.translate.use("zh-hk");
}
useEn() {
this.translate.use("en");
}
}
总结
本文通过几个示例简单介绍了 @ngx-translate/core、@ngx-translate/http-loader 及 @biesbjerg/ngx-translate-extract 这三个库的使用,在实际的开发中还会遇到很多其他的问题,这时就需要大家认真阅读上述库相关的说明文档。