I18n: RTL 文字方向的 UI 设计细节

    16 Jan, 2025

    大部分语言文字书写方向是 LTR(从左写到右) 方向,但是还有一些语言文字是 RTL (从右写到左) 方向,比如阿拉伯文,希伯来文、乌尔都文等。使用这些语言的 UI 界面也需要做一些细节调整。

    大部分语言文字书写方向是 LTR(从左写到右) 方向,但是还有一些语言文字是 RTL (从右写到左) 方向,比如阿拉伯文,希伯来文、乌尔都文等。使用这些语言的 UI 界面也需要做一些细节调整。尤其是阿拉伯语,是世界上目前有 6 亿人正在使用的文字语言,相应的,如果一个软件界面使用了阿拉伯语等 RTL 语言,也需要在 UI 做一些调整。

    RTL 适配的内容较为琐碎,本文就尝试做一些总结。

    UI 与功能界面

    我们常用的软件界面需要把功能区按照镜像方式颠倒过来。比如:

    如果导航从左向右展开,RTL 页面应从右向左展开。如果有侧边栏、侧边菜单,那么应当把它放到右边。窗口的关闭按钮同样也放在右边

    比如下图,就是设置页面,两种方向的对比。

    同样,底部菜单栏、水平菜单栏等图标排序方向,也是从右到左。

    如果网站有面包屑(crumb)组件,那么排序方式也应当翻转过来,比如 Home > Category > Subcategory 翻转过来后就是 Subcategory < Category < Home

    如果有时间线组件,那么记住:事件发生顺序要从右到左排列。尤其是要注意 折线图等含有时间轴的统计图表,顺序也是从右到左。 对于条形加载进度条,进度方向也要做出相应的调整

    • 如果有 Toggle Switch 组件,要记住,开(on)状态的指示器应在左侧,关(off)状态在右侧。如下图,

    文字与符号

    阿拉伯文默认对齐方式是右对齐。

    对于阿拉伯文,虽然书写方向是 RTL,但是在混排情况下,还有一些内容是 LTR。比如常用的印度 - 阿拉伯数字,仍然是从左写到右。比如“一千二百三十四”这个数字,仍然写为 12341234 而不是 43214321。在阿拉伯文中,与数字混写时,阿拉伯文是 RTL,但数字是 LTR。同理,如果阿拉伯文中夹杂少量英文单词,那么英文单词也是 LTR。

    هذا نص مختلط، هذا هو الرقم 1234، هذه هي الكلمة الإنجليزية English
    

    另一方面,阿拉伯人写的数学公式比较特殊,有两种情况,一是使用他们自己的阿拉伯字母作为公式符号,二是跟我们一样使用拉丁、希腊字母作为公式符号。

    这两种都需要分情况处理。

    第一种,如果阿拉伯人的数学公式,里面的变量、未知数等使用的是阿拉伯字母符号,那么公式必须镜像化处理。

    不仅推导方向也要改写成从右到左,一加一等于二就不能写成 1+1=21 + 1 = 2 而是 2=1+12 = 1 + 1. 比如下图的公式,算式是从右到左来进行推导演算的,

    还有符号的方向也要镜像化,比如下图中就是一个阿拉伯的高等数学网课截图,注意不定积分的符号方向

    还有数学根式

    但是,数学公式里没有使用阿拉伯字母符号,而是跟我们一样,使用了国际惯例的拉丁、希腊字母符号,就不需要镜像化处理。 比如下面的公式,里面使用了 x,e,ix,e,i拉丁字母作为未知数和变量符号,那么在书写的时候就不需要镜像化。

    图标

    对于图标,也有一点要注意:虽然阿拉伯文字是 RTL,但是阿拉伯人仍然是右撇子,做事还是跟我们一样习惯使用右手。 所以部分图标也不能简单镜像化。

    比如这个放大镜图标,大部分人仍然习惯用右手去拿放大镜,所以设计的时候,手柄位置仍然在右手位置,不要镜像过来。

    还有,这个笔记图标,也是同样的道理,阿拉伯人还是用右手写字,所以设计图标的时候,笔仍然要在右手位置,不要镜像过来。

    一般来说,大部分拟物图标都是按照人类的右手习惯来设计的,在 RTL 布局的设计中,一般不需要操心图标的翻转问题。

    不过还是要注意,如果图标中涉及到文本结构,那么图标还是需要反转,比如下图中,表达“目录树”和“文本”的图标,都需要做调整。

    运动与行为

    在 RTL 的设计中,要注意箭头代表的运动方向,比如分页组件、幻灯片按钮中的“上一项”和“下一项”按钮的箭头,箭头方向不是相反的,但是逻辑是相反的。

    在我们的标准中,左箭头 代表“上一项”,右箭头 代表下一项。

    但是在阿拉伯地区中,左箭头 代表“下一项”,右箭头 代表上一项。 比如在这个阿拉伯新闻网站的新闻列表中,底部分页组件长这样,当前页面是第一页,想跳到下一页,就需要点击左边的左箭头按钮。

    这种运动颠倒行为也可以类比,再比如轮播图组件,对于 RTL 布局,向右滑动是“上一张”,向左滑动是“下一张”。同理,导航中的“前进”和“后退”按钮也要调整过来。

    还有一点需要注意,在对话框中:取消按钮(Cancel)通常在左侧,确认按钮(Confirm)在右侧。

    比如下图中的对话框,左侧是取消按钮,右侧是确认按钮。

    同样的,在 UI 交互界面中,也要把高频使用的,或者希望用户电机的按钮放在右侧,把低频使用的、不希望用户按的按钮放在左侧

    在动画设计中也要做出相应的调整,“进入”动画要设计成“从右到左”,“退出”动画要设计成“从左到右”。

    在移动端,尤其是要注意滑动、拖动方向,在拖动菜单中也要做出调整

    前端设计实现

    如果你的前端页面支持 i18n,如果想要支持阿拉伯语、希伯来语等 RTL 文字,那么以上提到的几点需要注意。在前端设计的布局中,如何支持 RTL,有以下几点启示。

    一般来说,浏览器默认是 LTR 布局的,如果你想切换到 RTL,很简单,只需要在 <html> 或者 <body> 的 DOM 元素上添加 dir 属性,就可以把整个页面设置为 RTL。

    <html dir="rtl">
      <head>
      </head>
      <body>
      </body>
    </html>
    

    这样就可以改变排版流方向了,比如对于本博客页面

    在 CSS 上,有两种方法可以各自适应 RTL 和 LTR。

    第一种是手动法,你可以分别设置针对 RTL 和 LTR 元素的规则的选择器,比如下面的规则,分别对左右的内间距进行设置。

    /* 针对 LTR 的样式 */
    [dir="ltr"] .container {
      padding-left: 20px;
      padding-right: 10px;
    }
    
    /* 针对 RTL 的样式 */
    [dir="rtl"] .container {
      padding-left: 10px;
      padding-right: 20px;
    }
    

    另一种是使用 CSS 的逻辑性规则。比如 margin-inline-start 规则,可以自动检测当前页面的方向,然后再自动做出调整。

    .container {
      text-align: start; /* LTR 时等效为 left,RTL 时等效为 right */
      margin-inline-start: 20px; /* LTR 时等效为左侧间距,RTL 时等效为右侧间距 */
      margin-inline-end: 10px; /* LTR 时等效为右侧间距,RTL 时等效为左侧间距 */
    }
    

    在现有的 CSS 框架中,比如 Tailwind CSS,已经有开箱即用的、现成的 RTL 支持了。你可以使用 rtl:或者 ltr:前缀来自动根据当前布局应用类。

    另外,不要再使用 ml-*,mr-*,left-*,right-* 之类的类,也不要再使用margin-left之类的规则。因为他们是针对具体的客观方向设置距离,而不是针对具体的逻辑方向设置距离。这对自动适应 RTL 非常不利。

    而应当使用 ms-*,me-*,start-*,end-* 等类,或者 margin-start, margin-end 之类的规则,CSS 会自动根据当前的流方向来设置距离,以自动匹配 RTL 和 LTR。

    这是文档对此部分的说明。

    在上文中也提及到,像“前进”、“后退”按钮,还是“Toggle Switch”组件,它们的逻辑是相反的。所以,在 React 中,可以设置一个全局 State,来指示当前的布局是 RTL 和 LTR,以修改按钮的行为。并且,为每个 i18n 语言都设置对应的 RTL 和 LTR 属性,切换语言时也要自动调整布局的 State。