摘要:假如有這么一段句子這件衣服是人民幣如果我們想將一個數(shù)字以人民幣的形式寫進(jìn)去的話可以這么做最終顯示結(jié)果是這件衣服是人民幣其實(shí)它做了兩件事一個是加符號,另一個是加分隔符。同時(shí)表示人民幣,表示美元。
今天來介紹一個非常international的東西。
i18n
國際化(internationalization)的簡稱。之所以叫i18n,是因?yàn)樽帜?b>i和n之間有18個字母,所以才叫i18n。不要認(rèn)為這是一個高大上的名詞,其實(shí)就是因?yàn)閼胁藕唽懙摹iahiahia...
因?yàn)楸鞠盗惺且訰eact為中心,所以只介紹React項(xiàng)目中的國際化解決方案。當(dāng)然還有很多很多...很多別的國際化解決方案,但是不是所有的輪子都適合React這輛開往幼兒園的車。
實(shí)際上國際化在日常項(xiàng)目中用的沒那么頻繁,除非有業(yè)務(wù)需求,比如要做一個非常international的項(xiàng)目。目前在React中比較熱門的兩個包就是react-intl-universal 和 react-intl。因?yàn)楸疚闹攸c(diǎn)介紹對象是前者,所以我們先簡單介紹下后者。當(dāng)然在這里不會把它的使用方法列出來,而是把它的缺點(diǎn)列出來,為什么呢?因?yàn)楣P者懶??!
react-intl不足的地方主要是兩個:
它只能用于視圖層。舉個例子,比如React.Comoponent對象,但是對于Vanilla JS就會顯得很無力了,因?yàn)樗鼰o法在Vanilla JS中實(shí)例化。(這里會有人感到奇怪,Vanilla JS是什么鬼?哈哈...百gu度ge吧,不會發(fā)現(xiàn)新大陸)!
其次
想使用國際化方法,我們必須要利用它的一個方法將自己的組件轉(zhuǎn)化成另外一個class。這就比較蛋疼了,例子如下:
import { injectIntl } from "react-intl"; class MyComponent extends Component { render() { const intl = this.props; const title = intl.formatMessage({ id: "title" }); return ({title}); } }; export default injectIntl(MyComponent);
看我筆者第一篇文章的朋友應(yīng)該有印象:所有被包裹過的組件,如果你想獲得原本的組件的對象,那得調(diào)用相應(yīng)的方法。這里也不例外,如果我們想獲取組件的原對象,那就得這么做:
class MyComponent {...} export default injectIntl(MyComponent, {withRef: true}); class App { render() {} getMyInstance() { console.log("getMyInstance", this.refs.my.getWrappedInstance()); } }
這樣寫會不會覺得太麻煩了...
所以Alibaba前端組就按捺不住了,然后就搞出了自己的react-intl-universal??疵植痪褪窃趓eact-intl后面加個universal嗎?的確是這樣,不過筆者不清楚這個框架的核心邏輯是不是參考的react-intl,但是單從名字來看就有點(diǎn)"可疑"了,翻譯就是react-intl的通用版(當(dāng)然,純屬意淫,一笑而過!)。
作為一個國際化解決方案,首先實(shí)現(xiàn)國際化是它的基本功能。其次它還有一些別的功能,比如文本格式化、貨幣格式化、時(shí)間格式化等等,我相信這些都是我們頁面開發(fā)經(jīng)常使用到的功能。
i18n首先來看一下它的技術(shù)功能:國際化
react-intl-universal采用了與組件無關(guān)的方法來實(shí)現(xiàn)國際化。國際化的本質(zhì)其實(shí)就是將我們預(yù)先設(shè)置好的不同語言的句子按照語言環(huán)境顯示在頁面上。
import intl from "react-intl-universal";
通過intl這個對象來實(shí)現(xiàn)初始化和國際化處理。我們可以認(rèn)為這個intl是一個單例對象。我們在App啟動的時(shí)候?qū)ζ溥M(jìn)行初始化,爾后在別的地方再次導(dǎo)入的時(shí)候仍然是一個已經(jīng)初始化過的對象。在這種情況下,國際化處理就會變得異常簡單。其次就是準(zhǔn)備多語言句子了,傳統(tǒng)的在前端處理這個問題是將不同語言的句子放在不同的json文件中再導(dǎo)出,文件結(jié)構(gòu)如下:
這樣我們就可以在App啟動或者切換語言的時(shí)候?qū)胂鄳?yīng)的json對象了。
首先是API介紹
intl對象主要有三個常用的用于國際化處理的API,determineLocale、init、get。
determineLocale
看到方法名就應(yīng)該知道它是用來干什么了。它用來確定在整個體系中使用的是哪種語言??创a:
let currentLocale = intl.determineLocale({ urlLocaleKey: "lang", cookieLocaleKey: "lang" });
react-intl-universal確定語言的方式有三種,一個是通過urlLocaleKey,即lang關(guān)鍵字從url中獲取是哪種語言。比如:http://localhost?lang=en-US,因?yàn)閘ang對應(yīng)的值是en_US,所以語言為英文。其次是從Cookie獲取,因?yàn)镃ookie也是以鍵值對形式存儲的,所以會檢查當(dāng)前域下的Cookie是否有對應(yīng)的lang。如果上述兩種都沒有,那么會默認(rèn)使用瀏覽器當(dāng)前的語言類型。當(dāng)然上述的urlLocaleKey和cookieLocaleKey是可以自定義的,不是固定的lang.
init
init方法即用來初始化intl對象。初始化參數(shù)主要是兩個,一個是currentLocale即當(dāng)前的語言,另一個是locales即當(dāng)前語言對應(yīng)的json對象,比如{"en-US":{"key1":"value1"} 或者 {"zh-CN":{"key1":"值1"}}。
get
get方法就相對簡單,就是根據(jù)鍵去intl中獲取對應(yīng)的值,這里不做過多解釋。
完整的初始化過程如下:
class App extends Component{ .... componentDidMount() { this.loadLocales(); } loadLocales() { const _self = this; let currentLocale = intl.determineLocale({ //如果cookie和url中均沒有相關(guān)參數(shù),那么以瀏覽器語言為準(zhǔn) urlLocaleKey: "lang", cookieLocaleKey: "lang" }); http .get(`locales/${currentLocale}.json`) //理解為按需加載并且locales文件夾需要放在public文件下供http訪問 .then(res => { return intl.init({ currentLocale, locales: { [currentLocale]: res.data //如果key是變量,那么需要用[]包一下 } }); }) .then(() => { _self.setState({initDone: true}); }); } .... }
然后在需要國際化的地方這么使用
import intl from "react-intl-universal";{intl.get("name")}
是不是很簡單? 而且完全避免了react-intl的兩個缺點(diǎn)。
格式化工具前面說了react-intl-universal不僅僅可以用來做國際化處理,還可以用來做簡單的文本格式化處理。下面我們列舉幾個常用的。
Html Snippet假如我們的json文件中有這么一段
... "red": "紅色
", ...
如果我們直接用get方法獲取的話,那么會直接把
紅色
給打印出來。如果我們想將它以html片段的形式打印出來的話,就使用getHTML方法,它在獲取到句子的時(shí)候會進(jìn)行解析并生成最終的Html Snippet。 Default Message缺省值其實(shí)就是默認(rèn)值,是對于json鍵值對的默認(rèn)值。將入我們?nèi)カ@取一個json中沒有的鍵值對那么系統(tǒng)就會報(bào)錯。如何去規(guī)避這個問題呢?react-intl-universal給我們提供了這樣一個方法:
intl.get("not-exist-key").defaultMessage("default message")
這是一個鏈?zhǔn)秸{(diào)用。如果json中沒有not-exist-key這個鍵,那就會默認(rèn)返回defaultMessage的參數(shù)。簡寫是intl.get("not-exist-key").d("default message")。
Message With Variables假如某個句子包含了一個變量怎么辦?比如一個用戶名,我們只有在用戶登錄的時(shí)候才知道他的用戶名。
{ "me": "你好,我是{me}" }
此時(shí)就用到了get放的第二個參數(shù)。對于上面的例子,我們可以這樣處理:
{intl.get("me", {"me": "皮卡丘"})}
get方法會找出句子中被{}包住的變量me,然后在第二個參數(shù)(json對象)找出me對應(yīng)的值皮卡丘并將{me}整個用皮卡丘替換。另外需要注意的是,json對象只能為一層,不可嵌套。
Display Currency它還可以用來格式化貨幣。假如有這么一段句子
{ "price": "這件衣服是 {price,number,CNY} 人民幣", }
如果我們想將一個數(shù)字以人民幣的形式寫進(jìn)去的話可以這么做:
{intl.get("price", {"price": 1000})}
最終顯示結(jié)果是:這件衣服是 ¥1,000 人民幣
其實(shí)它做了兩件事:一個是加符號,另一個是加分隔符。同時(shí)CNY表示人民幣,USD表示美元。
然后是日期的處理。假如有這么一段話:
{ "date": "今天是{date,date,full}" }
然后我們這么使用它的話:
{intl.get("date",{"date":new Date()})}
顯示結(jié)果是今天是2018年12月3日星期一。其實(shí){date,date,full}這段指令就是將date變量替換成對應(yīng)日期(new Date())并以long形式展示。
同時(shí)日期展示形式有四種
short: shows date as shortest as possible
medium: shows short textual representation of the month
long: shows long textual representation of the month
full: shows dates with the most detail
他們之間有什么不同呢?我們用剛剛的例子做個展示:
short: 今天是18/12/3
medium: 今天是2018年12月3日
long: 今天是2018年12月3日
full: 今天是2018年12月3日星期一
Display Times最后是時(shí)間。我們按部就班來。假如有這么一段話:
{ "time": "現(xiàn)在時(shí)間是{time,time,short}" }
然后我們這么使用它的話:
{intl.get("time",{"time":new Date()})}
顯示結(jié)果是現(xiàn)在時(shí)間是下午5:54。其實(shí){time,time,short}這段指令就是將time變量替換成對應(yīng)日期(new Date())并以short形式展示。
但是時(shí)間展示形式只有三種,它沒有full
short: shows date as shortest as possible
medium: shows short textual representation of the month
long: shows long textual representation of the month
他們之間有什么不同呢?我們用剛剛的例子做個展示:
short: 現(xiàn)在時(shí)間是下午5:54
medium: 現(xiàn)在時(shí)間是下午5:58:22
long: 現(xiàn)在時(shí)間是GMT+8 下午5:58:50
上述貼出來的示例都是在中文環(huán)境下。如果有興趣的朋友可以把整個例子download下來本地運(yùn)行下,邊看邊寫,受益匪淺。好了,收拾下班咯...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.hztianpu.com/yun/99683.html
摘要:驗(yàn)證路由所謂的驗(yàn)證路由其實(shí)就是該路由的外層加了一層驗(yàn)證機(jī)制,有授權(quán)的用戶才能進(jìn)入,反之都無法進(jìn)入。一起學(xué)系列也隨著這篇的結(jié)束而告一段落了。大家一起加油最后再獻(xiàn)上和本篇博文有關(guān)的代碼鏈接和示例頁面 時(shí)隔那么久,博主終于從睡夢中醒來開始更新博客啦!為自己的勤勞歡呼...(pia pia pia打臉)!本次我們接著上一篇博客繼續(xù)聊React-Router4。上篇我們主要了解了React-Ro...
摘要:的出現(xiàn)真可謂是前端界的福音,正與之宗旨所說,。據(jù)統(tǒng)計(jì),目前世界上有的項(xiàng)目使用了。技術(shù)棧學(xué)習(xí)路線直到前段時(shí)間筆者的朋友給推薦了一個,真是欣喜若狂也更加堅(jiān)定了自己在繼續(xù)前進(jìn)的想法。這是一個外國友人總結(jié)的一套技術(shù)棧學(xué)習(xí)路線,先給傳送門。 我相信點(diǎn)進(jìn)來的同學(xué)都是沖著標(biāo)題來的,當(dāng)然本文也不會讓各位失望。不過在正式介紹標(biāo)題所述的內(nèi)容之前,我們不妨先放下技術(shù),一起回顧下自己做前端技術(shù)的心路歷程。 前...
摘要:而就是產(chǎn)品具體實(shí)現(xiàn)某一種語言和文化的過程。貨幣的符號,以及數(shù)字分割方式各個國家都存在不同。那么有沒有其他的復(fù)數(shù)形式回答當(dāng)然是肯定的,比如波蘭語。但這個是自己的語法,并非標(biāo)準(zhǔn),同時(shí)這個語法還會破壞的測試,并不是一個很好的選擇。 記得我剛來我們公司的時(shí)候,接手現(xiàn)在負(fù)責(zé)的項(xiàng)目的時(shí)候,我就發(fā)覺了一個問題:所有的文本資源都是硬編碼在代碼里面。這當(dāng)然會帶來很多問題。但考慮到我負(fù)責(zé)的這個項(xiàng)目是公司內(nèi)...
摘要:所以還是印證那句話是組件渲染的唯一依據(jù)。所以對組件的進(jìn)行約束是創(chuàng)建一個健康組件的必要條件。這里我們約束屬性類型為。使用方式運(yùn)行結(jié)果沒有錯誤假如我們再加入一個子組件控制臺如預(yù)期報(bào)錯自定義約束萬物皆有其局限性。 日常扯淡前的廢話 上一篇我們介紹了React中State對象,說到它是組件渲染的唯一依據(jù);當(dāng)然我們也可以認(rèn)為State是組件中的數(shù)據(jù)源之一,它保存著組件渲染的所有數(shù)據(jù)并且可以直接作...
摘要:本篇所說的文件下載也是基于和或者都行。的返回值是一個有意思的對象,它包含了很多方法,其中一個方法就是。通過的響應(yīng)頭獲取到文件名。接下來就是對標(biāo)簽的一系列操作,然后模擬點(diǎn)擊事件觸發(fā)下載動作。 距離上次博文更新已經(jīng)快一個月了,期間忙于各種事情無法脫身。今天難得閑暇 and then 就來更新啦...上篇中我們了解了下載React中如何實(shí)現(xiàn)文件的上傳,雖然不算什么高大上的技術(shù)但實(shí)際開發(fā)的時(shí)候...
閱讀 3571·2021-11-18 10:02
閱讀 1668·2021-10-12 10:12
閱讀 3076·2021-10-09 09:53
閱讀 5154·2021-09-09 09:34
閱讀 1033·2021-09-06 15:02
閱讀 2839·2021-08-05 10:02
閱讀 3250·2019-08-30 15:44
閱讀 3179·2019-08-28 18:04