本文主要介绍了react-intl实现React国际化多语言的方法,分享给大家,具体如下:效果预览效果预览效果预览React Intl 国际化步骤React Intl 国际化步骤React Intl 国际化步骤

创建国际化资源文件

根据语言获取国际化资源

引入 react-intl 的 local data

创建 LocaleProvider 国际化上下文组件

创建 react-intl 国际化上下文组件

使用 react-intl's components & apis,进行国际化开发
创建国际化资源文件根据语言获取国际化资源引入 react-intl 的 local data创建 LocaleProvider 国际化上下文组件创建 react-intl 国际化上下文组件使用 react-intl's components & apis,进行国际化开发1. 创建国际化资源文件
1. 创建国际化资源文件目前我们管理资源文件的方式是在 src/locales 文件夹下:

.
├── en-US.js
├── en-US.messages.js
├── zh-Hans.js
└── zh-Hans.messages.js

.
├── en-US.js
├── en-US.messages.js
├── zh-Hans.js
└── zh-Hans.messages.js
*.messages.js 是我们的资源文件(这里我们采用了 js 格式,你也可以使用 json 等等),返回的是一个对象,key 为我们翻译用的 id,value 为具体语言的翻译,内容是:

export default {
'page.localeProvider.react': '{ name }, a JavaScript library for building user interfaces.',
'page.localeProvider.react.html': '

{ name } makes it painless to create interactive UIs. Design simple views for each state in your application, and { name } will efficiently update and render just the right components when your data changes.

Declarative views make your code more predictable and easier to debug.

',
'page.localeProvider.unreadCount': 'You have {unreadCount} new {notifications}',
'page.localeProvider.title.date': 'Current date: ',
'page.localeProvider.title.time': 'Current time: ',
'page.localeProvider.title.relative': 'Relative current time: ',
'page.localeProvider.title.number': 'Comma number: ',
'page.localeProvider.title.price': 'Price: ',
'page.localeProvider.title.percent': 'Percent: ',
};
export default {
'page.localeProvider.react': '{ name }, a JavaScript library for building user interfaces.',
'page.localeProvider.react.html': '

{ name } makes it painless to create interactive UIs. Design simple views for each state in your application, and { name } will efficiently update and render just the right components when your data changes.

Declarative views make your code more predictable and easier to debug.

',
'page.localeProvider.unreadCount': 'You have {unreadCount} new {notifications}',
'page.localeProvider.title.date': 'Current date: ',
'page.localeProvider.title.time': 'Current time: ',
'page.localeProvider.title.relative': 'Relative current time: ',
'page.localeProvider.title.number': 'Comma number: ',
'page.localeProvider.title.price': 'Price: ',
'page.localeProvider.title.percent': 'Percent: ',
};en-US.js 文件封装了 messages、locale 等国际化上下文组件需要的内容:

import appLocaleData from 'react-intl/locale-data/en';
// 引入组件多语言
import paginationLocale from '@/components/pagination/locales/en-US';
import messages from './en-US.messages';

window.appLocale = {
// 合并所有 messages, 加入组件的 messages
messages: Object.assign({}, messages, {

Pagination: paginationLocale,
}),

// locale
locale: 'en-US',

// react-intl locale-data
data: appLocaleData,

// 自定义 formates
formats: {

date: {

normal: {

hour12: false,

year: 'numeric',

month: '2-digit',

day: '2-digit',

hour: '2-digit',

minute: '2-digit',

},

},

// 货币

money: {

currency: 'USD',

},
},
};

export default window.appLocale;

import appLocaleData from 'react-intl/locale-data/en';
// 引入组件多语言
import paginationLocale from '@/components/pagination/locales/en-US';
import messages from './en-US.messages';

window.appLocale = {
// 合并所有 messages, 加入组件的 messages
messages: Object.assign({}, messages, {

Pagination: paginationLocale,
}),

// locale
locale: 'en-US',

// react-intl locale-data
data: appLocaleData,

// 自定义 formates
formats: {

date: {

normal: {

hour12: false,

year: 'numeric',

month: '2-digit',

day: '2-digit',

hour: '2-digit',

minute: '2-digit',

},

},

// 货币

money: {

currency: 'USD',

},
},
};

export default window.appLocale;
有了这些资源文件以及相关的封装之后,我们就可以在 LocaleProvider 和 InltProvider 中使用了。
2. 根据语言加载国际化资源
2. 根据语言加载国际化资源上一步我们创建了不同语言版本的国际化资源文件,我们还需要一个函数能够根据语言,加载对应的资源文件:

/**
* 获取国际化资源文件
*
* @param {any} lang
* @returns
*/
function getLocale(lang) {
let result = {};
switch (lang) {

case 'zh-CN':

result = require('./locales/zh-Hans');

break;

case 'en-US':

result = require('./locales/en-US');

break;

default:

result = require('./locales/zh-Hans');
}

return result.default || result;
}

/**
* 获取国际化资源文件
*
* @param {any} lang
* @returns
*/
function getLocale(lang) {
let result = {};
switch (lang) {

case 'zh-CN':

result = require('./locales/zh-Hans');

break;

case 'en-US':

result = require('./locales/en-US');

break;

default:

result = require('./locales/zh-Hans');
}

return result.default || result;
}
3. 引入 react-intl 的 local data
3. 引入 react-intl 的 local data3. 引入 react-intl 的 local data
import { addLocaleData } from 'react-intl';
...

render() {
const appLocale = getLocale('en-US');
addLocaleData(...appLocale.data);
...
}

import { addLocaleData } from 'react-intl';
...

render() {
const appLocale = getLocale('en-US');
addLocaleData(...appLocale.data);
...
}
react-intl 在做国际化的时候需要一些特有的 local data,主要是进行相对时间翻译时,比如昨天、今天、明天、几分钟前、几个月前之类的。我们通过 addLocaleData 这个方法加载相关内容,大家可以根据实际情况加载需要的 locale-data。
4. 创建 LocaleProvider 国际化上下文组件
4. 创建 LocaleProvider 国际化上下文组件
为了组件能够国际化资源信息,我们需要一个 LocaleProvider 组件,用它来提供国际化的上下文,具体用法:

export default class LocaleProvider extends React.Component {
static propTypes = {

children: PropTypes.any,

locale: PropTypes.object,
};

static childContextTypes = {

// 语言信息

locale: PropTypes.object,
};

getChildContext() {

return {

locale: {

...this.props.locale,

},

};
}

render() {

return React.Children.only(this.props.children);
}
}

export default class LocaleProvider extends React.Component {
static propTypes = {

children: PropTypes.any,

locale: PropTypes.object,
};

static childContextTypes = {

// 语言信息

locale: PropTypes.object,
};

getChildContext() {

return {

locale: {

...this.props.locale,

},

};
}

render() {

return React.Children.only(this.props.children);
}
}
5. 创建 react-intl 国际化上下文组件
5. 创建 react-intl 国际化上下文组件为了能够使用 react-intl 进行国际化,跟 redux 这些框架一样,我们需要一个 Provider Component,用它来提供国际化的上下文,具体用法:

...
import { addLocaleData, IntlProvider } from 'react-intl';
import LocaleProvider from '@/components/locale-provider';
import Home from '@/views/home';
...

render() {
// 根据语言获取国际化资源
const appLocale = getLocale('en-US');
addLocaleData(...appLocale.data);

return (




locale={appLocale.locale}

messages={appLocale.messages}

formats={appLocale.formats}

>






);
}

...
import { addLocaleData, IntlProvider } from 'react-intl';
import LocaleProvider from '@/components/locale-provider';
import Home from '@/views/home';
...

render() {
// 根据语言获取国际化资源
const appLocale = getLocale('en-US');
addLocaleData(...appLocale.data);

return (




locale={appLocale.locale}

messages={appLocale.messages}

formats={appLocale.formats}

>






);
}
LocaleProvider 有三个配置参数:

locale, , 国际化资源.
locale, , 国际化资源.IntlProvider 有三个配置参数:

locale, , 语言标记,例如 'zh-CN' 'en-US'

messages, , 国际化所需的 key-value 对象

formats, , 自定义 format,比如日期格式、货币等
locale, , 语言标记,例如 'zh-CN' 'en-US'messages, , 国际化所需的 key-value 对象formats, , 自定义 format,比如日期格式、货币等在定义好 IntlProvider 之后,我们就可以在页面使用它提供的 api 或者组件来进行国际化了。6. 使用 react-intl's components & apis
6. 使用 react-intl's components & apisreact-intl 提供了丰富的组件和 api 来完成页面部分的国际化。
字符串的格式化
字符串的格式化a. 这个组件用于格式化字符串,是所有的组件中使用频率最高的组件。除了可以根据配置输出不同语言的简单字符串之外,还可以输出包含动态变化的参数的复杂字符串,具体的用法在后面的例子中会慢慢叙述。
比如我们在 *.message.js 配置文件中写了如下内容:

export default {
'page.localeProvider.react': '{ name }, a JavaScript library for building user interfaces.',
};
export default {
'page.localeProvider.react': '{ name }, a JavaScript library for building user interfaces.',
};使用这个组件的时候,我们这么写:

tagName="p"
id="page.localeProvider.react"
values={{

name: 'React',
}}
defaultMessage="{name} 是一个用于构建用户界面的 JAVASCRIPT 库。"
description="{name} 是什么?"
/>

tagName="p"
id="page.localeProvider.react"
values={{

name: 'React',
}}
defaultMessage="{name} 是一个用于构建用户界面的 JAVASCRIPT 库。"
description="{name} 是什么?"
/>


id 指代的是这个字符串在配置文件中的属性名

description 指的是对于这个位置替代的字符串的描述,便于维护代码,不写的话也不会影响输出的结果

defaultMessage 当在locale配置文件中没有找到这个id的时候,输出的默认值

tagName 实际生成的标签,默认是 span

values 动态参数. 格式为对象
id 指代的是这个字符串在配置文件中的属性名description 指的是对于这个位置替代的字符串的描述,便于维护代码,不写的话也不会影响输出的结果defaultMessage 当在locale配置文件中没有找到这个id的时候,输出的默认值tagName 实际生成的标签,默认是 spanvalues 动态参数. 格式为对象输出的结果:

React, a JavaScript library for building user interfaces.


React, a JavaScript library for building user interfaces.

b. 这个组件的用法和完全相同,唯一的不同就是输出的字符串可以包含HTML标签。
日期时间
日期时间
a. 用于格式化日期,能够将一个时间戳格式化成不同语言中的日期格式。
传入时间戳作为参数:
value={new Date(1459832991883)}
/>
value={new Date(1459832991883)}
/>输出结果:


4/5/2021

2021/5/4

4/5/2021
2021/5/4b. 用于格式化时间,效果与相似。
传入时间戳作为参数:

value={new Date(1459832991883)}
/>
value={new Date(1459832991883)}
/>输出结果:


1:09 AM

上午1:09

1:09 AM
上午1:09c. 通过这个组件可以显示传入组件的某个时间戳和当前时间的关系,比如“10 minutes ago”。
传入时间戳作为参数:

value={Date.now()}
/>
value={Date.now()}
/>输出结果:


now

10 seconds ago

1 minute ago

现在

10秒前

1分钟前

now
10 seconds ago
1 minute ago
现在
10秒前
1分钟前数字量词
数字量词a. 这个组件可用于格式化量词,在中文的语境中,其实不太会用得到,比如我们说一个鸡腿,那么量词就是‘个',我们说两个鸡腿,量词还是‘个',不会发生变化。但是在英文的语言环境中,描述一个苹果的时候,量词是apple,当苹果数量为两个时,就会变成apples,这个组件的作用就在于此。
传入组件的参数中,value为数量,其他的为不同数量时对应的量词,在下面的例子中,一个的时候量词为message,两个的时候量词为messages。实际上可以传入组件的量词包括 zero, one, two, few, many, other 已经涵盖了所有的情况。
结合 运用:

const unreadCount = 10;
const unreadCount2 = 1;
...



id="page.localeProvider.unreadCount"

defaultMessage={'你有{ unreadCount }条新信息'}

values={{

unreadCount: (


style={{

color: '#f30',

fontWeight: 'normal',

}}

>


value={unreadCount}

/>



),

notifications: (


value={unreadCount}

one="notification"

other="notifications"

/>

),

}}
/>




id="page.localeProvider.unreadCount"

defaultMessage={'你有{ unreadCount2 }条新信息'}

values={{

unreadCount: (


style={{

color: '#f30',

fontWeight: 'normal',

}}

>


value={unreadCount2}

/>



),

notifications: (


value={unreadCount2}

one="notification"

other="notifications"

/>

),

}}
/>



const unreadCount = 10;
const unreadCount2 = 1;
...



id="page.localeProvider.unreadCount"

defaultMessage={'你有{ unreadCount }条新信息'}

values={{

unreadCount: (


style={{

color: '#f30',

fontWeight: 'normal',

}}

>


value={unreadCount}

/>



),

notifications: (


value={unreadCount}

one="notification"

other="notifications"

/>

),

}}
/>




id="page.localeProvider.unreadCount"

defaultMessage={'你有{ unreadCount2 }条新信息'}

values={{

unreadCount: (


style={{

color: '#f30',

fontWeight: 'normal',

}}

>


value={unreadCount2}

/>



),

notifications: (


value={unreadCount2}

one="notification"

other="notifications"

/>

),

}}
/>


输出结果:


You have 10 new notifications


You have 1 notification



你有10条新信息


你有1条新信息



You have 10 new notifications


You have 1 notification


你有10条新信息


你有1条新信息

b. 这个组件最主要的用途是用来给一串数字标逗号,比如10000这个数字,在中文的语言环境中应该是1,0000,是每隔4位加一个逗号,而在英语的环境中是10,000,每隔3位加一个逗号。
传入数字作为参数:

value={1000}
/>
value={1000}
/>输出结果:

1,000
1,000 输出百分比
传入小数作为参数:

value={0.5}
style="percent"
/>
value={0.5}
style="percent"
/>输出结果:

50%
50% 输出货币
传入数字作为参数:

// locale.formats.money.currency 是 /locales/*.js 国际化资源配置的货币信息。中文: 'CNY'; 英文: 'USD'

value={123456.78}
style="currency"
currency={locale.formats.money.currency}
/>

// locale.formats.money.currency 是 /locales/*.js 国际化资源配置的货币信息。中文: 'CNY'; 英文: 'USD'

value={123456.78}
style="currency"
currency={locale.formats.money.currency}
/>
输出结果:


$123,456.78

¥123,456.78

$123,456.78
¥123,456.78注:项目在中文情况下也是每隔3位加一个逗号,具体原因详,如果有知道原因的请告知。
组件国际化
组件国际化组件国际化1. 创建获取上下文国际化资源函数
1. 创建获取上下文国际化资源函数
/**
* 获取 组件的语言配置
*
* @param {any} props 属性
* @param {any} context 上下文
* @param {any} componentName 组件名. 对应 context.locale.messages 中的 key 值
* @param {any} getDefaultLocale
*/
function getComponentLocale(props, context, componentName, getDefaultLocale) {
let locale = {};

// 如果 context 上下文中有多语言配置. 则取 context 上下文中的多语言值.
// 否则, 取默认值的多语言值.
if (context && context.locale && context.locale.messages[componentName]) {

locale = context.locale.messages[componentName];
} else {

const defaultLocale = getDefaultLocale();

locale = defaultLocale.default || defaultLocale;
}

let result = {

...locale,
};

// 如果属性有语言配置项, 则合并.
if (props.locale) {

result = {

...result,

...props.locale,

};


if (props.locale.lang) {

result.lang = {

...locale.lang,

...props.locale.lang,

};

}
}

return result;
}

/**
* 获取 组件的语言配置
*
* @param {any} props 属性
* @param {any} context 上下文
* @param {any} componentName 组件名. 对应 context.locale.messages 中的 key 值
* @param {any} getDefaultLocale
*/
function getComponentLocale(props, context, componentName, getDefaultLocale) {
let locale = {};

// 如果 context 上下文中有多语言配置. 则取 context 上下文中的多语言值.
// 否则, 取默认值的多语言值.
if (context && context.locale && context.locale.messages[componentName]) {

locale = context.locale.messages[componentName];
} else {

const defaultLocale = getDefaultLocale();

locale = defaultLocale.default || defaultLocale;
}

let result = {

...locale,
};

// 如果属性有语言配置项, 则合并.
if (props.locale) {

result = {

...result,

...props.locale,

};


if (props.locale.lang) {

result.lang = {

...locale.lang,

...props.locale.lang,

};

}
}

return result;
}
2. 创建国际化的组件
2. 创建国际化的组件
...
import { getComponentLocale } from '../_utils/getLocale';
...

export default class Pagination extends React.Component {
// context 上下文
static contextTypes = {

locale: PropTypes.object,
};

render() {

const currentlocale = getComponentLocale(this.props, this.context, 'Pagination', () => {

require('./locales/zh-CN');

});


return (







{currentlocale.prevText}





{currentlocale.nextText}







);
}
}


...
import { getComponentLocale } from '../_utils/getLocale';
...

export default class Pagination extends React.Component {
// context 上下文
static contextTypes = {

locale: PropTypes.object,
};

render() {

const currentlocale = getComponentLocale(this.props, this.context, 'Pagination', () => {

require('./locales/zh-CN');

});


return (







{currentlocale.prevText}





{currentlocale.nextText}







);
}
}

国际化规范附录
国际化规范附录国际化规范附录React Intl 编写规范React Intl 编写规范

必须填写 defaultMessage,并将 defaultMessage 作为中文翻译

id 不得重复

在使用 intl.formatMessage() 时,必须使用 defineMessages,预定义消息
必须填写 defaultMessage,并将 defaultMessage 作为中文翻译id 不得重复在使用 intl.formatMessage() 时,必须使用 defineMessages,预定义消息源码
源码源码整个项目源码
源码资料

API

国际化方案

Intl.NumberFormat


APIAPI国际化方案国际化方案Intl.NumberFormat

Intl.NumberFormat
标签:

你有充足的理由选择我们

深圳上海杭州北京前端外包开发:工作10年以上的小伙伴团队,前端开发工作是我们最大的事业。所有您担心的问题,都可以写到合同里。我们会100%努力完成,直到您满意!