React项目国际化介绍(react-i18next、react-intl)

国际化可以使web站点或者app在不同的国家或者地区使用。可以国际化的内容有文本,日期、时间和数字的格式,还有货币等。目前市场上流行的react国际化框架主要有react-i18n和react-intl,本文主要以文本国际化来介绍两种方案的入门用法及对比。

React-i18next

介绍

react-i18next是基于i18next的一款强大的国际化框架,可以用于react和react-native应用,以下是react-i18next一些特点:

  • 基于i18next不仅限于react,学一次就可以用在其它地方
  • 提供多种组件在hoc、hook和class的情况下进行国际化操作
  • 适合服务端的渲染
  • 历史悠久,始于2011年比大多数的前端框架都要年长
  • 因为历史悠久所以更成熟,目前还没有i18next解决不了的国际化问题
  • 有许多插件的支持,比如可以用插件检测当前系统的语言环境,从服务器或者文件系统加载翻译资源

准备开始

  1. 安装依赖
# npm
$ npm install react-i18next i18next --save
# 如果需要检测当前浏览器的语言或者从服务器获取配置资源可以安装下面依赖
$ npm install i18next-http-backend i18next-browser-languagedetector --save
  1. 在locales目录下添加多语言配置文件,文件类型为json。


    E5277497-767F-43AF-9E38-599F5DAD2FD9.png
#en.json
{
    "欢迎使用 react-i18next": "Welcome to react using react-i18next",
    "切换语言": "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",
    "切换语言": "言語を切り替える",
    "切换到中文": "中国語に切り替える",
    "切换到英文": "英文に切り替える",
    "切换到日文": "日本語に切り替える",
    "methods": {
        "renderProps": "renderProps方式で言語を変換する",
        "hook": "hook方式で言語を変換する",
        "hoc": "hoc方式で言語を変換する"
    }
}
#zh.json
{
    "methods": {
        "renderProps": "用renderProps转换",
        "hook": "用hook转换",
        "hoc": "用hoc转换"
    }
}
  1. 初始化配置,新建i18n.js文件,对i18n进行初始化操作及插件配置
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. 切换语言
<Button onClick={() => i18n.changeLanguage('zh')}>{t('切换到中文')}</Button>
  1. 通过RenderProps的方式国际化组件
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国际化
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)的方式处理国际化
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通过context api的方式为react项目提供多语言支持,可以对文本、数字、日期等进行翻译。以下代码以组件的方式进行国际化操作。

准备开始

  1. 安装依赖
npm i -S react-intl
  1. 在locales文件夹中创建多语言资源文件,与i18next不同的是,资源文件的类型为js类型,导出的是一个对象,因为翻译的文本中可以存在变量灵活替换,比如代码中的 { 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: "中国語に切り替える",
    changeToEnglish: "英文に切り替える",
    changeToJapanese: "日本語に切り替える",
    description: "描写",
    value: "値を使う(value) {value}",
    function: "関数はサブセットとする"
}
  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. 切换语言,react-intl没有提供切换语言的接口,所以需要开发者手动完成。以下是通过按钮点击修改state中语言的类型来切换语言的。
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())的方式来进行国际化处理,通过id获取对应的语言文本进行国际化。
<div style={{ margin: 20, background: 'red', color: 'white', width: 233 }}>
    <FormattedMessage id='welcome' />
</div>
  1. 使用缺省消息,如果当前的id在当前语言的资源文件中没有对应的配置,那就会显示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. 通过value传值
<div style={{ margin: 20, background: 'blue', color: 'white', width: 233 }}>
    <FormattedMessage id='value' values={{ value: 233 }} />
</div>
  1. 函数作为FormattedMessage的子组件,可以通过这种方式来传递国际化的组件。
<div style={{ margin: 20, background: 'green', color: 'white', width: 233 }}>
    <FormattedMessage id='function'>
        {
            txt => (
                <div style={{fontSize: 30}}>{txt}</div>
            )
        }
    </FormattedMessage>
</div>

对比

  • React-i18next初始化的时候需要将初始化配置放置在初始化文件(i18n.js)中,然后将初始化文件(i18n.js)通过import的方式引入到入口文件中即可。当然也可以通过I18nextProvider将i18n往下传递到各子组件。React-intl提供的是context api初始化方案,需要将初始化配置放在IntlProvider组件中,并且将入口文件的组件(如<App />)作为IntlProvider的子组件来使用;
  • React-i18next提供了切换语言的接口(i18n.changeLanguage),react-intl则需要对切换做一些封装的工作;
  • React-i18next提供了三种方式进行国际化操作(render props、hook和hoc), react-intl提供了api(intl.formatMessage())和组件(<FormattedMessage />)两种方式进行国际化;
  • React-i18next的语言资源文件为json格式,react-intl为js格式,同时支持变量传值;
  • React-i18next有很多插件可以使用比如检测当前系统语言,从后端获取数据等;
  • React-intl除文本翻译外还提供日期、时间和金额的国际化支持;

参考文档

Demo 地址

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343