语言和语言区域解析概览

从 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。以下示例介绍为何这些做法可提升资源解析的性能和可靠性。

资源解析示例

使用 7.0 以上的 Android 版本时,以不同的方式解析表 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 创建更成熟的应用行为和更优化的内容显示。例如,搜索可以基于用户的设置以多种语言显示结果。浏览器应用可避免翻译以用户理解的语言显示的页面,键盘应用可自动启用所有适用的布局。

格式化程序

直到 Android 6.0(API 级别 23),Android 仅支持许多常用语言(en、es、ar、fr、ru)的一个或两个语言区域。由于每种语言只有几种变体,因此,应用可以通过在资源文件中将一些数字和日期存储为硬编码字符串解决此问题。不过,随着 Android 扩展了支持的语言区域集,即使在一个语言区域中,日期、时间、货币及类似信息也会存在显著差异。对您的格式进行硬编码会让最终用户困惑不已。因此,在针对 Android 7.0 或更高版本开发应用时,请务必使用格式化程序代替硬编码数字和日期字符串。

例如,Android 7.0 和更高版本支持 27 个阿拉伯语言区域。这些语言区域可以共享大多数资源,但其中一些资源首选 ASCII 数字,另一些则首选本地数字。例如,如果您想要创建一个具有数字变量的句子,如“Choose a 4 digit pin”,则按如下所示使用格式化程序:

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