天天看點

React-Native全球化語言切換工具庫react-native-i18n

轉載請注明出處王亟亟的大牛之路

開篇啰嗦–階段感悟

最近2 -3個月基本都因為一些私事沒怎麼系統的工作和學習,途中看了幾天Kotlin的東西寫了些demo并且整了個小項目,但是整體狀态不是很好,這些天看到些95後碼農的強勢細思極恐。

現在大多數醒來就已經是中午,起得早去一下健身房,起的晚就家裡宅一天。公司有事或者有其他家事就去協調/溝通/處理下,整個人感覺都提前進入養老狀态(當然這個鍋有一半是沉迷王者榮耀不可自拔,不太好)

最近項目上基本沒啥事情了,然後讓手下的小夥伴們對之前做的一些内容進行二次封裝,然後他們引用了一個第三方國際化的庫我覺得不錯,然後看了看源碼就分享下,希望大家用得上(雖然現在産品的閱聽人群都是國内的,但是準備下好像沒毛病?)

廢話啰嗦完了,老規矩:https://github.com/ddwhan0123/Useful-Open-Source-Android (雖然我不怎麼工作了,但是git還是每天會花時間看看)

庫屬性介紹:

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

屬性 解釋
支援RN版本 所有版本
支援平台 iOS+Android
是否需要NativeModule
是否可移植
是否含有jni子產品

使用:

1.install (略,git裡都寫着了,就是npm那些事)

2.項目中使用

因為是一些靜态屬性引用,是以你用redux做儲存替換也可以,直接做飲用也可以(本文拿en,zh為例)。

首先是建英文版本的配置檔案,en/index.js

export default {
    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

export default {
    home: {
        greeting: 'Greeting in zh',
        tab_home: '首頁',
        tab_donate: '捐贈',
        tab_demo: '例子',
        language: '語言',
        live_demo: '例子',
        buy_me_coffee: '請我一杯coffee',
        gitee: 'Gitee',
        star_me: '關注我',
        donate: '貢獻',
        exit: '是否退出?',
    },
    donate: {
        donate: '支援我們~~',
        donate_desc: '© 2017 Pactera Technology International Limited. All rights reserved.',
    },
    demo: {
        dialog: '提示框',
        button: '按鈕',
        switch: '開關',
        action_sheet: '',
    }
};
           

屬性名,結構是一緻的隻是屬性不同,當然這裡是靜态的2個檔案,如果場景需要可以服務端下發json,那就是完全動态的了,這部分看業務需求了。

2.1 預設的語言環境

我們在上面寫了2種語言配置,那麼哪種作為初始化的呢?在業務層調用前,我們可以先進行預設

i18n/index.js

import i18n from 'react-native-i18n';
import en from './en';
import zh from './zh';

i18n.defaultLocale = 'en';
i18n.fallbacks = true;
i18n.translations = {
    en,
    zh,
};

export {i18n};
           

這邊進行了一些預設,預設語境為en,允許fallbacks狀态(為true時,順序向下周遊翻譯),預設轉換的檔案就2個,一個en一個zh,這個你也可以自行後續添加根據需求而定。

2.2 業務層調用

先是倒包

import {i18n} from '你預設的index的目錄';

調用(拿一個Toast做個例子)

兩種輸出結果如下:

React-Native全球化語言切換工具庫react-native-i18n
React-Native全球化語言切換工具庫react-native-i18n

源碼分析

這個庫的實作分為2部分,一部分是Native的版本判斷等功能以及js部分的核心實作fnando/i18n-js

i18n-js是一個輕量級的js翻譯庫,他支援各種格式和内容的換算和語言内容的切換,位址如下:https://github.com/fnando/i18n-js

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

React-Native全球化語言切換工具庫react-native-i18n

Native代碼就兩個類,是以我之前說你直接把Native代碼copy走然後項目依賴I18n.js也能達到這個效果

RNI18nPackage是一個普通的Package類,它的作用就是把我們的module加到主應用的getPackages()方法中的清單裡,然後一起打進包裡而已。

具體功能都在RNI18nModule裡

public class RNI18nModule extends ReactContextBaseJavaModule {

  public RNI18nModule(ReactApplicationContext reactContext) {
    super(reactContext);
  }
  //RN調用的控件名
  @Override
  public String getName() {
    return "RNI18n";
  }

  //對取出的Locale清單進行格式化的方法
  private String toLanguageTag(Locale locale) {
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
      return locale.toLanguageTag();
    }

    StringBuilder builder = new StringBuilder();
    builder.append(locale.getLanguage());

    if (locale.getCountry() != null) {
      builder.append("-");
      builder.append(locale.getCountry());
    }

    return builder.toString();
  }

  private WritableArray getLocaleList() {
    WritableArray array = Arguments.createArray();

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
      //擷取區域設定清單。這是擷取區域的首選方法。
      LocaleList locales = getReactApplicationContext()
          .getResources().getConfiguration().getLocales();

      for (int i = ; i < locales.size(); i++) {
        array.pushString(this.toLanguageTag(locales.get(i)));
      }
    } else {
      array.pushString(this.toLanguageTag(getReactApplicationContext()
          .getResources().getConfiguration().locale));
    }

    return array;
  }

  //js端可擷取屬性的清單
  @Override
  public Map<String, Object> getConstants() {
    HashMap<String, Object> constants = new HashMap<String,Object>();
    constants.put("languages", this.getLocaleList());
    return constants;
  }

  //提供給js端調用的方法,用來擷取預設的語言環境,回調方式用的是promise
  @ReactMethod
  public void getLanguages(Promise promise) {
    try {
      promise.resolve(this.getLocaleList());
    } catch (Exception e) {
      promise.reject(e);
    }
  }
}
           

加一個toast看下locale會出現什麼

效果如下:

React-Native全球化語言切換工具庫react-native-i18n

本想一探究竟内部的實作,結果是個不公開的類

React-Native全球化語言切換工具庫react-native-i18n

總結:

首先Native那裡擷取本手機的LocaleList然後格式化取第一個元素交由I18n.js處理,然後I18n.js根據key選用一套有效的語言規則,再之後流程就和使用時候的順序一樣了。

整個庫內建難度較低,使用起來比較簡便,使用下來沒碰到大坑,配合redux更美味。

demo項目會在完成第一版功能後開源,是以暫時還沒有将該項目源碼放出,敬請期待

有問題可以微信聯系,當然得注明來意,不添加備注不會通過,謝謝(私人微信 非誠勿擾)

React-Native全球化語言切換工具庫react-native-i18n

以後會同步微信釋出,掃麥麥的碼可以關注

React-Native全球化語言切換工具庫react-native-i18n