Techyou labs
文章RSS
评论RSS
登录
真正的爱应该超越生命的长度,心灵的宽度,灵魂的深度
搜索
关于作者
文章分类
Default
Linux/Unix
Database
Cloud
Networking
Security
Programming
最新文章
带你重走 TiDB TPS 提升 1000 倍的性能优化之旅
Unicode 中的 BIDI 双向性算法[转]
在linux中设置优先使用ipv4,而不是ipv6
linux下WPS高分辨率下因字体缩放导致字体发虚的问题
ssh-rsa not in pubkeyacceptedalgorithms问题解答及处理办法 Permission denied (publickey)
在 Ubuntu 22.04 中使用 PipeWire 替换 PulseAudio
MYSQL简单监控指标
deepin-wine6-stable下TIM悄悄崩溃问题
openwrt 设置ipv6地址分配
Redis 实战篇:巧用数据类型实现亿级数据统计
最新评论
renothing: 备注:路由器端优先设置ipv4并不影响客户端的ip...
renothing: 二次反向代理跟你应用程序得处理时间有关系吧?尤其是...
二次反向代理性能很差,怎么优化的?: 我也用nginx 做了个二次反向代理,但是并发连3...
hostyep: 交换链接么?目前每天保持30个左右对口IP,每月都...
yzhkpli: error while loading share...
美肤宝: 感谢分享。。。
lq: 嗯 喜欢弄得点单点
按月归档
March 2023
December 2022
November 2022
September 2022
August 2022
March 2022
January 2022
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
February 2021
September 2020
May 2020
September 2019
August 2019
July 2019
June 2019
May 2019
January 2019
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
April 2018
March 2018
December 2017
October 2017
September 2017
August 2017
April 2017
March 2017
February 2017
August 2016
July 2015
November 2014
September 2014
August 2014
July 2014
June 2014
July 2013
April 2013
September 2012
July 2012
May 2012
April 2012
February 2012
January 2012
December 2011
November 2011
October 2011
September 2011
August 2011
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
December 2009
November 2009
October 2009
September 2009
August 2009
June 2009
May 2009
April 2009
March 2009
February 2009
December 2008
November 2008
September 2008
August 2008
July 2008
June 2008
常用标签
Mysql
nginx
mysql优化
linux
debian
Powered by
Typecho)))
Optimized by
EAimTY
Unicode 中的 BIDI 双向性算法[转]
March 17, 2023
一切得从复制 iOS 通讯录联系人手机号说起,有同学发现复制的号码是 “(415)555-3695”,长度应该是 13,但Debug 打印的长度却是 15,WTF? 通过断点发现是前后分别多了一个不知何用 Unicode 字符:   U+202D 和 U+202C 这两个是个啥? 其实这两个都是关于方向的 Unicode 控制字符,U+202D 简称 LRO ,U+202C 简称 PDF 。那它们是做什么用,如何控制所谓方向的呢? ### Unicode 的方向性 #### 基础方向 定义的是一个区域的整体方向,例如一个页面、一个段落或一个句子。中英文环境一般是 (LTR) 从左至右,而阿拉伯文环境则为 (RTL) 右至左的书写顺序 #### 字符方向 日常我们书写文字会知道,书写的方向是决定于所书写的文字,汉子、拉丁文字是从左至右,阿拉伯文、希伯来文则是从右至左。相应的,Unicode 字符在设计时就考虑了不同文字方向性的问题,因此定义了每个 Unicode 字符的方向属性。 每个 Unicode 编码都被赋予一个方向性,并且有强弱之分: | 方向性 | 字符举例 | | ------------ | ------------ | | Strong Left-to-Right (LTR) | 强字符从左至右(英文字母、汉子都属于此类) | | Strong Right-to-Left (RTL) | 强字符从右至左(阿拉伯文字、希伯来文字属于此类) | | Neutral | 中性字符(大部分标点符号和空格属于此类) | | Weak Left-to-Right (LTR) / Right-to-Left (RTL) | 弱字符(数字和数字相关的符号属于此类) | Strong 强字符: 方向性确定,LTR 或 RTL,和上下文无关。并且可能会影响其前后字符的方向性。 Weak 弱字符: 和强字符一样方向性也是确定的,但是不会影响前后字符的方向性。 Neutral 中性字符: 方向性不确定,由上下文环境决定其方向。 #### Unicode 字符方向串 (Directional Run) 目前我们还没说到文章开始提到的 `LRO` 和 `PDF` 控制字符,下面我们先把这两个控制字符从号码中去掉,仅将 `“(415)555-3695”` 套用到阿拉伯文和中英文环境,观察会出现哪些问题: ``` هاتف: (415)555-3695 phone: (415)555-3695 座机: (415)555-3695 ``` 可以看到在中英文环境中,文本、数字和标点符号都按照从左至右的顺序书写,展示正常。 但在阿拉伯文环境中,电话号码好像按符号分割分组并方向展示了,这是怎么回事? 这里要引入 **方向串 (Directional Run)** 的概念,是指在一段文字中具有相同方向性的连续字符,并且其前后没有相同方向性的其它方向串。 **全局方向、文本中的字符强弱类型** 决定了如何分割方向串,以上面的例子做分析:  文本被分为 6 个不同的方向串,问题显而易见,由于中性符号被全局方向影响,使得原本号码被拆分成不同方向串,被重新排序。 #### 关于方向性的 Unicode 控制字符 为了解决上面的问题,Unicode 标准中定义了一系列方向性控制字符,这些字符在界面上不显示,也不占用任何展示空间。它们像是一些标记,影响着 BIDI 双向算法对文字书写方向的判断。 **隐式双向控制字符 (Implicit Markers)** ``` U+200E: LEFT-TO-RIGHT MARK (LRM) U+200F: RIGHT-TO-LEFT MARK (RLM) ``` 隐式控制字符的概念比较简单,可以理解为一个不会展示出来的强字符,LRM 为从左到右的强字符,而 RLM 为从右到左的强字符。 思考如何利用隐式控制解决上面号码的问题? 我们可以在每个中性字符 ‘-‘、’(‘、’’)’ 左右用` LTR` 字符包裹,这样中性字符被左至右的强字符包裹,它的方向也应该会变为从左至右。 来吧,尝试一下 (阿拉伯文手机的 Unicode 编码为` U+0647 U+0627 U+0062a U+0641 )`: ```
هاتف: (415)555-3695
``` هاتف: (415)555-3695 简直完美,成功了! 但写这么多未免繁琐,毕竟 iOS 实现相同效果只用了 LRO 和 PDF 两个字符,这两个字符又有什么作用呢? **显式双向控制字符 (Explicit Markers)** ``` U+202A: LEFT-TO-RIGHT EMBEDDING (LRE) U+202B: RIGHT-TO-LEFT EMBEDDING (RLE) U+202D: LEFT-TO-RIGHT OVERRIDE (LRO) U+202E: RIGHT-TO-LEFT OVERRIDE (RLO) U+202C: POP DIRECTIONAL FORMATTING (PDF) ``` 显式控制字符需要成对使用,前四个字符 `LER` `RLE` `LRO` `RLO` 为开始字符,最后一个 `PDF` 为结束字符。 - `LRE` & `RLE` : 接下来的文字片段内的方向变为 从左至右 / 从右至左。效果类似基础方向,将一段文本中的基础方向变更。 - `LRO` & `RLO` : 顾名思义 override,接下来的所有 Unicode 字符的方向性将被覆盖为 从左至右强字符 / 从右至左强字符。 还以上面的通讯录文本为例: ```
هاتف: (415)555-3695
``` هاتف: (415)555-3695 ```
هاتف: (415)555-3695
``` هاتف: (415)555-3695 Bingo!同样实现了通讯录所需效果。 那么,LRE / RLE 和 LRO / RLO 有什么区别,用在什么不同场景呢?接着看例子: ```
here left to right, here right to left.
here left to right, here right to left.
``` here left to right, here right to left. here left to right, here right to left. ```
here left to right, here right to left.
here left to right, here right to left.
``` here left to right, here right to left. here left to right, here right to left. #### iOS 对通讯录号码的处理 在从右至左的书写环境,虽然作为弱字符的数字还是按照从左至右的顺序书写,但是包含中性字符标点符号的电话号码,因为受到基础方向的影响,导致算法在不同环境下生成了不同的方向串,最终展示出错。 苹果为了避免这种错误产生,使用`LRO` 和 `PDF` 控制字符包裹号码部分,使得其中的字符始终为强字符从左至右。 至此我们了解到,iOS 通讯录中复制电话号码都出的两个字符,并不是什么 bug,而是有意为之的,是为了避免不同语言环境下,电话号码的展示不一致 ### 总结 这里仅讨论了复制阿拉伯数字到输入框时可能遇到的坑。大家可知道阿拉伯语言环境下 iOS 通讯录中是不用 阿拉伯数字 的,用的是 阿拉伯文数字,类似中文 一、二、三 和 1、2、3 的区别 作者:Sagi 链接:https://juejin.cn/post/6844903683935698952 来源:稀土掘金
暂无评论
添加新评论
称呼
Email
网站
取消回复
内容
发表评论