0. 前言
最近在项目中添加了语言国际化,多语言的功能。
React-intl是雅虎的语言国际化开源项目FormatJS的一部分,通过其提供的组件和API可以与ReactJS绑定。
React-intl提供了两种使用方法,一种是直接调取API,另一种是引用React组件。
React-intl提供的调取API方法如下:
1.导入injectIntl
import { injectIntl, FormattedMessage } from 'react-intl'
2.在组件中注入
export default connect(state => {
return {
...state
};
})(injectIntl(App));
或
export default connect(mapStateToProps,mapActionCreators)(injectIntl(App))
3.使用intl
对象
我们通过第二步的注入,现在在我们在 组件的props
上会得到一个 intl 对象,它提供的方法和咱们上边介绍的组件基本相对应,这时候我们想要显示字符串,可以使用formatMessage
方法:
如图:
const {intl} = this.props;
let demo = intl.formatMessage({id: 'intl.name'});
4.应用
或使用defineMessages
,来进行转换成字符串
1.导入injectIntl
和defineMessages
import { FormattedMessage, injectIntl, defineMessages } from "react-intl";
2.在组件中注入injectIntl
export default connect(state => {
return {
...state
};
})(injectIntl(App));
或
export default connect(mapStateToProps,mapActionCreators)(injectIntl(App))
3.使用defineMessages
定义和intl
对象
const {intl: { formatMessage }} = this.props;
const demo = defineMessages({
placeholder: {
id: "modal.invite.placeholder",
defaultMessage: "请输入邀请人昵称",
},
});
4.应用
React-intl提供的React组件有如下几种:
包裹在需要语言国际化的组建的最外层,为包含在其中的所有组建提供包含id和字符串的键值对。
日期时间
1.
用于格式化日期,能够将一个时间戳格式化成不同语言中的日期格式。
传入时间戳作为参数:
输出结果:
4/5/2016
2.
用于格式化时间,效果与
相似。
传入时间戳作为参数:
输出结果:
1:09 AM
3.
通过这个组件可以显示传入组件的某个时间戳和当前时间的关系,比如 "10 minutes ago" 。
传入时间戳作为参数:
输出结果:
now
10秒之后的输出结果:
10 seconds ago
1分钟之后的输出结果:
1 minute ago
数字量词
1.
这个组件最主要的用途是用来给一串数字标逗号,比如10000这个数字,在中文的语言环境中应该是1,0000,是每隔4位加一个逗号,而在英语的环境中是10,000,每隔3位加一个逗号。
传入数字作为参数:
输出结果:
1,000
2.
这个组件可用于格式化量词,在中文的语境中,其实不太会用得到,比如我们说一个鸡腿,那么量词就是‘个’,我们说两个鸡腿,量词还是‘个’,不会发生变化。但是在英文的语言环境中,描述一个苹果的时候,量词是apple,当苹果数量为两个时,就会变成apples,这个组件的作用就在于此。
传入组件的参数中,value为数量,其他的为不同数量时对应的量词,在下面的例子中,一个的时候量词为message,两个的时候量词为messages。实际上可以传入组件的量词包括 zero, one, two, few, many, other 已经涵盖了所有的情况。
传入组件的量词参数可以是一个字符串,也可以是一个组件,我们可以选择传入
输出结果:
messages
字符串的格式化
1.
这个组件用于格式化字符串,是所有的组件中使用频率最高的组件,因为基本上,UI上面的每一个字符串都应该用这个组件替代。
比如我们在locale配置文件中写了如下内容:
const zhCn = {
hello:"你好,世界!",
};
export default zhCn;
使用这个组件的时候,我们这么写:
id指代的是这个字符串在locale配置文件中的属性名,description指的是对于这个位置替代的字符串的描述,便于维护代码,不写的话也不会影响输出的结果,当在locale配置文件中没有找到这个id的时候,输出的结果就是defaultMessage的值。
输出的结果:
你好,世界!
2.
这个组件的用法和
完全相同,唯一的不同就是输出的字符串可以包含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. 使用
使用
组件包裹住需要您需要进行语言国际化的组件,用法和React-redux的
差不多,当
包裹住某个组件的时候,这个组件本身和组件内部包含的子组件就可以获得所有React-intl提供的接口以及在
中引入的locale配置文件的内容。
addLocaleData
:引入本地的 localedata
IntlProvider
:包裹需要翻译的组件,用来传递给子类语言信息
FormattedMessage
:包裹需要实现多国语言的文字
locale
是传递需要国际化的语言的缩写,通过这个参数可以确定格式化日期,数字,量词的时候按照哪一种语言的规则,这个是规则是
intl
提供的,一般浏览器会内置这个库,但是在Safari和IE11之前需要自己安装,安装的方法前面已经提及,请自己翻阅。
messages
是用于传递刚刚我们在第3步中定义的配置文件的,从示例代码中我们可以看出,首先我们使用Import
语句引入了配置文件,然后将配置文件的内容传递给了messages
这个参数,此时
组件中的所有组件都可以拿到配置文件中的内容了。
首先,我先获取localStorage
中存储的语言,如果没有设置过,那么我就获取浏览器的语言navigator.language
,如果设置过,那么就从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 } from "./../../lib/tools/utils.js";
const Intl = ({ children }) => {
addLocaleData([...zh, ...en, ...ja, ...ko]);
const defaultLang = getLanguage();
return (
{children}
);
};
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 getLanguage() {
const lang = navigator.language || navigator.userLanguage; // 常规浏览器语言和IE浏览器
const localStorageLang = localStorage.getItem("lang");
const defaultLang = localStorageLang || lang;
return defaultLang;
}
// 修改html.lang显示
export function changeHtmlLang(lang) {
return document.getElementById("lang").lang = lang;
}
// 设置语言
export function setLanguage(lang) {
const defaultLang = localStorage.setItem("lang", lang);
return defaultLang;
}
// 匹配语言
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了,你可以试一试了!!!