语言和区域设置解析概览

从 Android 7.0(API 级别 24)开始,Android 为多语言用户提供了增强支持,允许他们在设置中选择多个区域设置。Android 通过大幅扩展支持的区域设置数量并改变系统解析资源的方式来提供此功能。

本文档首先解释 Android 7.0(API 级别 24)以下版本中的资源解析策略。接着,它描述了 Android 7.0 中改进的资源解析策略。最后,它解释了如何利用扩展的区域设置数量来支持更多多语言用户。

解析语言资源面临的挑战

在 Android 7.0 之前,Android 无法总是成功匹配应用和系统区域设置。

例如,假设您遇到以下情况:

  • 您的应用的默认语言是 en_US(美式英语),并且在 es_ES 资源文件中也有西班牙语字符串。
  • 设备设置为 es_MX

当您的 Java 代码引用字符串时,系统会从默认(en_US)资源文件加载字符串,即使应用在 es_ES 下有本地化的西班牙语资源。这是因为当系统找不到完全匹配时,它会通过去除区域设置中的国家/地区代码来继续查找资源。最后,如果找不到匹配项,系统会回退到默认设置,即 en_US

如果用户选择应用完全不支持的语言(如法语),系统也会默认为 en_US。例如:

表 1. 没有精确区域设置匹配时的资源解析。

用户设置 应用资源 资源解析
fr_CH 默认 (en)
de_DE
es_ES
fr_FR
it_IT
尝试 fr_CH => 失败
尝试 fr => 失败
使用默认 (en)

在此示例中,系统显示英语字符串,而不知道用户是否能理解英语。这种行为在当今相当常见。

资源解析策略的改进

Android 7.0(API 级别 24)带来了更强大的资源解析功能,并自动找到更好的回退方案。但是,为了加快解析速度和提高可维护性,您应该将资源存储在最常见的父级方言中。例如,如果您以前将西班牙语资源存储在 values-es-rUS 目录中,请将其移动到 values-b+es+419 目录中,该目录包含拉丁美洲西班牙语。同样,如果您的资源字符串位于名为 values-en-rGB 的目录中,请将该目录重命名为 values-b+en+001(国际英语),因为 en-GB 字符串最常见的父级是 en-001。以下示例解释了为什么这些做法可以提高资源解析的性能和可靠性。

资源解析示例

对于 Android 7.0 及更高版本,表 1 中描述的情况会以不同方式解决:

表 2. 没有精确区域设置匹配时改进的解析策略。

用户设置 应用资源 资源解析
  1. fr_CH
默认 (en)
de_DE
es_ES
fr_FR
it_IT
尝试 fr_CH => 失败
尝试 fr => 失败
尝试 fr 的子项 => fr_FR
使用 fr_FR

现在用户获得的是法语资源,而不是英语。此示例还说明了为什么对于 Android 7.0 或更高版本,您应该将法语字符串存储在 fr 而不是 fr_FR 中。此处的操作是匹配最接近的父级方言,使解析更快且更可预测。

除了这种改进的解析逻辑,Android 现在还提供更多用户语言可供选择。让我们再次尝试上述示例,将意大利语指定为额外的用户语言,但应用不支持法语。

表 3. 应用仅匹配用户第二偏好的区域设置时的资源解析。

用户设置 应用资源 资源解析
  1. fr_CH
  2. it_CH
默认 (en)
de_DE
es_ES
it_IT
尝试 fr_CH => 失败
尝试 fr => 失败
尝试 fr 的子项 => 失败
尝试 it_CH => 失败
尝试 it => 失败
尝试 it 的子项 => it_IT
使用 it_IT

即使应用不支持法语,用户仍然能获得他们理解的语言。

设计您的应用以支持其他区域设置

Android 提供了工具,让应用内容的本地化和以用户首选语言吸引用户变得更加容易。我们建议使用以下技术以可扩展的方式配置您的应用,使其能够适应不同的语言和格式约定。

指定您的应用支持的语言

为确保语言解析正确,请使用模块级 build.gradle 文件中的 resConfigs 属性指定您的应用支持的语言。

以下代码示例展示了如何使用 resConfigs 来表示支持的语言。在此示例中,应用支持英语和西班牙语。

Groovy

android {
    defaultConfig {
        ...
        resConfigs "en", "es"
    }
}

Kotlin

android {
    defaultConfig {
        ...
        resConfigs("en", "es")
    }
}
由于构建系统合并应用及其依赖项中资源的方式,您必须以这种方式指定支持的语言,以确保正确接收用户语言设置。

LocaleList API

从 Android 7.0(API 级别 24)开始,Android 暴露了 LocaleList.getDefault() API,该 API 允许应用直接查询用户指定的语言列表。此 API 允许您创建更复杂的应用行为和优化内容显示。例如,搜索可以根据用户设置以多种语言显示结果。浏览器应用可以避免提供翻译用户已知语言的页面,键盘应用可以自动启用所有适当的布局。

格式化程序

直到 Android 6.0(API 级别 23),Android 只支持许多常用语言(en、es、ar、fr、ru)的一到两个区域设置。由于每种语言只有少数变体,因此应用可以将一些数字和日期作为硬编码字符串存储在资源文件中。然而,随着 Android 支持的区域设置集扩大,即使在单个区域设置中,日期、时间、货币和类似信息的格式也可能存在显著差异。硬编码您的格式可能会给最终用户带来困惑的体验。因此,在为 Android 7.0 或更高版本开发时,请务必使用格式化程序,而不是硬编码数字和日期字符串。

例如,Android 7.0 及更高版本支持 27 种阿拉伯语区域设置。这些区域设置可以共享大部分资源,但有些偏好 ASCII 数字,而另一些偏好本地数字。例如,当您想创建一个带数字变量的句子,例如“选择 4 位密码”时,请使用如下所示的格式化程序:

 format(locale, "Choose a %d-digit PIN", 4)