在HTML中实现bidi支持的例子

通过对比 Unicode 控制字符和 HTML 标记,读者可以了解在 Web 中实现文字方向性控制的两种方法以及其各自特点。本文使用在 HTML 中实现 bidi 支持的例子更能让读者对 bidi 在 Web 中的实现拥有更加直观和
深入的理解。

在开始介绍 bidi 算法和其在 HTML 中的实现之前,我们先来了解一下文字、语言和方向的关系,这也将有助于在后文中更好地理解 bidi 算法。

什么是文字和语言呢?我们引用 IBM Terminology 中的定义:

文字是使用于书面语的图形符号的集合。文字和语言或者国家/地区并不是一对一的关系。相同语系中的成员也可能使用不同的文字。例如,大部分的西欧语言都使用拉丁文,同样,阿拉伯文字不仅在阿拉伯国家中广泛使用而且也被用于伊朗的波斯语和">巴基斯坦的乌尔都语。 而语言是指用于交流信息的一套字符、惯例和规则的集合。

从上面的定义中我们可以了解到,文字和语言实际上是多对多的关系。一种文字可以被多种语言所使用,比如拉丁文。而另一方面,一种语言可能使用多种文字来表述,比如日语,它使用了日语汉字、平假名、片假名三种文字系统,而且还可以使用拉丁文来表述。

那书写方向和文字、语言有怎样的关系呢?严格来说,书写方向是与文字相关的,而与语言没有多大关系。就像上文中所谈到的,一种语言可以使用多种文字来表述,那同一种语言的书写方向就会因为所使用文字的不同而变化。比较经典的例子是阿塞拜疆语,它可以使用拉丁文字、西里尔文字和阿拉伯文字进行表述。当拉丁文字和西里尔文字被使用时,它的书写方向是从左到右,而当其使用阿拉伯文字时,书写方向就会变成从右到左。

文字的方向是多种多样的。多数的文字采用的是从左到右书写,而行的顺序是从上到下。而阿拉伯文字和希伯来文字等采用的是从右到左书写方向。我们当然还能很容易的想到,古代汉字的书写方向是从上到下,而行的顺序是从右到左。我们可以想象,如果现代汉字仍然采用古代的书写方向,这会让我们的 Web 工程师在设计页面方向和布局时是多么苦恼啊!

一般而言,当人们谈到从右到左的文字时,会首先联想到阿拉伯文字和希伯来文字。当然,还有一些其他的文字也是从右到左书写的,比如古叙利亚文字。而从左到右书写的文字主要包括拉丁文、西里尔文、希腊文等等。另外,形意文字(如中文、日文和韩文中使用的文字)一般也是按照从左到右的顺序书写,不过有时候也会出现其他的书写方向,就像前文介绍的汉字那样。

本文中将介绍的 bidi 实际是英文单词 bidirectional (双向)的缩写,进一步来说,我们这里所说的 bidi 是指双向文字。顾名思义,双向文字是指同时包含了两种书写方向的文字,也就是从左到右和从右到左的文字同时存在。一般来说,这种情况多数存在于从右向左书写的文字中,比如,阿拉伯文字和希伯来文字,这些文字中字母的书写顺序是从右到左的,但当其中包含数字(实际上阿拉伯数字是起源于印度的)或拉丁文字(如英文字母)时,数字和拉丁文字部分的书写顺序就会变成从左到右。同样,从左到右书写英文字母时遇到阿拉伯文字,那阿拉伯文字的部分就会按照从右到左来书写。

因此,对于全球化 Web 工程师来说,了解页面文字的方向性非常重要。因为显示双向的文字更为复杂,而正确地显示文字的方向是正确理解文字的基础,不同的方向可能会导致理解上的不一致。同时,页面的组织和排版也会受到阅读方向的影响。从下面的例子中您或许就能理解文字方向的重要性了(在该例子中,用大写英文字母表示从右到左的文字,而小写英文字母用来表示从左到右的文字。下文中的例子都将使用这种模式。):

John does not believe TAHT YAS SYAWLA I.

当我们从左到右来阅读时,这个句子是“John does not believe I always say that.”,而如果从右到左来阅读这个句子,它就变成了“I always say that John does not believe.”。两个方向从语义上来说都是合适的,所以当不清楚这个句子的阅读方向时,就无法确定它真正要表达的意思。

Unicode 双向算法介绍

在现代计算机应用中,最常用来处理双向文字的算法是 Unicode 双向算法(Unicode Bidirectional Algorithm),在后面的文章中我们将 Unicode 双向算法简称为 bidi 算法。该算法用来确认双向文字显示时的方向性。当然,除了方向性,该算法还涉及字形变化(Shaping)和镜像分析(Mirroring)等等其它和 bidi 相关的特性,不过这部分特性的实现大多由底层应用所控制,无需 Web 工程师进行设定或干预。

我们在此文中并不会详细解析 Unicode 双向算法,就如刚才所说,该算法的大部分内容将由底层实现。这个段落中,您将了解到 bidi 算法的一些核心的或和 Web 开发相关的概念,以便更好地在后面理解 HTML 中和 bidi 相关的设定是在改变或控制着什么特性。

双向字符类型(Bidirectional Character Types)

正如前文介绍的,书写方向是和文字相关,阿拉伯文字从右到左,拉丁文字从左到右。当人们在纸上书写时当然会记得这些规则,那计算机是如何知道的呢?实际上,Unicode 定义了它其中每个字符的方向属性,计算机就是根据这个方向属性来判断该文字的方向。

Unicode 方向属性包含三种类型:强字符、弱字符和中性字符。在这三种主要类型下面还有很多细小的属性分类。大部分的字符都属于强字符,比如英文字母、汉字和阿拉伯字母。它们的方向性是确定的,从左到右或者从右到左,和其上下文的 bidi 属性无关。并且,强字符在 bidi 算法中可能会影响其前后字符的方向性。中性字符的方向性是不确定的,由上下文的 bidi 属性来决定其方向,比如大部分的标点符号和空格。有意思的是弱字符的特性,它们的方向是确定的,但对其前后字符的方向性并不会产生影响。数字和数字相关的一些符号就属于弱字符。

基础方向(Base Direction)

或者也称为全局方向(Global Direction)、页面方向、段落方向,定义的是一个区域内的总体方向,比如一个页面、一个段落或者一个句子的方向。它决定了应该从这个区域的哪边开始书写文字。比如,当某个区域内的双向文字主要是从右到左的文字,并包含了从左到右的文字时,该区域的全局方向一般为从右到左,那么,第一个文字的输入位置就会在该区域的最右侧。

方向串(Directional Run)

方向串是指在一段文字中具有相同方向性的连续字符,并且其前后没有相同方向性的其它方向串。请参考一下关于方向串的例子:

图1. 关于方向串的例子

在这个例子中,包含了三个方向串。该句子以从左到右的方向串开始,然后是从右到左的方向串,最后以从左到右的方向串结尾。

要注意的是,方向串的排列顺序和数目往往会受到全局方向的影响。上面的例子中采用是从左到右的全局方向,如果该全局方向变为从右到左,那这个例句中方向串的排列顺序将如下图所示:

图2. 方向串的排列顺序

在从左到右的全局方向中,第一个方向串将从最右侧开始,在最左侧结束。可能您也观察到方向串的个数从之前的三变成了四,句子结尾处的句号的方向性随着全局方向的变化也发生了变化。这同时也说明了中性字符(这个句号)的方向性会受到上下文 bidi 属性的影响。

关于方向的 Unicode 控制字符

大部分情况,Unicode 双向算法能根据字符属性和全局方向等信息运算并正确地显示双向文字,这是该算法的隐性模式。在这种模式下,双向文字的显示方式基本上由算法完成,不需要人为的干预。但是,隐性模式的算法在处理复杂情况的双向文字时会显得不足,这时就可以使用显性模式来进行补充。在显性模式的算法中,除了隐性算法的运算外,可以在双向文字中加入关于方向的 Unicode 控制字符来控制文字的显示。这些被加入文字中的 Unicode 控制字符在显示界面上是不可见的,也不占用任何显示空间。它们只是在默默地影响着双向文字的显示。

Unicode 控制字符又可以分为两类,第一类为隐性双向控制字符:

U+200E: LEFT-TO-RIGHT MARK (LRM)U+200F: RIGHT-TO-LEFT MARK (RLM)

简单来说,您可以将这类的控制字符看成是不会显示出来的强字符,LRM 为从左到右的强字符,而 RLM 为从右到左的强字符。

而第二类当然就是显性双向控制字符:

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)

这类控制字符需要成对使用,列表中的前四个为开始字符,而最后一个为结束字符。当双向算法遇到 LRE 时,接下来文字片段内的方向开始变为从左到右。当双向算法遇到 RLE 时,接下来文字片段内的方向开始变为从右到左。当遇到 LRO 时,双向算法会将后面所有文字的双向属性视为从左到右强字符。当遇到 RLO 时,双向算法会将后面所有文字的双向属性视为从右到左强字符。如果一旦遇到 PDF 字符,双向属性的状态就会恢复到最后一个 LRE、RLE、LRO 或 RLO 之前的状态。

如何使用这些关于方向的 Unicode 控制字符,您可以参见后面使用 HTML 元素的例子。

关于方向的 HTML 元素

在 HTML 中除了可以使用那些关于方向的 Unicode 控制字符,还可以使用 HTML 中提供的标签或者属性来控制双向文字的显示。而且,当可以使用标签或者属性时,建议使用这些 HTML 元素来控制方向,而不使用Unicode 控制字符。最主要的原因是 Unicode 控制字符是不可见的,在使用和维护时容易出现问题,而 HTML元素可以避免这个问题。

属性 dir

与 LRE 控制字符和 RLE 控制字符相对应的 HTML 元素是 dir = "ltr" 和 dir = "rtl" (ltr 的英文全称为 left to right,而 rtl 的英文全称为 right to left)这两个属性,它们就像其他的属性一样,可以被用在块级元素或内联元素中,并控制该区域的方向性。属性 dir 这个关键字就是英文单词 direction (方向)的缩写。实际上,这个属性控制的就是相应元素内的全局方向。

HTML5 中给 dir 属性加入了一个新的值“auto”。这个值与上面提到的 ltr 和 rtl 不同,它并不明确相应元素内的全局方向,而需要根据不同的情况进行判断。这个判断依据就是该元素内的第一个强字符。如果第一个强字符是从左到右的属性,那么 dir="auto" 的结果就等于 dir="ltr"。同理,如果第一个强字符是从右到左的属性,那么 dir="auto" 的结果就等于 dir="rtl"。需要注意的是,这里的判断条件的第一个强字符,而会忽略之前遇到的弱字符和中性字符。这种模式可以被称为自动方向性或者上下文方向性。

标签 <bdo>

而与 LRO 控制字符和 RLO 控制字符相对应的 HTML 元素分别为:

<bdo dir = "rtl"></bdo><bdo dir = "ltr"></bdo>

其中,<bdo dir = "rtl"> 和 <bdo dir = "ltr"> 相当于 LRO 控制字符和 RLO 控制字符,表示一段控制区域的开始。而 </bdo> 的作用就像是 PDF 控制字符,表示此控制区域的结束。该标签根据 dir 属性覆盖相应元素内的字符方向性。

关键字 bdo 的英文全称为 bidirectional override (双向性超控)。需要注意的是,在这个标签中的 dir 属性不能赋值为 auto。

标签 <bdi>

HTML5 还加入了一个新的元素,那就是标签 <bdi>,它的英文全称为 bidirectional isolate (bidi 隔离,笔者觉得翻译成双向性片段会比较合适)。该标签用来在双向文字中加入方向片段,使得该片段脱离其父元素的全局方向。有点类似于 <span> 标签的作用,但不同的是 <bdi> 标签本身带有默认方向属性。

<bdi> 标签中可以使用 dir 属性来指定方向性,但默认情况下该属性的值为 auto。也就是说,使用 <bdi>...</bdi> 的结果和使用 <bdi dir="auto">...</bdi> 是一样的。

当您无法预知要显示内容的方向性时,建议使用此标签,比如用户的输入。让该区域根据上下文来判断优先使用的方向。

关于方向的 HTML 实体

还需要说明的是,隐性双向控制字符 LRM 和 RLM 并没有与之相对应的 HTML 元素,不过建议使用 HTML 实体来代替 Unicode 控制字符。至少在编辑器中,这些 HTML 实体是可见的。

表1. 关于方向的 HTML 实体

Unicode 控制字符 HTML 实体 作用 LEFT-TO-RIGHT MARK (LRM) &lrm; 从左到右强字符 RIGHT-TO-LEFT MARK (RLM) &rlm; 从右到左强字符

HTML 实现 bidi 支持的例子

我们将在这个部分介绍一些 HTML 中关于 bidi 支持的基本设置。但实际情况往往更为复杂,需要考虑的方向性问题更多。比如,在方向串的边界处出现弱字符或者中性字符时常常会出现显示顺序的问题,需要用到 HTML 方向元素。那我们下面的例子就从基础的设置开始。

HTML 页面的全局方向

就如之前所介绍的,属性 dir 可以指定 HTML 元素内的全局方向。同样,它也可以用来定义整个 HTML 页面的全局方向。并且,该页面内的其他 HTML 元素将默认继承该全局方向,除非您针对某个元素再次修改了其方向性。

当指定页面的全局方向时,可以将属性 dir 添加入 <html> 标签内(其中的语言属性是可选的):

<html lang=”en” dir=ltr>…</html>或者<html lang=”ar” dir=”rtl”>…</html>

覆盖字符的原有双向属性

这里需要使用到 <bdo> 标签,在某些特殊的情况下改变原本的字符双向属性。比如,之前我们的例子中使用大写英文字母来代替阿拉伯字符。但默认情况下大写英文字符的方向是从左到右的,这时就可以用 <bdo> 覆盖它。

默认情况下,

清单1. HTML 元素默认的方向

<!DOCTYPE HTML><html><body><p>APPLE</p></body></html>

您将看到的显示结果为:

图3. 正常大写英文字母

在使用 <bdo> 标签改变字符方向属性后,

清单2. 覆盖后的方向性

<!DOCTYPE HTML><html><body><p><bdo dir="rtl">APPLE</bdo></p></body></html>

您将看到的显示结果为:

图4. 改变方向属性后的大写英文字母

改变字符方向属性后,此区域内的英文字母排列顺序也变成从右到左了。

HTML 元素内方向的指定

当 HTML 文件中没有使用任何的 dir 属性,那么该文件的方向会默认为从左到右。

如果您将 dir 指定为 ltr:

清单3. 指定从左到右的全局方向

<bdi dir="ltr">The apple is called <bdo dir="rtl">APPLE</bdo> in Arabic.</bdi>

您将看到的显示结果为:

图5. dir="ltr" 的效果

如果您将 dir 指定为 rtl:

清单4. 指定从右到左的全局方向

<bdi dir="rtl">The apple is called <bdo dir="rtl">APPLE</bdo> in Arabic.</bdi>

您将看到的显示结果为:

图6. dir="rtl" 的效果

如果您将 dir 指定为 auto:

清单5. 指定自动的全局方向

<bdi dir="auto">The apple is called <bdo dir="rtl">APPLE</bdo> in Arabic.</bdi>

您将看到的显示结果为:

图7. dir="auto" 的效果

因为这个句子中的第一个强字符为英文大写字母 T,所以 dir="auto" 等同于 dir="ltr" 的效果。

需要修正的方向性

比如下面的代码:

清单6. 需要修正的方向

<p>These fruits are called <bdo dir="rtl">APPLE</bdo>, <bdo dir="rtl">PEAR</bdo> and <bdo dir="rtl">ORANGE</bdo> in Arabic.</p>

我们期望看到的显示结果为:

图8. 期望的显示结果

但实际上这个句子显示出来后,您会看到这样的结果:

因为 ELPPA 和 RAEP 之间是中性字符逗号和空格,那么 ELPPA、RAEP、逗号以及空格会被作为一个方向串来处理。想要让这个句子按照期望的方式来显示,有两种修正方式。其中之一是使用 HTML 实体将这个方向串从中截断,如:

清单7. 使用 HTML 实体修正方向

<p >These fruits are called <bdo dir="rtl">APPLE</bdo>&lrm;, <bdo dir="rtl">PEAR</bdo> and <bdo dir="rtl">ORANGE</bdo> in Arabic.</p>

其中的 LRM 作为和这个方向串不同方向性的强字符打断了这个方向串的连续性。

另一个方式是使用 <bdi> 标签将所有从右到左的片段隔离起来,如:

清单8. 使用 HTML 方向标签修正方向

<p>These fruits are called <bdi><bdo dir="rtl">APPLE</bdo></bdi>, <bdi><bdo dir="rtl">PEAR</bdo></bdi> and <bdi><bdo dir="rtl">ORANGE</bdo></bdi> in Arabic.</p>

这两种方式虽然使用上有所不同,但原理上是类似的,就是将这三个阿拉伯水果名作为三个方向片段交给 Unicode 双向算法来处理。

结束语

在实际编辑 HTML 页面时,使用 Unicode 控制字符和相应的 HTML 元素能起到相同的控制效果。可以根据情况选择具体使用哪种方式,但当 HTML 元素能够被使用时,建议使用此种方式来控制页面和元素的方向性。另外,还需要注意的是,有些浏览器现阶段并不支持 HTML5 中新加入的这些元素。因此,在设计页面时使用何种控制办法也需要考虑到这个因素,尽量让更多的浏览器支持您所制作的页面。

时间: 2024-10-28 16:55:50

在HTML中实现bidi支持的例子的相关文章

Microsoft SQL Server 2005 中的 XML 支持(1)

本文探讨 SQL Server 2005 中内置的 XML 支持.描述了这种支持如何与 .NET 框架 V2.0 和本机代码(例如 OLEDB 和 SQLXML)均支持的客户端编程相集成. 一.简介 可扩展标记语言 (XML) 作为一种与平台无关的数据表示形式已被广泛采用.它对于在松散耦合且完全不同的系统,以及各种企业到企业 (B2B) 应用和工作流范畴内交换信息是很有用的.数据交换已成为 XML 技术的主要驱动力之一.. XML 在企业应用程序中的使用正日益广泛,它主要用于对半结构化和非结构化

给某个DIV容器赋值js函数,ajax中使用,支持ie和firefox

给某个DIV容器赋值js函数,ajax中使用,支持ie和firefox   <script> function setValueForDiv(id,content){  var element = document.getElementById(id);  element.innerHTML = unescape(content);  if(!element.innerHTML)  {    try{     element.innerHTML = unescape(content);    

有关jive论坛搜索中文化的支持详解!

详解|中文 Jive的搜索借用了apche提供的lucene搜索引擎.lucene是一个纯Java的高性能的全文搜索引擎,你可以到apache的网站找到lucene的更多信息:http://jakarta.apache.org/lucene/docs/index.html 但在Jive使用的lucene包中,并不支持中文搜索,本站的系统也是构建在Jive之上进行扩展,中文搜索问题由JR管理系统主要开发人员之一cherami解决.很多关注Jive的朋友都来信向我们索取Jive中文搜索问题的解决方法

Silverlight 2中多语言支持实现(下)

引言 最近项目要在Silverlight 2应用程序中实现本地化,原以为这个过程非常简单,却没想到实现的时候 一波三折,好在结果还算不错.需求是这样的,用户第一次访问的时候,默认为英文,当用户选择一种显 示语言后,记录在本地,下次用户访问时直接显示已经选择的语言.现在我把整个实现的过程记录下来, 希望对大家有所帮助. 苦笑不得的缺陷 在Silverlight 2中多语言支持实现(上)文章的最后,我们通过修改项目文件中SupportedCultures 来实现了多语言的支持,之所以能够成功,是因为

CentOS支持中文和ssh支持中文输入的修改

  CentOS支持中文和ssh支持中文输入的修改           Linux支持中文,修改/etc/sysconfig/i18n文件 LANG="zh_CN.GB18030" SUPPORTED="zh_CN.GB18030:zh_CN:zh:en_US.UTF-8:en_US:en" SYSFONT="latarcyrheb-sun16" ssh支持中文输入的修改,如图: 1.如图,点击[Change],选择新宋体或者宋体 2.选择如图红

mysql中字符串索引问题与例子

  字符串索引与数字索引有一些方面如果没做好会非常的慢了,今天我们就一起来看看小编整理的一些mysql中字符串索引问题与例子了,因为字符索引相对来说也简单文章就简单的整理了一些例子,希望对各位有帮助. 事情的起因是线上日志发现的mysql慢查询.100万数据量的标准,联合查询全部走索引的情况下,尽然要600多毫秒.很不解,但是将索引列由varchar(50)型改为bigint型后,数据提升了30倍.究其原因就索引树上搜索时要进行大量的比较操作,而字符串的比较比整数的比较耗时的多. 所以建议一般情

IBM WebSphere Commerce在Madisons中的客户支持

客户制定这个术语指的是一个流程,在该流程中,客服代表(CSR)有权使用客户/购物者的身份,代表他们执行某些操作.这些客户是系统中的已注册购物者.客户制定这个术语可以与引导购物互换使用. WebSphere Commerce 提供业务用户工具 (WebSphere Commerce Accelerator and Sales Center),CSR 可以在这里管理来自潜在客户的查询.不过,这些工具是不同的应用程序,并且与消费者用于购物的店面应用程序的外观有所不同.虽然通过这些工具来执行 CSR 操

异常-java核心技术中一个关于数组的例子不理解,请教大家

问题描述 java核心技术中一个关于数组的例子不理解,请教大家 Person是Employer的父类,Employer有个新方法setBonus,代码如下 Employer[] emprs ={new Employer("张三"),new Employer("李四")}; Person[] ps =emprs; ps[0] = new Person("小明");//运行时该行报错ArrayStoreException emprs[0].setBo

excel-请问在.net中aspose.cells支持由Excel的名称管理器来获取单元格或者表格吗?

问题描述 请问在.net中aspose.cells支持由Excel的名称管理器来获取单元格或者表格吗? 请问aspose.cells支持由Excel的名称管理器来获取单元格或者表格吗?