相關學習推薦:微信小程式教學
I18n = Internationalization,國際化,因為單字由首末字元i/n和中間18個字母組成,簡稱i18n。對程式來說,就是要在不修改內部程式碼的情況下,能根據不同語言及地區顯示對應的介面,以支援不同語言的人順利使用程式。
網路產業進入下半場,精進營運是關鍵。多語言支援能讓產品更好地服務境內的其他語言用戶,也為產品出海打下基礎,隨著 WeChat/Alipay 的全球化,你的小程式是否做好準備了呢?
4月初,滴滴出行小程式團隊接獲支援英文版的需求,預計上線時間為6月上旬。目前滴滴出行小程式整合的眾多業務線和各種公共庫,展示給用戶的有前端硬編碼的靜態文字和服務端下發的文案,都要同步接入多語言。考慮到小程式目前的體積,光文本收集、語料翻譯、npm package 支持,聯調,測試,溝通成本等等,並且前端開發只投入1.5人力的情況下,時間是蠻緊迫的,但是我們抗住了壓力,最終英文版滴滴出行小程序如期上線,截止目前運行穩定,用戶反饋良好,得到了超出預期的收益。
當然這一切得益於各團隊同學的高效工作,和各團隊的通力配合,更得益於部門技術團隊 Mpx框架優雅的多語言能力支援。劃重點來咯,所謂工欲善其事必先利其器,如果你的公司業務需要開發小程序,也需要接入多語言,那麼請搬好小板凳,我們來看一下小程序框架Mpx 是如何優雅支持多語言能力。相信看完這篇,可以幫助你認識Mpx(https://github.com/didi/mpx) ,加深對框架的理解,最終利用Mpx 框架高效迭代小程序,年終獎多出那部分可以打賞一下作者,買杯咖啡哈(偷笑.jpg)
以下是滴滴出行小程式的中英文版本對比:
也歡迎大家在微信/支付寶裡搜尋滴滴出行小程序,實際使用感受下。 PS:切換語言的方法是,打開小程序,點擊左上角用戶頭像,進入側邊欄設定頁面,點擊切換中英文即可體驗。
在上述業務背景下,Mpx 框架-滴滴自研的專注提升小程式開發體驗的增強型小程式框架,內建i18n 能力便提上日程。
與 WEB 不同,小程式(本文以微信小程式為例)運行環境採用雙執行緒架構設計,渲染層的介面使用 WebView 進行渲染,邏輯層採用 JSCore 執行緒執行 JS腳本。邏輯層資料改變,透過 setData 將資料轉送到 Native(微信客戶端),Native 再將資料轉送到渲染層,以此更新頁面。由於線程間通訊成本較高,實際專案開發時需要控制頻率和數量。另外小程式的渲染層不支援運行JS ,一些如事件處理等操作無法在渲染層實現,因此微信官方提供了一套腳本語言WXS ,結合WXML ,可以構建出頁面的結構(不了解WXS ?戳這裡)。
基於小程式的雙執行緒架構設計,實現i18n 存在一些技術上的難點與挑戰,由於Mpx 框架早期構建起來的強大基礎,最終得以優雅支持多語言能力,實現了和vue-i18n基本一致的使用體驗。
在使用上,Mpx 支援 i18n 能力提供的 API 與 vue-i18n 大體對齊,用法上也基本一致。
編譯階段透過使用者配置的i18n 字典,結合框架內建的翻譯函數透過wxs-i18n-loader 合成為可執行的WXS 翻譯函數,並自動注入到有翻譯函數呼叫的模板中,具體調用方式如下圖。
// mpx文件<template> <view> <view>{{ $t('message.hello', { msg: 'hello' })}}</view> <!-- formattedDatetime计算属性,可基于locale变更响应刷新 --> <view>{{formattedDatetime}}</view> </view></template>复制代码
透過框架提供的 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 配置對象,主要包括語言字典和預設語言類型。
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 :github.com/didi/mpx/tr…
Mpx框架的 i18n 支持几乎完全实现了 vue-i18n 的全部能力,下面我们来详细说明 Mpx 框架 i18n 能力的具体实现。
基于小程序运行环境的双线程架构,我们尝试了不同方案,具体探索过程如下:
方案一:基于 Mpx 框架已提供的数据增强能力 computed 计算属性,来支持 i18n 。该方案与 uniapp 的实现思路相似(后文会进行对比分析),存在一定不足,包括线程通信带来的性能开销和for循环场景下的处理较复杂等,最终放弃。
方案二:基于 WXS + JS 支持 i18n 适配。通过视图层注入 WXS,将 WXS 语法转换为 JS 后注入到逻辑层,这样视图层和逻辑层均可实现 i18n 适配,并且在一定程度上有效减少两个线程间的通信耗时,提高性能。
从性能和合理性上考虑,我们最终采用了方案二进行 Mpx 的 i18n 方案实现。
Mpx i18n 架构设计图
由于各大小程序平台上,WXS 语法和使用均存在较大差异,因此该方案实现过程中也存在一些技术上的难点,这些难点基于 Mpx 框架的早期构建起来的跨平台能力也一一得以攻克,具体如下。
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 与 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 提供的计算属性中实现。
Mpx同时还支持转换产出H5,而 Mpx 提供的 i18n 能力在使用上与 vue-i18n 基本一致,输出 web 时框架会自动引入 vue-i18n,并使用当前的 Mpx i18n 配置信息对其进行初始化,用户无需进行任何更改,即可输出和小程序表现完全一致的 i18n web 项目。
上面分析了 Mpx 框架的 i18n 方案的技术细节,我们来看下和其他方案的对比,主要是和 uniapp - 基于 Vue 编写小程序的方案,和微信官方的方案,两者提供的 i18n 支持与Mpx的对比有何优劣。
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 能力,透過比較分析得出相比其他框架方案在使用成本和性能等方面有明顯的優勢,歡迎各位有相關需求的同學進行體驗嘗試。
#想了解更多程式設計學習,請關注php培訓欄位!
以上是小程式I18n最佳實踐案例的詳細內容。更多資訊請關注PHP中文網其他相關文章!