iT邦幫忙

2018 iT 邦幫忙鐵人賽
DAY 23
2

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></pre>
    
  • 增加i18n的標記,如:

    <h1 i18n>Hello i18n!</h1></pre>
    
  • 利用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 [src]="logo" title="Angular logo">

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

<img [src]="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 { }

參考資料


上一篇
[功能介紹-15] Router進階介紹
下一篇
[技術支援-2] 讓IDE支援Angular Language Service
系列文
用30天深入Angular 5的世界31

1 則留言

0
cwchiu
iT邦新手 4 級 ‧ 2019-01-15 14:54:31

如果介面想要提供繁體, 簡體以及英文三種語系切換該如何實現?

看更多先前的回應...收起先前的回應...
cwchiu iT邦新手 4 級‧ 2019-01-15 17:11:12 檢舉

感謝你的回覆. 不過該文是透過 http 抓取語系檔再搭配 pipe 實現多語系. 這表示 Angular i18n 無法實現動態多語系效果?

https://blog.johnwu.cc/article/angular-4-localization.html
可以的,這邊有動態多語系的範例

cwchiu iT邦新手 4 級‧ 2019-01-24 15:28:31 檢舉

謝謝你的回應, 可能我的問題問的不是很好. 因為我是按照這篇教學來練習 x18n 套件來實現多語系, x18n 使用 .xlf 檔來實做語系並且在編譯時將 .xlf 打包進 .js, 所以 我的理解是這個方法會導致每個語系要打包一次, 但共用邏輯不就重複打包?

透過動態載入語系包的作法是可以達成多語系無誤, 不過好像就沒辦法使用 x18n 套件, 這樣看來 x18n 套件似乎實用性不高. 以上是我的理解

請問有能自動檢查語系檔遺漏的工具嗎

我要留言

立即登入留言