當前位置:編程學習大全網 - 編程語言 - 使用Angular如何實現國際化(詳細教程)

使用Angular如何實現國際化(詳細教程)

本篇文章主要介紹了Angular 項目實現國際化的方法,現在分享給大家,也給大家做個參考。

正如angular官網所說,項目國際化是壹件具有挑戰性,需要多方面的努力、持久的奉獻和決心的任務。

本文將介紹angular項目的國際化方案,涉及靜態文件(html)和ts文件文案的國際化。

背景Angular: 5.0

Angular Cli: 1.6.1(1.5.x也可以)

NG-ZORRO: 0.6.8

Angular i18ni18n模板翻譯流程有四個階段:

在組件模板中標記需要翻譯的靜態文本信息(即打上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' ? zhCN : enUS;

constructor() {

}

// path為app.base.hello格式的字符串,這裏按json層級取匹配改變量

translate(path: string, data?: any): string {

let content = this._getObjectPath(this._locale, path) as string;

if (typeof content === 'string') {

if (data) {

Object.keys(data).forEach((key) => content = content.replace(new RegExp(`%${key}%`, 'g'), data[key]));

}

return content;

}

return path;

}

private _getObjectPath(obj: object, path: string): string | object {

let res = obj;

const paths = path.split('.');

const depth = paths.length;

let index = 0;

while (res && index < depth) {

res = res[paths[index++]];

}

return index === depth ? res : null;

}

}這樣,只需要在Pipe中調用Service的translate方法即可

*** 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?: object): string {

return this._locale.translate(path, keyValue);

}

}好了,現在我們處理邏輯已經完全結束了,下面介紹壹下如何使用

*** 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) {

}

ng

  • 上一篇:以太坊的智能合約
  • 下一篇:如何通過編程控制無人機的方向
  • copyright 2024編程學習大全網