正如angular官网所说,项目国际化是一件具有挑战性,需要多方面的努力、持久的奉献和决心的任务。
本文将介绍angular项目的国际化方案,涉及静态文件(html)和ts文件文案的国际化。
背景
- Angular: 5.0
- Angular Cli: 1.6.1(1.5.x也可以)
- NG-ZORRO: 0.6.8
Angular i18n
i18n模板翻译流程有四个阶段:
- 在组件模板中标记需要翻译的静态文本信息(即打上i18n标签)。
- Angular的i18n工具将标记的信息提取到一个行业标准的翻译源文件(如.xlf文件,使用ng xi18n)。
- 翻译人员编辑该文件,翻译提取出来的文本信息到目标语言,并将该文件还给你(需要翻译人员接入,本文采用将xlf文件转为json格式文件输出,最终将json文件转换回xlf格式文件)。
- Angular编译器导入完成翻译的文件,使用翻译的文本替换原始信息,并生成新的目标语言版本的应用程序。
你可以为每种支持的语言构建和部署单独的项目版本,仅需替换翻译后的xlf文件即可。
如何在模板文件中使用?
i18n提供了几种使用方式,还专门为单复数提供了翻译方式(个人没有使用,感觉不太方便)。接下来以一个单独的html文件来介绍几种使用方法。
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Angular i18n</title> </head> <body> <h1 i18n="Site Header|An introduction header for i18n Project@@stTitle">Angular 国际化项目</h1> <p> <span i18n="@@agDescription">国际化是一项很具有挑战性,需要多方面的努力、持久的奉献和决心的任务。</span> <span class="delete" i18n-title="@@agDelete" title="删除"></span> </p> <p><ng-container i18n=@@agLetGo>让我们现在开始吧!</ng-container>朋友!</p> </body> </html>
上述代码展示了几种i18n的使用方式:
1、使用i18n属性标记(可添加上说明性文案,格式如:title|description@@id,title和description可帮助翻译人员更好地理解文案含义,是否添加取决于自身项目情况)
可以在静态标签上直接打上i18n的tag,如
<span i18n="@@agDescription"></span>
生成的xlf(xml)字段格式为
<trans-unit id="agDescription" datatype="html"> <source>国际化是一项很具有挑战性,需要多方面的努力、持久的奉献和决心的任务。</source> <context-group purpose="location"> <context context-type="sourcefile">xxx.ts</context> <context context-type="linenumber">linenum</context> </context-group> </trans-unit>
2、为title添加i18n属性
对于html标签属性,同样可以添加i18n,如
<span class="delete" i18n-title="@@agDelete" title="删除"></span>
生成的xlf(xml)格式同上
3、翻译文本,而不必创建元素
我们有时候会出现一句话多个断句情况,如果每次都添加span、label这些元素包裹的话,可能严重影响页面布局,这时候我们可以使用ng-container来包裹需要翻译的文案。
<p> <ng-container i18n=@@agLetGo>让我们现在开始吧!</ng-container>朋友! </p>
在页面显示为
<p> <!----> LET'S GO朋友! </p>
* ng-container变为了注释块,这样做不会影响页面布局(尤其是应用了style样式的情况)
打上标签后,我们只要执行ng xi18n即可自动创建出xlf文件,通常为message.xlf,如需自定义,可自行前往 Angular CLI 官网查看。
XLF与JSON转换
xlf转json方法
我个人是采用xml2js库进行操作,简单代码如下:
const fs = require('fs');
xml2js = require('xml2js');
var parser = new xml2js.Parser();
fs.readFile(fileName, 'utf8', (err, data) => {
parser.parseString(data, function (err, result) {
// 读取新文件全部需要翻译的数据,并对比已翻译的进行取舍,具体转换成的格式结构可自行查看
result['xliff']['file'][0]['body'][0]['trans-unit'].forEach((item) => {
var itemFormat = {
"key" : item['$']['id'],
"value": item['source'][0]
};
// 执行相关操作,key-value形式是为了统一翻译文件结构,可按需定义
})
});
});
json转xlf方法
function backToXLF(translatedParams) {
// 文件格式可自行参考angular.cn官网的例子
var xlfFormat = {
"xliff": {
"$" : {
"version": "1.2",
"xmlns" : "urn:oasis:names:tc:xliff:document:1.2"
},
"file": [
{
"$" : {
"source-language": "en",
"datatype" : "plaintext",
"original" : "ng2.template"
},
"body": [
{
"trans-unit": []
}
]
}
]
}
};
if (translatedParams instanceof Array) {
// 获取原始名称
translatedParams.forEach((data) => {
var tmp = {
"$" : {
"id" : data.key,
"datatype": "html"
},
"source": [i18nItemsOrigin[data.key]], // 这里的i18nItemsOrigin是json格式,属性名为key值,表示原始文案
"target": [data.value]
};
// 数组,json项
xlfFormat['xliff']['file'][0]['body'][0]['trans-unit'].push(tmp);
});
}
var builder = new xml2js.Builder();
var xml = builder.buildObject(xlfFormat);
return xml;
}
这样提取文案信息和转换翻译后的文件就完成了,接下来我们需要把翻译好的文案应用到项目中去。
部署翻译文件
src目录下新建locale文件夹,将翻译转换后的demo.en-US.xlf文件存在改目录下
app文件夹下新建i18n-providers.ts
import {
LOCALE_ID,
MissingTranslationStrategy,
StaticProvider,
TRANSLATIONS,
TRANSLATIONS_FORMAT
} from '@angular/core';
import { CompilerConfig } from '@angular/compiler';
import { Observable } from 'rxjs/Observable';
import { LOCALE_LANGUAGE } from './app.config'; // 自行定义配置位置
export function getTranslationProviders(): Promise<StaticProvider[]> {
// get the locale string from the document
const locale = LOCALE_LANGUAGE.toString();
// return no providers
const noProviders: StaticProvider[] = [];
// no locale or zh-CN: no translation providers
if (!locale || locale === 'zh-CN') {
return Promise.resolve(noProviders);
}
// Ex: 'locale/demo.zh-MO.xlf`
const translationFile = `./locale/demo.${locale}.xlf`;
return getTranslationsWithSystemJs(translationFile)
.then((translations: string) => [
{ provide: TRANSLATIONS, useValue: translations },
{ provide: TRANSLATIONS_FORMAT, useValue: 'xlf' },
{ provide: LOCALE_ID, useValue: locale },
{
provide: CompilerConfig,
useValue: new CompilerConfig({ missingTranslation: MissingTranslationStrategy.Error })
}
]).catch(() => noProviders); // ignore if file not found
}
declare var System: any;
// 获取locale文件
function getTranslationsWithSystemJs(file: string) {
let text = '';
const fileRequest = new XMLHttpRequest();
fileRequest.open('GET', file, false);
fileRequest.onerror = function (err) {
console.log(err);
};
fileRequest.onreadystatechange = function () {
if (fileRequest.readyState === 4) {
if (fileRequest.status === 200 || fileRequest.status === 0) {
text = fileRequest.responseText;
}
}
};
fileRequest.send();
const observable = Observable.of(text);
const prom = observable.toPromise();
return prom;
}
main.ts文件修改为
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule } from './app/app.module';
import { environment } from './environments/environment';
import { getTranslationProviders } from './app/i18n-providers';
if (environment.production) {
enableProdMode();
}
getTranslationProviders().then(providers => {
const options = { providers };
platformBrowserDynamic().bootstrapModule(AppModule, options)
.catch(err => console.log(err));
});
别忘了将locale目录添加到.angular-cli.json里,来单独打包。
这样我们对静态文案的翻译工作基本已经完成了,但是有些动态文案如ts文件里的文案或者第三方框架属性该如何翻译呢?下面会介绍针对 ts 文件和 NG-ZORRO 框架实现动态文案翻译的方案。
ts文件文案和NG-ZORRO框架文案翻译
具体思路
通过Pipe调用Service方法,根据对应的唯一id值匹配json对象里的翻译结果,进而返回渲染到前端,参考于NG-ZORRO框架的国际化实现方案。
首先我们定义一下json翻译对象的格式,全部为三层结构,动态变量需要按%%包裹,这样做的原因是和项目结构相关联,也便于后期和i18n方式格式统一。
{
"app": {
"base": {
"hello": "文件文案",
"userCount": "一共%num%人"
}
}
}
格式已定,我们继续定义Service处理方式
这里复用NG-ZORRO的国际化方案 ,可以简化我们的开发,有兴趣的可以参看一下其源码。
*** TranslateService ***
import { Injectable } from '@angular/core';
// 引入语言配置和国际化文件文案对象
import { LOCALE_LANGUAGE } from '../app.config';
import { enUS } from '../locales/demo.en-US';
import { zhCN } from '../locales/stream.zh-CN';
@Injectable()
export class TranslateService {
private _locale = LOCALE_LANGUAGE.toString() === 'zh-CN' "htmlcode">
*** NzTranslateLocalePipe ***
import { Pipe, PipeTransform } from '@angular/core';
import { TranslateService } from '../services/translate.service';
@Pipe({
name: 'nzTranslateLocale'
})
export class NzTranslateLocalePipe implements PipeTransform {
constructor(private _locale: TranslateService) {
}
transform(path: string, keyValue"htmlcode">
*** NG-ZORRO 控件 ***
<nz-input [nzPlaceHolder]="'app.base.hello'|nzTranslateLocale"></nz-input> // 无动态参数
<nz-popconfirm [nzTitle]="'app.base.userCount'|nzTranslateLocale: {num:users.length}" ...>
... // 有动态参数
</nz-popconfirm>
*** ts文件 ***
export class AppComponent implements OnInit {
demoTitle='';
users = ['Jack', 'Johnson', 'Lucy'];
constructor(privete translateService: TranslateService) {
}
ngOnInit() {
this.demoTitle = this.translateService.translate('app.base.hello');
}
}
以上流程基本上能满足大部分angular项目的国际化需求,如果需要更加复杂的国际化情况,欢迎讨论。
总结
Angular到5.0的国际化已经相对来说简便了很多,我们只需要在合适的地方打上i18n的tag即可方便快速地提取需要翻译文案,具体如何处理翻译后的文件因人而异,多种方法可帮助我们转换(如本文通过nodejs)。
复杂一点的是无法通过打i18n标签来翻译的文本,NG-ZORRO的国际化方案弥补了这方面的不足,结合起来可以很方便地完成项目的国际化。 国际化如果没有专门的团队支持,翻译难度很大,需要考虑的东西很多,比如繁体还有澳门繁体、台湾繁体等,语法也不尽相同。
参考目录
Angular的国际化(i18n)在线例子
NG-ZORRO Locale 国际化
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
免责声明:本站文章均来自网站采集或用户投稿,网站不提供任何软件下载或自行开发的软件! 如有用户或公司发现本站内容信息存在侵权行为,请邮件告知! 858582#qq.com
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]