Android 本地化

本文档介绍 Android SDK 的本地化功能以及如何使用 Xamarin 访问它们

Android 平台功能

本部分介绍 Android 的主要本地化功能。 请跳到下一部分,查看特定代码和示例。

区域设置

用户在“设置”>“语言和输入”中选择语言。 此选择控制显示的语言和使用的区域设置(例如日期和数字格式)。

可以通过当前上下文的 Resources 查询当前区域设置:

var lang = Resources.Configuration.Locale; // eg. "es_ES"

此值是一个区域设置标识符,其中包含语言代码和区域设置代码,用下划线分隔。 作为参考,下面提供了 Java 区域设置列表通过 StackOverflow 支持的 Android 区域设置

常见示例包括:

  • en_US 表示英语(美国)
  • es_ES 表示西班牙语(西班牙)
  • ja_JP 表示日语(日本)
  • zh_CN 表示中文(中国)
  • zh_TW 表示中文(台湾)
  • pt_PT 表示葡萄牙语(葡萄牙)
  • pt_BR 表示葡萄牙语(巴西)

LOCALE_CHANGED

当用户更改语言选择时,Android 会生成 android.intent.action.LOCALE_CHANGED

活动可以选择通过设置活动的 android:configChanges 属性来处理此问题,如下所示:

[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/launcher",
    ConfigurationChanges = ConfigChanges.Locale | ConfigChanges.ScreenSize | ConfigChanges.Orientation)]

Android 中的国际化基础知识

Android 的本地化策略包括以下几个关键部分:

  • 资源文件夹,用于包含本地化的字符串、图像和其他资源。

  • GetText 方法,用于检索代码中的本地化字符串

  • AXML 文件中的 @string/id,用于自动将本地化字符串放入布局中。

资源文件夹

Android 应用程序管理资源文件夹中的大部分内容,例如:

  • layout - 包含 AXML 布局文件
  • drawable - 包含图像和其他可绘制资源
  • values - 包含字符串
  • raw - 包含数据文件

大多数开发人员已经熟悉在 drawable 目录中使用 dpi 后缀来提供图像的多个版本,从而让 Android 为每个设备选择正确的版本。 使用相同的机制通过在资源目录中添加语言和文化标识符后缀来提供多种语言翻译。

Screenshot of Resources/drawable and Resources/values folders for multiple cultural identifiers

注意

当指定 es 之类的顶级语言时,只需两个字符;但是,在指定完整区域设置时,目录名称格式需要用短划线和小写字母 r 来分隔两部分,例如 pt-rBR 或 zh-rCN。 将此值与代码中返回的值进行比较,该值带有下划线(例如 pt_BR)。 这两者与 .NET CultureInfo 类使用的值不同,后者仅包含短划线(例如 pt-BR)。 跨 Xamarin 平台工作时请记得这些差异。

Strings.xml 文件格式

本地化的 values 目录(例如 values-es 或 values-pt-rBR)应包含一个名为 Strings.xml 的文件,该文件将包含该区域设置的翻译文本

每个可翻译字符串都是一个 XML 元素,其资源 ID 指定为 name 属性,翻译后的字符串指定为值:

<string name="app_name">TaskyL10n</string>

需要根据正常的 XML 规则进行转义,并且 name 必须是有效的 Android 资源 ID(不含空格或短划线)。 下面是该示例的默认(英语)字符串文件的示例:

values/Strings.xml

<resources>
    <string name="app_name">TaskyL10n</string>
    <string name="taskadd">Add Task</string>
    <string name="taskname">Name</string>
    <string name="tasknotes">Notes</string>
    <string name="taskdone">Done</string>
    <string name="taskcancel">Cancel</string>
</resources>

西班牙语目录 values-es 包含一个同名文件 (Strings.xml),其中包含翻译

values-es/Strings.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="app_name">TaskyLeon</string>
    <string name="taskadd">agregar tarea</string>
    <string name="taskname">Nombre</string>
    <string name="tasknotes">Notas</string>
    <string name="taskdone">Completo</string>
    <string name="taskcancel">Cancelar</string>
</resources>

Screenshot of multiple values folders, each containing a Strings.xml file

设置字符串文件后,可以在布局和代码中引用翻译后的值。

AXML 布局文件

若要在布局文件中引用本地化的字符串,请使用 @string/id 语法。 示例中的此 XML 代码片段演示使用本地化资源 ID 设置的 text 属性(已省略其他一些属性):

<TextView
    android:id="@+id/NameLabel"
    android:text="@string/taskname"
    ... />
<CheckBox
    android:id="@+id/chkDone"
    android:text="@string/taskdone"
    ... />

GetText 方法

若要检索代码中翻译的字符串,请使用 GetText 方法并传递资源 ID:

var cancelText = Resources.GetText (Resource.String.taskcancel);

数量字符串

Android 字符串资源还允许创建数量字符串,以便翻译人员能够针对不同的数量提供不同的翻译,例如

  • "There is 1 task left."
  • "There are 2 tasks still to do."

(而不是常规的“There are n task(s) left”)。

在 Strings.xml 中

<plurals name="numberOfTasks">
   <!--
      As a developer, you should always supply "one" and "other"
      strings. Your translators will know which strings are actually
      needed for their language.
    -->
   <item quantity="one">There is %d task left.</item>
   <item quantity="other">There are %d tasks still to do.</item>
 </plurals>

若要呈现完整的字符串,请使用 GetQuantityString 方法,传递资源 ID 和要显示的值(传递两次)。 Android 使用第二个参数来确定要使用哪个 quantity 字符串,第三个参数是实际替换到字符串中的值(两者都是必需的)。

var translated = Resources.GetQuantityString (
                    Resource.Plurals.numberOfTasks, taskcount, taskcount);`

有效的 quantity 开关是:

  • 一个
  • 两种
  • few
  • 很多
  • 其他

Android 文档中对它们进行了更详细的描述。如果给定的语言不需要“特殊”处理,则那些 quantity 字符串将被忽略(例如,英语仅使用 oneother;指定 zero 字符串将不起作用,不会使用它)。

映像

本地化图像遵循与字符串文件相同的规则:应用程序中引用的所有图像都应放置在 drawable 目录中,以便能够回退

然后,应将特定于区域设置的图像放置在合格的 drawable 文件夹中,例如 drawable-es 或 drawable-ja(也可以添加 dpi 说明符)

在此屏幕截图中,四张图像保存在 drawable 目录中,但只有一张图像 flag.png 在其他目录中具有本地化副本

Screenshot of multiple drawable folders, each containing one or more localized .png files

其他资源类型

还可以提供其他类型的替代、特定于语言的资源,包括布局、动画和原始文件。 这意味着可为一种或多种目标语言提供特定的屏幕布局,例如,可以专门为德语创建一个允许使用很长文本标签的布局。

Android 4.2 引入了对从右到左 (RTL) 语言的支持(如果设置了应用程序设置 android:supportsRtl="true")。 资源限定符 "ldrtl" 可以包含在目录名称中,以包含专为 RTL 显示而设计的自定义布局。

有关资源目录命名和回退的详细信息,请参阅 Android 文档中的提供替代资源

应用程序名称

通过在 MainLauncher 活动中使用 @string/id,可以轻松本地化应用程序名称:

[Activity (Label = "@string/app_name", MainLauncher = true, Icon="@drawable/launcher",
    ConfigurationChanges =  ConfigChanges.Orientation | ConfigChanges.Locale)]

从右到左 (RTL) 语言

Android 4.2 及更高版本提供对 RTL 布局的全面支持,详细信息请参阅本机 RTL 支持博客

使用 Android 4.2(API 级别 17)及更高版本时,可以使用 startend 而不是 leftright 指定对齐值(例如 android:paddingStart)。 还有 LayoutDirectionTextDirectionTextAlignment 等新 API 可以帮助生成适应 RTL 阅读器的屏幕。

以下屏幕截图显示了阿拉伯语的本地化 Tasky 示例

Screenshot of Tasky app in Arabic

下一个屏幕截图显示了希伯来语的本地化 Tasky 示例

Screenshot of Tasky app in Hebrew

RTL 文本使用与 LTR 文本相同的方式通过 Strings.xml 文件进行本地化

测试

确保彻底测试默认区域设置。 如果由于某种原因无法加载默认资源(即它们丢失),应用程序将崩溃。

仿真器测试

有关如何使用 ADB shell 将仿真器设置为特定区域设置的说明,请参阅 Google 的在 Android Emulator 中测试部分。

adb shell setprop persist.sys.locale fr-CA;stop;sleep 5;start

设备测试

若要在设备上进行测试,请在“设置”应用中更改语言

提示

记下菜单项的图标和位置,以便可以将语言还原为原始设置。

总结

本文介绍使用内置资源处理本地化 Android 应用程序的基础知识。 可在此跨平台指南中了解有关 iOS、Android 和跨平台(包括 Xamarin.Forms)应用的 i18n 和 L10n 的详细信息。