滴滴出行小程序I18n最佳实践

做者: sky-admin猫儿不熊

背景

I18n = Internationalization,国际化,由于单词由首末字符i/n和中间18个字母组成,简称i18n。对程序来讲,就是要在不修改内部代码的状况下,能根据不一样语言及地区显示相应的界面,以支持不一样语言的人顺利使用程序。

业务背景

互联网行业进入下半场,精细化运营是关键。多语言支持能让产品更好地服务境内的其余语言用户,也为产品出海打下基础,随着 WeChat/Alipay 的全球化,你的小程序是否作好准备了呢?html

4月初,滴滴出行小程序团队接到支持英文版的需求,预计上线时间为6月上旬。当前滴滴出行小程序集成的众多业务线和各类公共库,展现给用户的有前端硬编码的静态文本和服务端下发的文案,都要同步接入多语言。考虑到小程序当前的体量,光文本收集、语料翻译、npm package 支持,联调,测试,沟通成本等等,而且前端开发只投入1.5人力的状况下,时间是蛮紧迫的,可是咱们抗住了压力,最终英文版滴滴出行小程序如期上线,截止目前运行稳定,用户反馈良好,获得了超出预期的收益。前端

固然这一切得益于各团队同窗的高效工做,和各团队的通力配合,更得益于部门技术团队 Mpx框架优雅的多语言能力支持。划重点来咯,所谓工欲善其事必先利其器,若是你的公司业务须要开发小程序,也须要接入多语言,那么请搬好小板凳,咱们来看一下小程序框架 Mpx 是如何优雅支持多语言能力。相信看完这篇,能够帮助你认识 Mpx(https://github.com/didi/mpx) ,加深对框架的理解,最终利用 Mpx 框架高效迭代小程序,年终奖多出那部分能够打赏一下做者,买杯咖啡哈(偷笑.jpg)vue

如下是滴滴出行小程序的中英文版本对比: webpack

滴滴出行微信小程序i18n

也欢迎你们在微信/支付宝里搜索滴滴出行小程序,实际使用感觉下。PS:切换语言的方法是,打开小程序,点击左上角用户头像,进入侧边栏设置页面,点击切换中英文便可体验。git

技术背景

在上述业务背景下,Mpx 框架——滴滴自研的专一提高小程序开发体验的加强型小程序框架,内建 i18n 能力便提上日程。github

与 WEB 不一样,小程序(本文以微信小程序为例)运行环境采用双线程架构设计,渲染层的界面使用 WebView 进行渲染,逻辑层采用 JSCore 线程运行 JS脚本。逻辑层数据改变,经过 setData 将数据转发到 Native(微信客户端),Native 再将数据转发到渲染层,以此更新页面。因为线程间通讯成本较高,实际项目开发时须要控制频次和数量。另外小程序的渲染层不支持运行 JS ,一些如事件处理等操做没法在渲染层实现,所以微信官方提供了一套脚本语言 WXS ,结合 WXML ,能够构建出页面的结构(不了解 WXS ?戳这里)。web

基于小程序的双线程架构设计,实现 i18n 存在一些技术上的难点与挑战,因为 Mpx 框架早期构建起来的强大基础,最终得以优雅支持多语言能力,实现了和vue-i18n 基本一致的使用体验。npm

使用

在使用上,Mpx 支持 i18n 能力提供的 API 与 vue-i18n 大致对齐,用法上也基本一致。gulp

模板中使用 i18n

编译阶段经过用户配置的 i18n 字典,结合框架内建的翻译函数经过 wxs-i18n-loader 合成为可执行的 WXS 翻译函数,并自动注入到有翻译函数调用的模板中,具体调用方式以下图。小程序

// mpx文件
<template>
  <view>
    <view>{{ $t('message.hello', { msg: 'hello' })}}</view>
    <!-- formattedDatetime计算属性,可基于locale变动响应刷新 -->
    <view>{{formattedDatetime}}</view>
  </view>
</template>

JS 中使用 i18n

经过框架提供的 wxs2js 能力,将 WXS 翻译函数转换为 JS 模块注入到 JS 运行时,使运行时环境中也可以调用翻译函数。

// mpx文件
<script>
  import mpx, { createComponent } from '@mpxjs/core'
  createComponent({
    ready () {
      // js中使用
      console.log(this.$t('message.hello', { msg: 'hello' }))
      // 局部locale变动,生效范围为当前组件内
      this.$i18n.locale = 'en-US'
      setTimeout(() => {
        // 全局locale变动,生效范围为项目全局
        mpx.i18n.locale = 'zh-CN'
      }, 10000)
    },
    computed: {
      formattedDatetime () {
        return this.$d(new Date(), 'long')
      }
    }
  })
</script>

定义 i18n 字典

项目构建时传入 i18n 配置对象,主要包括语言字典和默认语言类型。

new MpxWebpackPlugin({
  i18n: {
    locale: 'en-US',
    // messages既能够经过对象字面量传入,也能够经过messagesPath指定一个js模块路径,在该模块中定义配置并导出,dateTimeFormats/dateTimeFormatsPath和numberFormats/numberFormatsPath同理
    messages: {
      'en-US': {
        message: {
          hello: '{msg} world'
        }
      },
      'zh-CN': {
        message: {
          hello: '{msg} 世界'
        }
      }
    },
    // messagesPath: path.resolve(__dirname, '../src/i18n.js')
  }
})

若是是经过 Mpx 提供的 cli 工具生成的项目,这部分配置会在 mpx.conf.js 文件中,不光能够直接内联写在该文件中,也能够指定语言包的路径。

以上,Mpx 的 i18n 方案接入成本低,使用优雅,体验优秀。直观感觉可参考下面 mpx i18n demo :https://github.com/didi/mpx/t...

方案

Mpx框架的 i18n 支持几乎彻底实现了 vue-i18n 的所有能力,下面咱们来详细说明 Mpx 框架 i18n 能力的具体实现。

方案探索

基于小程序运行环境的双线程架构,咱们尝试了不一样方案,具体探索过程以下:

方案一:基于 Mpx 框架已提供的数据加强能力 computed 计算属性,来支持 i18n 。该方案与 uniapp 的实现思路类似(后文会进行对比分析),存在必定不足,包括线程通讯带来的性能开销和for循环场景下的处理较复杂等,最终放弃。
方案二:基于 WXS + JS 支持 i18n 适配。经过视图层注入 WXS,将 WXS 语法转换为 JS 后注入到逻辑层,这样视图层和逻辑层都可实现 i18n 适配,而且在必定程度上有效减小两个线程间的通讯耗时,提升性能。

从性能和合理性上考虑,咱们最终采用了方案二进行 Mpx 的 i18n 方案实现。

mpx-i18n内部流程示意图

Mpx i18n 架构设计图

因为各大小程序平台上,WXS 语法和使用均存在较大差别,所以该方案实现过程当中也存在一些技术上的难点,这些难点基于 Mpx 框架的早期构建起来的跨平台能力也一一得以攻克,具体以下。

实现难点

WXS 在模板中运行的跨平台处理

WXS 是运行在视图层中的 JS,能够减小与逻辑层通讯耗时,提升性能。所以 Mpx 框架在迭代初期便已支持在模板和 JS 运行环境使用 WXS 语言,而且针对小程序跨平台 WXS 语法进行抹平。
在模板中,Mpx 自定义一个 webpack chunk template,以微信 WXS 做为 DSL,利用 babylon 将注入的 WXS 转化成 ast,而后遍历 ast 节点,抹平各大平台对 WXS 语法的处理差别,输出各平台能够识别的类 WXS 文件。目前主要支持微信(WXS)、支付宝(sjs)、百度(filter)、QQ(qs)、头条(sjs)等小程序平台。

WXS 在逻辑层运行的跨平台处理

WXS 与 JavaScript 是不一样的语言,有本身的语法,并不和 JavaScript 一致。而且 WXS 的运行环境和其余 JavaScript 代码是隔离的,WXS 中不能调用其余 JavaScript 文件中定义的函数,也不能调用小程序提供的API。
所以在逻辑层,Mpx 将注入的 WXS 语法转化为 JS,经过 webpack 注入到当前模块。例如 WXS 全局方法 getRegExp/getDate 在 JS 中是没法调用的,Mpx将它们分别转化成 JS 模块,再经过 webpack addVariable 将模块注入到 bundle.js 中。
同理,Mpx 会将编译时注入的 i18n wxs 翻译函数和 i18n 配置对象挂载到全局 global 对象上,利用 mixin 混入到页面组件,并监听 i18n 配置对象,这样JS和模板中便可直接调用 i18n 翻译函数,实现数据响应。

以上即是 Mpx 框架在小程序中支持 i18n 能力的技术细节,因为 WXS 是能够在视图层执行的类 JS 语法的一门语言,这样就减小了小程序逻辑层和视图层的通讯耗时,提高性能。可是因为实现依赖类 WXS 能力,以及 WXS 执行环境的限制,目前模板上可直接使用的翻译函数包括 $t/$tc/$te ,若是须要格式化数字或日期可使用对应的翻译函数在 JS 中 Mpx 提供的计算属性中实现。

输出 web 时使用 i18n

Mpx同时还支持转换产出H5,而 Mpx 提供的 i18n 能力在使用上与 vue-i18n 基本一致,输出 web 时框架会自动引入 vue-i18n,并使用当前的 Mpx i18n 配置信息对其进行初始化,用户无需进行任何更改,便可输出和小程序表现彻底一致的 i18n web 项目。

对比

上面分析了 Mpx 框架的 i18n 方案的技术细节,咱们来看下和其余方案的对比,主要是和 uniapp - 基于 Vue 编写小程序的方案,和微信官方的方案,二者提供的 i18n 支持与Mpx的对比有何优劣。

uniapp的方案

uniapp 提供了对 i18n 能力的支持,是直接引入vue-i18n。但小程序中没法在模板上调用 JS 方法,本质上是利用计算属性 Computed 转换好语言,而后利用模板插值在小程序模板中使用。

模板中:
<view>{{ message.hello }}</view>

JS里须要写:

computed: {  
    message () {  
      return { hello: this.$t('message.hello') }
    }
  }

所以该方案存在一个性能问题,最终的渲染层所看到的文本仍是经过 setData 跨线程通讯完成,这样就会致使线程间通讯增多,性能开销较大。

而且,早期这种形式使用成本较高,后来 uniapp 也针对其作过优化,实现了能够在模板上写 $t() 的能力,使用上方便了很多。

这个 $t() 的实现是在编译时候识别到 $t 就自动替换,帮你替换成一个 uniapp 的 computed 数据,所以数据部分仍是和以前同样要维护两份。尤为是模板上的for循环,即便 for 里只有一个数据要被转换,整个列表都要被替换成一个计算属性,在线程间通讯时进一步加大了性能开销。

微信官方的方案

微信小程序自己也提供了一个 i18n 的方案,仓库地址是:wechat-miniprogram/miniprogram-i18n 。

这个方案从 i18n 自己的实现来说和Mpx框架的设计是相似的,也是基于 WXS 实现(英雄所见略同啊)。但由于周边配套上没有完整的体系,总体使用体验上就也略逊于基于Mpx框架来开发支持 i18n 的国际化小程序了。

主要的点就是,官方提供的方案,要基于 gulp 工具进行一次额外构建,同时在JS中使用时候还要额外引入一个 behavior 去让JS中也可使用翻译能力。

而Mpx框架经过一次统一的Webpack构建产出完整的内容,用户无需担忧语言包更新后忘记从新构建,在JS中使用的时候不光更方便,并且语言信息仍是个响应式的,任何组件均可以很方便地监听语言值的变化去作一些其余的事情。

最后,Mpx的 i18n 方案对比微信官方的方案还有个巨大的优势,结合Mpx的跨平台能力,能实现均以这个方案,一套代码产出支持微信/支付宝/百度/QQ/头条多个平台的支持 i18n 的小程序。

总结

Mpx 框架专一小程序开发,指望为开发者提供最温馨的开发体验,有众多优秀的功能特性,帮助开发者提效。本文介绍的是其内置的 i18n 能力,经过对比分析得出相比其余框架方案在使用成本和性能等方面有明显的优点,欢迎各位有相关需求的同窗进行体验尝试。

将来 Mpx 还会持续迭代优化,提供更多更好的能力帮助小程序开发者提效。在使用过程当中遇到任何问题,欢迎你们在 Git 上提 issue,团队成员会及时响应。同时也鼓励你们一块儿为开源社区作贡献,参与到 Mpx 共建中来,为小程序技术发展添砖加瓦。

Git地址 [https://github.com/didi/mpx]
Mpx文档 [https://mpxjs.cn/]

欢迎技术交流与反馈,顺便star一下鼓励开源项目贡献者,咱们将持续发力贡献社区。

附:以往Mpx文章连接
滴滴开源小程序框架Mpx - https://mpxjs.cn/articles/1.0.html
滴滴小程序框架Mpx发布2.0,支持小程序跨平台开发,可直接转换已有微信小程序 - https://mpxjs.cn/articles/2.0.html
小程序开发者,为何你应该尝试下MPX - https://mpxjs.cn/articles/mpx1.html
Mpx 小程序框架技术揭秘 - https://mpxjs.cn/articles/mpx2.html
滴滴出行小程序体积优化实践 - https://mpxjs.cn/articles/size-control.html

相关文章
相关标签/搜索