React-Intl,實(shí)現(xiàn) React 項(xiàng)目的前端國(guó)際化
本文講解如何使用 React-Intl 庫(kù)給你的 React 應(yīng)用做國(guó)際化。
安裝
React 項(xiàng)目默認(rèn)你已經(jīng)搭建好了。可以用過氣的 CRA,流行的 vite,或者用 React 推薦的 Next.js。
安裝 React-Intl。
或者用 yarn。
使用
接著我們需要將國(guó)際化能力注入到 React 應(yīng)用中。
使用的是經(jīng)典的 context 上下文方案:
IntlProvider 是一個(gè) context.provider 組件,用來注入一些國(guó)際化需要的信息。其中最重要的信息是 locale 和 messages。
locale 是一個(gè)字符串,代表一個(gè)語言標(biāo)識(shí),使用了 BCP 47 語言標(biāo)記規(guī)范。比如中文用 ??zh?
??,英文用 ??en?
??,簡(jiǎn)體用 ??zh-CN?
?。
標(biāo)識(shí)符是會(huì)提供給瀏覽器自帶的 Intl 對(duì)象使用的,Intl 對(duì)象的方法會(huì)通過它確定如何做轉(zhuǎn)換,比如不同國(guó)家數(shù)字的分隔符是不同的。
可以看到,原點(diǎn)、逗號(hào)、空格,什么都有。所以你要傳一個(gè)正確的語言標(biāo)識(shí)符。
messages 就簡(jiǎn)單多了,就是一個(gè) id 到 value 的映射,組件中傳一個(gè) id,就能拿到對(duì)應(yīng)的語言文案了。比如
更具體的引入寫法:
- 計(jì)算一個(gè)語言標(biāo)識(shí)符,因?yàn)榫W(wǎng)站支持的語言可能就兩三種,當(dāng)用戶客戶端的語言不在范圍內(nèi)時(shí),給一個(gè)兜底的。
- 確認(rèn)語言后,找出對(duì)應(yīng)的 messages 對(duì)象。
然后是一些其他的點(diǎn):如果語言很多,可以考慮做語言包懶加載。另外還要做用戶修改語言后,更新 locale 和 messages props。
組件
然后是在業(yè)務(wù)組件中使用國(guó)際化文案。
最常用的就是 FormattedMessage 組件了,給 id props 提供 id 即可。
如果你需要得到文案字符串,傳入到一些組件中,比如 tooltip,你可以用主流的 hook 寫法:
或者可以用 HOC(高階組件),我沒用過,我不寫類組件。
類型安全
如果你用 TypeScript,你會(huì)希望傳入的 id 是有類型的,反正寫錯(cuò) id。React-Intl 提供了全局類型的設(shè)置。你只需要這樣寫:
keyof typeof zh 就是將中文 message 對(duì)象的 key 提取為一個(gè)聯(lián)合類型。
這里我巧妙地用了一個(gè) & 交叉類型,這樣不在二者 id 的交集內(nèi)的 key 會(huì)被排除在外,防止使用一個(gè)沒有在所有語言中都被定義的 id。
locale 也可以設(shè)置類型,防止錯(cuò)誤設(shè)置一些不支持的語言標(biāo)識(shí)。如下:
可能你希望 en 和 zh 的 key 要一致,我這里想到一個(gè)比較巧妙的做法。en 作為兜底語言,用 typeof 拿到類型,作為其他語言的類型,防止 id 漏寫。
message 不支持嵌套
React-Intl 的 message 是不支持嵌套的。
你可以這樣寫:
但不能這樣寫:
這個(gè)我是支持的。
嵌套并無必要,我們加前綴就好了,并且方便全局搜索,能夠快速定義一個(gè)國(guó)際化 id 的文本位置。類似 Vue 框架會(huì)做大量的駝峰和連線符的變換,全局搜索非常不友好,我不喜歡。
如果你喜歡嵌套的風(fēng)格,可以考慮寫一些腳本,支持將嵌套的轉(zhuǎn)換為拍平格式。
結(jié)尾
以上是 React-Intl 的一些入門用法。