Android 语言国际化

前言

我们在使用Android手机系统的时候经常在“设置”项里面会提供用户多种系统语言选择,比如:中文、英语…… 大家或许已经发现这些语言显示顺序都是“从左往右”;但是有一些语言是“从右往左”显示的,比如阿拉伯语、希伯来语等语言,当在这种语言环境下时,我们需要怎么来处理布局文件呢?接下来的时间我们就来讨论处理阿拉伯语等“从右往左”显示语言的问题。

布局

首先我们先讲解布局问题,在Android系统中为了支持不同语言显示,可以定义特定(阿拉伯语、希伯来语……)语言布局文件,具体如图所示:


图中layout-ar对应的就是阿拉伯语的布局文件,因此我们只需要修改该目录下的布局文件,就可以实现我们在阿拉伯语言环境中的现实效果。在Android4.2之前,我们需要对每一种“从右往左”显示的语言copy一份布局文件进行修改,如图中layout-fa layout-iw等,这样做的缺点就是会产生许多冗余布局文件。

Android4.2版本之后,Google针对阿拉伯等bidi语言(备注:bidi语言即“从右往左”书写的语言)view和文字布局文件做了重大修改,类似2D图形加速机制,可以从Activity/Application控制、Window代码控制、View资源控制共3个级别的控制。所有关于bidi语言的布局文件都可以放在layout-ldrtl目录,如图所示:


layout-ldrtl是Google专门为bidi语言预留的布局目录,所以在Android4.2版本之后,layout-fa layout-iw等目录可以直接删除,只需要在layout-ldrtl目录下定义bidi语言布局即可。

Activity/Application控制

在Manifest文件中我们可以设置android:supportsRtl属性,具体请参考如下代码:

  1. <application  
  2.     android:allowBackup="true"  
  3.     android:icon="@drawable/ic_launcher"  
  4.     android:label="@string/app_name"  
  5.     android:theme="@style/AppTheme"  
  6.     android:supportsRtl="true" >  

View控制

在layout-ldrtl目录的布局文件中设置android:layoutDirection属性,具体请参考如下代码:

  1. <LinearLayout  
  2. xmlns:android="http://schemas.android.com/apk/res/android"  
  3. xmlns:tools="http://schemas.android.com/tools"  
  4. android:layout_width="match_parent"  
  5. android:layout_height="match_parent"  
  6. android:layoutDirection="rtl" >  
  7.     <TextView  
  8. android:layout_width="wrap_content"  
  9. android:layout_height="wrap_content"  
  10. android:text="@string/hello_world"  
  11. android:layoutDirection="rtl" />  
  12. </LinearLayout>  
备注:layout-ldrtl优先级介绍,layout-ldrtl优先级要低于语言级别(layout-ar),因此如果存在layout-ar目录,会首先去查找layout-ar目录下的布局文件,因此建议删除layout-ar等bidi语言目录。layout-ldrtl优先级又高于分辨率等级,优先级归纳如下:

layout-ar(语言级别) > layout-ldrtl > layout-800*540(分辨率)

代码控制

介绍了以上两种静态的控制方式后,我们再来看看动态控制bidi语言显示方式,具体请参考如下代码:

  1. if ("ar".equals(Locale.getDefault().getLanguage())) {  
  2.     getWindow().getDecorView().setLayoutDirection(View.LAYOUT_DIRECTION_RTL);  
  3. }  
以上就是bidi语言涉及的布局修改及配置方式,组合使用以上几种方式便可以解决我们在国际化中遇到的bidi语言问题。
HashCode
当大家阅读到这儿的时候,可能会存在疑问,Hashcode和语言会有什么关系呢?其实Hashcode问题才是最终决定我写这篇博客的目的。说到Hashcaode我们先来回忆一下Java中hashcode的作用,简单的说hashcode就是标识对象的唯一标识(备注:非严谨的说法)。最近在开发Android系统开发中遇到这样一个问题,当手机拍照后正常显示(图标显示Camera图标)应该如图1-1所示:

         

                              图1-1                                                                                           图1-2                                            

但是在Azeri和Turkish语言环境中却显示成了文件夹图标,如下图1-2所示,经过调查最终发现是以下代码在不同语言环境下Hashcode不同造成的,具体代码如下所示:

  1. public static int getBucketId(String path) {  
  2.     return path.toLowerCase().hashCode();  
  3. }  
按照以下方式更改后就能正常显示,具体代码如下:
  1. public static int getBucketId(String path) {  
  2.     return path.toLowerCase(Locale.ENGLISH).hashCode();//使用英语字符转换  
  3. }  
Android的解释信息如下:

Converts this string to lower case, using the rules of locale.
Most case mappings are unaffected by the language of a Locale. Exceptions include dotted and dotless I in Azeri and Turkish locales, and dotted and dotless I and J in Lithuanian locales. On the other hand, it isn't necessary to provide a Greek locale to get correct case mapping of Greek characters: any locale will do.
大概意思就是阿塞拜疆和土耳其语言环境中使用的字符编码不一样,我们必须将字符编码设置成统一的本地编码这样Hashcode才保持一致

具体编码请参考:http://www.unicode.org/Public/UNIDATA/SpecialCasing.txt

总结:Android语言国际化就总结这么多,希望对大家有所助力;大家如果对语言国际化有新的见解或者更好的实现方式,请在commit中评论,我们共同讨论。

©️2020 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页