快訊!我的新書登上天瓏網路書店11月份暢銷榜第一名啦!看過的都說讚!歡迎大家前往訂購!
>>>> AI 職場超神助手:ChatGPT 與生成式 AI 一鍵搞定工作難題 <<<<

[技術支援-1] 支援多語系

Angular i18n可做到的事

  • 以本地格式顯示日期,數量,百分比和貨幣。
  • 在組件模板中翻譯文字。
  • 翻譯單數和複數
  • 翻譯HTML屬性的替代文字

可以透過CLI來產生XLS檔案,並透過XLS檔案來設定多語系字串,接著使用下面的字串來產生網站檔案:
ng serve –aot –locale zh-Hant
假如是使用JIT的方式去佈暑網站,則也要在頁面設定LOCALE_ID的值如下:

import { LOCALE_ID, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from '../src/app/app.component';

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  providers: [ { provide: LOCALE_ID, useValue: 'zh-Hant' } ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

從上面的範例可以看出,Angular多語系的實作方式是讓每個語言獨立一個 index.html 版本。這樣優點是網站瀏覽較為快速,缺點則是修改時要重新REBULE的工程較大。

此連結有Angular所有支援的語系:Angular repository
在angular5的地區設定是使用BCP47,這個規格隨著時間而有些微改變如下:

LOCALE NAME OLD LOCALE ID NEW LOCALE ID
Indonesian in id
Hebrew iw he
Romanian Moldova mo ro-MD
Norwegian Bokmål no, no-NO nb
Serbian Latin sh sr-Latn
Filipino tl fil
Portuguese Brazil pt-BR pt
Chinese Simplified zh-cn, zh-Hans-CN zh-Hans
Chinese Traditional zh-tw, zh-Hant-TW zh-Hant
Chinese Traditional Hong Kong zh-hk zh-Hant-HK

以本地格式顯示日期,數量,百分比和貨幣

預設所有管道如DatePipeCurrencyPipeDecimalPipe 和PercentPipe所使用語言環境的數據格式都是en-US,如果要設置為其他語言環境,則需要導入該新語言環境的語言環境數據。

利用CLI的--locale會自動為我們設置這部份,若要手動設置方法如下:

import { registerLocaleData } from '@angular/common';
import localeFr from '@angular/common/locales/fr';

// the second parameter 'fr' is optional
registerLocaleData(localeFr, 'fr');

template內的多語系支援

在angular內,設定多語系檔案的順序如下:

  • 開發於template先使用預設的語言做開發,如:
    <h1>Hello i18n!</h1>
  • 增加i18n的標記,如:
    <h1 i18n>Hello i18n!</h1>
  • 利用CLI產生messages.xlf,如下:
    ng xi18n
  • 將完成的翻譯文件合併到應用程式中:
    ng serve –aot –i18nFile=src/locale/messages.fr.xlf –i18nFormat=xlf –locale=fr

為了使翻議者能夠更準確的翻議,可以在i18n的指令裡面增加上下文說明,如:

<h1 i18n="An introduction header for this sample">Hello i18n!</h1>

如果相同的文字需要有不同的翻議,則可增加meaning的設定。其格式為meaning|description,如:

<h1 i18n="site header|An introduction header for this sample">Hello i18n!</h1>

若有相同翻議字串但meaning不同,則會有不同的翻譯。若翻議字串相同,description不同,則依然是相同的翻議。
除了使用meaning以外,也可以自己定義一個翻議字串的ID來使用,如:

<h1 i18n="@@introductionHeader">Hello i18n!</h1>

假如兩個翻議字串不同卻取了相同的ID,會造成翻譯後有著相同的字串:

<h3 i18n="@@myId">Hello</h3>
<p i18n="@@myId">Good bye</p>

翻譯檔案內容如下:

<trans-unit id="myId" datatype="html">
  <source>Hello</source>
  <target state="new">Bonjour</target>
</trans-unit>

則生成的HTML內容如下:

<h3>Bonjour</h3>
<p>Bonjour</p>

如果有時候只是想要翻譯文字而不想使用任何HTML TAG,則可以使用ng-container

<ng-container i18n>I don't output any element</ng-container>

翻譯HTML屬性的替代文字

假如有一個像下面的圖片有著純文字的替代文字

<img &#91;src&#93;="logo" title="Angular logo">

可以使用這樣的tag來做i18n的設定

<img &#91;src&#93;="logo" i18n-title title="Angular logo" />

這種技術適用於任何元素的任何屬性。
使用i18n-x="<meaning>|<description>@@" 語法來指定含義,說明和標識。

翻譯單數和複數

在一些語言的狀況下,不同的數量使用的詞彙不一樣,例如時間,可以顯示”just now”, “one minute ago”或”x minutes ago”
這時候可以用這樣的方式來設定翻譯文字

<span i18n>Updated {minutes, plural, =0 {just now} =1 {one minute ago} other {{{minutes}} minutes ago}}</span>

上面第一個參數minutes是最重要的,用來設定這個字串要放入的變數
第二個參數plural為翻譯類型(請參見:ICU Message Format
第三個參數則是設定各種數字要顯示的文字
第三個參數可設定的選項有下面這些:

  • =0 (or any other number)
  • zero
  • one
  • two
  • few
  • many
  • other

也可以根據要顯示的變數內容來顯示不同的翻譯字串

<span i18n>The author is {gender, select, m {male} f {female} o {other}}</span>

利用ng xi18n來產生翻譯原檔

使用CLI打入可產生messages.xlf的翻譯原檔,預設是產生xlf檔案
ng xi18n
如果想要產出其他類型檔案可以加上--i18nFormat的參數如下:
ng xi18n –i18nFormat=xlf
ng xi18n –i18nFormat=xlf2
ng xi18n –i18nFormat=xmb
接著把messages.xlf改名為messages.fr.xlf(假使要翻譯的目標語言為fr)
下面為一個產出的xlf檔案內容的範例:

<trans-unit id="introductionHeader" datatype="html">
  <source>Hello i18n!</source>
  <target>Bonjour i18n !</target>
  <note priority="1" from="description">An introduction header for this sample</note>
  <note priority="1" from="meaning">User welcome</note>
</trans-unit>

target裡面要填的就是目標翻譯語言要顯示的文字

合併翻譯檔案回應用程式裡

使用AOT的方式

使用下面三個參數:

  • --i18nFile: 翻譯檔案的位置
  • --i18nFormat: 翻譯檔案的格式
  • --locale: 被翻譯的語系名稱

ng serve –aot –i18nFile=src/locale/messages.fr.xlf –i18nFormat=xlf –locale=fr

使用JIT的方式

src/main.ts裡設定所使用的語系
import { enableProdMode, TRANSLATIONS, TRANSLATIONS_FORMAT } from ‘@angular/core’;
import { platformBrowserDynamic } from ‘@angular/platform-browser-dynamic’;

import { AppModule } from ‘./app/app.module’;
import { environment } from ‘./environments/environment’;

if (environment.production) {
enableProdMode();
}

// use the require method provided by webpack
declare const require;
// we use the webpack raw-loader to return the content as a string
const translations = require(`raw-loader!./locale/messages.fr.xlf`);

platformBrowserDynamic().bootstrapModule(AppModule, {
providers: [
{provide: TRANSLATIONS, useValue: translations},
{provide: TRANSLATIONS_FORMAT, useValue: ‘xlf’}
]
});
src/app/app.module.ts裡加上LOCALE_ID

import { LOCALE_ID, NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';

import { AppComponent } from '../src/app/app.component';

@NgModule({
  imports: [ BrowserModule ],
  declarations: [ AppComponent ],
  providers: [ { provide: LOCALE_ID, useValue: 'fr' } ],
  bootstrap: [ AppComponent ]
})
export class AppModule { }

參考資料


17年資歷女工程師,專精於動畫、影像辨識以及即時串流程式開發。經常組織活動,邀請優秀的女性分享她們的技術專長,並在眾多場合分享自己的技術知識,也活躍於非營利組織,辦理活動來支持特殊兒及其家庭。期待用技術改變世界。

如果你認同我或想支持我的努力,歡迎請我喝一杯咖啡!讓我更有動力分享知識!