阿拉伯语排版与数字渲染的技术债
传统阿拉伯语排版与 Web 渲染之间的差距
现代 Web 浏览器无法原生执行传统的阿拉伯语对齐(justification),这种对齐依赖于拉长字母形状而非拉伸单词之间的空格。虽然拉丁字母脚本通过增加词间空格来实现对齐,但古典阿拉伯语排版使用 taṭwīl(或 kashida)——即在特定的字母对之间延伸连接笔画——以确保两端对齐,同时又不破坏文本的视觉织理。
目前,CSS text-align: justify 在处理阿拉伯语时默认采用拉丁式的词间距,这在阿拉伯语传统中在美学上是不正确的。要在 Web 上实现真正的对齐,通常需要手动插入 U+0640 TATWEEL 字符,这种“黑客”手段会降低可搜索性,破坏屏幕阅读器,并在文本重排时失效。
阿拉伯语塑形(Shaping)的复杂性
阿拉伯语本质上是连写的,这意味着字母必须根据其在单词中的位置改变形状。单个码点必须以四种形式之一进行渲染:孤立形(isolated)、起始形(initial)、中间形(medial)或末尾形(final)。
塑形引擎的角色
为了正确渲染阿拉伯语,软件必须使用塑形引擎(例如 HarfBuzz)在渲染时应用 OpenType 特性。该过程包括:
- 位置变化:根据相邻字符选择正确的字形(glyph)。
- 连字(Ligatures):应用必要的 (
rlig)、标准的 (liga) 和可选的 (dlig) 连字。例如,lām-alif 连字对于识字能力是强制性的。 - 标记堆叠(Mark Stacking):正确地在垂直方向上定位元音符号和变音符号。
如果没有塑形引擎,文本将渲染为一系列脱离的、孤立的字母,从左到右排列,这是旧版 PDF 生成器、某些 Python 库(如 matplotlib)以及收据打印机的常见故障。
双向(Bidi)布局与“撒谎”的光标
阿拉伯语文本经常存在于混合内容环境中(例如,包含英文版本号或 URL 的阿拉伯语散文),这会触发 Unicode 双向算法(UAX #9)。该算法根据字符的方向性特征将其解析为“运行段”(runs):阿拉伯语是强右向左(RTL),拉丁语是强左向右(LTR),而数字是“弱”方向性的。
常见的 Bidi 故障
- 光标跳跃:由于屏幕上的视觉顺序与内存中的逻辑顺序不同,光标经常在运行段边界处发生意外的跳跃或回退。这种不一致性在不同的浏览器和编辑器中表现各异。
- 范围翻转:在阿拉伯语段落中,像 "10-20" 这样的范围可能会渲染为 "20-10",因为连字符是中性的,而数字被重新分类为阿拉伯数字,导致运行段根据规范进行交换。
- 标点符号位移:当周围的上下文方向发生变化时,末尾的感叹号或句号经常会“瞬间移动”到行末的另一端。
数字问题
由于在不同地区使用着三套截然不同的数字集,阿拉伯语渲染变得更加复杂:
- 阿拉伯-印度数字 (٠١٢٣٤٥٦٧٨٩):用于埃及、苏丹、黎凡特、伊拉克和海湾地区。
- 拉丁数字 (0-9):主要用于马格里布地区(摩洛哥、阿尔及利亚、突尼斯)。
- 扩展阿拉伯-印度数字 (۰۱۲۳۴۵۶۷۸۹):用于伊朗、汗达斯坦和巴基斯坦。
除了字形之外,数字的双向行为也存在问题。根据 UAX #9 的 W2 规则,如果数字前面有阿拉伯字母,数字会被重新分类为 ARABIC NUMBER,这会改变中性字符(如连字符)在它们周围的行为,从而经常导致电话号码或日期的顺序错误。
历史技术债:从抄写员到“简化版阿拉伯语”
数字时代对阿拉伯语的挣扎是几个世纪以来试图将复杂脚本放入僵化的机械系统中的结果:
- 早期印刷 (1514):早期的活字印刷产生了脱离的、不识字的字母形状,因为排字工不理解该脚本的连写要求。
- 布拉克印刷厂 (1820):埃及政府资助的努力最终通过为每种位置形式和连字创建数百个独立的金属字模,实现了高质量的排版。
- 简化版阿拉伯语 (1958):为了适应 Linotype 机器的 90 通道约束,出版商 Kamel Mrowa 帮助创建了“简化版阿拉伯语”,它将起始形融合为中间形并去除了连字。这种出于效率驱动的减法成为了新闻编辑室和打字机的全球标准。
志愿者基础设施
现代 Web 上大部分功能性的阿拉伯语渲染是无偿或非商业性劳动的产物,而非行业投资:
- Amiri Font:由 Khaled Hosny 创建,他是一位医生,通过自学字体工程来复兴布拉克印刷厂的字体。它仍然是目前最好的免费 Naskh 字体之一。
- HarfBuzz:Chrome 和 Android 使用的塑形引擎,由 Behdad Esfahbod 和 Khaled Hosny 等志愿者 heavily 参与开发。
- SIL International:为翻译工作提供了关键的字体支持(例如 Scheherazade New)。
尽管有这些进步,关于 OpenType jstf 表(用于对齐优先级)的实现仍处于“僵持”状态。由于浏览器厂商并未优先实现这些表,由抄写员在 10 世纪解决的传统书法对齐问题在现代 Web 技术栈中仍未得到解决。