[RN庫] React Native國際化多語言

庫屬性介紹

項目地址:https://github.com/AlexanderZaytsev/react-native-i18n

屬性????????????????????????????????????????????????????????????解釋

支持RN版本????????????????????????????????????????????所有版本

支持平臺????????????????????????????????????????????????iOS+Android

是否需要NativeModule????????????????????????????????是

是否可移植????????????????????????????????????????????????????是

是否含有jni模塊????????????????????????????????????????????否

使用

1.install(略趾断,git里都寫著了鹏漆,就是npm那些事)

2.項目中使用

因為是一些靜態(tài)屬性引用划鸽,所以你用redux做儲存替換也可以尽棕,直接做飲用也可以(本文拿en,zh為例)。

首先是建英文版本的配置文件味赃,en/index.js

exportdefault{

home:{

greeting:'Greeting in en',

tab_home:'Home',

tab_donate:'Donate',

tab_demo:'Demo',

language:'language',

live_demo:'Live Demo',

buy_me_coffee:'Buy me a coffee',

gitee:'Gitee',

star_me:'Star me',

donate:'donate',

exit:'exit?',

},

donate:{

donate:'donate us~~~',

donate_desc:'? 2017 Pactera Technology International Limited. All rights reserved.',

},

demo:{

dialog:'dialog',

button:'button',

switch:'switch',

action_sheet:'Action Sheet',

}

};

然后是中文的zh/index.js

exportdefault{

home:{

greeting:'Greeting in zh',

tab_home:'首頁',

tab_donate:'捐贈',

tab_demo:'例子',

language:'語言',

live_demo:'例子',

buy_me_coffee:'請我一杯coffee',

gitee:'Gitee',

star_me:'關(guān)注我',

donate:'貢獻(xiàn)',

exit:'是否退出?',

},

donate:{

donate:'支持我們~~',

donate_desc:'? 2017 Pactera Technology International Limited. All rights reserved.',

},

demo:{

dialog:'提示框',

button:'按鈕',

switch:'開關(guān)',

action_sheet:'',

}

};

屬性名掀抹,結(jié)構(gòu)是一致的只是屬性不同,當(dāng)然這里是靜態(tài)的2個文件心俗,如果場景需要可以服務(wù)端下發(fā)json,那就是完全動態(tài)的了傲武,這部分看業(yè)務(wù)需求了。

默認(rèn)的語言環(huán)境

我們在上面寫了2種語言配置城榛,那么哪種作為初始化的呢揪利?在業(yè)務(wù)層調(diào)用前,我們可以先進(jìn)行預(yù)設(shè)

i18n/index.js

import i18nfrom'react-native-i18n';

import enfrom'./en';

import zhfrom'./zh';

i18n.defaultLocale ='en';

i18n.fallbacks = true;

i18n.translations = {

en,

zh,

};

export {i18n};

這邊進(jìn)行了一些預(yù)設(shè)狠持,默認(rèn)語境為en疟位,允許fallbacks狀態(tài)(為true時,順序向下遍歷翻譯)喘垂,預(yù)設(shè)轉(zhuǎn)換的文件就2個甜刻,一個en一個zh,這個你也可以自行后續(xù)添加根據(jù)需求而定正勒。

業(yè)務(wù)層調(diào)用

先是倒包

import {i18n} from '你預(yù)設(shè)的index的目錄';

調(diào)用(拿一個Toast做個例子)

ToastAndroid.show(i18n.t('home.exit'),ToastAndroid.SHORT);


源碼分析

這個庫的實現(xiàn)分為2部分得院,一部分是Native的版本判斷等功能以及js部分的核心實現(xiàn)fnando/i18n-js

i18n-js是一個輕量級的js翻譯庫,他支持各種格式和內(nèi)容的換算和語言內(nèi)容的切換章贞,地址如下:https://github.com/fnando/i18n-js

那么翻譯轉(zhuǎn)換這塊是 I18n.js做的那么Native做了些啥呢祥绞?我們來一探究竟(以安卓為例,蘋果看不懂鸭限,抱歉)

Native代碼就兩個類蜕径,所以我之前說你直接把Native代碼copy走然后項目依賴I18n.js也能達(dá)到這個效果

RNI18nPackage是一個普通的Package類,它的作用就是把我們的module加到主應(yīng)用的getPackages()方法中的列表里败京,然后一起打進(jìn)包里而已丧荐。

具體功能都在RNI18nModule里

publicclassRNI18nModuleextendsReactContextBaseJavaModule{

publicRNI18nModule(ReactApplicationContext reactContext) {

super(reactContext);

}

//RN調(diào)用的控件名

@Override

publicStringgetName() {

return"RNI18n";

}

//對取出的Locale列表進(jìn)行格式化的方法

privateStringtoLanguageTag(Locale locale) {

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {

returnlocale.toLanguageTag();

}

StringBuilder builder =newStringBuilder();

builder.append(locale.getLanguage());

if(locale.getCountry() !=null) {

builder.append("-");

builder.append(locale.getCountry());

}

returnbuilder.toString();

}

privateWritableArraygetLocaleList() {

WritableArray array = Arguments.createArray();

if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {

//獲取區(qū)域設(shè)置列表。這是獲取區(qū)域的首選方法喧枷。

LocaleList locales = getReactApplicationContext()

.getResources().getConfiguration().getLocales();

for(inti =0; i < locales.size(); i++) {

array.pushString(this.toLanguageTag(locales.get(i)));

}

}else{

array.pushString(this.toLanguageTag(getReactApplicationContext()

.getResources().getConfiguration().locale));

}

returnarray;

}

//js端可獲取屬性的列表

@Override

publicMap<String, Object>getConstants() {

HashMap<String, Object> constants =newHashMap<String,Object>();

constants.put("languages",this.getLocaleList());

returnconstants;

}

//提供給js端調(diào)用的方法,用來獲取默認(rèn)的語言環(huán)境弓坞,回調(diào)方式用的是promise

@ReactMethod

publicvoidgetLanguages(Promise promise) {

try{

promise.resolve(this.getLocaleList());

}catch(Exception e) {

promise.reject(e);

}

}

}

加一個toast看下locale會出現(xiàn)什么

Toast.makeText(getReactApplicationContext(),"locales.get(i) "+locales.get(i),Toast.LENGTH_LONG).show();

本想一探究竟內(nèi)部的實現(xiàn)隧甚,結(jié)果是個不公開的類

總結(jié)

首先Native那里獲取本手機(jī)的LocaleList然后格式化取第一個元素交由I18n.js處理,然后I18n.js根據(jù)key選用一套有效的語言規(guī)則渡冻,再之后流程就和使用時候的順序一樣了戚扳。

整個庫集成難度較低,使用起來比較簡便族吻,使用下來沒碰到大坑帽借,配合redux更美味珠增。

準(zhǔn)備階段

react-native-i18n第三方多語言庫

安裝:yarn add react-native-i18n

react-native-device-info用戶獲取系統(tǒng)本地語言環(huán)境

安裝:yarn add react-native-device-infoandreact-native link react-native-device-info

實踐階段:

在項目中創(chuàng)建zh.js、en.js砍艾、I18n.js三個js文件蒂教,DataRepository.js是一個我自定義的數(shù)據(jù)持久化類,在這個demo中的作用是存取用戶改變后的語言環(huán)境脆荷,直接拷貝過去就可以用(不是必須的)凝垛。

代碼分別為:

zh.js

exportdefault{

english:'英文',

chinese:'中文',

changeToEnglish:'切換到英文',

changeToChinese:'切換到中文',

changeToSystem:'切換到系統(tǒng)語言',

}

en.js

exportdefault{

english:'english',

chinese:'chinese',

changeToEnglish:'change to english',

changeToChinese:'change to chinese',

changeToSystem:'change to System',

}

I18n.js

importI18n,{ getLanguages }from'react-native-i18n'

importDeviceInfofrom'react-native-device-info'

importDataRepositoryfrom'../dao/DataRepository'

importenfrom'./en'

importzhfrom'./zh'

I18n.defaultLocale ='en';

I18n.fallbacks =true;

I18n.translations = {

en,

zh,

};

I18n.localeLanguage =()=>{

newDataRepository().fetchLocalRepository('localLanguage')

.then((res)=>{

I18n.locale = res;

})

.catch((error)=>{

I18n.locale = DeviceInfo.getDeviceLocale();

});

returnI18n.locale;

};

export{ I18n, getLanguages };

重點方法、屬性講解

I18n.t(): 使用頻率是最高的蜓谋,舉個栗子:

<Textstyle={styles.welcome}>

{I18n.t('english')}

</Text>

以上I18n.t('english')中的english參數(shù)就是在zh.js梦皮、en.js文件中的語言配置項


具體顯示內(nèi)容會隨著語言環(huán)境調(diào)用相應(yīng)的語言配置文件,呈現(xiàn)給用戶相應(yīng)的語言內(nèi)容桃焕。

I18n.getLanguages獲取用戶首選的語言環(huán)境

I18n.locale: 設(shè)置本地語言環(huán)境剑肯。

I18n.defaultLocale首選默認(rèn)語言

I18n.fallbacks: 看文檔說明我理解的意思是:如果獲取到的系統(tǒng)語言類似en_USen-GB這樣的,插件初始化的時候發(fā)現(xiàn)沒有en_US.jsen-GB.js观堂,這個時候如果設(shè)置了I18n.fallbacks = true;系統(tǒng)就會按這樣的(en_USen.js)順序去查找文件让网,就會去找有一個en.js這樣的文件, 官方建議使用I18n.fallbacks = true;

更多關(guān)于i18n-js的屬性和方法請點擊這里查看

ios需要配置語言環(huán)境

使用過程中發(fā)現(xiàn)一個刷新的問題:

我在使用過程中發(fā)現(xiàn)調(diào)用了I18n.locale=‘我設(shè)置的語言’后型将,當(dāng)前的界面語言并沒有改變寂祥,而其他界面的語言已經(jīng)改變了,就比如說我上面截圖的側(cè)滑菜單七兜,當(dāng)我在側(cè)滑菜單切換語言后發(fā)現(xiàn)側(cè)滑菜單里面的語言并沒有發(fā)現(xiàn)變化丸凭,而首頁的語言環(huán)境已經(jīng)改變了,我不知道為什么腕铸,摸索最后找到了一種解決方案(可能不是最佳方案惜犀,但是解決了刷新當(dāng)前界面語言的問題,如果有更好的方法歡迎分享)狠裹,解決方案:調(diào)用一下setState(無論設(shè)置的這個state屬性在render中有沒有被使用虽界,都有效)。 具體代碼看App.js涛菠,我項目中有使用localeLanguage所以我把改變后的語言存到state中

this.setState({

localeLanguage: I18n.locale

});

請注意莉御,js的名字最好都是語言的縮寫,下面提供參考:

突然有個想法看看沒有支持的語言會變成什么:看來如果沒有支持某種語言就會默認(rèn)使用英語俗冻,我曾經(jīng)試過分別調(diào)換這兩個的引入順序發(fā)現(xiàn)結(jié)果還是英語

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末礁叔,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子迄薄,更是在濱河造成了極大的恐慌琅关,老刑警劉巖,帶你破解...
    沈念sama閱讀 216,997評論 6 502
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讥蔽,死亡現(xiàn)場離奇詭異涣易,居然都是意外死亡画机,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,603評論 3 392
  • 文/潘曉璐 我一進(jìn)店門新症,熙熙樓的掌柜王于貴愁眉苦臉地迎上來步氏,“玉大人,你說我怎么就攤上這事账劲〈粱ぃ” “怎么了?”我有些...
    開封第一講書人閱讀 163,359評論 0 353
  • 文/不壞的土叔 我叫張陵瀑焦,是天一觀的道長腌且。 經(jīng)常有香客問我,道長榛瓮,這世上最難降的妖魔是什么铺董? 我笑而不...
    開封第一講書人閱讀 58,309評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮禀晓,結(jié)果婚禮上精续,老公的妹妹穿的比我還像新娘。我一直安慰自己粹懒,他們只是感情好重付,可當(dāng)我...
    茶點故事閱讀 67,346評論 6 390
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著凫乖,像睡著了一般确垫。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上帽芽,一...
    開封第一講書人閱讀 51,258評論 1 300
  • 那天删掀,我揣著相機(jī)與錄音,去河邊找鬼导街。 笑死披泪,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的搬瑰。 我是一名探鬼主播款票,決...
    沈念sama閱讀 40,122評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼泽论!你這毒婦竟也來了艾少?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 38,970評論 0 275
  • 序言:老撾萬榮一對情侶失蹤佩厚,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后说订,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體抄瓦,經(jīng)...
    沈念sama閱讀 45,403評論 1 313
  • 正文 獨居荒郊野嶺守林人離奇死亡潮瓶,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,596評論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了钙姊。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片毯辅。...
    茶點故事閱讀 39,769評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖煞额,靈堂內(nèi)的尸體忽然破棺而出思恐,到底是詐尸還是另有隱情,我是刑警寧澤膊毁,帶...
    沈念sama閱讀 35,464評論 5 344
  • 正文 年R本政府宣布胀莹,位于F島的核電站,受9級特大地震影響婚温,放射性物質(zhì)發(fā)生泄漏描焰。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,075評論 3 327
  • 文/蒙蒙 一栅螟、第九天 我趴在偏房一處隱蔽的房頂上張望荆秦。 院中可真熱鬧,春花似錦力图、人聲如沸步绸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,705評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽瓤介。三九已至,卻和暖如春晓折,著一層夾襖步出監(jiān)牢的瞬間惑朦,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,848評論 1 269
  • 我被黑心中介騙來泰國打工漓概, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留漾月,地道東北人。 一個月前我還...
    沈念sama閱讀 47,831評論 2 370
  • 正文 我出身青樓胃珍,卻偏偏與公主長得像梁肿,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子觅彰,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,678評論 2 354

推薦閱讀更多精彩內(nèi)容