深入指南
國際化

使用翻譯檔案

在你將元件準備好進行翻譯之後,可以使用 extract-i18n Angular CLI 指令,將元件中標記的文字擷取到一個來源語言(source language)檔案中。

標記的文字包括以 i18n 標記的文字、以 i18n-attribute 標記的屬性,以及如為翻譯準備元件所述以 $localize 標記的文字。

請完成下列步驟,為你的專案建立並更新翻譯檔案。

  1. 擷取來源語言檔案。
    1. 選擇性地變更位置、格式與名稱。
  2. 將來源語言檔案複製一份,為每種語言建立一個翻譯檔案。
  3. 翻譯每個翻譯檔案。
  4. 分別翻譯複數形式與替代運算式。
    1. 翻譯複數形式。
    2. 翻譯替代運算式。
    3. 翻譯巢狀運算式。

擷取來源語言檔案

若要擷取來源語言檔案,請完成下列動作。

  1. 開啟終端機視窗。
  2. 切換到你專案的根目錄。
  3. 執行下列 CLI 指令。
ng extract-i18n

extract-i18n 指令會在你專案的根目錄中,建立一個名為 messages.xlf 的來源語言檔案。 有關 XML Localization Interchange File Format(XLIFF,version 1.2)的更多資訊,請參閱 XLIFF。

使用下列 extract-i18n 指令選項,可以變更來源語言檔案的位置、格式與檔案名稱。

指令選項 說明
--format 設定輸出檔案的格式
--out-file 設定輸出檔案的名稱
--output-path 設定輸出目錄的路徑

變更來源語言檔案的位置

若要在 src/locale 目錄中建立檔案,請將輸出路徑指定為選項。

extract-i18n --output-path 範例

下列範例將輸出路徑指定為選項。

ng extract-i18n --output-path src/locale

變更來源語言檔案的格式

extract-i18n 指令可以建立下列翻譯格式的檔案。

使用 --format 指令選項明確指定翻譯格式。

HELPFUL: XMB 格式會產生 .xmb 來源語言檔案,但翻譯檔案使用的是 .xtb。

extract-i18n --format 範例

下列範例示範了幾種翻譯格式。

ng extract-i18n --format=xlf
ng extract-i18n --format=xlf2
ng extract-i18n --format=xmb
ng extract-i18n --format=json
ng extract-i18n --format=arb

變更來源語言檔案的名稱

若要變更擷取工具產生的來源語言檔案名稱,請使用 --out-file 指令選項。

extract-i18n --out-file 範例

下列範例示範如何為輸出檔案命名。

ng extract-i18n --out-file source.xlf

為每種語言建立一個翻譯檔案

若要為某個地區設定(locale)或語言建立翻譯檔案,請完成下列動作。

  1. 擷取來源語言檔案。

  2. 複製一份來源語言檔案,為每種語言建立一個翻譯檔案。

  3. 重新命名翻譯檔案,加上地區設定。

    messages.xlf --> messages.{locale}.xlf
  4. 在你專案的根目錄建立一個名為 locale 的新目錄。

    src/locale
  5. 將翻譯檔案移到新目錄中。

  6. 將翻譯檔案送交你的譯者。

  7. 對你想加入應用程式的每種語言,重複上述步驟。

法文的 extract-i18n 範例

例如,若要建立法文翻譯檔案,請完成下列動作。

  1. 執行 extract-i18n 指令。
  2. 複製一份 messages.xlf 來源語言檔案。
  3. 將複本重新命名為 messages.fr.xlf,作為法文(fr)翻譯。
  4. 將 fr 翻譯檔案移到 src/locale 目錄。
  5. 將 fr 翻譯檔案送交譯者。

翻譯每個翻譯檔案

除非你精通該語言,而且有時間編輯翻譯,否則你很可能會完成下列步驟。

  1. 將每個翻譯檔案送交譯者。
  2. 譯者使用 XLIFF 檔案編輯器完成下列動作。
    1. 建立翻譯。
    2. 編輯翻譯。

法文翻譯流程範例

為了示範流程,請檢視範例 Angular 國際化應用程式中的 messages.fr.xlf 檔案。範例 Angular 國際化應用程式包含一份法文翻譯,讓你無需特殊的 XLIFF 編輯器或法文知識就能編輯。

下列動作說明法文的翻譯流程。

  1. 開啟 messages.fr.xlf,找出第一個 <trans-unit> 元素。 這是一個翻譯單元(translation unit),也稱為文字節點(text node),代表先前以 i18n 屬性標記的 <h1> 問候標籤的翻譯。

    src/locale/messages.fr.xlf (<trans-unit>)

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

    id="introductionHeader" 是一個自訂 ID,但不含來源 HTML 中要求的 @@ 前綴。

  2. 複製文字節點中的 <source>... </source> 元素,將它重新命名為 target,然後把內容換成法文文字。

    src/locale/messages.fr.xlf (<trans-unit>,翻譯後)

    <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>

    在較複雜的翻譯中,說明與含義元素中的資訊與上下文,能協助你選擇正確的翻譯用詞。

  3. 翻譯其他文字節點。 下列範例顯示翻譯的方式。

    src/locale/messages.fr.xlf (<trans-unit>)

    <trans-unit id="ba0cc104d3d69bf669f97b8d96a4c5d8d9559aa3" datatype="html">
      <source>I don&apos;t output any element</source>
      <target>Je n'affiche aucun élément</target>
    </trans-unit>
    <trans-unit id="701174153757adf13e7c24a248c8a873ac9f5193" datatype="html">
      <source>Angular logo</source>
      <target>Logo d'Angular</target>
    </trans-unit>

IMPORTANT: 不要變更翻譯單元的 ID。 每個 id 屬性都是由 Angular 產生的,取決於元件文字的內容與指定的含義。

如果你變更了文字或含義,id 屬性就會改變。 有關管理文字更新與 ID 的更多資訊,請參閱自訂 ID。

翻譯複數形式

依每種語言的需要,新增或移除複數形式(plural cases)。

HELPFUL: 有關語言的複數規則,請參閱 CLDR plural rules。

minute plural 範例

若要翻譯 plural,請翻譯 ICU 格式的比對值。

  • just now
  • one minute ago
  • <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago

下列範例顯示翻譯的方式。

src/locale/messages.fr.xlf (<trans-unit>)

<trans-unit id="5a134dee893586d02bffc9611056b9cadf9abfad" datatype="html">
  <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago} }</source>
  <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes} }</target>
</trans-unit>

翻譯替代運算式

Angular 也會將替代的 select ICU 運算式擷取為個別的翻譯單元。

gender select 範例

下列範例顯示元件範本中的一個 select ICU 運算式。

app.component.html

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

在此範例中,Angular 將運算式擷取為兩個翻譯單元。 第一個包含 select 子句之外的文字,並為 select 使用一個佔位符(<x id="ICU">):

src/locale/messages.fr.xlf (<trans-unit>)

<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
  <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
  <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
</trans-unit>

IMPORTANT: 翻譯文字時,必要時可以移動佔位符,但不要將它移除。 如果你移除了佔位符,ICU 運算式就會從你翻譯後的應用程式中被移除。

下列範例顯示第二個翻譯單元,其中包含 select 子句。

src/locale/messages.fr.xlf (<trans-unit>)

<trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">
  <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>
  <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>
</trans-unit>

下列範例顯示翻譯完成後的兩個翻譯單元。

src/locale/messages.fr.xlf (<trans-unit>)

<trans-unit id="f99f34ac9bd4606345071bd813858dec29f3b7d1" datatype="html">
  <source>The author is <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></source>
  <target>L'auteur est <x id="ICU" equiv-text="{gender, select, male {...} female {...} other {...}}"/></target>
</trans-unit>
<trans-unit id="eff74b75ab7364b6fa888f1cbfae901aaaf02295" datatype="html">
  <source>{VAR_SELECT, select, male {male} female {female} other {other} }</source>
  <target>{VAR_SELECT, select, male {un homme} female {une femme} other {autre} }</target>
</trans-unit>

翻譯巢狀運算式

Angular 處理巢狀運算式的方式,與處理替代運算式相同。 Angular 會將運算式擷取為兩個翻譯單元。

巢狀 plural 範例

下列範例顯示第一個翻譯單元,其中包含巢狀運算式之外的文字。

src/locale/messages.fr.xlf (<trans-unit>)

<trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">
  <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>
  <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>
</trans-unit>

下列範例顯示第二個翻譯單元,其中包含完整的巢狀運算式。

src/locale/messages.fr.xlf (<trans-unit>)

<trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">
  <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>
  <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>
</trans-unit>

下列範例顯示翻譯後的兩個翻譯單元。

src/locale/messages.fr.xlf (<trans-unit>)

<trans-unit id="972cb0cf3e442f7b1c00d7dab168ac08d6bdf20c" datatype="html">
  <source>Updated: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></source>
  <target>Mis à jour: <x id="ICU" equiv-text="{minutes, plural, =0 {...} =1 {...} other {...}}"/></target>
</trans-unit>
<trans-unit id="7151c2e67748b726f0864fc443861d45df21d706" datatype="html">
  <source>{VAR_PLURAL, plural, =0 {just now} =1 {one minute ago} other {<x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes ago by {VAR_SELECT, select, male {male} female {female} other {other} }} }</source>
  <target>{VAR_PLURAL, plural, =0 {à l'instant} =1 {il y a une minute} other {il y a <x id="INTERPOLATION" equiv-text="{{minutes}}"/> minutes par {VAR_SELECT, select, male {un homme} female {une femme} other {autre} }} }</target>
</trans-unit>

下一步