庫屬性介紹
項目地址: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é)果還是英語