处理RTL文字的源代码和代码示例

为阿拉伯语、希伯来语和许多其他语言的页面编辑代码会带来挑战,除非使用专门的编辑器。出于类似的原因,在说明文档中包含双向文本代码示例也很困难。本页面探讨了内容开发者可能面临的一些问题,并在可能的情况下提供一些建议。

这些内容对编辑工具的开发者也可能有用。

本文假你不熟悉双向文本的概念和Unicode双向文本算法的作用。如你不不熟悉,应该在继续之前先阅读文章Unicode双向文本算法基础

如你不熟悉如何在HTML中使用双向文本,你可以读一下HTML中的行内标记和双向文本

编辑标记语言的代码

目前缺乏创建使用从右到左文字的HTML页面的良好编辑环境。由于HTML标记和转义中的语法字符包含标点符号和通常是强LTR类型的字母,你总是在处理包含双向文本的源代码。如果编辑器不知道标记不是普通的文本,它可能会移动字符并产生一些奇怪的效果,使编码变得困难。标记中的强类型字母和标点符号会出现你不意想不到的地方,有时会干扰内容本身的顺序。

以下显示了在从左到右上下文中的一些简单标记。源代码包含一个p标签,后跟一个class属性,再跟一个title属性,其值为阿拉伯语文本(العربي)。元素的内容(نشاط التدويل!)以阿拉伯语文本开始,以感叹号结束。感叹号单独显示,以说明它最终出现的位置。在从左向右环境中的结果顺序(其中阿拉伯语文本用方括号中的文本表示)如下所示。

你希望看到的:

<p class="myclass" title="[title_value]">![element_content]</p>

你在简单的文本编辑器中实际看到的:

<p class="myclass" title="[element_content]<"[title_value]!</p>

使用阿拉伯语文本的相同例子:

<p class="myclass" title="العربي">نشاط التدويل!</p>

我们可以看到,title文本和段落的内容的顺序颠倒了,尖括号的方向也是。此外,句末标点符号(如这里的感叹号)出现在错误的位置。当段落内容包含多处双向文本时,该内容的可读性可能会受到严重影响。

如你要创建很多从右向左的文本,把编辑器的基方向设置为从右向左是有意义的。这有助于确保段落内容和标点符号都正确显示。然而,这往往会使整体源代码变得更糟,如下面的示例所示。

如下一个例子所示,如果源代码的整体上下文是从右向左的,情况可能会变得更糟(尽管这不太常见,因为标记语言通常是英语,所以编辑源代码的上下文不太可能是从右向左的)。在这种情况下,相同源代码的结果是:

你希望看到的:

<p class="myclass" title="[title_value]">![element_content]</p>

你在简单的文本编辑器中实际看到的:

<p/>![element_content]<"[title_value]"=p class="myclass" title>

使用阿拉伯语文本的相同例子:

<p class="myclass" title="العربي">نشاط التدويل!</p>

例子里的源代码在用户代理中会正确显示,只有编写和维护源代码会有问题。

如果可以的话,确保使用从左向右文字的属性出现在属性列表的最后(在下面的例子中,是class属性)会有一点帮助。这会使从左向右上下文中的语法看起来符合预期,尽管段落文本的问题还是存在。在从右到左的上下文中,它会防止标记与内容的交互,但事情仍然有点混乱。

你希望看到的:

<p title="[title_value]" class="myclass">![element_content]</p>

你在简单的文本编辑器中实际看到的(LTR上下文在上,RTL在下):

<p title="[title_value]" class="myclass">[element_content]!</p>.
<p/>![element_content]<"class="myclass "[title_value]"=p title>.

使用阿拉伯语文本的相同例子:

<p title="العربي" class="myclass">نشاط التدويل!</p>

<p title="العربي" class="myclass">نشاط التدويل!</p>

对于编辑者来说,在对整个源代码应用方向覆盖后在LTR模式下编辑并不是一个很好的想法。为此,我们需要一个对Unicode双向文本算法一无所知的编辑器,因为这样避免了文本的重排。这让理解标记语言和内容的混合变得更加容易,不过编辑者必须倒着阅读所有RTL内容。在阿拉伯字母等连写文字中,这尤其成问题,因为正常的连字形状以及方向都会改变。

يحق لكل فرد أن يغادر

يحق لكل فرد أن يغادر

相同的阿拉伯语文本在RTL上下文(上)和LTR上下文(下)

将编辑器的整体方向设置为LTR,并在新的一行开始内容也有帮助,但这并不总是对行内的标记有帮助,句末标记还会出现在错误的位置。此外,你应该尽量避免在结束标签之前包含空白字符,因为这可能导致其他问题

你希望看到的:

<p class="myclass" title="[title_value]">
.[element_content]</p>

你在简单的文本编辑器中实际看到的:

<p class="myclass" title="[title_value]">
[element_content].</p>

使用阿拉伯语文本的相同例子:

<p class="myclass" title="العربي">
نشاط التدويل!</p>

理想的解决方案是用一个它将标记识别为特殊的构造,为源代码中的字符产生合理的显示顺序的代码编辑器。如你的标记包含dir属性来更改内容的方向上下文,你的编辑器应该识别这一点并在源代码的顺序中产生相应的更改。一些编辑器可能有将标签转换为图形的编辑模式,这可以解决这个问题。

编辑包含格式化字符的源代码

如你用Unicode控制字符,比如RIGHT TO LEFT MARK(RLM)或ZERO-WIDTH NON JOINER(ZWNJ),你通常无法在源代码中看到这些字符,因为它们是不可见的。如果你的编辑器为这些字符创建可见标记,这将非常有帮助。

你可能认为一个不错的替代方案是使用预定义的HTML字符实体引用&rlm;&zwnj;,或它们的等价字符值引用&#x200F; &#x200C;

不幸的是,这种方法通常具有与前一节中描述的相同问题。下面的例子显示了在编辑器中将&x200F;添加到双向文本的3个不同位置时会看到什么。这个编辑器将上下文设置为RTL。在这个简单的例子中,文本不会被移动,但转义的部分会。

你希望看到的:

 [arabic_text⁴] [english_text³][arabic_text²]&#x200F;[arabic_text¹]
 [arabic_text³] [english_text²]&#x200F;[arabic_text¹]
 [arabic_text³] &#x200F;[english_text²][arabic_text¹]

你在简单的文本编辑器中实际看到的:

 [arabic_text⁴] [english_text³][arabic_text²];x200F#&[arabic_text¹]
 [arabic_text³] x200F;[english_text²]#&[arabic_text¹]
 [arabic_text³] ;[english_text²]&#x200F [arabic_text¹]

同样,理想的解决方案是编辑器识别这些转义序列并将所有相关的字符保持在一起,按LTR顺序排列。

处理代码示例

鉴于上述情况,当代码片段包含RTL文本时,为教程或文章创建示例可能很棘手,这并不令人意外。显示代码片段在大多数编辑器中的实际外观可能没有帮助;相反,我们需要用额外的隐藏标记来让语法保持在一起并显示文本逻辑顺序的内容。这包括用dir属性值修改文本的基方向,或者其他方法。

通常,作者通过不显示RTL文本来解决这个问题。例如,在前面的所有示例中,我们从主要的示例中删除了实际的阿拉伯语文本,只在实时代码示例中显示它。

在英语上下文中执行此操作的其他常见方法包括通过大写翻译表示代码的阿拉伯语/希伯来语/等部分,并对标记和所有的LTR文本使用从左到右的全小写字符。通常(但不是所有情况下),大写文本中的字母从右到左书写,因为这让标点符号的定位更加真实。从右到左书写的大写文本试图指示渲染结果,从左到右的文本指示内存中字符的顺序。

以下提供了一些例子。

大写翻译:

<p class="myclass" title="HEBREW">INTERNATIONALIZATION ACTIVITY!</p>

反向的大写翻译:

<p class="myclass" title="WERBEH">!YTIVITCA NOITAZILANOITANRETNI</p>

使用希伯来文本的输出示例:

פעילות הבינאום!

提供指向页面的链接,或提供包含原文种的代码输出的面板总是有用的。