Android中的资源本地化

Android会运行在许多地区的许多设备上。为满足大多数用户的需要,应用程序应该使用与应用所在的地区相适应的文本、音频文件、数字、货币符号以及图形等。

本文档介绍Android应用程序本地化的最佳时实践。这个原则适用于你正在使用的任何IDE开发工具,如自带有ADT的Eclipse、基于Ant的工具等。

首先要掌握Java的编程只是,并且熟悉Android的资源加载过程,以及XML中用于界面元素的声明方法。在开发方面要掌握Activity的生命周期以及国际化和本地化的一般原则。

使用Android资源框架把应用程序本地化的外观尽可能的与核心Java功能分离,是一个良好的实践。

  • 可以把大多数或者所有的应用程序的用户界面的内容放到资源文件中。

  • 用户界面的行为,以及其他处理,是通过Java代码来驱动的。如,如果用户输入的数据需要以来不同地区来格式化或排序,那么就要使用Java代码来编程处理这些数据。

Android中的资源切换

资源是文本字符串、布局、声音、图形以及Android应用程序中需要的其他静态数据。一个应用程序能够包含多个资源集,每个都是针对不同的设备配置来定制的。当用户运行应用程序时,Android会自动的选择并加载跟设备最匹配的资源。

当编写应用程序时,需要创建一组默认的资源,外加用于不同地区的可选资源。

当用户运行应用程序时候,Android系统会基于地区来选择加载合适的资源。

在编写应用程序时,要给应用程序创建默认和可选资源。对于这些资源的创建,要把他们放到res/目录下,特定命名的子目录的文件中。

为什么默认资源是重要的

当应用程序运行在一个没有提供特定语言文本的语言环境时,Android会从res/values/starings.xml中加载默认的字符串。如果默认的文件不存在,或者是缺少应用程序需要的字符串,那么应用程序就不会运行,并且会提示一个错误。下面的示例演示了当默认文本文件不完整时所发生的问题:

  • 应用程序编译时可能不会有问题。当Eclipse这样的IDE,如果资源有错误,它是不会报告任何错误的。

  • 当应用程序在设置了英语语言环境的设备上启动时,应用程序能够正确的运行,因为res/values-en/string.xml中包含了它所需要的文本字符串。

  • 但是当应用程序在设置了英语意外的其他语言环境的设备上启动这个应用程序时,用户会看到一个错误信息和强制关闭按钮。

要防止这种情况发生,必须确保res/values/string.xml文件存在,并且定义了每个需要字符串。这适用于所有类型的资源,不只是字符串。你要给应用程序需要的所有类型的资源创建默认资源文件,包括布局文件、可描画资源、动画资源等。

如何创建默认资源

把应用程序的默认文本放到下面位置和名称的一个文件中:

res/values/strings.xml

在这个文件中的文本字符串应该使用默认的语言,这种语言是期望大多数应用程序用户会说的语言。

必须设置的默认资源还包括其他的任何可描画资源和布局资源,以及动画资源:

  • res/drawable/

    这个目录中至少要包含一个图形文件,用于Android启动应用的图标

  • res/layout/

    这个目录存放定义默认布局的XML文件

  • res/anim/

    如果需要,可以有任意个res/anim-文件夹

  • res/xml/

    如果需要,可以有任意个res/xml-文件夹

  • res/raw

    如果需要,可以有任意个res/raw-文件夹

在代码中,检查每个引用的Android资源。确保每个资源都有默认的资源定义,还要确保默认字符串文件的完整性,本地化字符串文件可以是全部字符串的一个子集,但默认字符串文件必须要包含全部字符串。

如何创建可选资源

本地化应用程序的大部分工作是给不同的语言提供可选的文本。在某些情况下,还需要提供可选的图形、声音、布局以及其他特定环境的资源。

应用程序能够用不同的限定符指定许多res/<qualifiers>/目录。使用特定语言或语言加地区的组合限定符,能够给不同的语言环境创建可选资源。(资源目录的名称必须是在“提供可选资源”文档中介绍的命名方案,否则不会被编译)。

例如:

假设应用程序默认语言是英语。还假设要把应用程序中的文本本地化为法语,并且还想要应用程序适用于日语环境(除了应用程序的标题以外)。这时需要创建三个可代替strings.xml文件,每个文件被保存在指定的资源目录中:

  • res/values/strings.xml

    包含应用程序使用的所有的英语文本,包括标题的命名文本。

  • res/values-fr/strings.xml

    包含字符串的所有法语文本,包含标题。

  • res/values-ja/strings.xml

    包含除了标题以为的所有字符串的日语文本。

如果Java代码中应用了R.string.title资源,在运行时会发生下面的情况:

  • 如果设备被设置成法语以外的其他任意语言,那么Android会从res/valuyes/strings.xml文件中加载标题。

  • 如果设备被设置成法语语言环境,那么Android就会从res/values-fr/strings.xml文件中加载标题

要注意的是,如果设备是日语环境,那么Android会首先从res/values-ja/strings.xml文件中查找标题,但是因为这个文件中没有包含标题字符串,所以Android会返回使用默认的标题,即从res/values/strings.xml文件中加载标题资源。

Android会优先选择哪个资源?

如果有多个资源文件跟设备配置匹配,Android会使用下列规则来决定使用哪个资源文件。其中有的在资源目录名中指定了限定符,语言环境几乎始终是要有限选择的。

例如:

假设应用程序包含了一个默认的图形集和两组其他图形,每组都被优化用于不同的设备:

  • res/drawable/ 包含默认图形

  • res/drawable-small-land-stylus/ 包含了用于手写笔输入和OVGA低密度横向屏幕设备的图形

  • res/drawable-ja/ 包含了适用于日语环境的图形

如果应用程序运行在配置了日语环境的设备上,那么即使是设备期望使用手写笔,并且屏幕是QVGA的低密度屏,那么Android也会从res.drawable-ja/目录中加载图形。

例外:只有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。这是因为资源选择的过程中,MCC的优先级要比语言的优先级高。

选择的过程不总是像这个例子这样直截了当。详细内容请阅读“Android应用资源---访问资源”一节中的“如何查找和匹配最佳资源”。所有的限定符都在“Android应用资源---提供资源”一节中的表2中进行了说明。

在Java代码中引用资源

在应用程序的Java代码中,引用资源的语法是:R.resource_type.resource_name或android.R.resource_type.resource_name(Android系统资源)。

设计可以在任何语言环境中工作的应用程序

不能假设应用程序所运行的设备上的任何事情。设备可能有你所不期望的硬件,或者设置了你计划外或没有测试过的语言环境。因此要进行程序设计,以便不管它在什么样设备上都能正常的运行或友好的失败。

重要:确保应用程序包含所有默认资源集。

确保包括了含有应用程序需要的所有图片和文本的res/drawable/和res/values/文件夹(在文件夹名称中不带有任何其他修饰)。

如果应用程序遇到了即使是一个默认资源错误,它也不会在那个不支持的设备环境上运行。例如,res/values/strings.xml默认文件可能缺少一个应用程序需要的字符串,在应用程序运行在一个不支持的语言环境中,并且试图加载res/values/strings.xml文件时,用户会看到一个错误消息和一个强制关闭按钮。项Eclipse这样的IDE不会发现这类错误,在被支持语言环境的设备或模拟器上测试时,不会发现这个问题。

设计灵活的布局

如果为了适应某种语言(如用长单词的德语),需要重排布局,那么可以为这种语言创键一个可选的布局(如,res/layout-de/main.xml)。但是,这样做会使应用程序更难维护。更好的办法是创建一个更灵活的单一布局。

另一种典型的情况是由于语言的差异对布局的不同需求。如,当应用程序运行在日语环境中时,需要一个包含了两个名称字段的通信录格式,而运行在其他的一些语言中时,需要三个名称字段。有两种方法可以处理这种情况:

  • 创建一个带有三个字段的布局,然后基于语言环境,用编程的方法启用或禁用其中一个名称字段。

  • 创建一个主布局,主布局中含有包含了另一个可变字段的子布局。第二个布局能够针对不同的语言进行不同的配置。

避免创建多余的资源文件和文本字符串

在应用程序中不可能给每种资源都创建特定语言环境的可选资源。如,定义在res/layout/main.xml文件中的布局可以在任何语言环境中工作,因此没有必要给任何语言环境都创建可选的布局资源文件。

还有,可能不需要给每个字符串都创建可选的文本。如,假设下列情况:

  • 应用程序的默认语言是美式英语。应用程序使用的每个字符串都使用美式英语的拼写,它们被保存在res/values/strings.xml文件中。

  • 对于一些重要的短语,想要提供英式英语拼写。以便应用程序运行在英国的设备上时使用这些可选资源。

要做这件事情,需要创建一个叫做res/values-en-rGB/strings.xml的小文件,其中只包含了与在美国运行时不同的字符串。其余所有的字符串,应用程序都会使用被定义在res/values/strings.xml文件中的默认字符串。

使用Android的Context对象手动的查找设备的语言环境

可以使用Android提供的Context对象来查找设备的语言环境:

String locale = context.getResources().getConfiguration().locale.getDisplayName();
Copyright© 2020-2022 li-xyz 冀ICP备2022001112号-1