BUG|Flutter文本字符打点和国际化
2022-09-30 本文已影响0人
厘米姑娘
当文本要按照字符进行打点时,需要注意不是所有语言都适合。
发现问题
中东地区运营人员反馈,红框圈出来的两处阿拉伯文本显示异常,可以参考正文内容是正常的。
定位原因
现在让昵称区和正文区显示同一段文本,可见确实有所不同:
通过代码对比发现,区别在于是否对文本进行“空格替换”:
text.replaceAll('', '\u200b')
\u200b
是个宽度为0的空格,那么替换的作用是什么呢?举个例子如下图,这里展示现支持的所有语言,左边是一端段完整文本,右边是限制了文本可展示宽度后的打点效果,可以看到,默认情况下会按照单词进行打点。
大多数场景这种打点规则其实没什么问题,但有些场景就不太行了。试想下如果用户昵称是如
“AAAAAAAAAAAAAAAAAAAAAAAA”这种较长且连续的单词,一旦被打点就会被完全省略成“...”,再比如一些固定宽度的按钮,希望是尽可能多地填满而不是留一块空格。其实就是按照字符打点,所以引入“零宽空格”把每个字符隔开当作单独的“单词”,打点效果如图:
看起来不错,但眼尖的可能会发现阿拉伯语在打点前后发生变化了,这是因为阿拉伯字母有着复杂的变形规则:
计算机在显示阿拉伯字母时,会根据选择阿拉伯字母的书写风格、当前选择的字体、显示位置、书写空间等情况,将字母原型经过Shape(字母位置变形)、Ligature(字母连写变形)、Diacritics(字母标注变元音符号变形)、Kashida(为了凑满一整行字母延长变形)、Tatwell(插入字母链接符号)等等一系列的操作,才可以将一段阿拉伯字母渲染输出。
其中,最主要的变形是Shape和Ligature。用汉语来粗略比喻,就像“不好”要显示成“孬”、“混凝土”要显示成“砼”、“不用”要显示成“甭”等等。
解决办法
因此不能随便在阿拉伯字母中插入其他字符,这会影响到其变形规则导致错误。解决办法是先保证其正确显示,这里判断下不再对阿拉伯语进行替换:
static String getSpaceReplaceText(String text) {
if (UserInfoHolder.lang.toLowerCase().startsWith("ar")) {
return text;
}
return text.replaceAll('', '\u200b');
}
然后再考虑打点的问题,事实上阿拉伯字母的连写规则本身就有缩短文本宽度的目的,甚至之前经过替换后由于展示不下被打点的文本,改成不替换后反倒能完全展示了。
总结
除了阿拉伯语有使用阿拉伯字母,波斯语、达里语、哈萨克语、中国的维吾尔语等也在应用,当前尚未引入相关地区语言,因此如果涉及到这些地区,同样的都不能进行替换。