0. 前言

最近在项目中添加了语言国际化,多语言的功能。
React-intl是雅虎的语言国际化开源项目FormatJS的一部分,通过其提供的组件和API可以与ReactJS绑定。
React-intl提供了两种使用方法,一种是引用React组建,另一种是直接调取API。
React-intl提供的React组件有如下几种:
<IntlProvider />
包裹在需要语言国际化的组建的最外层,为包含在其中的所有组建提供包含id和字符串的键值对。
日期时间
1.<FormattedDate />
用于格式化日期,能够将一个时间戳格式化成不同语言中的日期格式。
传入时间戳作为参数:
<FormattedDate
value={new Date(1459832991883)}
/>
输出结果:
<span>4/5/2016</span>
2.<FormattedTime>
用于格式化时间,效果与<FormattedDate />
相似。
传入时间戳作为参数:
<FormattedTime
value={new Date(1459832991883)}
/>
输出结果:
<span>1:09 AM</span>
3.<FormattedRelative />
通过这个组件可以显示传入组件的某个时间戳和当前时间的关系,比如 "10 minutes ago" 。
传入时间戳作为参数:
<FormattedRelative
value={Date.now()}
/>
输出结果:
<span>now</span>
10秒之后的输出结果:
<span>10 seconds ago</span>
1分钟之后的输出结果:
<span>1 minute ago</span>
数字量词
1.<FormattedNumber />
这个组件最主要的用途是用来给一串数字标逗号,比如10000这个数字,在中文的语言环境中应该是1,0000,是每隔4位加一个逗号,而在英语的环境中是10,000,每隔3位加一个逗号。
传入数字作为参数:
<FormattedNumber
value={1000}
/>
输出结果:
<span>1,000</span>
2.<FormattedPlural />
这个组件可用于格式化量词,在中文的语境中,其实不太会用得到,比如我们说一个鸡腿,那么量词就是‘个’,我们说两个鸡腿,量词还是‘个’,不会发生变化。但是在英文的语言环境中,描述一个苹果的时候,量词是apple,当苹果数量为两个时,就会变成apples,这个组件的作用就在于此。
传入组件的参数中,value为数量,其他的为不同数量时对应的量词,在下面的例子中,一个的时候量词为message,两个的时候量词为messages。实际上可以传入组件的量词包括 zero, one, two, few, many, other 已经涵盖了所有的情况。
<FormattedPlural
value={10}
one='message'
other='messages'/>
传入组件的量词参数可以是一个字符串,也可以是一个组件,我们可以选择传入<FormattedMessage />组件,就可以实现量词的不同语言的切换。
输出结果:
<span>messages</span>
字符串的格式化
1.<FormattedMessage />
这个组件用于格式化字符串,是所有的组件中使用频率最高的组件,因为基本上,UI上面的每一个字符串都应该用这个组件替代。
比如我们在locale配置文件中写了如下内容:
const zhCn = {
hello:"你好,世界!",
};
export default zhCn;
使用这个组件的时候,我们这么写:
<FormattedMessage
id=hello'
description=问好'
defaultMessage='你好,世界!'
/>
id指代的是这个字符串在locale配置文件中的属性名,description指的是对于这个位置替代的字符串的描述,便于维护代码,不写的话也不会影响输出的结果,当在locale配置文件中没有找到这个id的时候,输出的结果就是defaultMessage的值。
输出的结果:
<span>你好,世界!</span>
2.<FormattedHTMLMessage />
这个组件的用法和<FormattedMessage />
完全相同,唯一的不同就是输出的字符串可以包含HTML标签,但是官方不太推荐使用这个方法,这个组件的用法我就不举例了。
1. 安装
假设你已经在你的系统中安装了node.js和npm。
打开终端,进入项目根目录,输入以下指令安装React-intl:
npm install react-intl -save
注意:为了兼容Safari各个版本,需要同时安装 intl,intl在大部分的『现代』浏览器中是默认自带的,但是Safari和IE11以下的版本就没有了,这里需要注意一下。
安装intl需要在终端中输入以下指令:
npm install intl --save
2. 引用
import { FormattedMessage } from 'react-intl'
由于我使用的是ES6 的语法,所以是支持直接引用组件的。你当然可以使用ES5的方式引用。
require ReactIntl from 'react-intl'
3. 创建locale配置文件
这里,我们将文件命名为zh_CN.js、en_US.js、ja_JP.js、ko_KR.js,分别代表中文、美式英语、日语、韩语的配置包。
在zh_CN.js编写如下代码:
const zhCn = {
hello:"你好,世界!",
};
export default zhCn;
在en_US.js编写如下代码:
const enUs = {
hello:"Hello, world!",
};
export default enUs;
在ja_JP.js编写如下代码:
const jaJp = {
hello:"こんにちは、世界!",
};
export default jaJp;
在ko_KR.js编写如下代码:
const koKr = {
hello:"안녕, 세계!",
};
export default koKr;
我们就创建好了locale文件。
4. 使用<IntlProvider />
使用<IntlProvider />
组件包裹住需要您需要进行语言国际化的组件,用法和React-redux的<Provider />
差不多,当<IntlProvider />
包裹住某个组件的时候,这个组件本身和组件内部包含的子组件就可以获得所有React-intl提供的接口以及在<IntlProvider />
中引入的locale配置文件的内容。
addLocaleData
:引入本地的 localedata
IntlProvider
:包裹需要翻译的组件,用来传递给子类语言信息
FormattedMessage
:包裹需要实现多国语言的文字

locale
是传递需要国际化的语言的缩写,通过这个参数可以确定格式化日期,数字,量词的时候按照哪一种语言的规则,这个是规则是intl
提供的,一般浏览器会内置这个库,但是在Safari和IE11之前需要自己安装,安装的方法前面已经提及,请自己翻阅。
messages
是用于传递刚刚我们在第3步中定义的配置文件的,从示例代码中我们可以看出,首先我们使用Import
语句引入了配置文件,然后将配置文件的内容传递给了messages
这个参数,此时<App />
组件中的所有组件都可以拿到配置文件中的内容了。
我是把每次选择的语言存贮在本地localStorage
中,这样下次进来就是你上次选中的语言,如果没有选中那就是默认中文。

5. 实现效果
好了,看一下实现效果

6. 配置文件代码
一、
import React from "react";
import PropTypes from "prop-types";
import { IntlProvider, addLocaleData } from "react-intl";
import zh from "react-intl/locale-data/zh";
import en from "react-intl/locale-data/en";
import ja from "react-intl/locale-data/ja";
import ko from "react-intl/locale-data/ko";
import { chooseLocale, getLanguage, setLanguage } from "./../../lib/tools/utils.js";
addLocaleData([...zh, ...en, ...ja, ...ko]);
const Intl = ({ children }) => {
const defaultLang = getLanguage();
if (!defaultLang) {
setLanguage("zh");
}
if (defaultLang === "zh") {
setLanguage("zh");
}
if (defaultLang === "en") {
setLanguage("en");
}
if (defaultLang === "ja") {
setLanguage("ja");
}
if (defaultLang === "ko") {
setLanguage("ko");
}
return (
<IntlProvider locale={defaultLang} messages={chooseLocale()}>
{children}
</IntlProvider>
);
};
Intl.propTypes = {
children: PropTypes.node.isRequired,
}
export default Intl;
二、
import enUs from "./../locale/en_US";
import zhCn from "./../locale/zh_CN";
import jaJp from "./../locale/ja_JP";
import koKr from "./../locale/ko_KR";
// 设置语言
export function setLanguage(lang) {
const defaultLang = localStorage.setItem("lang", lang);
return defaultLang;
}
// 获取语言
export function getLanguage() {
const defaultLang = localStorage.getItem("lang");
return defaultLang;
}
// 修改html.lang显示
export function changeHtmlLang(lang) {
return document.getElementById("lang").lang = lang;
}
// 匹配语言
export function chooseLocale() {
switch (getLanguage()) {
case "en":
changeHtmlLang(getLanguage());
return enUs;
case "zh":
changeHtmlLang(getLanguage());
return zhCn;
case "ja":
changeHtmlLang(getLanguage());
return jaJp;
case "ko":
changeHtmlLang(getLanguage());
return koKr;
default:
changeHtmlLang(getLanguage());
return zhCn;
}
}
7. 结束语
好了,国际化已经over了,你可以试一试了!!!
网友评论