react項目國際化實現(xiàn)過程以及store中如何實現(xiàn)多語言開發(fā)

前言

前段時間公司拓展了海外業(yè)務,因此需要前端系統(tǒng)的開發(fā)在完成業(yè)務需求的同時襟齿,可以實現(xiàn)國際化铸本,以滿足用戶的使用需要。

技術挑戰(zhàn)

之前完全沒有接觸相關的技術体斩,乍一看感覺很是簡單梭稚,就是翻譯一下文案。但是真正著手做的時候發(fā)現(xiàn)面臨很多技術上的挑戰(zhàn)絮吵,隨著項目上線弧烤,所以梳理一下整個開發(fā)過程中的思路。

需要進行國際化開發(fā)的內容

label蹬敲、placeholder暇昂、字段校驗提示信息
需要進行語言切換的內容.png
第三方插件

公司項目中用到了第三發(fā)組件:Antdesign和bootstraptable莺戒,都支持國際化開發(fā),但是其中bootstraptable的官方文檔對相關的內容較少急波,所以花費了較多的時間从铲。

開發(fā)思路

了解到React有支持國際化的組件-ReactIntl,所以除第三方插件以外澄暮,項目中的文案名段,基本都可以實現(xiàn)。
項目中文案整理.png

把需要翻譯的文案提取出來泣懊,放到對應的語言文件(en_US.js)中伸辟,因為項目中好多內容是重復的,所以工作量不是很大嗅定,如果內容很多的話自娩,這種方式的工作量太大了,需要更換方案渠退。
開發(fā)過程

  • 安裝ReactR-Intl組件
    React-intl是雅虎的語言國際化開源項目FormatJS的一部分忙迁,通過其提供的組件和API可以與ReactJS綁定。上面這句話援引了官方文檔的說辭碎乃,主要表達的是姊扔,這是一個很好的開源項目,有大團隊支持梅誓,使用量也很大恰梢,不會有太多坑,可以放心用梗掰。
    React-intl提供了兩種使用方法嵌言,一種是引用React組件,另一種是直接調取API及穗,官方更加推薦在React項目中使用前者摧茴,只有在無法使用React組件的地方,才應該調用框架提供的API埂陆,事實上苛白,我在項目的過程大部分都是用API的方式。
  1. 安裝react-intl需要執(zhí)行下面的命令:
npm install intl --save
  1. 在項目中引入react-intl
import { FormattedMessage } from 'react-intl';

該組件提供了全面的API來幫助我們進行開發(fā)焚虱,這里我們不詳細講解各個API购裙,只是介紹如何使用,其中使用頻率較高API包括:FormattedMessage(字符串格式化API)鹃栽、injectIntl(高階組件)躏率、FormattedPlural(格式化量詞)

  1. 通過代碼來了解一下如何使用上述API
import { injectIntl, FormattedMessage  } from 'react-intl';
class  Mycomponent extends Reflux.Component{
render(){
      const {messages, loacal} = this.props.intl;
    return (
        <Input placeholder={messages["warehouseCodeplacehoder"]}/>
      <Button type="primary" htmlType="submit" icon="search" ><FormattedMessage id="common_SearchSubmitBtn"/></Button>
        )
    }
}
export default injectIntl(Mycomponent );

通過injectIntl 在我們在 組件的 props 上會得到一個 intl 對象,它提供formatDate禾锤、formatTime私股、formatPlural摹察、formatMessage等方法和locale恩掷、formats、messages等屬性供嚎,這時候我們想要顯示字符串黄娘,可以使用formatMessage進行字符串的格式化。loacal可以拿到當前代碼的語言環(huán)境克滴。

可以直接利用messages['id]的方式逼争,可以直接從語言文件中拿到當前語言環(huán)境下文檔中對應id的字符串。
對于其他的字符串劝赔,可以使用formatMessageAPI進行格式化誓焦。
這種方式的應用場景還是蠻多的。

  • 配置語言文件
    語言的配置文件zh-config.js是比較關鍵的着帽,我們舉例說明
import appLocaleData from 'react-intl/locale-data/zh';
import messages from './zh_CN';
window.appLocale = {
  messages: Object.assign({}, messages),
  locale: 'zh-CN',
  data: appLocaleData,
  },
};
export default window.appLocale;

下面是語言文件zh.js杂伟,即key-value鍵值對

const zh_CN = {
            id: "中文字符串",
}
export default zh_CN;

主入口文件mian.js

import React, {Component} from 'react';
import { IntlProvider, addLocaleData } from 'react-intl';

function getLocale(lang){
  let result={};
  switch(lang){
    case 'zh_CN':
    result = require('./locale/zh-config');
    break;
    case 'en_US':
    result = require('./locale/en-US.config');
    break;
    default: result = require('./locale/zh-config');
  }
  return result.default || result;
}

class Lang extends React.Component{
  constructor(props){
      super(props);
      this.state={
          lan:" "
      }
      this.changeLang=this.changeLang.bind(this);
  }
  changeLang(p){
     if(p==='en-US'){
      this.setState({
        lan:"en_US"
      })
    }
   else {
      this.setState(
        {lan:"zh_CN"}
        )
    }
  }
  render(){
    const {lan} = this.state;
    const appLocale = getLocale(lan);
    addLocaleData(...appLocale.data);
    window.lang = appLocale.locale;
      return (
      <div >
      <IntlProvider 
          locale={appLocale.locale} 
          messages={appLocale.messages}
          >
           <LocaleProvider locale={appLocale.antd}>
          <Index />
          </LocaleProvider>
      </IntlProvider>
     
      <Radio.Group style={style}>
          <Radio.Button onClick={() => this.changeLang('zh-CN')} >中文</Radio.Button>
          <Radio.Button onClick={() => this.changeLang('en-US')}>En</Radio.Button>
      </Radio.Group>
      </div>
      )
  }
}
ReactDOM.render(<Lang/>,document.getElementById('root'));

當設置了上述兩個文件時,我們可以根據當前l(fā)ocale值來找對應的配置文件仍翰,從而找到對應的語言文件赫粥,再去匹配對應的id,拿到value值予借。我們在主入口文件中進行設置越平,切換到對應語言時,導入該語言的配置文件和語言包灵迫,從而全面替換字符串秦叛,實現(xiàn)多語言切換。

  • bootstraptable的國際化開發(fā)
    bootstraptable的國際化開發(fā)難點在于瀑粥,他的官方文檔這方面寫的較簡潔挣跋,所以摸索了較長時間,最后也是同過injectIntl高階組件包裹table利凑,從而拿到當前語言浆劲,再配置表格自動導入對應的語言包。
import createReactClass from 'create-react-class';
import 'bootstrap';
import 'bootstrap-table';
import {injectIntl } from "react-intl";
import Main from './main/Main';

const Layout = createReactClass({
changeLang (p){
    switch(p){
      case "en-US": require("bootstrap-table-locale-en");
      break;
      case "th-TH":  require("bootstrap-table-locale-th");
      break;
      case "zh-CN": require("bootstrap-table-locale-zh");
      break;
      default:  require("bootstrap-table-locale-en");
    }
  },
  render(){
    this.changeLang(this.props.intl.locale)
    return (
      <div>  
        <Main {...this.props}></Main>
      </div>
    );
  },
});

module.exports = injectIntl(Layout);
  • antd國際化開發(fā)
    antd 提供了一個 React 組件 LocaleProvider 用于全局配置國際化文案哀澈。
    LocaleProvider 使用 React 的 context 特性牌借,只需在應用外圍包裹一次即可全局生效。
    mian.js中有具體的使用方法割按,可以參考膨报。

解決store中的多語言實現(xiàn)

項目中調用接口的回調處理都在store文件中實現(xiàn),會有一些提示信息。但是react-intl并不支持store中字符串的多語言现柠,這個比較不好處理院领,在git上找到了一種解決方案
首先添加一個組件 CurrentLocale.js

import {injectIntl} from 'react-intl';

// Does not actually render anything visible. 
// We need it to provide access to internationalization for classes
// which are not a React component
class CurrentLocale extends React.Component {
    static CurrentLocale = null;

    componentWillMount() {
        if (!CurrentLocale.instance)
            CurrentLocale.instance = this;
    }

    render() {
        return null;
    }
}

export default injectIntl(CurrentLocale);

export function intl() {
    return CurrentLocale.instance.props.intl;
}

export function formatMessage(...args) {
    return intl().formatMessage(...args);
}

在項目入口處引入
然后在store文件中引入使用即可

import {formatMessage} from "../../../../locale/CurrentLocale";

class MyComponent extends Reflux.Store{
     onFunctionCompleted(res){
            if(res.state==='success'){
                message.success(formatMessage({id:"OperateSuccess"}));
            }else{
                Modal.error({title:formatMessage({id:"OperateFailed"}),content:res.error});
            }
        }
     }
export default MyComponent ;

寫在后面

畢業(yè)后的第一個項目就要求實現(xiàn)國際化够吩,對于之前沒有項目經驗又沒有人帶的我來說比然,挑戰(zhàn)巨大。因為之前沒有接觸過周循,所以全部都是邊學邊用强法,發(fā)現(xiàn)可以參考的文章不是很多,所以總結一下自己開發(fā)過程中的難點和通點湾笛,如果這篇文章可以幫助到大家饮怯,那么也算是做了一件有意義的事情。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末嚎研,一起剝皮案震驚了整個濱河市蓖墅,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌临扮,老刑警劉巖论矾,帶你破解...
    沈念sama閱讀 212,185評論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異公条,居然都是意外死亡拇囊,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,445評論 3 385
  • 文/潘曉璐 我一進店門靶橱,熙熙樓的掌柜王于貴愁眉苦臉地迎上來寥袭,“玉大人,你說我怎么就攤上這事关霸〈疲” “怎么了?”我有些...
    開封第一講書人閱讀 157,684評論 0 348
  • 文/不壞的土叔 我叫張陵队寇,是天一觀的道長膘掰。 經常有香客問我,道長佳遣,這世上最難降的妖魔是什么识埋? 我笑而不...
    開封第一講書人閱讀 56,564評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮零渐,結果婚禮上窒舟,老公的妹妹穿的比我還像新娘。我一直安慰自己诵盼,他們只是感情好惠豺,可當我...
    茶點故事閱讀 65,681評論 6 386
  • 文/花漫 我一把揭開白布银还。 她就那樣靜靜地躺著,像睡著了一般洁墙。 火紅的嫁衣襯著肌膚如雪蛹疯。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,874評論 1 290
  • 那天热监,我揣著相機與錄音捺弦,去河邊找鬼。 笑死狼纬,一個胖子當著我的面吹牛羹呵,可吹牛的內容都是我干的骂际。 我是一名探鬼主播疗琉,決...
    沈念sama閱讀 39,025評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼歉铝!你這毒婦竟也來了盈简?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 37,761評論 0 268
  • 序言:老撾萬榮一對情侶失蹤太示,失蹤者是張志新(化名)和其女友劉穎柠贤,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體类缤,經...
    沈念sama閱讀 44,217評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡臼勉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,545評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了餐弱。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片宴霸。...
    茶點故事閱讀 38,694評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖膏蚓,靈堂內的尸體忽然破棺而出瓢谢,到底是詐尸還是另有隱情,我是刑警寧澤驮瞧,帶...
    沈念sama閱讀 34,351評論 4 332
  • 正文 年R本政府宣布氓扛,位于F島的核電站,受9級特大地震影響论笔,放射性物質發(fā)生泄漏采郎。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,988評論 3 315
  • 文/蒙蒙 一狂魔、第九天 我趴在偏房一處隱蔽的房頂上張望蒜埋。 院中可真熱鬧,春花似錦毅臊、人聲如沸理茎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,778評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽皂林。三九已至朗鸠,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間础倍,已是汗流浹背烛占。 一陣腳步聲響...
    開封第一講書人閱讀 32,007評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沟启,地道東北人忆家。 一個月前我還...
    沈念sama閱讀 46,427評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像德迹,于是被迫代替她去往敵國和親芽卿。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,580評論 2 349

推薦閱讀更多精彩內容

  • 開始之前胳搞,先了解目前常用的 React 國際化插件:The Best Libraries for React i1...
    Evelynzzz閱讀 41,778評論 0 18
  • 發(fā)現(xiàn) 關注 消息 iOS 第三方庫卸例、插件、知名博客總結 作者大灰狼的小綿羊哥哥關注 2017.06.26 09:4...
    肇東周閱讀 12,066評論 4 62
  • 時間過的真快啊肌毅,似乎就在轉瞬間筷转,我們天人永隔已經五載。你的弟弟也已經到了一個狗都嫌棄的年紀悬而。前幾天呜舒,有人跟媽媽聊...
    禾言_2176閱讀 3,842評論 1 1
  • 我初中和高中的班主任很是巧地都姓張,都是三十歲出頭的年輕人笨奠,偏偏都有點顯老袭蝗,同樣永遠模糊的鏡片,同樣喜歡把襯衫扎進...
    珂鳴閱讀 258評論 0 1
  • 寫給讀者的話: 敬愛的讀者,你好腺兴! 如果你是因為標題而進來的讀者左电,那么,恭喜你被騙了页响,因為我寫下的這篇文章篓足,純粹是...
    謝卓錕閱讀 3,582評論 6 3