react-intl前端国际化快速入门

5,619 阅读3分钟

最近在给大前端项目增加国际化支持,国际化也叫本地化,简单来说就是让页面可以切换语言来使不同语言的人能看懂。

现在社区也很多优秀的国际化解决方案。这些解决方案通常和相应技术栈绑定。但其原理基本是一致的,从我的理解来看,都是将页面的文字提出来统一管理,给页面“挖坑”,用id占位置,在不同语言环境下给这个坑填上不同的文字。以react-intl为例子。

React-intl

1.安装

npm install --save react-intl

2.配置多语言映射关系

可以在项目中新建文件夹locale统一管理,例如:

image.png

en_US.js

const en_US = {
    "menu" : "Menu",
    "hello" : "Hello
}
export {
    en_US
}   

zh_CN.js

const en_US = {
    "menu" : "菜单",
    "hello" : "你好
}
export {
    en_US
}   

index.js

index.js
import { zh_CN } from './zh_CN';
import { en_US } from './en_US';

console.log('enUS', enUS);
function loadLocale(lang) {
    let locale = null;
    let message = null;
    switch (lang) {
        case 'en-US':
            locale = 'en-US';
            message = en_US;
            antLocale = enUS;
            break;
        case 'zh-CN':
            locale = 'zh-CN';
            message = zh_CN;
            antLocale = zhCN;
                break;
        default:
            locale = 'zh-CN';
            message = zh_CN;
            antLocale = zhCN;
            break;
    }
    return { locale, messagee };
}
export { loadLocale };

3.全局配置

在入口组件中引入国际化容器IntlProvider,并包裹组件,例如:

Main.jsx

import React, { Component } from 'react';
import ReactDOM, { render } from 'react-dom';
import { IntlProvider } from 'react-intl';
import { loadLocale } from './locale/index';
import Content from './Content.jsx'

class Index extends Component {
    constructor(props) {
        super(props);
        this.state = {
            lang: 'zh-CN',
        };
    }
    render() {
        const { lang } = this.state;
        const { locale, message } = loadLocale(lang);
        return (
                <IntlProvider locale={locale} messages={message}>
                    <Content />
                </IntlProvider>
            </div>
        );
    }
}


ReactDOM.render(
    <Index />
  document.getElementById('root')
);

其中message也就是id和字符串的对应关系

4.在组件中使用

有两种使用方式

组件方式

<FormattedMessage/> 代替字符串在组件中的位置,并配置相关组件属性,例如:

Conten.jsx

import React from 'react';
import { FormattedMessage } from 'react-intl';

class Content extends React.Component {
    constructor(props) {
            super(props);
            this.state = {};
    }
    render() {
        return (
            <div>
                <FormattedMessage id="hello" />
            </div>
        );
    }
}

export default Content;

此时,<FormattedMessage id="hello" /> 会根据id和外层的 <IntlProvider>组件的locale和message寻找当前语言对应id的字符串,也就是‘你好’。

函数方式

用injectIntl()处理组件,向组件注入intl对象,intl的intl.formatMessage可以

例如:

Conten.jsx

import React from 'react';
import { injectIntl } from 'react-intl';

class Content extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
        };
    }
    render() {
        const { intl } = props
        return (
            <div>
                {
                    intl.formatMessage({ id : hello})
                }
            </div>
        );
    }
}
const ContenIntl = injectIntl(Content)
export default ContenIntl;

同样的,intl.formatMessage({ id : hello})会在当前语言环境下返回‘你好’。

5.在非组件中使用

在组件中使用没有问题,但是在非组件中(例如Store)如何使用呢?react-intl提供了方法在非组件环境创建intl对象。

createIntlCache创建一个缓存实例以供跨语言环境全局使用。 createIntl则可以创建一个intl对象供全局使用。

import { createIntl, createIntlCache } from 'react-intl';
import { zh_CN } from './zh_CN';
const cache = createIntlCache();
const message = 
const intl = createIntl(
    {
        locale: 'zh-CN',
        messages: zh_CN,
    },
    cache
);
export { intl };

此时创建出的intl可以供全局使用,用法和在组件中的函数方式一样:intl.formatMessage({ id : hello})

6.复杂字符串

以上介绍了简单字符串的国际化,都是通过id来实现,但对于一些复杂的字符串,例如包含不同时间格式和不同数字格式的复杂字符串,则需要通过value,并将message写成类似模板字符串的形式。

//定义复杂字符串
en_US = {
    'info' : 'hello,{name}, today is {currentDate, date} ,your earnings today are {currentNumber,number} '
}

zh_CN = {
    'info' : '你好,{name}, 今天是{currentDate, date} ,你今天的收益为{currentNumber, number} '
}

//传值
<FormattedMessage
        id="info"
        values={{
                number: 98949,
                name: '小鱼',
                date: Date.now(),
        }}
/>

这里的{}相当于一个占位符,react-intl在处理的时候,会将传入的values的属性填入指定的位置,这里的date、number则是声明值的类型。

此时,在en-US环境下,字符串为 hello,小鱼, today is 1/10/2022 ,your earnings today are 98,949,在zh-CN环境下,字符串为你好,小鱼, 今天是2022/1/10 ,你今天的收益为98,949.我们可以看到出现了不同的时间和数字格式。

资料

文档: formatjs.io/docs/gettin…