likes
comments
collection
share

企业级:阿拉伯市场适配解决方案

作者站长头像
站长
· 阅读数 21

背景

最近在公司接到一个需求,是对公司的一个产品进行阿拉伯适配。之前也接过类似的需求,什么西班牙语,俄罗斯语啦,这些无非就是对语言进行翻译,(因为公司原有的产品就已经使用了i18n进行了国际化适配了),但是仔细了解过后发现阿拉伯的适配和之前的方案有很大的不同。

这主要是由于阿拉伯国家的阅读习惯的不同导致的。大多数国家的阅读习惯都是是从左往右的,但阿拉伯的阅读习惯却是从右往左的。

这也就导致了阿拉伯国家的页面特点:

  • 排版是从右往左。
  • 文本是向右对齐且从右往左阅读,文本方向始终和语言保持一致,比如数字(电话号码、时间)
  • 方向性图标和我们的方向相反,但其他的图标和图片不会镜像

企业级:阿拉伯市场适配解决方案

所以要适配阿拉伯国际,不仅仅在于它文案的适配,更多的是在于其语言习惯的变化。

如何适配页面呢?

目前市面上最常见的适配方案有两种,一种是"通过transform进行镜像翻转",另一种是“在html标签上直接添加dir="rtl"来改变页面的排版方向”。下面我们来详细分析分析两种方案的利弊吧!

方案一:通过transform进行镜像翻转

在阿拉伯语页面上,我们可以对全局应用 transform: scaleX(-1) 来实现页面的水平翻转。这样可以快速解决布局镜像的问题。然后,再对于不需要翻转的内容,进行二次翻转。这里我们可以使用一个特定的类(如 .not-flip)来包裹,并再次应用 transform: scaleX(-1) 来进行反向翻转,从而保持内容的正常显示。

在阿拉伯语页面上添加上全局翻转:

/* 全局应用水平翻转 */
html[lang="ar"] {
    transform: scaleX(-1);
}

/* 对不需要翻转的内容进行反向翻转 */
html[lang="ar"] .not-flip {
    transform: scaleX(-1);
}

我们可以将翻转相关的样式单独放在一个CSS文件中,并通过条件加载或动态添加CSS类的方式来应用,如果需要动态处理,可以使用JavaScript来检测语言并应用或移除翻转样式。

示例:

// 等待整个文档内容完全加载后再执行
document.addEventListener("DOMContentLoaded", function() {
    // 检查文档的根元素(html)的语言是否为阿拉伯语
    if (document.documentElement.lang === "ar") {
        // 如果是阿拉伯语,将根元素的水平缩放设置为-1,实现水平翻转
        document.documentElement.style.transform = "scaleX(-1)";
        // 选择所有带有类名 "not-flip" 的元素
        const notFlipElements = document.querySelectorAll(".not-flip");
        // 遍历所有选中的 "not-flip" 元素
        notFlipElements.forEach(function(element) {
            // 将每个 "not-flip" 元素的水平缩放设置为-1,恢复正常显示
            element.style.transform = "scaleX(-1)";
        });
    }
});

处理后的效果如下:

企业级:阿拉伯市场适配解决方案 如上图所示,通过翻转解决了布局问题,但文字和图像也被翻转。为了解决这个问题,对于不需要翻转的内容(如文字、非指向性图像),需要进行二次翻转。

优缺点

优点: 无需修改js逻辑,只需要处理css。

缺点: 首次翻转只需要处理根节点,而二次翻转则需要处理所有不需要翻转的元素,工作量较大。

方案二:在html标签上直接添加dir="rtl"

在html标签上直接添加dir="rtl"的作用和direction: rtl样式的效果是一样,它可以改变我们网站的整体布局,实现从右到左(RTL)的页面布局,这种方式会改变文本、表格列和水平溢出的方向,但不会改变文字和图片的显示方向

html标签属性添加默认值dir="ltr", 例如如: <html dir="rtl">

处理后的效果如下:

企业级:阿拉伯市场适配解决方案

在设置页面为RTL(从右到左)布局后,我们可以发现UI并没有完全兼容RTL场景。具体观察到以下情况:

  1. 文本对齐:
    • 如果元素没有预先定义 text-align,那么该元素的文本会从左对齐变成右对齐。
    • 如果设置了 leftcenter,则 direction 的设置不会对其产生影响。
  2. 布局方向:
    • inline-blockflextablegrid 的布局方向会受到影响。
    • absolutefixedfloatmarginpadding 等属性不会受到影响。

为了确保页面在RTL布局时能够正常呈现,我们需要对未被影响的属性进行调整。目前有以下三种解决方案:

使用CSS逻辑属性与逻辑值

CSS逻辑属性和逻辑值使用抽象术语块向和行向描述其流向:

  • 块向尺度(block):垂直于文本流向的尺寸。
  • 行向尺度(inline):与行内文本流向平行的方向上的尺度。

在LTR(从左到右)布局时:(把css样式代码从物理特性修改成逻辑性质)

逻辑值

详细的对照可以看下面这两张图

Physical Property(物理特性)

企业级:阿拉伯市场适配解决方案

Logical Property (逻辑性质)

企业级:阿拉伯市场适配解决方案

通过改写为逻辑属性,可以同时适配LTR和RTL布局,无需专门为RTL布局进行适配。例如:将 margin-left 改写成 margin-inline-startleft: 0; 改写成 inline-start: 0;我们只需要全局替换需要调整的行向尺度的CSS属性即可。

使用开源工具 postcss-rtl

在GitHub上可以找到 postcss-rtl 开源插件,它的原理是对CSS文件进行处理,将CSS属性中的 left 改为 right,right 改为 left,从而自动适配RTL布局。

我们需要注意的是

  • 浏览器兼容性:

使用逻辑属性时需要考虑浏览器的兼容性问题。对于B端项目,可以考虑使用逻辑属性,因为这些项目通常在兼容性较好的环境中运行。

  • 代码处理范围:

开发者只能处理本地代码,无法处理npm包中的代码。因此,使用 postcss-rtl 插件可以自动处理所有CSS文件,包括本地代码和第三方库的样式。

vue引入示例

webpack中引入插件postcss-rtl(opens new window)

vue-cli2脚手架配置: 安装依赖npm install postcss-loader postcss-rtl --save-dev

webpack 配置文件(例如 cloud/build/utils.js)中添加 postcss-loaderpostcss-rtl 插件。

// 定义一个 postcssLoader 对象,用于配置 postcss-loader
var postcssLoader = {
  loader: 'postcss-loader', // 指定使用 postcss-loader
  options: {
    postcssOptions: { // 配置 postcss 的选项
      plugins: [
        [ 'postcss-rtl', {} ] // 添加阿拉伯语右排布局插件 postcss-rtl
      ]
    }
  }
}

// 生成用于 extract text plugin 的加载器字符串的函数
function generateLoaders(loader, loaderOptions) {
  // 初始化一个包含 cssLoader、autoprefixerLoader 和 postcssLoader 的加载器数组
  var loaders = [cssLoader, autoprefixerLoader, postcssLoader]
  
  // 如果传入了 loader 参数,则将相应的 loader 配置添加到加载器数组中
  if (loader) {
    loaders.push({
      loader: loader + '-loader', // 动态指定 loader 名称,例如 'sass-loader'
      options: Object.assign({}, loaderOptions, { // 合并传入的 loaderOptions 和 sourceMap 选项
        sourceMap: options.sourceMap // 将 sourceMap 选项添加到 loader 配置中
      })
    })
  }

  // 省略其他代码...
  ...
}

vue-cli3脚手架配置: 安装依赖yarn add postcss-rtl -D 

webpack中(apps-moblie-docs/vue.config.js)文件里添加postcss-rtl插件

css: {
  // 是否启用 sourceMap,根据 isProduction 变量确定
  sourceMap: !isProduction,

  // 加载器选项
  loaderOptions: {
    // PostCSS 相关配置
    postcss: {
      // PostCSS 插件列表
      plugins: [
        // 添加阿拉伯语右排布局插件 postcss-rtl
        require('postcss-rtl')()
      ]
    }
  }
}

app.vue入口里添加根据语言判断修改html的dir属性,比如: document.documentElement.setAttribute('dir', this.$i18n.locale === 'ar' ? 'rtl' : 'ltr')

方向的图标处理:

// 适配右排布局图标方向
[dir=rtl]{
  .components-icons{
    &.components-icons-back{
      &:before {
        display: inline-block;
        transform: scaleX(-1);
      }
    }
  }
}
  • 元素拼接的语句的处理:
// 适配右排布局
[dir=rtl] {
  .yun-row__desc {
    direction: ltr;
    display: inline-flex;
    justify-content: flex-end;
  }
}

使用[dir="rtl"]和[dir="ltr"]对不能自动适配的属性进行适配

示例:

[dir="rtl"].box {
//选择所有具有 dir="rtl" 属性并且类名为 .box 的元素。
    float: right;
    margin-right: 0;
    margin-left: 16px;
}
[dir="ltr"]  .box {
    float: left;
    margin-right: 16px;
    margin-left: 0;
}

优点:是工作量减少,代码入侵减少;

缺点:是需要处理方向性的图标的方向和被元素拼接的语句(断句)。

这里推荐几个自动将 CSS 从 LTR 转换为 RTL 的工具

  • CSS 转换包

    • CSS FLIP :这是一个由 Twitter 开源的项目,可以帮助你将 LTR CSS 转换为 RTL 格式。你可以通过 npm 包管理器安装它(npm install css-flip),安装完成后,可以使用命令行界面 (CLI) 将 LTR 的 CSS 文件转换为 RTL 格式。

    • RTL CSS :它类似于 CSS FLIP,同样可以通过 npm 包管理器进行安装,RTL CSS 可以配合 PostCSS 等工具链使用,也可以单独使用其命令行界面。

  • 在线转换工具

    • CSSJanus : 这是一个在线的 LTR 到 RTL CSS 转换工具。他可以免去我们安装依赖包的过程,你只需要将 LTR 的 CSS 代码复制粘贴到该网站,就可以得到转换后的 RTL 代码。
    • Rastchin : 和CSSJanus类类似,不同的是它除了基本的转换功能之外,Rastchin 还提供了一些额外的选项,例如生成压缩的 RTL CSS 代码,以及检查 LTR CSS 代码的语法错误等。

结论

方案优点缺点
transform无需修改js逻辑,只需要处理css代码入侵大,工作量大
direction工作量减少,代码入侵减少处理方向性的图标的方向和被元素拼接的语句(断句)
转载自:https://juejin.cn/post/7382987557544099840
评论
请登录