欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android RTL 及小语种和适配

程序员文章站 2022-09-02 19:22:31
一、需要单独适配的原因 包括中文、英文、+-等各种符号,都是从左往右显示,而阿拉伯语、波斯语等则是从右往左显示,等等问题都需要进行本地化适配。 二、适配须知 2.1)RTL语...

一、需要单独适配的原因

包括中文、英文、+-等各种符号,都是从左往右显示,而阿拉伯语、波斯语等则是从右往左显示,等等问题都需要进行本地化适配。

二、适配须知

2.1)RTL语言有以下6种:

       
阿拉伯语 ar Arbic  
波斯语 fa Persian  
希伯来语 iw Hebrew  
乌尔都语(印度、巴基斯坦) ur Urdu  
*语   *  

2.2)数字:
西阿拉伯数字:(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
东阿拉伯数字:( - - - - - - - - - )
波斯数字:( - - - - - - - - - )
其他有一些语言也有自己的数字.

2.3)
强字符:具有明确方向的字符,这种类型字符的例子包括大多数字母字符、音节字符、汉语表意文字、非欧洲或非阿拉伯数字,以及这些语言脚本的标点。
弱字符:具有模糊方向的字符,这种类型字符的例子包括欧洲数字、中东阿拉伯-印度数字、算术符号和货币账号。许多语言脚本中的标点符号,如冒号、逗号。
中性字符:不根据上下文就无法确定方向性,例如段落分隔符、制表符和大多数其他空格字符。

三、需要进行的修改

一、控件的显示

“+8618310002000”这类号码会被显示成“8618310002000+”,就是因为阿拉伯语是从右往左显示的,所以加号显示在了最右边。

设置控件的textDirection属性即可,控制组件的文字对齐方式:

android:textAlignment="viewStart"
.setTextDirection(View.TEXT_DIRECTION_LTR);
.setTextAlignment(View.TEXT_ALIGNMENT_VIEW_START);

此外还有layoutDirection属性来设置组件的布局排列方式。

二、数字的格式化

比如,将西阿拉伯数字改成东阿拉伯数字。
西阿拉伯数字:(0, 1, 2, 3, 4, 5, 6, 7, 8, 9)
东阿拉伯数字:( - - - - - - - - - )

这类问题又细分为以下几种:
1)纯数字,可以使用 Character.getNumericValue来转换,给控件设置LTR属性即可。
2)带有“+”,“,”等中性字符、弱字符符号,比如前者用在+86,后者用在分机号,可以给控件设置LTR属性,也可以通过BidiFormatter.getInstance().unicodeWrap(),它会根据上下文来添加LTR属性。
3)带有“@”等强字符符号,比如SIP账号“abc@10.239.224.22”,需要使用\u202A等标记来强制改变方向。同时空格等中性符号,如果在阿拉伯语环境下会显示成RTL,例如将号码“183 1000 2000”显示成“2000 1000 183”,因此也需要使用此类符号。

同时在场景中又细分为以下几种:
1)直接进行转换的数字:控件中展示给用户的数字,如“1秒、2秒”
2)用户的输入但是需要转换的数字:比如在联系人中输入号码10086,则转换成
3)不应该转换的数字:收到短信中包含数字,联系人名字中包含的数字(验证过iOS中也是处理)
同时记录另一个问题,在某些只能输入数字的情况下,iOS的键盘能够输入多种数字,Android目前看到的都只能输入西阿拉伯数字。

我针对上述情况拆分出以下3个方法。

1)localizeString(String str)
将字符串中的数字进行翻译,但不改变方向)。
例如10086,10010等共2人,会被翻译成“人2共等10086,10010”,(由于wiki本身RTL支持不好,我复制过来顺序都显示的错的,所以举例中只改了方向,数字文字都不变,下文同理)。
数字本身是LTR的,先翻译10086,逗号是弱性字符,跟着左边,再往后才是10010(这里应该让10086显示在右边比较好,但是考虑到这个场景问题不大,暂不处理),接下来是阿拉伯语,因此后面的方向是RTL的。

2)localizeNumber(String number)
localizeNumber(String number, boolean nameIsNumber)
对号码中的数字进行翻译,默认nameIsNumber为true,当为false时表示为name,因此不翻译。

2.1)中性字符,例如加号
例如+8618310002000,当为阿拉伯语环境时,第一个+号显示出来之后根据上下文环境判断是RTL,因此号码显示在+号左边,最终是8618310002000+。此时使用View.TEXT_DIRECTION_LTR即可。
例如+86 183 1000 2000,当为阿拉伯语环境时,同上+号第一个显示,86紧随+号,同时空格也是中性字符,在RTL环境下也是继续往左显示,最终显示为2000 1000 183 86+。但此时添加View.TEXT_DIRECTION_LTR只能让+号显示正确,空格并不生效,原因尚不清楚。

2.2)弱字符:例如冒号、逗号
例如播分机号时10086,1,1,它会继承前面的顺序,因此顺序不变还是10086,1,1。如果是10086\u202B,1:2,这里的\u202B是RTL的属性,首先是10086,然后逗号前有RTL标记,因此其之后改变方向为RTL,所以最终是100861:2,。

2.3)强字符:例如@等符号
例如SIP号码123@10.238.24.140,@和阿拉伯语一样属于强字符,因此显示为10.238.24.140@123,这次需要使用\u202A标记来将方向改成LTR。

3)localizeDigit(String str, boolean isNeedLTR)
这个方法是最终用来处理的,因为处理有前提,不推荐外部调用,所以设置成了private。
当前需要改成LTR且环境是RTL时,才添加\202A标记,减少不必要的操作同时降低风险。

三、双向字符集

这类问题比较复杂,原生系统中也大量存在。

没有发现什么特别好的办法,加标记是可行的,但是很麻烦。比如使用\u200f和\202A等标记,具体就不展开讲了,核心内容在上一节已经举例讲过了。