React項(xiàng)目國(guó)際化介紹(react-i18next、react-intl)

國(guó)際化可以使web站點(diǎn)或者app在不同的國(guó)家或者地區(qū)使用??梢試?guó)際化的內(nèi)容有文本,日期、時(shí)間和數(shù)字的格式,還有貨幣等。目前市場(chǎng)上流行的react國(guó)際化框架主要有react-i18n和react-intl,本文主要以文本國(guó)際化來(lái)介紹兩種方案的入門用法及對(duì)比。

React-i18next

介紹

react-i18next是基于i18next的一款強(qiáng)大的國(guó)際化框架,可以用于react和react-native應(yīng)用,以下是react-i18next一些特點(diǎn):

  • 基于i18next不僅限于react,學(xué)一次就可以用在其它地方
  • 提供多種組件在hoc、hook和class的情況下進(jìn)行國(guó)際化操作
  • 適合服務(wù)端的渲染
  • 歷史悠久,始于2011年比大多數(shù)的前端框架都要年長(zhǎng)
  • 因?yàn)闅v史悠久所以更成熟,目前還沒(méi)有i18next解決不了的國(guó)際化問(wèn)題
  • 有許多插件的支持,比如可以用插件檢測(cè)當(dāng)前系統(tǒng)的語(yǔ)言環(huán)境,從服務(wù)器或者文件系統(tǒng)加載翻譯資源

準(zhǔn)備開(kāi)始

  1. 安裝依賴
# npm
$ npm install react-i18next i18next --save
# 如果需要檢測(cè)當(dāng)前瀏覽器的語(yǔ)言或者從服務(wù)器獲取配置資源可以安裝下面依賴
$ npm install i18next-http-backend i18next-browser-languagedetector --save
  1. 在locales目錄下添加多語(yǔ)言配置文件,文件類型為json。


    E5277497-767F-43AF-9E38-599F5DAD2FD9.png
#en.json
{
    "歡迎使用 react-i18next": "Welcome to react using react-i18next",
    "切換語(yǔ)言": "change language",
    "切換到中文": "change to Chinese",
    "切換到英文": "change to English",
    "切換到日文": "change to Japenese",
    "methods": {
        "renderProps": "change language with render props",
        "hook": "change language with hook",
        "hoc": "change language with hoc"
 }
#ja.json
{
    "歡迎使用 react-i18next": "ご利用を歓迎する react-i18next",
    "切換語(yǔ)言": "言語(yǔ)を切り替える",
    "切換到中文": "中國(guó)語(yǔ)に切り替える",
    "切換到英文": "英文に切り替える",
    "切換到日文": "日本語(yǔ)に切り替える",
    "methods": {
        "renderProps": "renderProps方式で言語(yǔ)を変換する",
        "hook": "hook方式で言語(yǔ)を変換する",
        "hoc": "hoc方式で言語(yǔ)を変換する"
    }
}
#zh.json
{
    "methods": {
        "renderProps": "用renderProps轉(zhuǎn)換",
        "hook": "用hook轉(zhuǎn)換",
        "hoc": "用hoc轉(zhuǎn)換"
    }
}
  1. 初始化配置,新建i18n.js文件,對(duì)i18n進(jìn)行初始化操作及插件配置
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';

import resources from './locales/resources'
// don't want to use this?
// have a look at the Quick start guide 
// for passing in lng and translations on init

i18n
  // load translation using http -> see /public/locales (i.e. https://github.com/i18next/react-i18next/tree/master/example/react/public/locales)
  // learn more: https://github.com/i18next/i18next-http-backend
  .use(Backend)
  // detect user language
  // learn more: https://github.com/i18next/i18next-browser-languageDetector
  .use(LanguageDetector)
  // pass the i18n instance to react-i18next.
  .use(initReactI18next)
  // init i18next
  // for all options read: https://www.i18next.com/overview/configuration-options
  .init({
    fallbackLng: 'zh',
    lng: 'zh',
    debug: true,
    resources: resources,
    interpolation: {
      escapeValue: false, // not needed for react as it escapes by default
    }
  });

export default i18n;
  1. i18n.js文件引入到入口文件中App.js
import React from 'react';
import './i18n';

export default class App extends React.Component {

    render() {
        return (
            <div>
                {/* 省略...... */}
            </div>
        )
    }
}

  1. 切換語(yǔ)言
<Button onClick={() => i18n.changeLanguage('zh')}>{t('切換到中文')}</Button>
  1. 通過(guò)RenderProps的方式國(guó)際化組件
import React from 'react';
import { Translation } from 'react-i18next';

const Index = () => {
    return (
        <Translation>
            {
                t => {
                    return (
                        <div style={{background: 'red', margin: 20, color: 'white', width: 200}}>
                            {t('methods.renderProps')}
                        </div>
                    );
                }
            }

        </Translation>
    )
}

export default Index;
  1. 在hook中使用react-i18next國(guó)際化
import React from 'react';
import { useTranslation } from 'react-i18next';

const Index = () => {
    const { t } = useTranslation();
    return (
        <div style={{ background: 'yellow', margin: 20, width: 200 }}>
            {t('methods.hook')}
        </div>
    )
}

export default Index;
  1. 使用高階組件(Hoc)的方式處理國(guó)際化
import React from 'react';
import { withTranslation } from 'react-i18next';

const Index = ({ t }) => {
  return (
    <div style={{ background: 'blue', margin: 20, color: 'white', width: 200 }}>
      {t('methods.hoc')}
    </div>
  );
}

export default withTranslation()(Index);

React-intl

介紹

React-intl通過(guò)context api的方式為react項(xiàng)目提供多語(yǔ)言支持,可以對(duì)文本、數(shù)字、日期等進(jìn)行翻譯。以下代碼以組件的方式進(jìn)行國(guó)際化操作。

準(zhǔn)備開(kāi)始

  1. 安裝依賴
npm i -S react-intl
  1. 在locales文件夾中創(chuàng)建多語(yǔ)言資源文件,與i18next不同的是,資源文件的類型為js類型,導(dǎo)出的是一個(gè)對(duì)象,因?yàn)榉g的文本中可以存在變量靈活替換,比如代碼中的 { value }。
    1603187400393.jpg
export default {
    welcome: "Welcome to use react-intl",
    changeToChinese: "change to Chinese",
    changeToEnglish: "change to English",
    changeToJapanese: "change to Japanese",
    description: "description",
    value: "use value {value}",
    function: "function as the child"
}
export default {
    welcome: "react?intlの使用を歓迎します",
    changeToChinese: "中國(guó)語(yǔ)に切り替える",
    changeToEnglish: "英文に切り替える",
    changeToJapanese: "日本語(yǔ)に切り替える",
    description: "描寫",
    value: "値を使う(value) {value}",
    function: "関數(shù)はサブセットとする"
}
  1. 初始化,將入口文件的組件App包裹在IntlProvider組件中。
import React from 'react';
import { IntlProvider, FormattedMessage } from 'react-intl';
import App from './App';

export default class Index extends React.Component {

    render() {
        const { locale } = this.state;
        return (
            <IntlProvider locale={locale} messages={this.messages[locale]}>
                <App >
            </IntlProvider>
        )
    }
}
  1. 切換語(yǔ)言,react-intl沒(méi)有提供切換語(yǔ)言的接口,所以需要開(kāi)發(fā)者手動(dòng)完成。以下是通過(guò)按鈕點(diǎn)擊修改state中語(yǔ)言的類型來(lái)切換語(yǔ)言的。
import React from 'react';
import { IntlProvider, FormattedMessage } from 'react-intl';
import { Button, Row, Col } from 'antd';
import zh from './locales/zh';
import en from './locales/en';
import ja from './locales/ja';

export default class Index extends React.Component {

    messages = {
        zh: zh,
        en: en,
        ja: ja
    }
    state = {
        locale: 'zh'
    }

    render() {
        return (
            <IntlProvider locale={this.state.locale} messages={this.messages[this.state.locale]}>
                <Row gutter={16} style={{ margin: 20 }}>
                    <Col>
                        <Button onClick={() => this.setState({ locale: 'zh' })}>
                            <FormattedMessage id='changeToChinese' />
                        </Button>
                    </Col>
                    <Col>
                        <Button onClick={() => this.setState({ locale: 'en' })}>
                            <FormattedMessage id='changeToEnglish' />
                        </Button>
                    </Col>
                    <Col>
                        <Button onClick={() => this.setState({ locale: 'ja' })}>
                            <FormattedMessage id='changeToJapanese' />
                        </Button>
                    </Col>
                </Row>
            </IntlProvider>
        )
    }
}
  1. 與react-i18next不同,react-intl只提供了組件(文本組件 FormattedMessage)和api(intl.formatMessage())的方式來(lái)進(jìn)行國(guó)際化處理,通過(guò)id獲取對(duì)應(yīng)的語(yǔ)言文本進(jìn)行國(guó)際化。
<div style={{ margin: 20, background: 'red', color: 'white', width: 233 }}>
    <FormattedMessage id='welcome' />
</div>
  1. 使用缺省消息,如果當(dāng)前的id在當(dāng)前語(yǔ)言的資源文件中沒(méi)有對(duì)應(yīng)的配置,那就會(huì)顯示defaultMessage中的文本。
<div style={{ margin: 20, background: 'purple', color: 'white', width: 233 }}>
    <FormattedMessage id='defaultMessage' defaultMessage='使用缺省消息' />
</div>
  1. 使用描述
<div style={{ margin: 20, background: 'black', color: 'white', width: 233 }}>
    <FormattedMessage id='description' defaultMessage='描述' description='使用描述' />
</div>
  1. 通過(guò)value傳值
<div style={{ margin: 20, background: 'blue', color: 'white', width: 233 }}>
    <FormattedMessage id='value' values={{ value: 233 }} />
</div>
  1. 函數(shù)作為FormattedMessage的子組件,可以通過(guò)這種方式來(lái)傳遞國(guó)際化的組件。
<div style={{ margin: 20, background: 'green', color: 'white', width: 233 }}>
    <FormattedMessage id='function'>
        {
            txt => (
                <div style={{fontSize: 30}}>{txt}</div>
            )
        }
    </FormattedMessage>
</div>

對(duì)比

  • React-i18next初始化的時(shí)候需要將初始化配置放置在初始化文件(i18n.js)中,然后將初始化文件(i18n.js)通過(guò)import的方式引入到入口文件中即可。當(dāng)然也可以通過(guò)I18nextProvider將i18n往下傳遞到各子組件。React-intl提供的是context api初始化方案,需要將初始化配置放在IntlProvider組件中,并且將入口文件的組件(如<App />)作為IntlProvider的子組件來(lái)使用;
  • React-i18next提供了切換語(yǔ)言的接口(i18n.changeLanguage),react-intl則需要對(duì)切換做一些封裝的工作;
  • React-i18next提供了三種方式進(jìn)行國(guó)際化操作(render props、hook和hoc), react-intl提供了api(intl.formatMessage())和組件(<FormattedMessage />)兩種方式進(jìn)行國(guó)際化;
  • React-i18next的語(yǔ)言資源文件為json格式,react-intl為js格式,同時(shí)支持變量傳值;
  • React-i18next有很多插件可以使用比如檢測(cè)當(dāng)前系統(tǒng)語(yǔ)言,從后端獲取數(shù)據(jù)等;
  • React-intl除文本翻譯外還提供日期、時(shí)間和金額的國(guó)際化支持;

參考文檔

Demo 地址

https://github.com/freezing2616/react-i18n-demo

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

友情鏈接更多精彩內(nèi)容