本地化您的应用

许多地区的许多设备上都搭载了 Android。为了覆盖大多数用户,请确保您的应用以适合其所在语言区域的方式处理文本、音频文件、数字、货币和图形。

本页介绍了本地化 Android 应用的最佳实践。

您需要具备 Kotlin 的实战知识,并 熟悉 Android 资源加载、 activity 生命周期等开发注意事项, 以及国际化和本地化的基本原则。

使用 Android 资源框架将应用的已本地化部分与应用的核心功能尽可能分开,是一种很好的做法。

  • 将应用界面的大部分内容或全部内容放入资源 文件中,如本页和应用资源概览中所述。
  • 另一方面,界面的行为是由基于 Kotlin 的代码驱动的。 例如,如果用户输入的数据需要根据语言区域使用不同的格式或排序方式,则可以使用 Kotlin 以编程方式处理数据。本页不讨论如何对基于 Kotlin 的代码进行本地化。

本指南介绍了所有 Android 应用中使用的核心 Android 本地化系统。如需了解如何在 Jetpack Compose 界面中加载这些本地化资源, 请参阅 Compose 中的资源

有关如何将应用中的字符串本地化的简短指南,请参阅 支持不同的语言和文化

概述:Android 中的资源切换

资源是指文本字符串、声音、图形和您的 Android 应用需要的任何其他静态数据。应用可以包含多组资源,每组资源针对不同的设备配置进行定制。当用户运行应用时,Android 会自动选择并加载与设备最匹配的资源。

本页主要关注本地化和语言区域。有关资源切换和可以指定的所有配置类型(例如屏幕方向、触摸屏类型等)的完整说明,请参阅提供备用资源

编写应用时,您需要为应用创建将使用的默认资源和备用资源。当用户运行您的应用时,Android 系统会根据设备的语言区域选择要加载的资源。 如要创建资源,您需要将文件放在项目的 res/ 目录下特别命名的子目录中。

为什么默认资源很重要

当应用在您没有提供特定于该语言区域的文本的语言区域中运行时,Android 就会从 res/values/strings.xml 加载默认字符串。如果缺少此默认文件,或者此文件缺少应用需要的字符串,那么应用就不会运行,而是显示错误。以下示例说明了默认文本文件不完整时可能会发生的情况。

示例:

某个应用基于 Kotlin 的代码仅引用了两个字符串:text_atext_b。该应用包含一个本地化资源文件 (res/values-en/strings.xml),该文件以英语定义了 text_atext_b。 该应用还包含一个默认资源文件 (res/values/strings.xml),该文件包含 text_a 的定义,但不包含 text_b 的定义。

  • 当此应用在语言区域设置为英语的设备上启动时,应用可能会正常运行,因为 res/values-en/strings.xml 包含所需的两个文本字符串。
  • 但是,当应用在语言区域设置为非英语的设备上启动时,用户会看到错误消息和“强行关闭”按钮。应用不会加载。

为避免这种情况,请确保存在 res/values/strings.xml 文件,并且该文件定义了每个所需的字符串。这种情况适用于所有类型的资源,而不仅仅是字符串:您需要创建一组包含应用会调用的所有资源(例如可绘制对象、字体、颜色等)的默认资源文件。如需了解与测试相关的信息,请参阅 测试默认资源部分。

使用资源进行本地化

本部分介绍如何创建默认资源以及备用资源, 还说明了如何为资源分配优先级以及如何在代码中引用资源。

创建默认资源

将应用的默认文本放在 res/values/strings.xml 中。对于这些字符串,请使用默认语言,即您预计应用的大多数用户所说的语言。

默认资源集还包含任何默认的可绘制对象,还可以包含其他类型的资源,例如图标或字符串。这些资源位于以下目录中:

  • res/drawable/:必需的目录,至少包含一个图形文件,用于在 Google Play 上显示应用图标
  • res/xml/:如果您有任何 res/xml-<qualifiers> 文件夹,则为必需
  • res/raw/:如果您有任何 res/raw-<qualifiers> 文件夹,则为必需

创建备用资源

在将应用本地化的过程中,很大一部分工作是提供不同语言的备用文本。在某些情况下,您还需要提供备用图形、声音和其他特定于语言区域的资源。

应用可以指定许多 res/<qualifiers>/ 目录,每个目录都有不同的限定符。如需为不同的语言区域创建备用资源,您可以使用指定语言或语言-区域组合的限定符。资源目录的名称必须符合 提供备用资源中所述的命名方案, 否则您的应用将无法编译。

示例:

假设应用的默认语言为英语,并且您希望将应用中的所有文本本地化为法语,并将应用标题以外的所有文本本地化为日语。在这种情况下,您需要创建三个 strings.xml 文件,每个文件都存储在特定于语言区域的资源目录中:

  1. res/values/strings.xml
    包含应用使用的所有字符串的英文文本,包括名为 title 的字符串的文本。
  2. res/values-fr/strings.xml
    包含所有字符串(包括 title)的法语文本。
  3. res/values-ja/strings.xml
    包含所有字符串(title 除外)的日语文本。

如果基于 Kotlin 的代码引用了 R.string.title,则运行时会出现以下情况:

  • 如果设备设置为法语以外的任何语言,Android 会从 res/values/strings.xml 文件加载 title
  • 如果设备设置为法语,Android 会从 res/values-fr/strings.xml 文件加载 title

如果设备设置为日语,Android 会在 res/values-ja/strings.xml 文件中查找 title。但由于该文件中未包含此类字符串,因此 Android 会回退到默认设置,并从 res/values/strings.xml 文件加载英语版 title

哪些资源优先?

如果多个资源文件与设备的配置匹配,则 Android 会遵循一组规则来决定使用哪个文件。在可通过资源目录名称指定的限定符中,语言区域几乎总是优先于其他限定符。

示例:

假设某个应用包含一组默认图形和另外两组其他图形,这两组图形中的每一组都针对不同的设备设置进行了优化:

  • res/drawable/
    包含默认图形。
  • res/drawable-small-land-stylus/
    包含针对以下设备进行了优化的图形:需要使用触控笔输入数据,并且配有横屏 QVGA 低密度屏幕。
  • res/drawable-ja/
    包含针对日语进行了优化的图形。

如果应用在配置为使用日语的设备上运行,则 Android 会从 res/drawable-ja/ 加载图形,即使设备恰好需要使用触控笔输入数据,并且配有横屏 QVGA 低密度屏幕也是如此。

例外:在选择过程中,唯二优先于语言区域的限定符是移动设备国家/地区代码 (MCC) 和移动网络代码 (MNC)。

示例:

假设您遇到以下情况:

  • 应用代码调用 R.string.text_a
  • 有两个相关的资源文件:
    • res/values-mcc404/strings.xml,其中包含应用默认语言(在本例中为英语)的 text_a
    • res/values-hi/strings.xml,其中包含印地语的 text_a
  • 应用在具有以下配置的设备上运行:
    • SIM 卡连接到印度的移动网络 (MCC 404)。
    • 语言设置为印地语 (hi)。

Android 会从 res/values-mcc404/strings.xml(英语)加载 text_a,即使设备配置为印地语也是如此。这是因为在资源选择过程中,Android 优先考虑 MCC 匹配,而不是语言匹配。

选择过程并不总是像这些示例所显示的那样简单。 如需更详细地了解该过程,请参阅 Android 如何找到最匹配的资源应用资源概览中按优先顺序介绍和列出了所有限定符。

在代码中引用资源

在应用的 Kotlin 代码中,您需要使用语法 R.resource_type.resource_nameandroid.R.resource_type.resource_name来引用资源。 如需了解详情,请参阅 访问应用资源

管理本地化字符串

本部分介绍了管理与本地化相关的字符串的最佳实践。

将所有字符串放入 strings.xml 中

在构建应用时,请不要硬编码任何字符串,而应将所有字符串声明为默认的 strings.xml 文件中的资源,以便于对其进行更新和本地化。然后,strings.xml 文件中的字符串可以轻松地提取、翻译并再次集成到您的应用中(使用适当的限定符),而无需更改已编译的代码。

例如,使用 Compose 时,您可以按如下方式加载字符串:

// In the res/values/strings.xml file
// <string name="compose">Jetpack Compose</string>

// In your Compose code
Text(
    text = stringResource(R.string.compose)
)

如果要生成带有文本的图片,也应将这些字符串放在 strings.xml 中,并在翻译后重新生成图片。

遵循针对界面字符串的 Android 指南

在设计和开发界面时,请密切关注与用户沟通的方式。一般而言,应使用友好而简洁的风格,并且整个界面应采用一致的风格。

请务必阅读并遵循 Material Design 关于 写作风格和字词选择的建议。这样做能够让您的应用显得更有品质,并且有助于用户快速理解您的界面。

另外,还应尽可能地使用 Android 标准术语,例如对于界面元素,使用操作栏、选项菜单、系统栏、通知等。正确且一致地使用 Android 术语可以简化翻译工作,并为用户带来更好的最终产品。

为声明的字符串提供充分的上下文

strings.xml 文件中声明字符串时,请确保清楚说明使用该字符串的上下文。此信息对翻译人员来说非常宝贵,有助于提高翻译质量。它还有助于您更有效地管理字符串。

示例如下:

<!-- The action for submitting a form. This text is on a button that can fit 30 chars -->
<string name="login_submit_button">Sign in</string>

考虑提供以下上下文信息:

  • 字符串的用途是什么?它会在何时何处呈现给用户?
  • 它在界面中的位置?例如,按钮文字的翻译不如文本框中文字的翻译灵活。

标记消息中不可翻译的部分

通常,字符串包含不应翻译成其他语言的文本。常见的示例包括一段代码、某个值的占位符、特殊符号或名称。准备字符串进行翻译时,请查找并标记必须保持原样不进行翻译的文本,避免翻译人员对其进行更改。

如需标记不需要翻译的文本,可以使用 <xliff:g> 占位符标记。 以下标记示例可以指示文本 "%1$s" 在 翻译过程中不会被更改,以免破坏消息:

<string name="countdown">
  <xliff:g id="time" example="5 days">%1$s</xliff:g> until holiday
</string>

在声明占位符标记时,请添加说明此占位符用途的 ID 属性。如果您的应用稍后会替换占位符的值,请务必提供属性示例来说明预期的用途。

以下是一些其他占位符标记的示例:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<!-- Example placeholder for a special Unicode symbol -->
<string name="star_rating">Check out our 5
    <xliff:g id="star">\u2605</xliff:g>
</string>
<!-- Example placeholder for a URL -->
<string name="app_homeurl">
    Visit us at <xliff:g
    id="application_homepage">http://my/app/home.html</xliff:g>
</string>
<!-- Example placeholder for a name -->
<string name="prod_name">
    Learn more at <xliff:g id="prod_gamegroup">Game Group</xliff:g>
</string>
<!-- Example placeholder for a literal -->
<string name="promo_message">
    Please use the "<xliff:g id="promotion_code">ABCDEFG</xliff:g>" to get a discount.
</string>
...
</resources>

本地化核对清单

有关本地化和分发 Android 应用的过程的完整概述,请参阅应用的翻译与本地化

关于本地化的建议

在本地化您的应用时,请遵循以下建议。

将应用设计为可在任何语言区域中使用

切勿对用户用来运行您的应用的设备做任何假设。设备可能包含您没有预料到的硬件,或者可能设置为您未计划支持或无法测试的语言区域。请将您的应用设计为无论在什么设备上都能正常运行,并在无法运行时能够安全地退出。

重要提示:请确保您的应用包含一套完整的默认资源,其中包含 res/drawable/res/values/ 文件夹(文件夹名称中没有任何其他修饰符),这两个文件夹中包含了应用需要的所有图片和文本。

即使应用只缺少一个默认资源,它也无法在设置为不受支持的语言区域的设备上运行。例如,如果 res/values/strings.xml 默认文件缺少应用所需的一个字符串,则当应用在不受支持的语言区域中运行并尝试加载 res/values/strings.xml 时,用户会看到错误消息和“强制关闭”按钮。

如需了解详情,请参阅测试默认资源部分。

避免创建超出您需要的资源文件和文本字符串

您可能不需要为应用中的每个资源创建特定于语言区域的备用资源。例如,在 res/drawable/ 目录中定义的应用徽标可能适用于任何语言区域,在这种情况下,无需创建任何备用图形文件。

此外,您可能也不需要为每一个字符串创建替代文本。例如,假设:

  • 您应用的默认语言是美式英语。应用使用的每个字符串都已使用美式英语拼写在 res/values/strings.xml 中定义。
  • 对于一些重要的短语,您需要提供英式英语拼写。 您希望在应用在英国的设备上运行时使用这些备用字符串。

为此,可以创建一个名为 res/values-en-rGB/strings.xml 的小文件,该文件仅包含应用在英国的设备上运行时有所不同的字符串。对于所有其他字符串,应用会退回到默认状态,使用在 res/values/strings.xml 中定义的字符串。

使用 LocalConfiguration 手动查找语言区域

您可以使用 Android 提供的 LocalConfiguration 查找语言区域,如以下示例所示:

val locale = LocalConfiguration.current.locales[0]

使用应用翻译服务

应用翻译服务集成在 Play 管理中心。您可使用该服务获得即时报价并向翻译公司下订单。您可以为应用界面字符串、Play 商店商品详情文本、IAP 名称和广告系列文本订购一种或多种语言的翻译。

使用 Gemini 翻译应用字符串

您可以在 Android Studio 中使用 Android Studio 中的 Gemini 直接在项目中翻译应用的字符串资源。如需了解详情,请参阅 应用的翻译与本地化

测试已本地化的应用

在设备上或使用 Android 模拟器测试已本地化的应用。尤其需要测试并确保您的应用中包含所有必要的默认资源。

在设备上测试

请注意,您测试所用的设备可能与其他地方的消费者所用设备有很大差异。您设备上提供的语言区域可能与其他设备上提供的语言区域不同。此外,设备屏幕的分辨率和密度也可能不同,这可能会影响界面中的字符串和可绘制对象的显示。

您可以通过“设置”应用更改设备的语言区域或语言。

使用可组合项预览进行测试

在设备上进行测试之前,您可以在 Android Studio 中使用可组合项预览 来测试本地化界面,而无需部署到模拟器。如需 预览不同语言的界面,请使用 @Preview 注释(例如 @Preview(locale = "fr"))。您还可以通过指定 RTL 语言区域(例如 @Preview(locale = "ar"))来测试从右向左 (RTL) 的布局。

在模拟器上测试

如需详细了解如何使用模拟器,请参阅 在 Android 模拟器上运行应用

创建和使用自定义语言区域

“自定义”语言区域是 Android 系统映像未明确支持的语言或区域组合。您可以通过在模拟器中创建自定义语言区域来测试应用在该语言区域中的运行情况。您可以采用下列两种方法:

  • 使用“自定义语言区域”应用(可从应用标签页访问)。创建自定义语言区域后,可以通过按住语言区域的名称来切换到该语言区域。
  • 通过 adb shell 更改到自定义语言区域,如以下部分中所述。

当您将模拟器设置为 Android 系统映像中未提供的语言区域时,系统本身会以其默认语言显示。不过,您的应用可以正确本地化。

通过 adb shell 更改模拟器语言区域

如要使用 adb shell 更改模拟器中的语言区域,请执行以下操作:

  1. 选择您要测试的语言区域并确定其 BCP-47 语言标记,例如加拿大法语为 fr-CA
  2. 启动模拟器。
  3. 在主机的命令行 shell 中,运行以下命令:
    adb shell
    或者,如果您连接了设备,请添加 -e 选项表明您希望使用模拟器:
    adb -e shell
  4. adb shell 提示符 (#) 处,运行以下命令:
    setprop persist.sys.locale [BCP-47 language tag];stop;sleep 5;start
    将方括号中的部分替换为第 1 步中的相应代码。

    例如,如要用加拿大法语进行测试,请运行以下命令:
    setprop persist.sys.locale fr-CA;stop;sleep 5;start

这会导致模拟器重启。再次出现主屏幕后,重新启动您的应用,此时应用会以新的语言区域启动。

测试默认资源

如需测试应用是否包含所需的全部字符串资源,请执行以下操作:

  1. 将模拟器或设备设置为应用不支持的语言。例如,如果应用在 res/values-fr/ 中包含法语字符串,但在 res/values-es/ 中不包含任何西班牙语字符串,则将模拟器的语言区域设置为西班牙语。您可以使用“自定义语言区域”应用将模拟器设置为不支持的语言区域。
  2. 运行应用。
  3. 如果应用显示错误消息和“强制应用关闭”按钮,则表示它可能正在查找一个未提供的字符串。请确保 res/values/strings.xml 文件中包含应用使用的每个字符串的定义。

如果测试成功,请针对其他类型的配置重复此测试。例如,如果应用具有名为 res/values-land/strings.xml 的字符串文件,但不包含名为 res/values-port/strings.xml 的文件,则将模拟器或设备设置为纵向屏幕方向,看看应用是否会运行。

其他资源

如需详细了解本地化,请参阅以下其他资源:

文档

视图内容