將應用程式本地化

Android 作業系統在許多地區和裝置上都相當普及;為了盡可能觸及最多使用者,應用程式應以適合在地使用者的方式處理文字、音訊檔案、數字、貨幣和圖形。

本文將介紹讓 Android 應用程式本地化的最佳做法。

您應該已經相當熟悉 Kotlin 或 Java 程式設計語言,並且也很清楚 Android 資源載入XML 中的使用者介面元素宣告活動生命週期等開發考量,以及國際化和本地化的一般原則。

建議您使用 Android 資源架構,盡可能區分應用程式的本地化功能與核心應用程式功能:

  • 您可以依照本主題和「提供資源」中所述,將應用程式使用者介面的大部分或全部「內容」放入資源檔案。
  • 另一方面,使用者介面的「行為」是由 Kotlin 或 Java 程式碼驅動。舉例來說,如果使用者輸入的資料必須依語言代碼而有不同的格式設定或排序,那麼您就必須使用 Kotlin 或 Java 程式設計語言,透過程式處理資料。本主題內容不包括如何本地化以 Kotlin 或 Java 為基礎的程式碼。

如需本地化應用程式字串的簡易指南,請參閱「支援不同的語言」。

總覽:Android 中的資源切換

資源是文字字串、版面配置、音效、圖形,以及 Android 應用程式所需的任何其他靜態資料。應用程式可以包含多組資源,每組資源都針對不同的裝置設定自訂。當使用者執行應用程式時,Android 會自動選取並載入與裝置最相符的資源。

本主題著重於本地化和語言代碼。如需資源切換和所有可以指定的設定類型 (螢幕方向、觸控螢幕類型等) 完整說明,請參閱「提供額外資源」。

編寫應用程式時,您可建立應用程式要使用的預設和額外資源。當使用者執行應用程式時,Android 系統會根據裝置的語言代碼選取要載入的資源。如要建立資源,請將檔案放在專案 res/ 目錄的專屬名稱子目錄中。

預設資源的重要性

只要應用程式使用的語言代碼不是您提供的語言代碼特定文字,Android 就會從 res/values/strings.xml 載入預設字串。如果缺少這個預設檔案,或是缺少應用程式所需的字串,應用程式就不會執行,而且會顯示錯誤。以下範例說明預設文字檔案不完整時可能發生的情況。

範例:

應用程式以 Kotlin 或 Java 為基礎的程式碼指的是只有兩個字串:text_atext_b。此應用程式包含本地化資源檔案 (res/values-en/strings.xml),會以英文定義 text_atext_b。此應用程式也包含預設的資源檔案 (res/values/strings.xml),其中包含 text_a 的定義,但不適用於 text_b

  • 當此應用程式在語言代碼設為英文的裝置中啟動時,應用程式也許可以正常執行,而這是因為 res/values-en/strings.xml 同時包含所需的文字字串。
  • 但是,在設定使用非英文的裝置中啟動該應用程式時,系統就會向使用者顯示錯誤訊息和「強制關閉」按鈕。應用程式也不會載入。

為了避免發生這種情況,請確認 res/values/strings.xml 檔案確實存在,並定義每個必要的字串。這種情況適用於所有類型的資源,並非只有字串:您必須建立一組預設資源檔案,其中包含應用程式呼叫的所有資源 (版面配置、可繪項目、動畫等等)。如要進一步瞭解測試,請參閱「測試預設資源」。

使用資源進行本地化

如何建立預設資源

將應用程式的預設文字放入 res/values/strings.xml

res/values/strings.xml 中的文字字串應使用預設語言,也就是您預期大部分應用程式使用者使用的語言。

預設資源集也必須包含所有預設可繪項目和版面配置,而且可納入其他類型的資源 (例如動畫):

  • res/drawable/ (必要目錄,至少要包含一個圖片檔讓應用程式在 Google Play 顯示圖示)
  • res/layout/ (必要目錄,需包含定義預設版面配置的 XML 檔案)
  • res/anim/ (如有任何 res/anim-<qualifiers> 資料夾,則為必要目錄)
  • res/xml/ (如有任何 res/xml-<qualifiers> 資料夾,則為必要目錄)
  • res/raw/ (如有任何 res/raw-<qualifiers> 資料夾,則為必要目錄)

提示:在程式碼中檢查各個 Android 資源的參照。確認每個資源都已定義預設資源。此外,請確認預設字串檔案完整:「本地化」字串檔案可以僅包含部分字串,但「預設」字串檔案必須包含全部。

如何建立額外資源

本地化應用程式時,絕大多數都是為其他語言提供替代文字。在某些情況下,您也必須提供替代圖形、音效、版面配置和其他語言代碼特定資源。

應用程式可以指定多個 res/<qualifiers>/ 目錄,每個都有不同的限定詞。如要建立不同語言代碼的額外資源,請使用指定語言或語言地區組合的限定詞。資源目錄的名稱必須符合「提供額外資源」中所述的命名配置,否則應用程式無法編譯。

範例:

假設應用程式的預設語言為英文。假設您也想將應用程式中的所有文字翻譯成法文,並將應用程式中的大部分文字 (應用程式名稱除外) 翻譯成日文。在此情況下,您可以建立三個額外的 strings.xml 檔案,每個檔案都儲存在特定語言代碼的資源目錄中:

  1. res/values/strings.xml
    包含應用程式使用的所有字串英文文字,包括名稱為 title 的字串文字。
  2. res/values-fr/strings.xml
    包含所有字串的法文文字,包括 title
  3. res/values-ja/strings.xml
    包含所有字串的日文文字,title「除外」。

如果以 Kotlin 或 Java 為基礎的程式碼參照 R.string.title,則執行階段會發生以下情況:

  • 如果裝置設定使用的語言不是法文,Android 就會從 res/values/strings.xml 檔案載入 title
  • 如果裝置設定使用的語言是法文,Android 會從 res/values-fr/strings.xml 檔案載入 title

請注意,如果裝置設定使用的語言是日文,Android 會在 res/values-ja/strings.xml 檔案中尋找 title。不過,由於該檔案不包含此類字串,Android 會改回使用預設設定,並從 res/values/strings.xml 檔案以英文載入 title

哪些資源的優先順序最高?

如果有多個資源檔案符合裝置的設定,Android 會根據一組規則來決定要使用的檔案。在可於資源目錄名稱中指定的限定詞中,語言代碼幾乎總是會優先處理

範例:

假設應用程式包含一組預設的圖形和另外兩組圖形,每組都根據不同的裝置設定最佳化:

  • res/drawable/
    包含預設圖形。
  • res/drawable-small-land-stylus/
    包含為預期使用觸控筆輸入,且有橫向 QVGA 低密度螢幕的裝置使用而最佳化的圖形。
  • res/drawable-ja/
    包含為日文使用最佳化的圖形。

如果應用程式在設定為使用日文的裝置中執行,即使裝置是預期會使用觸控筆輸入,且有橫向 QVGA 低密度螢幕,Android 都會從 res/drawable-ja/ 載入圖形。

例外:在選取過程中,唯一優先順序超過語言代碼的限定詞是 MCC 和 MNC (行動裝置國家/地區代碼和行動網路識別碼)。

範例:

假設您遇到下列情況:

  • 應用程式程式碼呼叫 R.string.text_a
  • 您有兩個相關的資源檔案可用:
    • res/values-mcc404/strings.xml,其中包含應用程式預設語言的 text_a,本例則為英文。
    • res/values-hi/strings.xml,包含印度文的 text_a
  • 應用程式在有下列設定的裝置中執行:
    • SIM 卡已連上印度的行動網路 (MCC 404)。
    • 語言已設為印度文 (hi)。

即使裝置設定為使用印度文,Android 也會從 res/values-mcc404/strings.xml 載入 text_a (英文)。這是因為在資源選取過程中,Android 會優先使用 MCC 比對,而非語言比對。

如上述範例所示,選取程序並不容易。如需更精細的程序說明,請參閱「Android 如何尋找最相符的資源」。所有限定詞都會按照提供額外資源表 2 中的優先順序說明和列出。

參照程式碼中的資源

在應用程式以 Kotlin 或 Java 為基礎的程式碼中,您可以使用語法 R.resource_type.resource_nameandroid.R.resource_type.resource_name 來參照資源。詳情請參閱「存取資源」。

管理本地化字串

將所有字串移至 strings.xml

建構應用程式時,請勿使用任何硬式編碼字串,請在預設的 strings.xml 檔案中將「所有」字串宣告為資源,讓更新及本地化更容易進行。然後您就可以輕鬆地擷取和翻譯 strings.xml 檔案中的字串,也可以將這些字串反向整合至應用程式中 (使用合適的限定詞),而不需任何編譯程式碼的變更。

如果使用文字產生圖片,您也要將這些字串放入 strings.xml,然後在翻譯後重新產生圖片。

遵循 Android 的 UI 字串指南

設計和開發 UI 時,請務必留意您對使用者說明的方式。一般來說,請以簡潔扼要的方式提供簡短易懂的說明,並維持所有使用者介面的風格一致。

請務必詳閱並遵循質感設計針對行文方式和用詞提供的建議,這可讓您為使用者呈現設計更完善的應用程式,並讓使用者更快瞭解如何使用您的使用者介面。

除此之外,請儘量使用 Android 標準術語,例如使用者介面元素使用「動作列」、「選項選單」、「系統列」、「通知」等名稱。正確使用 Android 術語並保持一致,可以讓翻譯作業更容易進行,進而為使用者提供更好的產品使用體驗。

為宣告的字串提供足夠的結構定義

strings.xml 檔案中宣告字串時,請務必一併說明字串的結構定義。這些資訊對於翻譯人員非常重要,也可以帶來更好的翻譯品質。此外,還能協助您以更有效率的方式管理字串。

範例如下:

<!-- The action for submitting a form. This text is on a button that can fit 30 chars -->
<string name="login_submit_button">Sign in</string>

考慮提供的結構定義資訊可能包括:

  • 這個字串的作用是什麼?向使用者顯示的時機及位置為何?
  • 這會在版面配置的何處顯示?舉例來說,文字方塊的翻譯會比按鈕翻譯更靈活。

標記不需翻譯的訊息部分

字串中通常包含不應翻譯成其他語言的文字。常見的範例包括程式碼的片段、某個值的預留位置、特殊符號或名稱。在準備要翻譯的字串時,請找出並標示不應翻譯的文字,這樣翻譯人員才不會變更內容。

如要標示不應翻譯的文字,請使用 <xliff:g> 預留位置標記。以下是可確保文字「%1$s」不會在翻譯期間變更 (否則可能導致訊息顯示不完整) 的標記範例:

<string name="countdown">
  <xliff:g id="time" example="5 days">%1$s</xliff:g> until holiday
</string>

宣告預留位置標記時,請務必加入 ID 屬性,說明預留位置的作用。如果應用程式會取代預留位置的值,請務必提供範例屬性,說明預計用途。

以下是其他預留位置標記的範例:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Example placeholder for a special unicode symbol -->
<string name="star_rating">Check out our 5
    <xliff:g id="star">\u2605</xliff:g>
</string>
<!-- Example placeholder for a URL -->
<string name="app_homeurl">
    Visit us at <xliff:g
    id="application_homepage">http://my/app/home.html</xliff:g>
</string>
<!-- Example placeholder for a name -->
<string name="prod_name">
    Learn more at <xliff:g id="prod_gamegroup">Game Group</xliff:g>
</string>
<!-- Example placeholder for a literal -->
<string name="promo_message">
    Please use the "<xliff:g id="promotion_code">ABCDEFG</xliff:g>" to get a discount.
</string>
...
</resources>

本地化檢查清單

如需本地化和發布 Android 應用程式的完整程序總覽,請參閱「本地化檢查清單」文件。

本地化提示

以任何語言代碼都可使用的方式設計應用程式

我們無法確認使用者執行應用程式時會使用的裝置。裝置可能會有超出我們預期的硬體,或是可能會設定為使用您並未規劃使用或無法測試的語言代碼。設計應用程式時,要讓應用程式能夠在不論於哪一種裝置中執行都可以正常運作,或是以不令人反感的方式結束運作。

重要:請確認您的應用程式包含完整的預設資源。

請務必加入 res/drawable/res/values/ 資料夾 (資料夾名稱不含其他修飾詞),包含應用程式所需的所有圖片和文字。

如果應用程式缺少一個預設資源,該應用程式就無法在設定使用不支援的語言代碼的裝置中執行。舉例來說,res/values/strings.xml 預設檔案可能缺少應用程式所需的一個字串:如果應用程式在不支援的語言代碼中執行,並嘗試載入 res/values/strings.xml,使用者就會看到錯誤訊息和強制關閉按鈕。

詳情請參閱「測試預設資源」。

設計靈活的版面配置

如果您需要依照特定語言重新安排版面配置 (例如:德文),您可以針對該語言建立額外的版面配置 (例如:res/layout-de/main.xml)。但是,這樣做可能會導致應用程式更難以維護。建議您建立更有彈性的單一版面配置。

另一個常見情況是語言需要不同的版面配置。舉例來說,您可能有一個聯絡表單,其中應包含應用程式以日文執行時的兩個名稱欄位,但如果應用程式以其他語言執行則需要三個名稱欄位。有兩種方式可以協助您處理這種情況:

  • 根據語言使用您可以透過程式啟用或停用欄位的版面配置,或
  • 讓主要版面配置包含另一個包含可變更欄位的版面配置。第二種版面配置可針對不同語言有不同的設定。

避免建立過多不必要的資源檔案和文字字串

您也許不必為應用程式中的每個資源建立語言代碼特定的額外資源。舉例來說,res/layout/main.xml 檔案中定義的版面配置可能適用於任何語言代碼,因此您不需要建立任何額外的版面配置檔案。

此外,您可能不需要為每個字串建立額外文字。舉例來說,假設:

  • 應用程式的預設語言為美式英文。應用程式使用的每一個字串,都會在 res/values/strings.xml 中定義,並使用美式英文拼字。
  • 對於少數重要的詞組,您想要提供英式英文拼字。您希望在英國的裝置中執行應用程式時,可以使用這些額外字串。

為此,您可以建立一個名為 res/values-en-rGB/strings.xml 的小檔案,其中僅包含當應用程式在英國執行時會使用的不同字串。至於所有其他字串,應用程式會返回至預設設定,並使用 res/values/strings.xml 中定義的資源。

使用 Android Context 物件進行手動語言代碼查詢

您可以使用 Android 提供的 Context 物件查詢語言代碼:

Kotlin

val primaryLocale: Locale = context.resources.configuration.locales[0]
val locale: String = primaryLocale.displayName

Java

Locale primaryLocale = context.getResources().getConfiguration().getLocales().get(0);
String locale = primaryLocale.getDisplayName();

使用應用程式翻譯服務

應用程式翻譯服務已整合至 Play 管理中心,您也可以透過 Android Studio 存取。此服務可以讓您以迅速又輕鬆的方式取得即時報價,並向翻譯公司下訂單。您可以訂購下列一或多種語言的應用程式翻譯:應用程式 UI 字串、Play 商店資訊文字、IAP 名稱和廣告活動文字。

測試本地化應用程式

在裝置中測試

請注意,您要測試的裝置可能與其他地區消費者所用的裝置有很大的差異。您的裝置裝置提供的語言代碼可能與其他裝置不同。此外,裝置螢幕的解析度和密度可能也會不同,並且可能會影響 UI 中的字串和可繪項目顯示方式。

如要變更裝置的語言代碼或語言,請使用「設定」應用程式。

在模擬器中測試

如要進一步瞭解如何使用模擬器,請參閱 Android Emulator

建立及使用自訂語言代碼

「自訂」語言代碼是 Android 系統映像檔未明確支援的語言/地區組合。您可以在模擬器中建立自訂語言代碼,測試應用程式在自訂語言代碼中的執行方式。有兩種方式可以協助您測試:

  • 使用可從應用程式分頁存取的自訂語言代碼應用程式 (建立自訂語言代碼後,按住語言代碼名稱即可切換使用)。
  • 從 ADB 殼層變更為自訂語言代碼,如下所述。

當您將模擬器設定為 Android 系統映像檔中沒有提供的語言代碼時,系統自身就會以其預設語言顯示。不過,您的應用程式應會正確地本地化。

從 ADB 殼層變更模擬器語言代碼

使用 ADB 殼層變更模擬器中的語言代碼。

  1. 選擇要測試的語言代碼,然後判斷其 BCP-47 語言標記,舉例來說,加拿大法文是 fr-CA
  2. 啟動模擬器。
  3. 在主機電腦的指令列殼層中執行下列指令:
    adb shell
    如果裝置已連接,請加入 -e 選項以指定您要使用模擬器:
    adb -e shell
  4. 在 ADB 殼層通知 (#) 中,執行此指令:
    setprop persist.sys.locale [BCP-47 language tag];stop;sleep 5;start
    將括號括住的部分替換為步驟 1 中的適當程式碼。

例如,要測試加拿大法文:

setprop persist.sys.locale fr-CA;stop;sleep 5;start

這會導致模擬器重新啟動。當主畫面再次顯示時,重新啟動應用程式,然後您就會注意到應用程式是以新的語言代碼啟動。

測試預設資源

以下說明如何測試應用程式是否包含其所需的每個字串資源:

  1. 將模擬器或裝置設定為使用應用程式不支援的語言。舉例來說,如果 res/values-fr/ 中的應用程式有法文字串,但在 res/values-es/ 中沒有西班牙文字串,就將模擬器的語言代碼會設為西班牙文。您可以使用自訂語言代碼應用程式,將模擬器設為不支援的語言代碼。
  2. 執行應用程式。
  3. 如果應用程式顯示錯誤訊息和「強制關閉」按鈕,就表示應用程式可能在尋找無法使用的字串。請確認 res/values/strings.xml 檔案包含應用程式使用的所有字串定義。

如果測試成功,請為其他設定類型重複進行測試。舉例來說,如果應用程式有一個名稱為 res/layout-land/main.xml 的版面配置檔案,但沒有名稱為 res/layout-port/main.xml 的檔案,請將模擬器或裝置設為直向,然後查看應用程式是否能夠執行。