react中文國際化自動化插件 react-i18n-auto實現方案(webpack+bable插件)

react-i18n-auto使用方法,請參考

react國際化目前現狀——前言


國際化對於某些大型公司很常見的業務,他們基本也都有本身的一套國際化規範,但對於小公司而言可能並無這些需求,平時也不太注重。若是有需求,一般解決的方法就是使用 react-intl ,react-i18next等一些現有的npm包。如下是我大體瞭解的方案,以react-intl爲例,以下:node

參考文檔:react-intl 國際化 文檔指引react

方案一:React組件引用
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import {IntlProvider, FormattedMessage} from 'react-intl';
...

ReactDOM.render(
  <IntlProvider locale="en">
    <App />
  </IntlProvider>,
  document.getElementById('container')
);)

App.jswebpack

import {FormattedMessage} from 'react-intl';
...
class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      name: 'Eric',
      unreadCount: 1000,
    };
  }
  render() {
    const {name, unreadCount} = this.state;
    return <p>
        <FormattedMessage id="welcome"
          defaultMessage={
            `Hello {name}, you have {unreadCount, number} 
             {unreadCount, plural, one {message} other {messages}}`
          } values={{name: <b>{name}</b>, unreadCount}}/>
    </p>
  }
}

看出來了嗎?若是你沒有學習過,你根本不會知道上面的屬性表明着什麼,這樣的國際化已經變了原有的頁面結構,並且每用到一處就得改動對應的代碼,及其繁瑣。git

方案二:函數式調用
import React, {Component} from 'react';
import locale from './resources/locale';
import t from 'xxx';
...
class App extends Component {
  render() {
    return <div>
        <header>{ t.i18n('我是要翻譯的內容') }</header>
        <div>{ t.text(locale.a.b) }</div> //這是我另外一處要翻譯的內容
    </div>
  }
}
// resources語言包結構
const locale = {
    a:{
        b:'這是我另外一處要翻譯的內容',
        c:'ccc',
        d:'xxx',
        ...
    }
    ...
}

這是經過函數調用的思路來實現的,這種不會對react的層級結構有太大影響,也相對靈活,其痛點在於語言包文件管理時命名讓人很頭痛,幾十個翻譯字段還好。想想你有個項目有幾千個翻譯字段,並且仍是一個老項目,一個個字段取名,而後在翻譯到對應的頁面上,香不香?這種方法不只有可能會遺漏,還可能會出錯。github

對於目前已有的國際化方案,先拋開學習成本不說,立立刻手,作一個國際化項目大概須要多久呢?一天?一週?仍是一個月?,個人答案是基本在一週以上,對於緊急的項目時間是極其重要的。web

因爲現有的國際化方案都極其繁瑣、枯燥,且隨着項目的進展愈來愈難以維護,尤爲是對於多人開發的大型項目。既然不盡如人意,咱們不妨探討一下方便快速的國際化方案。npm

國際化自動化——思路


對於國際化這種重複性的工做,最合適的就是自動化,一切交給程序來解決,豈不是更香?segmentfault

自動化的大體思路就是經過代碼自動實現上面的方案二,具體作法:babel

  1. 自動提取語言包文件
  2. 自動添加頁面翻譯
  3. 額外的其餘工做

爲了實現自動化,最早想到的是webpack,網上搜索了一遍發現並無現成的工具可用,只能本身手寫一個插件,學習了一番怎麼寫插件以後,發現webpack文檔並無面面俱到,都只給你個大概,想了解更詳細的信息只能本身去看源碼,學習成本陡然增長。dom

ps:學習無果以後,我還試着想能不能經過正則來實現呢,都是字符串處理啊。想一想仍是太天真了,這估計和寫個js解析引擎也差很少了。

因爲webpack的構建都是基於babel實現的,直接擼一個babel插件是否是會更好呢?因而着手學習babel,發現文檔更齊全,更加規範。學習babel以前,要先了解AST語法樹請參考:AST Explorer(https://astexplorer.net),AST很早以前就有了,但不多用於普通開發者,直到nodejsreactwebpack等技術的興起,才被普遍使用。

babel根據AST規範將咱們的js代碼解析成樹狀結構,如同咱們常見的dom樹同樣,用不一樣的標籤,表示不一樣的語義。AST則定義了不一樣的類型來表示不一樣js代碼的語義,具體可參考@babel/typesAPI,列出了全部已實現的語法類型及其用法。

關於babel的更多詳細解析請移步至:剖析 Babel——Babel 總覽 http://www.alloyteam.com/2017/04/analysis-of-babel-babel-overview/

有了babel的認知基礎以後咱們就能夠開始寫babel插件了。它可以原子級別的控制咱們的代碼,輕鬆實現咱們想要的功能。

babel插件開發格式以下
export  default  function() { 
    return { 
        visitor: { 
            Identifier(path) { // 全部類型爲Identifier的AST樹,都會經過此方法進行處理
                const name = path.node.name; 
                // reverse the name: JavaScript -> tpircSavaJ
                // 編譯前 var JavaScript;
                // 編譯後 var tpircSavaJ;
                path.node.name = name .split("") .reverse() .join(""); 
            },
            StringLiteral(path) { // 處理StringLiteral(字符串)類型
                let {node} = path;
                ...
            },
        },
    };
}

react-i18n-auto全自動化——實現


實現方式:react國際化自動化插件 react-i18n-auto

使用安裝

npm install react-i18n-auto --save-dev

添加babel插件配置項

{ 
    "plugins": [
        ...
        "react-i18n-auto"
        ...
    ] 
}

編譯前效果:

export  default  class App extends React.Comment{
    render(){
        let title = '這是翻譯的文字'
        return <div title={title}>
            <div title='這是要翻譯的標題'>
                我是要翻譯的內容
            </div>
        </div>
    }
}

編譯後效果:

export  default  class App extends React.Comment{
    render(){
        let title = $T('aa8ds','這是翻譯的文字')
        return <div title={title}>
            <div title={$T('see23','這是要翻譯的標題')}>
                {$T('ae22s','我是要翻譯的內容')}
            </div>
        </div>
    }
}

自動生成的語言包配置

locale.js

export let locale = {
    "aa8ds":"這是翻譯的文字",
    "see23":"這是要翻譯的標題",
    "ae22s":"我是要翻譯的內容",
}

react-i18n-auto實現了對源碼的無污染,開發時無感知,隻影響打包後的代碼,實現所有自動化。只需將locale.js翻譯成對應的語言包文件,根據語言加載對應的語言包便可。對於React項目可實現快速完成國際化開發任務。

更多使用詳情請參考:react-i18n-auto github主頁

本文參考連接:
  1. 剖析 Babel——Babel 總覽
  2. babel plugins
  3. @babel/types
相關文章
相關標籤/搜索