在許多情況下,多語言使用者會將系統語言設為某種語言 (例如英文),卻想在特定應用程式中選擇使用其他語言,例如荷蘭文、中文或北印度文。為了讓這類使用者在應用程式中享有更優質的體驗,Android 13 針對支援多種語言的應用程式推出下列功能:
系統設定:集中管理各項設定的頁面,使用者可在此為各應用程式選取偏好的語言。
您可以設定應用程式,自動產生支援個別應用程式語言偏好所需的檔案,並顯示在系統設定中。詳情請參閱啟用自動支援個別應用程式語言功能的操作說明。
其他 API:利用這類公用 API (例如
LocaleManager
中的setApplicationLocales()
和getApplicationLocales()
方法),應用程式可在執行階段設定與系統語言不同的語言。這些 API 會自動與系統設定保持同步;因此,使用這些 API 建立自訂應用程式內語言選單的應用程式,無論使用者選擇的語言偏好設定為何,都能為使用者提供一致的使用者體驗。此外,公用 API 也有助於減少樣板程式碼的數量,可支援分割 APK,並支援應用程式自動備份功能,儲存應用程式層級的使用者語言設定。
為了提供與 Android 舊版本的回溯相容性,AndroidX 中也提供同等的 API。但若是 Android 12 (API 級別 32) 以下版本,回溯相容的 API 是與 AppCompatActivity 結構定義搭配運作,而非應用程式結構定義。請使用 Appcompat 1.6.0 以上版本存取回溯相容的 API。
功能實作方式總覽
下表根據不同用途提供建議的實作方式。
用途 | 建議實作方式 |
---|---|
應用程式未提供應用程式內語言選單 |
|
應用程式已提供應用程式內語言選單 |
|
使用者的系統設定
從 Android 13 開始,Android 針對個別應用程式語言偏好,在系統設定中加入集中管理這類設定的頁面。為確保在搭載 Android 13 以上版本的裝置上,可透過系統設定指定應用程式語言,請啟用自動支援個別應用程式語言功能 (建議做法) 或手動設定支援功能。
啟用自動支援個別應用程式語言功能
從 Android Studio Giraffe 和 AGP 8.1 開始,您可以將應用程式設為自動支援個別應用程式語言偏好。AGP 會根據專案資源產生 LocaleConfig
檔案,並在最終資訊清單檔案中加入該檔案的參照,為您省去手動操作的麻煩。AGP 會使用應用程式模組 res
資料夾中的資源和任何程式庫模組依附元件,決定要加入 LocaleConfig
檔案的語言代碼。也就是說,如果要在應用程式中加入新的語言資源,不必擔心如何更新 LocaleConfig
檔案。
請注意,自動個別應用程式語言功能支援在 Android 13 (API 級別 33) 以上版本中執行的應用程式。如要使用這項功能,必須將 compileSdkVersion
設為 33 以上。如要為先前的 Android 版本設定個別應用程式語言偏好,還是需要使用 API 和應用程式內語言選單。
如要啟用自動支援個別應用程式語言功能,請按照下列步驟操作:
- 如要開啟這項功能,請在模組層級
build.gradle.kts
檔案 (若使用 Groovy 則為build.gradle
檔案) 的androidResources {}
區塊中使用generateLocaleConfig
設定。這項功能預設為關閉。Kotlin
android { androidResources { generateLocaleConfig = true } }
Groovy
android { androidResources { generateLocaleConfig true } }
- 指定預設語言代碼:
- 在應用程式模組的
res
資料夾中,建立名為resources.properties
的新檔案。 在
resources.properties
檔案中,使用unqualifiedResLocale
標籤設定預設語言代碼。如要設定語言代碼名稱的格式,請參閱「如何設定語言代碼名稱格式」一節。
- 在應用程式模組的
AGP 會使用 res
資料夾中的 values-*
目錄,將這個預設語言代碼和所有指定替代語言代碼加進自動產生的 LocaleConfig
檔案。
如何設定語言代碼名稱格式
如要設定語言代碼名稱的格式,請將語言代碼與選用的指令碼和區碼結合,並以連字號分隔。
- 語言:使用二或三個字母的 ISO 639-1 代碼。
- 指令碼 (選用):使用 ISO 15924 代碼。
- 地區 (選用):使用兩個字母的 ISO 3166-1-alpha-2 代碼或三位數的 UN_M.49 代碼。
舉例來說,假設預設語言代碼是美式英文:
unqualifiedResLocale=en-US
使用 android:localeConfig
在系統設定中新增支援的語言
您可以手動設定應用程式,確保在搭載 Android 13 以上版本的裝置上,可透過系統設定指定應用程式語言。方法是建立 locales_config
XML 檔案,並使用 android:localeConfig
屬性將該檔案加入應用程式資訊清單。如果省略 android:localeConfig
資訊清單項目,表示使用者無法在系統設定中,為應用程式設定與系統語言不同的語言。
如何在使用者的系統設定中手動新增應用程式支援的語言:
建立名為
res/xml/locales_config.xml
的檔案,並指定應用程式的語言,其中包括應用程式的最終備用語言代碼,也就是res/values/strings.xml
中指定的語言代碼。如要瞭解格式規定,請參閱「如何設定語言代碼名稱格式」一節。 如需最常用的語言代碼清單,另請參閱
locale_config.xml
範例檔案。例如,假設應用程式支援下列語言,則
locales_config.xml
檔案應採用如下格式:- 英文 (美國) 做為最終備用語言代碼
- 英文 (英國)
- 法文
- 日文
- 中文 (簡體、澳門)
- 中文 (繁體、澳門)
<?xml version="1.0" encoding="utf-8"?> <locale-config xmlns:android="http://schemas.android.com/apk/res/android"> <locale android:name="en-US"/> <locale android:name="en-GB"/> <locale android:name="fr"/> <locale android:name="ja"/> <locale android:name="zh-Hans-MO"/> <locale android:name="zh-Hant-MO"/> </locale-config>
在資訊清單中新增一行,指向這個新檔案:
<manifest> ... <application ... android:localeConfig="@xml/locales_config"> </application> </manifest>
您可以透過以下項目,動態更新應用程式的 localeConfig
:
LocaleManager.setOverrideLocaleConfig
:自訂語言組合
。這樣一來,
依區域自訂語言清單、執行 A/B 實驗,並更新
是否使用伺服器端本地化推送 (如
範例:
Kotlin
//For setOverrideLocaleConfig val localeManager = applicationContext .getSystemService(LocaleManager::class.java) localeManager.overrideLocaleConfig = LocaleConfig( LocaleList.forLanguageTags("en-US,ja-JP,zh-Hans-SG") ) //For getOverrideLocaleConfig // The app calls the API to get the override LocaleConfig val overrideLocaleConfig = localeManager.overrideLocaleConfig // If the returned overrideLocaleConfig isn't equal to NULL, then the app calls the API to get the supported Locales val supportedLocales = overrideLocaleConfig.supportedLocales()
Java
//For setOverrideLocaleConfig mContext.getSystemService(LocaleManager.class).setOverrideLocaleConfig(new LocaleConfig(LocaleList.forLanguageTags("en-US,ja-JP,zh-Hans-SG"))); //For getOverrideLocaleConfig // The app calls the API to get the override LocaleConfig LocaleConfig overrideLocaleConfig = mContext.getSystemService(LocaleManager.class).getOverrideLocaleConfig(); // If the returned overrideLocaleConfig isn't equal to NULL, then the app calls the API to get the supported Locales LocaleList supportedLocales = overrideLocaleConfig.getSupportedLocales();
此外,IME 現在可以
LocaleManager.getApplicationLocales
敬上
您就能得知目前應用程式的 UI 語言,更新鍵盤語言
顯示:
Kotlin
val currentAppLocales: LocaleList = applicationContext.getSystemService(LocaleManager::class.java).getApplicationLocales(appPackageName)
Java
LocaleList currentAppLocales = mContext.getSystemService(LocaleManager.class).getApplicationLocales(appPackageName);
在 Gradle 中指定支援的語言
如果您還沒有在應用程式模組層級的 build.gradle
檔案中提供 resourceConfigurations
屬性,請使用該屬性指定相同的語言:
android {
...
defaultConfig {
resourceConfigurations += ["en", "en-rGB", "fr", "ja", "b+zh+Hans+MO", "b+zh+Hant+MO"]
}
}
如果已提供 resourceConfigurations
屬性,建構系統僅會將這些指定語言的語言資源納入 APK,以防止納入其他程式庫支援但您的應用程式不支援的語言翻譯字串。詳情請參閱指定應用程式支援的語言相關說明。
使用者如何在系統設定中選取應用程式語言
使用者可以透過系統設定,為各個應用程式選取偏好的語言。他們可以透過兩種方法存取這些設定:
透過「系統」設定
依序點選「設定」>「系統」>「語言與輸入設定」>「應用程式語言」> (選取所需應用程式)
透過「應用程式」設定
依序點選「設定」>「應用程式」> (選取所需應用程式) >「語言」
處理應用程式內語言選單
若應用程式已有應用程式內語言選單,或是想要使用如此的語言選單,請使用公用 API 來處理設定 (不要自訂應用程式邏輯) 和為您的應用程式取得使用者的偏好語言。如果您的應用程式內語言選單使用了公用 API,則裝置的系統設定會自動更新,以符合使用者透過應用程式內體驗選擇的任何語言。
為了提供與 Android 舊版本的回溯相容性,我們強烈建議在實作應用程式內語言選單時使用 AndroidX 支援資料庫。不過,您也可以視需要直接實作架構 API。
使用 AndroidX 支援資料庫的實作方式
在 Appcompat 1.6.0 以上版本中,請使用 setApplicationLocales()
和 getApplicationLocales()
方法。請注意,若是 Android 12 (API 級別 32) 以下版本,回溯相容的 API 是與 AppCompatActivity 結構定義搭配運作,而非應用程式結構定義。
舉例來說,如要設定使用者偏好的語言,您可以要求使用者在語言選單中選取所需語言代碼,然後在系統中設定該值:
Kotlin
val appLocale: LocaleListCompat = LocaleListCompat.forLanguageTags("xx-YY") // Call this on the main thread as it may require Activity.restart() AppCompatDelegate.setApplicationLocales(appLocale)
Java
LocaleListCompat appLocale = LocaleListCompat.forLanguageTags("xx-YY"); // Call this on the main thread as it may require Activity.restart() AppCompatDelegate.setApplicationLocales(appLocale);
請注意,除非應用程式會自行處理語言代碼設定變更,否則呼叫 setApplicationLocales()
會導致重建 Activity
。
使用 AppCompatDelegate.getApplicationLocales()
擷取使用者偏好的語言代碼。使用者可能已從系統設定或應用程式內語言選單中選取了想要的應用程式語言代碼。
支援 Android 12 以下版本
如要支援搭載 Android 12 (API 級別 32) 以下版本的裝置,請在應用程式的 AppLocalesMetadataHolderService
服務資訊清單項目中,將 autoStoreLocales
值設為 true
,並將 android:enabled
設為 false
,指示 AndroidX 處理語言代碼儲存空間,如以下程式碼片段所示:
<application
...
<service
android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"
android:enabled="false"
android:exported="false">
<meta-data
android:name="autoStoreLocales"
android:value="true" />
</service>
...
</application>
請注意,將 autoStoreLocales
值設為 true
會導致主執行緒發生封阻式讀取情形,而如果您正在記錄執行緒違規事件,則可能造成 StrictMode
diskRead
和 diskWrite
違規事件。詳情請參閱 AppCompatDelegate.setApplicationLocales()
相關說明。
處理自訂儲存空間
省略資訊清單項目或將 autoStoreLocales
設為 false
信號,即可自行處理儲存空間。在此情況下,您必須在活動生命週期的 onCreate
之前,以及在 Android 12 (API 級別 32) 以下版本中發出 AppCompatDelegate.setApplicationLocales()
入口呼叫之前,提供已儲存的語言代碼。
如果應用程式有自訂語言代碼儲存位置,建議您在自訂語言代碼儲存空間解決方案與 autoStoreLocales
之間進行一次性交遞,讓使用者能繼續以自己偏好的語言享用您的應用程式。如果裝置是在升級至 Android 13 後首次執行該應用程式,就特別適合使用這種做法。在此情況下,您可以從自訂儲存空間擷取語言代碼,並將語言代碼傳入 AppCompatDelegate.setApplicationLocales()
,藉此提供使用者所要求的既有語言代碼。
使用 Android 架構 API 的實作方式
雖然我們強烈建議使用 AndroidX 支援資料庫實作應用程式內語言選單,您還是可以針對搭載 Android 13 的裝置使用 Android 架構中的 setApplicationLocales()
和 getApplicationLocales()
方法。
舉例來說,如要設定使用者偏好的語言,您可以要求使用者在語言選單中選取所需語言代碼,然後在系統中設定該值:
// 1. Inside an activity, in-app language picker gets an input locale "xx-YY"
// 2. App calls the API to set its locale
mContext.getSystemService(LocaleManager.class
).setApplicationLocales(new LocaleList(Locale.forLanguageTag("xx-YY")));
// 3. The system updates the locale and restarts the app, including any configuration updates
// 4. The app is now displayed in "xx-YY" language
如要取得目前的使用者偏好語言並顯示在語言選單中,應用程式可從系統中取回這個值:
// 1. App calls the API to get the preferred locale
LocaleList currentAppLocales =
mContext.getSystemService(LocaleManager.class).getApplicationLocales();
// 2. App uses the returned LocaleList to display languages to the user
其他最佳做法
請謹記下列最佳做法。
在其他應用程式中叫用意圖時考慮語言
以語言為主的意圖或許能讓您指定叫用的應用程式要使用哪種語言。例如 Speech Recognizer API 的 EXTRA_LANGUAGE
功能。
考慮為 Chrome 自訂分頁使用 Accept-Language 標頭
建議您新增 Accept-Language 標頭
透過 Browser.EXTRA_HEADERS
叫用 Chrome 自訂分頁時,以應用程式的語言開啟網頁。
如果在系統設定中移除了個別應用程式語言偏好,請將應用程式語言代碼重設為系統語言代碼
如果您從系統設定移除應用程式的語言偏好設定,也就是從應用程式的 AndroidManifest.xml
移除 android:localeConfig
,使用者便無法輕易將應用程式語言重設為系統預設值。
因此,您移除 android:localeConfig
後,請考慮使用 LocaleListCompat.getEmptyLocaleList()
或 LocaleList.getEmptyLocaleList()
,將應用程式語言代碼重設為系統語言代碼,如下列程式碼片段所示:
Kotlin
// Use the AndroidX APIs to reset to the system locale for backward and forward compatibility AppCompatDelegate.setApplicationLocales( LocaleListCompat.getEmptyLocaleList() ) // Or use the Framework APIs for Android 13 and above to reset to the system locale val context = LocalContext.current context.getSystemService(LocaleManager::class.java) .applicationLocales = LocaleList.getEmptyLocaleList()
Java
// Use the AndroidX APIs to reset to the system locale for backward and forward compatibility AppCompatDelegate.setApplicationLocales( LocaleListCompat.getEmptyLocaleList() ); // Or use the Framework APIs for Android 13 and above to reset to the system locale mContext.getSystemService(LocaleManager.class) .setApplicationLocales(LocaleList.getEmptyLocaleList());
其他資源
如需其他資訊,請參閱程式碼範例、網誌文章和影片。
locale_config.xml 檔案範例
Android 開放原始碼計畫 (AOSP) 已預設為一組標準的最常用語言代碼提供系統層級的翻譯。本節所提供的 locale_config.xml
範例檔案逐一顯示了這些語言代碼的建議格式。您可以參考這個範例檔案,瞭解如何為應用程式支援的語言組合自行建構 locale_config.xml
檔案。
<?xml version="1.0" encoding="utf-8"?>
<locale-config xmlns:android="http://schemas.android.com/apk/res/android">
<locale android:name="af"/> <!-- Afrikaans -->
<locale android:name="am"/> <!-- Amharic -->
<locale android:name="ar"/> <!-- Arabic -->
<locale android:name="as"/> <!-- Assamese -->
<locale android:name="az"/> <!-- Azerbaijani -->
<locale android:name="be"/> <!-- Belarusian -->
<locale android:name="bg"/> <!-- Bulgarian -->
<locale android:name="bn"/> <!-- Bengali -->
<locale android:name="bs"/> <!-- Bosnian -->
<locale android:name="ca"/> <!-- Catalan -->
<locale android:name="cs"/> <!-- Czech -->
<locale android:name="da"/> <!-- Danish -->
<locale android:name="de"/> <!-- German -->
<locale android:name="el"/> <!-- Greek -->
<locale android:name="en-AU"/> <!-- English (Australia) -->
<locale android:name="en-CA"/> <!-- English (Canada) -->
<locale android:name="en-GB"/> <!-- English (United Kingdom) -->
<locale android:name="en-IN"/> <!-- English (India) -->
<locale android:name="en-US"/> <!-- English (United States) -->
<locale android:name="es"/> <!-- Spanish (Spain) -->
<locale android:name="es-US"/> <!-- Spanish (United States) -->
<locale android:name="et"/> <!-- Estonian -->
<locale android:name="eu"/> <!-- Basque -->
<locale android:name="fa"/> <!-- Farsi -->
<locale android:name="fi"/> <!-- Finnish -->
<locale android:name="fil"/> <!-- Filipino -->
<locale android:name="fr"/> <!-- French (France) -->
<locale android:name="fr-CA"/> <!-- French (Canada) -->
<locale android:name="gl"/> <!-- Galician -->
<locale android:name="gu"/> <!-- Gujarati -->
<locale android:name="hi"/> <!-- Hindi -->
<locale android:name="hr"/> <!-- Croatian -->
<locale android:name="hu"/> <!-- Hungarian -->
<locale android:name="hy"/> <!-- Armenian -->
<locale android:name="in"/> <!-- Indonesian -->
<locale android:name="is"/> <!-- Icelandic -->
<locale android:name="it"/> <!-- Italian -->
<locale android:name="iw"/> <!-- Hebrew -->
<locale android:name="ja"/> <!-- Japanese -->
<locale android:name="ka"/> <!-- Georgian -->
<locale android:name="kk"/> <!-- Kazakh -->
<locale android:name="km"/> <!-- Khmer -->
<locale android:name="kn"/> <!-- Kannada -->
<locale android:name="ko"/> <!-- Korean -->
<locale android:name="ky"/> <!-- Kyrgyz -->
<locale android:name="lo"/> <!-- Lao -->
<locale android:name="lt"/> <!-- Lithuanian -->
<locale android:name="lv"/> <!-- Latvian -->
<locale android:name="mk"/> <!-- Macedonian -->
<locale android:name="ml"/> <!-- Malayalam -->
<locale android:name="mn"/> <!-- Mongolian -->
<locale android:name="mr"/> <!-- Marathi -->
<locale android:name="ms"/> <!-- Malay -->
<locale android:name="my"/> <!-- Burmese -->
<locale android:name="nb"/> <!-- Norwegian -->
<locale android:name="ne"/> <!-- Nepali -->
<locale android:name="nl"/> <!-- Dutch -->
<locale android:name="or"/> <!-- Odia -->
<locale android:name="pa"/> <!-- Punjabi -->
<locale android:name="pl"/> <!-- Polish -->
<locale android:name="pt-BR"/> <!-- Portuguese (Brazil) -->
<locale android:name="pt-PT"/> <!-- Portuguese (Portugal) -->
<locale android:name="ro"/> <!-- Romanian -->
<locale android:name="ru"/> <!-- Russian -->
<locale android:name="si"/> <!-- Sinhala -->
<locale android:name="sk"/> <!-- Slovak -->
<locale android:name="sl"/> <!-- Slovenian -->
<locale android:name="sq"/> <!-- Albanian -->
<locale android:name="sr"/> <!-- Serbian (Cyrillic) -->
<locale android:name="sr-Latn"/> <!-- Serbian (Latin) -->
<locale android:name="sv"/> <!-- Swedish -->
<locale android:name="sw"/> <!-- Swahili -->
<locale android:name="ta"/> <!-- Tamil -->
<locale android:name="te"/> <!-- Telugu -->
<locale android:name="th"/> <!-- Thai -->
<locale android:name="tr"/> <!-- Turkish -->
<locale android:name="uk"/> <!-- Ukrainian -->
<locale android:name="ur"/> <!-- Urdu -->
<locale android:name="uz"/> <!-- Uzbek -->
<locale android:name="vi"/> <!-- Vietnamese -->
<locale android:name="zh-Hans"/> <!-- Chinese (Simplified) -->
<locale android:name="zh-Hant"/> <!-- Chinese (Traditional) -->
<locale android:name="zu"/> <!-- Zulu -->
</locale-config>