bidi(双向文字)与RTL布局总结

  BIDI

  双向文字就是一个字符串中包含了两种文字,既包含从左到右的文字又包含从右到左的文字。

  大多数文字都是从左到右的书写习惯,比如拉丁文字(英文字母)和汉字,少数文字是从右到左的书写方式比如阿拉伯文(ar)跟希伯来文(he)。对于需要国际化支持的web应用来说,由于阅读习惯的不同在web页面排版和布局中会给开发人员带来麻烦。这种情况多数出现在从右到左的文字中,比如字符串中出现阿拉伯文、英文字母、数字以及标点符号。本文就是我在工作中遇到该类问题的总结。

  在现代计算机应用中,最常用来处理双向文字的算法是 Unicode 双向算法(Unicode Bidirectional Algorithm),在后面的文章中我们将 Unicode 双向算法简称为 bidi 算法。

  我们的web产品中使用的字符都属于unicode字符,而unicode字符的方向属性总共包含三类:强字符、中性字符、弱字符。

  强字符的方向属性是确定的,与上下文的bidi属性无关,而且强字符在bidi算法中可能会对其前后的中性字符产生影响。大部分的字符都属于强字符,比如拉丁字符、汉字、阿拉伯字符。

  中性字符的方向性并不确定,受其上下文的bidi属性影响(前后的强字符)。比如大部分的标点符号(“-”,“[]”,"()"等)跟空格。

  弱字符的方向性是确定的,但不会对其上下文的bidi属性产生影响。比如数字以及跟数字相关的符号。

    一个区域内有总体方向,决定从这个区域的哪边开始书写文字,通常称为基础方向。浏览器会根据你的默认语言来设置默认的基础方向,如英语、汉语的基础方向为从左到右,阿拉伯语的基础方向为从右到左。

  方向串是指在一段文字中具有相同方向性的连续字符,并且其前后没有相同方向性的其它方向串。

  下方假设大写字母为从右到左的文字。

  

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

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

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

<p dir="rtl">The apple is called <bdo dir="rtl">APPLE</bdo> in ar.</p>

  

  Web中控制文字方向的方式有三种:html实体(&lrm; &rlm;)、bid与bdo标签+dir属性、css属性(direction + unicode-bidi)

  &lrm;与&rlm;可以用来打断方向串的连续性,影响中性字符的方向

  

   下面这段文本中共有四个中性字符:"."、 "+"、 "("、")";受从左到右基础方向影响这几个字符的方向性都表现为从左到右,界面也是正常的。

<p dir="ltr">My first paragraph.U+202(C)</p>

  如果将基础方向设置为从右到左

<p dir="rtl">My first paragraph.U+202(C)</p>

  最右边的")"受基础方向影响会出现我们不想要的结果,而其他三个中性字符受上下文方向性影响依旧保持从左到右的方向性。

  我们可以使用&lrm;实体来改变")"的方向性。

<p dir="rtl">My first paragraph.U+202(C)‎</p>

  在上文介绍方向串时已经看到大写字母变成从右到左的方向这就是bdo元素+dir的作用,覆盖元素内文本的方向性。

  bdi元素的目的是设置一个隔离区域。如果不设置dir则使用上下文的基础方向。

<ul>
<li>Username Bill:80 points</li>
<li>Username <bdi><bdo dir="rtl">Steve</bdo></bdi>: 78 points</li>
</ul>

  大家可以试试把bdi元素去掉是什么效果,试着分析一下里面的方向串。

  如果设置dir属性那么就为这个隔离区域设置了一个基础方向。

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

  

  注意里面的空格跟标点符号的方向性。

  directionunicode-bidi这两个是css属性,通常放在一起来控制文本的方向,大家可以自己查看一下css手册

  direction+unicode-bidi:embed 的效果类似于bdi元素; direction+ unicode-bidi: bidi-override 的效果类似于bdo元素。

  实际项目中我遇到阿拉伯语下在表格中显示负数问题,看起来的效果是:“88-”;使用以上属性direction:ltr,unicode-bidi:embed,可以改变显示效果:“-88”。

 

  RTL布局

   工作中遇到的另一个跟语言相关的问题就是页面布局问题。阿拉伯文(ar)跟希伯来文(he)的页面布局同英语下的页面布局刚好是镜像关系。这一点大家可以试试把浏览器的语言设置为阿拉伯语,观察一下浏览器上的控件布局(要保证你能再设置回来)。

  首先判断用户设置的语言,如果是ar跟he则将全局基础方向设置为rtl,这时基本可以解决大多数问题。

function localeIsSame(locale1, locale2){
    return locale1.indexOf(locale2) > -1 || locale2.indexOf(locale1) > -1;
  }

  function _setRTL(locale){
    var rtlLocales = ["ar", "he"];
    var dirNode = document.getElementsByTagName("html")[0];
    var isRTLLocale = false;
    for (var i = 0; i < rtlLocales.length; i++) {
      if (localeIsSame(rtlLocales[i], locale)) {
        isRTLLocale = true;
      }
    }

    if (isRTLLocale) {
      dirNode.setAttribute("dir", "rtl");
      dirNode.className += " esriRtl jimu-rtl";
      dirNode.className += " " + locale + " " +
        (locale.indexOf("-") !== -1 ? locale.split("-")[0] : "");
    }else {
      dirNode.setAttribute("dir", "ltr");
      dirNode.className += " esriLtr jimu-ltr";
      dirNode.className += " " + locale + " " +
        (locale.indexOf("-") !== -1 ? locale.split("-")[0] : "");
    }

    window.isRTL = isRTLLocale;
  }

 然后将float和text-align以及控制间距的margin、padding从所有的css class中抽离出来单独成类,如:

  

  在RTL时将他们左右互换

  

  在代码中与rtl布局相关的部分通过判断全局变量window.isRTL来处理。

html[dir='rtl'] caption,
html[dir='rtl'] th {
  text-align: right;
}

.jimu-rtl {
  direction: rtl;
}

.jimu-align-trailing {
  text-align: right;
}
.jimu-align-leading {
  text-align: left;
}
.jimu-float-trailing {
  float: right;
}
.jimu-float-leading {
  float: left;
}
.jimu-numeric-value {
  direction: ltr;
  unicode-bidi: embed;
}
/* if a ltr element is inside a rtl page */
.jimu-ltr .jimu-float-leading {
  float: left !important;
}

/* RTL alignment */
.jimu-rtl .jimu-align-trailing {
  text-align: left;
}
.jimu-rtl .jimu-align-leading {
  text-align: right;
}

.jimu-rtl .jimu-float-trailing {
  float: left;
}
.jimu-rtl .jimu-float-leading {
  float: right;
}
/******* margins ******/
.jimu-leading-margin0 {
  margin-left: 0;
}
.jimu-leading-margin025 {
  margin-left: 0.25em;
}
.jimu-leading-margin05 {
  margin-left: 0.5em;
}
.jimu-leading-margin1 {
  margin-left: 1em;
}
.jimu-leading-margin15 {
  margin-left: 1.5em;
}
.jimu-leading-margin2 {
  margin-left: 2em;
}
.jimu-leading-margin25 {
  margin-left: 2.5em;
}
.jimu-leading-margin3 {
  margin-left: 3em;
}
.jimu-leading-margin35 {
  margin-left: 3.5em;
}
.jimu-leading-margin4 {
  margin-left: 4em;
}
.jimu-leading-margin5 {
  margin-left: 5em;
}
.jimu-leading-margin6 {
  margin-left: 6em;
}
.jimu-leading-margin7 {
  margin-left: 7em;
}
.jimu-leading-margin10 {
  margin-left: 10em;
}

.jimu-trailing-margin025 {
  margin-right: 0.25em;
}
.jimu-trailing-margin05 {
  margin-right: 0.5em;
}
.jimu-trailing-margin075 {
  margin-right: 0.75em;
}
.jimu-trailing-margin1 {
  margin-right: 1em;
}
.jimu-trailing-margin15 {
  margin-right: 1.5em;
}
.jimu-trailing-margin2 {
  margin-right: 2em;
}
.jimu-trailing-margin25 {
  margin-right: 2.5em;
}
.jimu-trailing-margin3 {
  margin-right: 3em;
}
.jimu-trailing-margin35 {
  margin-right: 3.5em;
}
.jimu-trailing-margin4 {
  margin-right: 4em;
}
.jimu-trailing-margin5 {
  margin-right: 5em;
}
.jimu-trailing-margin6 {
  margin-right: 6em;
}

.jimu-leading-padding05 {
  padding-left: 0.5em;
}
.jimu-leading-padding1 {
  padding-left: 1em;
}
.jimu-trailing-padding1 {
  padding-right: 1em;
}

/* RTL related: margins, padding */
.jimu-rtl .jimu-leading-margin0 {
  margin-right: 0;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin025 {
  margin-right: 0.25em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin05 {
  margin-right: 0.5em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin075 {
  margin-right: 0.75em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin1 {
  margin-right: 1em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin15 {
  margin-right: 1.5em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin2 {
  margin-right: 2em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin25 {
  margin-right: 2.5em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin3 {
  margin-right: 3em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin35 {
  margin-right: 3.5em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin4 {
  margin-right: 4em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin5 {
  margin-right: 5em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin6 {
  margin-right: 6em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin7 {
  margin-right: 7em;
  margin-left: auto;
}
.jimu-rtl .jimu-leading-margin10 {
  margin-right: 10em;
  margin-left: auto;
}

.jimu-rtl .jimu-trailing-margin025 {
  margin-left: 0.25em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin05 {
  margin-left: 0.5em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin075 {
  margin-left: 0.75em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin1 {
  margin-left: 1em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin15 {
  margin-left: 1.5em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin2 {
  margin-left: 2em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin25 {
  margin-left: 2.5em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin3 {
  margin-left: 3em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin4 {
  margin-left: 4em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin5 {
  margin-left: 5em;
  margin-right: auto;
}
.jimu-rtl .jimu-trailing-margin6 {
  margin-left: 6em;
  margin-right: auto;
}

.jimu-rtl .jimu-leading-padding05 {
  padding-right: 0.5em;
  padding-left: auto;
}
.jimu-rtl .jimu-leading-padding1 {
  padding-right: 1em;
  padding-left: auto;
}
.jimu-rtl .jimu-trailing-padding1 {
  padding-left: 1em;
  padding-right: auto;
}

  参考文章:

  bidi算法及HTML中的实现

  direction:rtl在布局中的使用

      实践:使用 HTML 标记显示全局化中从右到左的文字

时间: 2024-10-18 01:42:02

bidi(双向文字)与RTL布局总结的相关文章

在安卓应用上支持从右到左(RTL)布局

世界上的大部分语言的书写方式都是从左到右,但是也有一些语言是从右到左(Right to Left,以下简称为 RTL )书写的,譬如阿拉伯语,希伯来语以及叙利亚语.虽然这些都是小语种,支持RTL能给当地用户更好的体验. 从 Google 官网得知,安卓在SDK17(4.2 Jelly Bean)版本的以上能原生的支持RTL,只需以下几个步骤就能实现. 在 AndroidManifest.xml 的 uses-sdk 标签中,将 targetSdkVersion 或 minSdkVersion 设

10个在文字排版/网页布局中的常见错误

这篇文章的目的是帮助设计者们和顾客们去理解好的排版技巧的重要性,当避免一些常见的错误的时候.请记住这些错误的大部分是主观的以及在项目.目标或环境能够被改变的 下面列出了10个在排版/布局中使用到的常见错误,这些错误可能在你设计的效果和外观中产生大的影响.当在考虑印刷时它能为你节省时间和金钱. 1.没有足够的行间距(leading) 行间距/leading能改善整页中文字块的阅读效果,这样做是为了当读者阅读下一行的时候不会找不到他们的位置.太小文字可能引起一种受压迫感.记住不同的字体需要不同的行间

HTML教程-表格内文字的对齐/布局

教程 表格中数据的排列方式有两种,分别是左右排列和上下排列.左右排列是以ALIGN属性来设置,而上下排列则由VALIGN属性来设置.其中左右排列的位置可分为三种:居左(left).居右(right)和居中(center):而上下排列基本上比较常用的有四种:上齐(top).居中(middle).下齐(bottom)和基线(baseline). #=left, center, right #=top,middle,bottom,baseline 左右排列 居左 居中 居右 A B C 显示结果: 居

在 Java 开发过程中支持双向字符集语言(BiDi)

BiDi 是什么 W3C 对双向字符集语言(即 BiDi)进行了如下的定义: 双向字符集语言通常是指文字可以从左到右(LTR)和从右到左(RTL)双向书写的文字. 例如,阿拉伯和希伯来语言的文字书写通常是从右到左,但是其中的其它字符集(例如拉丁 文字)依然保持从左到右的格式.当然其它的语言文字,例如英文,如果包含阿拉伯或者希 伯来文字摘要的话,也可以是双向书写的.通常将主方向称为全局方向. 对于介绍一种的新的知识或者技术,笔者通常习惯于从"what. why.who.how"几个方 面

iOS8的颜色、文字和布局学习

  在去年,Apple针对新时代用户彻底更新了其设计语言.现在的设计语言相对之前大为简化,能够让设计师将精力集中到动画和功能上,而不是繁复的视觉细节上. 很多人都曾问过我:设计应当如何入门?成为一名优秀设计师有没有捷径可走?要我说,虽然没有捷径,但确实有几个适用于iOS的设计技巧和规则能够从全局角度改变你的设计方式. 当然,即便你目前的设计目标是完全不同于iOS的平台,相互之间的设计理念也是相通的,你可以将在web和印刷领域学习到的技巧运用到iOS设计中去.iOS 8是一个让设计寻回根源的平台,

在HTML中实现bidi支持的例子

通过对比 Unicode 控制字符和 HTML 标记,读者可以了解在 Web 中实现文字方向性控制的两种方法以及其各自特点.本文使用在 HTML 中实现 bidi 支持的例子更能让读者对 bidi 在 Web 中的实现拥有更加直观和 深入的理解. 在开始介绍 bidi 算法和其在 HTML 中的实现之前,我们先来了解一下文字.语言和方向的关系,这也将有助于在后文中更好地理解 bidi 算法. 什么是文字和语言呢?我们引用 IBM Terminology 中的定义: 文字是使用于书面语的图形符号的

Android 4.2原生支持从右到左的文字排列格式

转自 http://www.importnew.com/3517.html Android 4.1(Jelly Bean)  在TextView和EditText 元素里对"双向文字顺序"提供了有限的功能支持,允许应用程序在编辑和显示字符的时候,能够同时支持从左到右(LTR)以及从右到左(RTL)的排列格式.Android 4.2目前已经对"从右到左"的文字排列顺序给予了原生级别的全面支持,包括提供了一个布局镜面工具,使得开发者把能够将优质的用户体验带给每一位用户,

CSS3让网页更富于表现和支持更复杂布局

文章简介:CSS3 Region:基于HTML和CSS3的富页面布局. 译自:CSS3 regions: Rich page layout with HTML and CSS3中文:CSS3 Region:基于HTML和CSS3的富页面布局请尊重版权,转载请注明来源,多谢! 互联网已经成为一个提供参考.教材.新闻.文章和交互应用的大宝库了.然而,当为印刷设计内容时,一些功能显然仍然不可能或者很难使用Web标准来实现. 印刷出版物正在探索更好的方法来转换或者改变他们的内容以适应富数字格式.我们也看

Web设计误区:网页设计精良的布局

文章描述:设计一个非常好的布局是一件非常不容易的事情,而且判断的方式也非常主观.任何一个设计可能会取悦你,也可能让其它人厌恶.尽管这样,这里仍旧有些大家都承认的设计误区. 即使Web设计已经成为一个真正的产业,开发一个网站仍旧是技术和艺术的结合.一个网站的设计既可以带来大量流量,同时也可以吓走大量用户,当然这些都和设计师相关.经验.天份和能力是一个设计师最强大的工具.一个设计精良的布局是Web设计的基础,而且,这也是一个非常耗时的工作. 设计一个非常好的布局是一件非常不容易的事情,而且判断的方式