5分鐘前端國際化

螞蟻金服資料體驗技術發表於2017-10-24

作者簡介 Kid 螞蟻金服·資料體驗技術團隊

背景

需要國際化的react專案已經迭代了1年多,檔案眾多,包含了jsx和普通的js物件檔案。粗略估計有幾千個中文詞條。本文先介紹了採用的國際化方案,然後給出了國際化的過程和一個自己開發的指令碼i18n-pick,按照教程,可以幫助前端jsx專案5分鐘快速國際化。

方案選擇

先大體上介紹下我選擇的國際化方案。國際化方案很多,我這裡列舉主要的幾種:

  • 編譯期間轉化:例如wepack的i18n-webpack-plugin,打包的時候對_('key')進行轉義
  • 執行期間轉化:react-intl等,把中文詞條寫成intl.get()的方式,在執行時獲取中文文案
  • wordpress的getText方案:gettext是一個filter 鉤子, 用來替換和本地化翻譯文字, 替換 __()、_e()、_x()、_ex() 和 _n() 函式包含的文字

由於專案中我選擇了antd作為視覺元件庫。所以想和antd提供的官方的國際化方式保持統一。antd推薦的是react-intl,不過另一款類似的react-intl-universal也有不少人推薦,兩者都比較成熟。所以我對兩種進行了比較:

react-intl react-intl-universal
切換不重新整理頁面
js檔案支援(重要)
名詞單雙數,預設值,html
無破壞性 劣(裝飾器的程式碼實現會改變ref)

名詞單雙數,預設值,html這種功能兩者都有。我這裡就不多說了,具體的功能感興趣的可以去看下API。比較關注的其實是js檔案支援那塊。react-intl只支援在jsx檔案的內容中使用,但是由於專案配置化程式設計的緣故,很多中文是寫在js物件中的。react-intl不支援在普通js物件中使用,很不方便。而且他的裝飾器實現會改變元件的ref。他唯一的好處是他的切換不需要重新整理頁面,不過這種低頻的操作重新整理頁面倒也無妨。

針對以上的原因,最終選擇了react-intl-universal作為國際化方案。不過後來真實使用的時候,發現他提供的支援js物件的方式不是很好,於是還是直接採取了react-intl-universal的思想。簡單的包裝了下他們的依賴intl-messageformat~這裡不詳細描述了,他的api官網文件可以查到。

國際化方案選擇完了之後,開始執行階段。以上無論是選擇哪種方案,編碼時基本都要求一種特殊的形式。要麼intl.get(),要麼是文案前加上_#這種。對於已經迭代了很久的專案,這就涉及到了一項力氣活。對中文文案進行提取以及替換。在這裡就直接分享指令碼i18n-pick,描述下整個的國際化過程了。

使用教程

主要分為3步,安裝,掃描和提取,然後使用翻譯工具來進行詞條的翻譯,具體步驟如下:

安裝

cnpm i i18n-pick cnpm用的淘寶映象,會快一些。

掃描

./node_modules/i18n-pick/bin/i18n-pick.js scan [path] 命令最後的path選擇你的程式碼目錄,執行完成後會在專案根目錄生成i18n-messages資料夾,包含jsx.text,text.text和zh-CH.json三個檔案。具體實現是呼叫了babel的transformFileSync方法,在編譯成語法樹的時候,解析下面幾種babel-type

  • JSXAttribute
  • JSXText
  • AssignmentExpression
  • ObjectProperty
  • ArrayExpression

這裡的基本含括了所有的情況,如果有遺漏的,歡迎聯絡我。將解析的這幾種的value與/[\u4e00-\u9fa5]/進行比對。將包含中文文案的檔名,行數,文案內容記錄下來。JSX內的中文文案存到jsx.text,一般JS內的中文文案存到text.text。

分開存的原因是因為替換的時候,JSX內的文案需要加上大括號才行。

同時我會把提取出來的文案內容存到了zh-CH.json中。這裡為了配合翻譯工具atool-i10n的使用,json中的儲存格式也是按照他的要求提供的。這裡有個小tip,參見附錄。

提取

./node_modules/i18n-pick/bin/i18n-pick.js pick 然後執行pick操作,就是將jsx.text,text.text檔案的內容按行分析,對檔案進行內容替換。這裡最開始我將key值定為了自增長的數字。為了保證原始碼一定的閱讀性,我同時將原文案以/**/註釋的形式標在文末。後來,吸取了評論區lany9527同學的建議。將中文作為了key值~~然後我會在檔案頭部import一下依賴。效果如下:

5分鐘前端國際化

base/reactIntlUnicersal這個檔案需要自己放到自己的專案中,程式碼可以參考連結

翻譯

然後建議安裝atool-l18n這種翻譯工具,直接翻譯成英文文案。就可以編譯執行了~當然後續還得有一些css的調整工作。 cnpm i atool-l10n

node_modules/.bin/atool-l10n

總結

本文主要是分享了一個文案提取的指令碼,來讓前端jsx專案快速國際化。如有使用上的問題,歡迎在評論區詢問~

tip

多謝評論區lany9527同學的建議,指令碼已經更新。不再以自增長的數字作為key值了。換成以中文名作為key進行提取,已經更新指令碼~

附錄:

1.目前指令碼不支援中文中有換行的情況,所以得修正下scan之後的三個檔案的內容。並且這部分內容得手動去替換。不過這種情況很少,我的專案掃出2000個詞條只有兩條有這個問題。

5分鐘前端國際化

2.第二種是pick操作執行之後可能會編譯出錯,那是因為你的專案中可能手寫了\n這樣的文案,得手動處理下這種情況。

5分鐘前端國際化

3.第三種是不支援中文中含有\"的情況,這部分也得自己處理,原因是我以中文作為key,為了提取後的值過eslint,得用單引號引起來。就得對雙引號單引號進行轉義。無法處理已經轉義過的內容。在完成了文案的轉化之後可以再用scan命令掃描一遍,看下哪些沒有處理好的,再手動處理下~

感興趣的同學可以關注專欄或者傳送簡歷至 'yifei.pyf####alibaba-inc.com'.replace('####', '@'),歡迎有志之士加入~

原文地址:github.com/ProtoTeam/b…

相關文章