语言包结构设计
1.目录结构设计
-
common lang
server side lang - 与后台共用的部分
front end side lang - 前端通用的部分
-
feature lang
-
found
found.zh-cn.json - 发现模块 - 简体中文语言包
found.zh-tw.json - 发现模块 - 繁体中文(台湾)语言包
found.zh-hk.json - 发现模块 - 繁体中文(香港)语言包
found.en-ww.json - 发现模块 - 英文(全球)语言包
found.en-us.json - 发现模块 - 英文(美国)语言包
-
2.语言包内部结构设计
-
common
// zh-cn.json { "TITLE": "欢迎使用APP", "HOME": "首页", "LEARN": "学习", "FOUND": "发现", "MY": "我的", "CANCEL": "取消", "OK": "确认" } // en-ww.json { "TITLE": "Welcome To APP", "HOME": "HOME", "LEARN": "LEARN", "FOUND": "FOUND", "MY": "MY", "CANCEL": "CANCEL", "OK": "OK" }
-
feature
// found.zh-cn.json { "FOUND_PRE_POST_MSG": "帖子正在提交中" 或 "{{content}}正在提交中" - content: 帖子或评论 } // found.en-ww.json { "FOUND_PRE_POST_MSG": "It is submitting." }
实现方案
利用已有的 ng2-translate 库实现多语言切换功能。
使用示例:
1.安装 ng2-translate
npm install ng2-translate --save
2.在 app.module.ts 中添加以下代码
import { Http } from '@angular/http';
import { TranslateModule, TranslateStaticLoader, TranslateLoader } from 'ng2-translate/ng2-translate';
export function createTranslateLoader(http: Http) {
return new TranslateStaticLoader(http, './assets/i18n', '.json');
}
@NgModule({
imports: [
TranslateModule.forRoot({
provide: TranslateLoader,
useFactory: (createTranslateLoader),
deps: [Http]
})
]
})
3.在 src/assets/i18n 目录下添加语言包,如 en-ww.json 和 zh-cn.json 文件
3.1 en-ww.json
{
"TITLE": "Welcome To APP",
"HINT": "Select your language",
"HOME": "HOME",
"LEARN": "LEARN",
"FOUND": "FOUND",
"MY": "MY",
"CANCEL": "CANCEL",
"OK": "OK"
}
3.2 zh-cn.json
{
"TITLE": "欢迎使用APP",
"HINT": "请选择语言",
"HOME": "首页",
"LEARN": "学习",
"FOUND": "发现",
"MY": "我的",
"CANCEL": "取消",
"OK": "确认"
}
4.ng2-translate应用
4.1 TranslatePipe
<ion-title> {{ 'HELLO' | translate:param }} </ion-title>
param = {value: 'Dayana'};
4.2 TranslateService
import {TranslateService} from 'ng2-translate';
constructor(translate: TranslateService) {
// 设置默认的语言包
translate.setDefaultLang('en');
// 切换语言包
translate.use('en');
}
translate.get('HELLO', {value: 'Dayana'}).subscribe((res: string) => {
console.log(res); //=> 'Hello Dayana'
});
4.3 TranslateDirective
<div [translate]="'HELLO'" [translateParams]="{value: 'Dayana'}"></div>
或
<div translate [translateParams]="{value: 'Dayana'}">HELLO</div>
5.示例
<ion-tabs>
<ion-tab [root]="tab1Root" [tabTitle]="('HOME' | translate)"
tabIcon="home">
</ion-tab>
<ion-tab [root]="tab2Root" [tabTitle]="('LEARN' | translate)"
tabIcon="information-circle">
</ion-tab>
<ion-tab [root]="tab3Root" [tabTitle]="('FOUND' | translate)"
tabIcon="contacts">
</ion-tab>
</ion-tabs>
打包方案
利用 npm scripts 提供的钩子,在运行 serve 或 build 任务前,合并各个目录下的语言包,统一输出至 src/assets/i18n 目录下。在开发阶段可以运行 npm run dev ,通过已注册的钩子 predev: gulp generate-lang-json,即调用 gulp generate-lang-json 任务生成语言包。
具体实现:
/**
* 合并各个子目录下的语言包文件,生成独立的语言包
*/
var langJson = {};
gulp.task('generate-lang-json', function () {
return gulp.src(['src/**/*' + i18nLang + '.json', '!src/assets/**/*.json'])
.pipe(through2.obj(function (file, encoding, callback) {
var originalContents = String(file.contents);
var subLangJson;
try {
subLangJson = JSON.parse(originalContents);
for (key in subLangJson)
{
if(langJson[key]){
throw new Error('The key \''+langJson[key]
+' \'is repeat,file path:'+file.history);
}else{
langJson[key] = subLangJson[key]
}
}
} catch (e) {
console.dir(e);
throw new Error('Parse language file path failed');
}
file.contents = new Buffer(JSON.stringify(langJson));
callback(null, file);
}))
.pipe(rename(i18nLang + '.json'))
.pipe(gulp.dest('src/assets/i18n/'))
});
旧版本数据处理
公司现有的系统是采用 ionic 1.x 的版本开发,近期已经开始进行 ionic 2.x 的升级工作。因此需要抽取现有系统中的静态文本,然后对已有的文本进行分类。比如分为通用消息、功能模块内的消息。下面主要介绍一下,文本采集和处理思路。
使用正则匹配项目的JS文件(模板和业务逻辑文件)
对采集的文本进行去重处理
转成JavaScript对象,如代码段一
调用百度或其他翻译的API进行英文翻译,如代码段二
转换成标准的语言包
代码段一
{
"签到表": "签到表",
"讲师名单": "讲师名单",
"助教名单": "助教名单",
"全部评价": "全部评价",
"线下课程详情": "线下课程详情",
"培训地址": "培训地址",
"全部培训": "全部培训",
"混合培训": "混合培训",
"线下培训": "线下培训",
"在线培训": "在线培训",
"报名中": "报名中",
"预报名": "预报名"
}
代码段二
{
'签到表': 'Attendance list',
'讲师名单': 'lecturers',
'助教名单': 'Teaching assistant list',
'全部评价': 'All evaluation',
'线下课程详情': 'Online course details',
'培训地址': 'Training address',
'全部培训': 'All training',
'混合培训': 'Mixed training',
'线下培训': 'Offline training',
'在线培训': 'Online training',
'报名中': 'Enrollment',
'预报名': 'Forecast name'
}
语言包字段查询功能
为了方便地查询语言包中已定义的字段或字段值,我们实现了一个简单的查询功能,具体代码如下:
tools.html
<ion-header>
<ion-navbar>
<ion-title>tools</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<ion-searchbar (ionInput)="filterItems($event)" (ionClear)="reset()"></ion-searchbar>
<ion-grid>
<ion-row *ngFor="let item of items">
<ion-col width-100>{{item}}</ion-col>
</ion-row>
</ion-grid>
</ion-content>
tools.ts
import { Component } from '@angular/core';
import { NavController, NavParams } from 'ionic-angular';
import { Http } from '@angular/http';
@Component({
selector: 'page-tools',
templateUrl: 'tools.html'
})
export class ToolsPage {
constructor(
public navCtrl: NavController,
public navParams: NavParams,
public http: Http) {
}
_originItems: Array<string>; // 保存转化后的原始数据
items: Array<string>; // 页面上列表的数据源
ionViewDidLoad() {
this.http.get(`assets/i18n/zh-cn.json`)
.map(res => res.json())
.subscribe(res => {
this.items = this._originItems = this.transformItem(res);
});
}
/**
* 转换语言包JSON对象
* {key: value}对象转换为'key - value'数组
*/
transformItem(originItems: Array<any>) {
let items = [];
for (let key in originItems) {
items.push(`${key} - ${originItems[key]}`);
}
return items;
}
/**
* 搜索过滤
*/
filterItems(ev: any) {
let val = ev.target.value;
if (val && val.trim() != '') {
val = (<string>val).toUpperCase();
this.items = this._originItems.filter((item) => {
return item.indexOf(val) > -1;
});
} else {
this.reset();
}
}
/**
* 重置列表
*/
reset() {
this.items = this._originItems;
}
}
参考文档
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。