语言和区域设置解析概述

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

本文档首先解释了低于 7.0(API 级别 24)版本的 Android 中的资源解析策略。接下来,它描述了 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

现在用户将获得法语资源而不是英语资源。此示例还展示了为什么你应该将法语字符串存储在 fr 而不是 fr_FR 中,以用于 Android 7.0 或更高版本。这里采取的行动是匹配最接近的父方言,从而使解析更快且更可预测。

除了改进的解析逻辑外,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 位数的 PIN 码”)时,请使用如下所示的格式化程序

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