处理应用内语言选择器

处理应用内语言选择器

系统设置中的应用语言偏好

在许多情况下,多语言用户会将系统语言设置为一种语言(例如英语),但他们希望为特定应用选择其他语言,如荷兰语、中文或印地语。为了帮助应用为这些用户提供更好的体验,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。

实现该功能的概览

下表显示了针对不同使用场景推荐的实现方式。

使用场景

推荐的实现方式

您的应用没有应用内语言选择器

启用自动应用语言支持以生成 LocaleConfig 文件,并将您应用的语言添加到系统设置中。

(可选)如果您想添加应用内语言选择器:请使用 Compose 实现一个,或者使用 AndroidX 库并选择加入我们的API 实现,通过 autoStoreLocales 支持向后兼容性。

您的应用已有应用内语言选择器

启用自动应用语言支持以生成 LocaleConfig 文件,并将您应用的语言添加到系统设置中。

迁移您的自定义应用逻辑以使用 Compose 或公共 API,从而确保用户获得一致的体验。

处理以下边缘情况

在运行 Android 13 的设备上首次运行您的应用时,调用 AppCompatDelegate.setApplicationLocales。

在以下情况下,调用 AppCompatDelegate.setApplicationLocales 以向系统提供用户之前请求的语言区域 (Locale):

如果您为 Android 12(API 级别 32)及更低版本选择了加入自动存储功能

如果您的应用需要从自定义备份存储位置迁移数据

用户系统设置

从 Android 13 开始,Android 在系统设置中加入了一个中心化位置,用于设置“应用语言偏好”。为确保您的应用语言可以在运行 Android 13 或更高版本的设备上的系统设置中进行配置,请启用自动应用语言支持(推荐)或手动配置支持。

启用自动应用语言支持

这是为应用添加“应用语言偏好”支持的推荐方式,因为它不需要进行 XML 修改。

注意: 此功能不会像手动设置过程那样对您的项目进行更改。自动处理过程中的所有更改均在生成的文件中完成。例如,您不会在应用的清单文件中看到 android:localeConfig 条目,也不会看到 res/xml/locale_config.xml 文件。这是符合预期的,因为所有更改都是在应用构建时自动生成的。

从 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 文件中。

警告: 如果开启了自动应用语言支持,而您又手动创建了 LocaleConfig 文件,构建将会失败。在启用自动应用语言支持并构建应用之前,您必须删除手动创建的 LocaleConfig 文件。

如何形成语言区域名称

要形成语言区域名称,请将语言代码与可选的脚本和地区代码组合,并用连字符分隔:

语言:使用双字母或三字母的 ISO 639-2 代码。

脚本(可选):使用 ISO 15924 代码。

地区(可选):使用双字母 ISO 3166-1-alpha-2 代码或三位数字 UN_M.49 代码。

例如,如果您的默认语言区域是美式英语

unqualifiedResLocale=en-US

使用 android:localeConfig 将支持的语言添加到系统设置中

注意: 如果可能,我们建议启用自动应用语言支持,而不是手动进行配置。

您可以手动设置应用,以确保其语言可以在运行 Android 13 或更高版本的设备上的系统设置中进行配置。为此,请创建一个 locale_config XML 文件,并使用 android:localeConfig 属性将其添加到应用的清单文件中。省略 android:localeConfig 清单条目表示用户不应在系统设置中独立于系统语言来设置您的应用语言。

要将您应用支持的语言手动添加到用户的系统设置中:

创建一个名为 res/xml/locale_config.xml 的文件,并指定您应用的语言,包括您应用的最终回退语言区域(即在 res/values/strings.xml 中指定的语言区域)。

关于格式要求,请参阅如何形成语言区域名称。另请参阅示例 locale_config.xml 文件以获取最常用语言区域的列表。

例如,对于支持以下语言的应用,请这样格式化 locale_config.xml 文件:

英语(美国)作为最终回退语言区域

英语(英国)

法语

日语

中文(简体,澳门)

中文(繁体,澳门)

在清单文件中,添加一行指向此新文件:

...

...

android:localeConfig="@xml/locale_config">

您可以使用 LocaleManager.setOverrideLocaleConfig 动态更新应用的 localeConfig,从而自定义 Android 设置中应用语言列表中显示的语言集。这使您能够针对每个地区自定义语言列表、运行 A/B 测试,并利用服务器端语言推送提供更新后的语言区域,如下例所示:

//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()

此外,输入法 (IME) 现在可以使用 LocaleManager.getApplicationLocales 来获知当前应用的 UI 语言,从而更新键盘语言,如下所示:

val currentAppLocales: LocaleList = applicationContext.getSystemService(LocaleManager::class.java).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,设备的系统设置会自动更新,以匹配用户通过您的应用内界面选择的语言。

使用 Jetpack Compose 实现

对于完全使用 Jetpack Compose 构建的应用,系统会在应用区域设置更改时自动处理 UI 更新。调用 API 设置新语言会触发配置变更。Compose 会通过重组 UI 并使用新语言区域自动解析任何 stringResource 调用来做出响应。

为了与 Android 12(API 级别 32)及更低版本向后兼容,我们强烈建议在实现应用内语言选择器时使用 AndroidX 支持库 (AppCompatDelegate)。如果您使用这种方法,托管 Compose UI 的 Activity 必须继承自 AppCompatActivity。不过,如果您需要,也可以直接实现框架 API。

以下代码片段展示了如何在可组合函数中读取当前应用区域设置并设置新语言区域的示例:

import androidx.appcompat.app.AppCompatDelegate

import androidx.compose.material3.Button

import androidx.compose.material3.Text

import androidx.compose.runtime.Composable

import androidx.core.os.LocaleListCompat

@Composable

fun LanguageSelector() {

// Retrieve the currently configured app locale.

// If no app-specific locale is set, LocaleListCompat.get(0) returns null,

// so we safely fall back to a default (e.g., "en").

val appLocales = AppCompatDelegate.getApplicationLocales()

val currentLocaleTag = appLocales.get(0)?.toLanguageTag() ?: "en"

// Example UI: A button to toggle between English and Spanish

Button(

onClick = {

val newLanguageTag = if (currentLocaleTag == "en") "es" else "en"

val localeList = LocaleListCompat.forLanguageTags(newLanguageTag)

// Setting the locale re-creates the Activity by default,

// which automatically applies the new configuration to Compose.

AppCompatDelegate.setApplicationLocales(localeList)

}

) {

Text(

text = if (currentLocaleTag == "en") "Switch to Spanish" else "Switch to English"

)

}

}

警告: 如果您在 Compose 中使用 setApplicationLocales,则必须让您的 Activity 继承自 AppCompatActivity。否则,设置应用语言将无法生效。

要设置用户的首选语言,您可以让用户在语言选择器中选择一个语言区域,然后将该值设置到系统中:

val appLocale: LocaleListCompat = 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 处理语言区域存储,如下面的代码片段所示:

...

android:name="androidx.appcompat.app.AppLocalesMetadataHolderService"

android:enabled="false"

android:exported="false">

android:name="autoStoreLocales"

android:value="true" />

...

请注意,将 autoStoreLocales 设置为 true 会导致主线程上的阻塞读取,如果您正在记录线程违规,则可能会导致 StrictMode diskRead 和 diskWrite 违规。有关更多信息,请参阅 AppCompatDelegate.setApplicationLocales。

自定义存储处理

省略清单条目或将 autoStoreLocales 设置为 false 表示您正在自行处理存储。在这种情况下,您必须在 Activity 生命周期的 onCreate 之前提供存储的语言区域,并在 Android 12(API 级别 32)或更低版本中对 AppCompatDelegate.setApplicationLocales 的调用进行限制。

如果您的应用具有自定义语言区域存储位置,我们建议在您的自定义存储解决方案和 autoStoreLocales 之间进行一次性切换,以便用户继续以其偏好的语言使用您的应用。这特别适用于设备升级到 Android 13 后首次运行应用的情况。在这种情况下,您可以通过从自定义存储中检索语言区域并将它们传递给 AppCompatDelegate.setApplicationLocales 来提供用户之前请求的语言区域。

使用 Android 框架 API 实现

虽然我们强烈建议您使用 AndroidX 支持库来实现应用内语言选择器,但您也可以在运行 Android 13 的设备上使用 Android 框架中的 setApplicationLocales 和 getApplicationLocales 方法。

以下代码片段展示了如何使用 LocaleManager 系统服务设置和获取用户的首选语言:

import android.app.LocaleManager

import android.content.Context

import android.os.Build

import android.os.LocaleList

import androidx.annotation.RequiresApi

import java.util.Locale

@RequiresApi(Build.VERSION_CODES.TIRAMISU)

fun setAppLanguage(context: Context, languageTag: String) {

// 1. Retrieve the system service

val localeManager = context.getSystemService(LocaleManager::class.java)

// 2. Create a LocaleList from the language tag (e.g., "es-ES" or "ja")

val localeList = LocaleList(Locale.forLanguageTag(languageTag))

// 3. Set the locale. The system automatically updates the locale and

// restarts the app, including any necessary configuration updates.

localeManager.applicationLocales = localeList

}

@RequiresApi(Build.VERSION_CODES.TIRAMISU)

fun getAppLanguage(context: Context): String {

val localeManager = context.getSystemService(LocaleManager::class.java)

val currentLocales = localeManager.applicationLocales

// Return the primary app locale, or fall back to the system default

return if (!currentLocales.isEmpty) {

currentLocales.get(0).toLanguageTag()

} else {

Locale.getDefault().toLanguageTag()

}

}

其他最佳实践

请注意以下最佳实践:

在调用其他应用的 Intent 时考虑语言因素

以语言为中心的 Intent 可能允许您指定希望被调用的应用使用的语言。一个例子是来自语音识别 API 的 EXTRA_LANGUAGE 功能。

考虑为 Chrome 自定义标签页使用 Accept-Language 标头

考虑通过 Browser.EXTRA_HEADERS 添加 Accept-Language 标头,以便在调用 Chrome 自定义标签页时以应用语言打开网页。

如果您在系统设置中删除了应用语言偏好设置,请将应用语言区域重置为系统区域设置

如果您从系统设置中删除了应用的语言偏好设置(通过从应用的 AndroidManifest.xml 中删除 android:localeConfig),用户将无法轻松地将应用语言重置回系统默认值。

因此,如果您删除了 android:localeConfig,请考虑使用 LocaleListCompat.getEmptyLocaleList 或 LocaleList.getEmptyLocaleList 将应用语言区域重置为系统区域设置,如下面的代码片段所示:

// 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()

示例 locale_config.xml 文件

默认情况下,Android 在 Android 开源项目 (AOSP) 中包含了一组最常用语言区域的标准系统级翻译。本节中包含的示例 locale_config.xml 文件显示了这些语言区域中每一个的建议格式。参考此示例文件,帮助您为您应用支持的语言集构建自己的 locale_config.xml 文件。

其他资源

请参阅我们的代码示例、博客文章和视频以获取更多信息。

应用语言偏好设置第 1 部分 博客

应用语言偏好设置第 2 部分 博客

构建面向多语言世界应用 视频

Compose 中的资源

相关推荐

好玩的格斗类手游有哪些 热门格斗类手游推荐
365名品汇推荐码多少

好玩的格斗类手游有哪些 热门格斗类手游推荐

📅 10-06 👍 60
5个神仙级沙雕动画制作工具推荐,拿走不谢!
best365官网投注链接

5个神仙级沙雕动画制作工具推荐,拿走不谢!

📅 12-20 👍 217
共享单车哪个好骑成都之争:多款品牌体验评测 • 本地金