使用Angular如何實現國際化(詳細教學)
本篇文章主要介紹了Angular 專案實現國際化的方法,現在分享給大家,也給大家做個參考。
正如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' ? 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) { } ngOnInit() { this.demoTitle = this.translateService.translate('app.base.hello'); } }
以上流程基本上能滿足大部分angular專案的國際化需求,如果需要更加複雜的國際化情況,歡迎討論。
總結
Angular到5.0的國際化已經相對來說簡便了很多,我們只需要在合適的地方打上i18n的tag即可方便快速地提取需要翻譯文案,具體如何處理翻譯後的檔案因人而異,多種方法可協助我們轉換(如本文透過nodejs)。
複雜一點的是無法透過打i18n標籤來翻譯的文本,NG-ZORRO的國際化方案彌補了這方面的不足,結合起來可以很方便地完成專案的國際化。國際化如果沒有專門的團隊支持,翻譯難度很大,需要考慮的東西很多,比如繁體還有澳門繁體、台灣繁體等,語法也不盡相同。
參考目錄
Angular的國際化(i18n)線上範例
NG-ZORRO Locale 國際化
上面是我整理給大家的,希望今後對大家有幫助。
相關文章:
在SpringMVC中post如何取得多選框value的值(程式碼實例)
jQuery SpringMVC中的複選框選擇與傳值實例_jquery
以上是使用Angular如何實現國際化(詳細教學)的詳細內容。更多資訊請關注PHP中文網其他相關文章!

熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

記事本++7.3.1
好用且免費的程式碼編輯器

SublimeText3漢化版
中文版,非常好用

禪工作室 13.0.1
強大的PHP整合開發環境

Dreamweaver CS6
視覺化網頁開發工具

SublimeText3 Mac版
神級程式碼編輯軟體(SublimeText3)

熱門話題

Angular.js是一種可自由存取的JavaScript平台,用於建立動態應用程式。它允許您透過擴展HTML的語法作為模板語言,以快速、清晰地表示應用程式的各個方面。 Angular.js提供了一系列工具,可協助您編寫、更新和測試程式碼。此外,它還提供了許多功能,如路由和表單管理。本指南將討論在Ubuntu24上安裝Angular的方法。首先,您需要安裝Node.js。 Node.js是一個基於ChromeV8引擎的JavaScript運行環境,可讓您在伺服器端執行JavaScript程式碼。要在Ub

隨著網路的快速發展,前端開發技術也不斷改進與迭代。 PHP和Angular是兩種廣泛應用於前端開發的技術。 PHP是一種伺服器端腳本語言,可以處理表單、產生動態頁面和管理存取權限等任務。而Angular是一種JavaScript的框架,可以用來開發單一頁面應用程式和建構元件化的網頁應用程式。本篇文章將介紹如何使用PHP和Angular進行前端開發,以及如何將它們

隨著全球化的發展以及互聯網的普及,越來越多的網站和應用程式開始致力於實現國際化和多語言支援功能,以滿足不同人群的需求。為了實現這些功能,開發者需要使用一些先進的技術及框架。在本文中,我們將介紹如何使用Gin框架來實現國際化和多語言支援功能。 Gin框架是一個輕量級的Web框架,由Go語言編寫。它具有高效、易用和靈活等特點,已經成為了許多開發者的首選框架。除此之外,

使用FastAPI框架建立國際化的Web應用FastAPI是一個高效能的PythonWeb框架,它結合了Python類型註解和效能較好的非同步支持,使得開發Web應用變得更加簡單、快速和可靠。在建構一個國際化的網路應用程式時,FastAPI提供了方便的工具和理念,讓應用程式能夠輕鬆支援多種語言。下面我將給一個具體的程式碼範例,介紹如何使用FastAPI框架構

Angular框架中元件的預設顯示行為不是區塊級元素。這種設計選擇促進了元件樣式的封裝,並鼓勵開發人員有意識地定義每個元件的顯示方式。透過明確設定CSS屬性 display,Angular組件的顯示可以完全控制,從而實現所需的佈局和響應能力。

身份驗證是任何網路應用程式中最重要的部分之一。本教程討論基於令牌的身份驗證系統以及它們與傳統登入系統的差異。在本教程結束時,您將看到一個用Angular和Node.js編寫的完整工作演示。傳統身份驗證系統在繼續基於令牌的身份驗證系統之前,讓我們先來看看傳統的身份驗證系統。使用者在登入表單中提供使用者名稱和密碼,然後點擊登入。發出請求後,透過查詢資料庫在後端驗證使用者。如果請求有效,則使用從資料庫中獲取的使用者資訊建立會話,然後在回應頭中傳回會話訊息,以便將會話ID儲存在瀏覽器中。提供用於存取應用程式中受

PHP8.0中的國際化庫:UnicodeCLDR和Intl擴展隨著全球化的進程,開發跨語言、跨地域的應用程式變得越來越普遍。國際化是實現這一目標的重要組成部分。在PHP8.0中,引入了UnicodeCLDR和Intl擴展,這兩個組件都為開發者提供了更好的國際化支援。 UnicodeCLDRUnicodeCLDR(CommonLocaleDat

1.準備資料庫為多語言資料建立新資料表,包括下列欄位:CREATETABLEtranslations(idINTNOTNULLAUTO_INCREMENT,localeVARCHAR(255)NOTNULL,keyVARCHAR(255)NOTNULL,valueTEXTNOTNULL,PRIMARYKEY(id));2.pid));頂部或側邊欄新增語言切換器,讓使用者可以選擇首選語言。 //取得目前語言$current_locale=isset($_GET["locale"])?$_
