Angular項目如何實現(xiàn)國際化-創(chuàng)新互聯(lián)

這篇文章主要介紹Angular項目如何實現(xiàn)國際化,文中介紹的非常詳細(xì),具有一定的參考價值,感興趣的小伙伴們一定要看完!

創(chuàng)新互聯(lián)建站專注為客戶提供全方位的互聯(lián)網(wǎng)綜合服務(wù),包含不限于網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計、德陽網(wǎng)絡(luò)推廣、成都微信小程序、德陽網(wǎng)絡(luò)營銷、德陽企業(yè)策劃、德陽品牌公關(guān)、搜索引擎seo、人物專訪、企業(yè)宣傳片、企業(yè)代運(yùn)營等,從售前售中售后,我們都將竭誠為您服務(wù),您的肯定,是我們大的嘉獎;創(chuàng)新互聯(lián)建站為所有大學(xué)生創(chuàng)業(yè)者提供德陽建站搭建服務(wù),24小時服務(wù)熱線:18982081108,官方網(wǎng)址:muchs.cn

正如angular官網(wǎng)所說,項目國際化是一件具有挑戰(zhàn)性,需要多方面的努力、持久的奉獻(xiàn)和決心的任務(wù)。
本文將介紹angular項目的國際化方案,涉及靜態(tài)文件(html)和ts文件文案的國際化。

背景

  1. Angular: 5.0

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

  3. NG-ZORRO: 0.6.8

Angular i18n

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

  1. 在組件模板中標(biāo)記需要翻譯的靜態(tài)文本信息(即打上i18n標(biāo)簽)。

  2. Angular的i18n工具將標(biāo)記的信息提取到一個行業(yè)標(biāo)準(zhǔn)的翻譯源文件(如.xlf文件,使用ng xi18n)。

  3. 翻譯人員編輯該文件,翻譯提取出來的文本信息到目標(biāo)語言,并將該文件還給你(需要翻譯人員接入,本文采用將xlf文件轉(zhuǎn)為json格式文件輸出,最終將json文件轉(zhuǎn)換回xlf格式文件)。

  4. Angular編譯器導(dǎo)入完成翻譯的文件,使用翻譯的文本替換原始信息,并生成新的目標(biāo)語言版本的應(yīng)用程序。

你可以為每種支持的語言構(gòu)建和部署單獨(dú)的項目版本,僅需替換翻譯后的xlf文件即可。

如何在模板文件中使用?

i18n提供了幾種使用方式,還專門為單復(fù)數(shù)提供了翻譯方式(個人沒有使用,感覺不太方便)。接下來以一個單獨(dú)的html文件來介紹幾種使用方法。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Angular i18n</title>
</head>
<body>
  <h2 i18n="Site Header|An introduction header for i18n Project@@stTitle">Angular 國際化項目</h2>
  <p>
   <span i18n="@@agDescription">國際化是一項很具有挑戰(zhàn)性,需要多方面的努力、持久的奉獻(xiàn)和決心的任務(wù)。</span>
   <span class="delete" i18n-title="@@agDelete" title="刪除"></span>
  </p>
  <p><ng-container i18n=@@agLetGo>讓我們現(xiàn)在開始吧!</ng-container>朋友!</p>
</body>
</html>

上述代碼展示了幾種i18n的使用方式:

1、使用i18n屬性標(biāo)記(可添加上說明性文案,格式如:title|description@@id,title和description可幫助翻譯人員更好地理解文案含義,是否添加取決于自身項目情況)

可以在靜態(tài)標(biāo)簽上直接打上i18n的tag,如

<span i18n="@@agDescription"></span>

生成的xlf(xml)字段格式為

<trans-unit id="agDescription" datatype="html">
 <source>國際化是一項很具有挑戰(zhàn)性,需要多方面的努力、持久的奉獻(xiàn)和決心的任務(wù)。</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標(biāo)簽屬性,同樣可以添加i18n,如

<span class="delete" i18n-title="@@agDelete" title="刪除"></span>

生成的xlf(xml)格式同上

3、翻譯文本,而不必創(chuàng)建元素

我們有時候會出現(xiàn)一句話多個斷句情況,如果每次都添加span、label這些元素包裹的話,可能嚴(yán)重影響頁面布局,這時候我們可以使用ng-container來包裹需要翻譯的文案。

<p>
  <ng-container i18n=@@agLetGo>讓我們現(xiàn)在開始吧!</ng-container>朋友!
</p>

在頁面顯示為

<p>
  <!---->
  LET'S GO朋友!
</p>

* ng-container變?yōu)榱俗⑨寜K,這樣做不會影響頁面布局(尤其是應(yīng)用了style樣式的情況)

打上標(biāo)簽后,我們只要執(zhí)行ng xi18n即可自動創(chuàng)建出xlf文件,通常為message.xlf,如需自定義,可自行前往 Angular CLI 官網(wǎng)查看。

XLF與JSON轉(zhuǎn)換

xlf轉(zhuǎn)json方法

我個人是采用xml2js庫進(jìn)行操作,簡單代碼如下:

const fs = require('fs');
xml2js = require('xml2js');
var parser = new xml2js.Parser();
fs.readFile(fileName, 'utf8', (err, data) => {
 parser.parseString(data, function (err, result) {
  // 讀取新文件全部需要翻譯的數(shù)據(jù),并對比已翻譯的進(jìn)行取舍,具體轉(zhuǎn)換成的格式結(jié)構(gòu)可自行查看
  result['xliff']['file'][0]['body'][0]['trans-unit'].forEach((item) => {
   var itemFormat = {
    "key" : item['$']['id'],
    "value": item['source'][0]
   };
   // 執(zhí)行相關(guān)操作,key-value形式是為了統(tǒng)一翻譯文件結(jié)構(gòu),可按需定義
  })
 });
});

json轉(zhuǎn)xlf方法

function backToXLF(translatedParams) {
 // 文件格式可自行參考angular.cn官網(wǎng)的例子
 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]
   };
   // 數(shù)組,json項
   xlfFormat['xliff']['file'][0]['body'][0]['trans-unit'].push(tmp);
  });
 }
 var builder = new xml2js.Builder();
 var xml = builder.buildObject(xlfFormat);
 return xml;
}

這樣提取文案信息和轉(zhuǎn)換翻譯后的文件就完成了,接下來我們需要把翻譯好的文案應(yīng)用到項目中去。

部署翻譯文件

src目錄下新建locale文件夾,將翻譯轉(zhuǎn)換后的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里,來單獨(dú)打包。

這樣我們對靜態(tài)文案的翻譯工作基本已經(jīng)完成了,但是有些動態(tài)文案如ts文件里的文案或者第三方框架屬性該如何翻譯呢?下面會介紹針對 ts 文件和 NG-ZORRO 框架實現(xiàn)動態(tài)文案翻譯的方案。

ts文件文案和NG-ZORRO框架文案翻譯

具體思路

通過Pipe調(diào)用Service方法,根據(jù)對應(yīng)的唯一id值匹配json對象里的翻譯結(jié)果,進(jìn)而返回渲染到前端,參考于NG-ZORRO框架的國際化實現(xiàn)方案。

首先我們定義一下json翻譯對象的格式,全部為三層結(jié)構(gòu),動態(tài)變量需要按%%包裹,這樣做的原因是和項目結(jié)構(gòu)相關(guān)聯(lián),也便于后期和i18n方式格式統(tǒng)一。

{
  "app": {
    "base": {
      "hello": "文件文案",
      "userCount": "一共%num%人"
    }
  }
}

格式已定,我們繼續(xù)定義Service處理方式

這里復(fù)用NG-ZORRO的國際化方案 ,可以簡化我們的開發(fā),有興趣的可以參看一下其源碼。

*** 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中調(diào)用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);
 }
}

好了,現(xiàn)在我們處理邏輯已經(jīng)完全結(jié)束了,下面介紹一下如何使用

*** NG-ZORRO 控件 ***
<nz-input [nzPlaceHolder]="'app.base.hello'|nzTranslateLocale"></nz-input> // 無動態(tài)參數(shù)
<nz-popconfirm [nzTitle]="'app.base.userCount'|nzTranslateLocale: {num:users.length}" ...>
... // 有動態(tài)參數(shù)
</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項目如何實現(xiàn)國際化”這篇文章的所有內(nèi)容,感謝各位的閱讀!希望分享的內(nèi)容對大家有幫助,更多相關(guān)知識,歡迎關(guān)注創(chuàng)新互聯(lián)成都網(wǎng)站設(shè)計公司行業(yè)資訊頻道!

另外有需要云服務(wù)器可以了解下創(chuàng)新互聯(lián)scvps.cn,海內(nèi)外云服務(wù)器15元起步,三天無理由+7*72小時售后在線,公司持有idc許可證,提供“云服務(wù)器、裸金屬服務(wù)器、高防服務(wù)器、香港服務(wù)器、美國服務(wù)器、虛擬主機(jī)、免備案服務(wù)器”等云主機(jī)租用服務(wù)以及企業(yè)上云的綜合解決方案,具有“安全穩(wěn)定、簡單易用、服務(wù)可用性高、性價比高”等特點(diǎn)與優(yōu)勢,專為企業(yè)上云打造定制,能夠滿足用戶豐富、多元化的應(yīng)用場景需求。

當(dāng)前文章:Angular項目如何實現(xiàn)國際化-創(chuàng)新互聯(lián)
網(wǎng)站地址:http://muchs.cn/article44/dejjhe.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供用戶體驗標(biāo)簽優(yōu)化、搜索引擎優(yōu)化、企業(yè)網(wǎng)站制作、網(wǎng)站建設(shè)網(wǎng)站策劃

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

網(wǎng)站托管運(yùn)營