最近搭建一个项目,从0开始作,须要作多语言的国际化,今天搞了一下,基本达到了想要的效果,第一次发掘金勿喷,在这里简单分享下:html
国际化是一个看似简单,实则很是复杂的领域,实际进行国际化工做时,你们会发现它每每会涉及不少内容:前端
并且,国际化方案每每与具体的技术栈是绑定的。react
本国际化方案仅针对 React 技术栈,且不会涉及服务端国际化内容。git
国际化的核心步骤有两步:github
也说不上是探索吧,就Google了一波, GitHub 上找了一个比较成熟的库以下:
react-i18next
npm
react-intl
json
接下来一一介绍一下如何使用浏览器
安装bash
npm install i18next react-i18next --save复制代码
引入App.js
import i18n from 'i18next';
import { useTranslation, initReactI18next } from 'react-i18next';
复制代码
初始化
const lng = 'en';
i18n
.use(initReactI18next) // passes i18n down to react-i18next
.init({
resources: {
en: {
translation: {
Welcome: 'Welcome to React',
},
},
zh: {
translation: {
Welcome: '欢迎进入react',
},
},
},
lng: lng,
fallbackLng: lng,
interpolation: {
escapeValue: false,
},
});
复制代码
实际使用结果
function App() {
const { t } = useTranslation();
return (
<div className="App">
<p>{t('Welcome')}</p>
</div>
);
}
export default App;
复制代码
封装后的成果:
// ...
import i18n from '@src/i18n';
// xxx component
console.log('i18n来一发:', i18n.t('INVALID_ORDER'));
render() {
// ...
<button> {i18n.t('INVALID_ORDER')} </button>
}复制代码
背景:
用于国际化 React 组件,提供 React 组件和 API 来格式化日期,数字,字符串(包括单复数和翻译)。
react-intl库是业界很受欢迎的库之一。 react-intl用包裹组件的形式装饰你的React.Component,动态注入国际化消息,以便可以动态加载语言环境数据,而且无需从新加载页面
npm install react-intl --save复制代码
React Intl 依赖这些数据来支持单复数和相对时间格式化的功能。
// Main.js
import { addLocaleData } from 'react-intl'; /* react-intl imports */
import en from 'react-intl/locale-data/en';
import zh from 'react-intl/locale-data/zh';
addLocaleData([...en, ...zh]); // 引入多语言环境的数据 复制代码
虽然我只用到了文本翻译的功能,觉得就不须要加载这些数据,但后来发现这是必须的步骤。否则会报错:
[React Intl] Missing locale data for locale: "zh". Using default locale: "en" as fallback.复制代码
使用
因为项目中用到了react-hot-loader
,根组件 Main
被<AppContainer>
包裹了,而且是从单独的一个文件 import 了 Main
组件。
//app.js
import { AppContainer } from 'react-hot-loader'
import Main from './components/Main'
//... ...
const render = Component => {
ReactDOM.render(
<AppContainer>
<Component />
</AppContainer>,
document.getElementById('app')
)
}
render(Main);复制代码
因而直接在 Main.js 中使用<IntlProvider>
组件。把它加到 render()
返回节点的最外层就好了。
// Main.js
import { addLocaleData, IntlProvider } from 'react-intl'; /* react-intl imports */
render(){
return (
<IntlProvider>
//··· ···
</IntlProvider>
)
}复制代码
好比要支持中英文,为了方便以后维护,能够新建两个文件:
locale目录下新建
// en_US.js
const en_US = {
hello: "Hello!",
//... ...
}
export default en_US;
// zh_CN.js
const zh_CN = {
hello: "你好!",
//... ...
}
export default zh_CN;复制代码
而后在Main.js中引入这两个变量。
// Main.js
import zh_CN from "../locale/zh_CN" // import defined messages in Chinese
import en_US from "../locale/en_US" // import defined messages in English复制代码
即配置<IntlProvider>
组件的两个属性locale
和messages
。
// Main.js
render(){
let messages = {}
messages['en'] = en_US;
messages['zh'] = zh_CN;
return (
<IntlProvider locale={this.state.lang} messages={messages[this.state.lang]}>
//··· ···
</IntlProvider>
)
}复制代码
这样基本配置就完成了,能够经过改变 this.state.lang
的值来改变页面语言。
// Main.js
/**
* Change language
* @param {String} lang new language
*/
changeLanguage(lang) {
this.setState({
lang: lang
})
}复制代码
基本只须要使用到一个组件:<FormattedMessage>
。这个组件默认生成一个<span>
,内容是翻译后的文本,也就是 messages
中对应字段的值。
在须要添加国际化文本的组件中,引入FormattedMessage
组件。
import { FormattedMessage } from 'react-intl'; /* react-intl imports */
//... ...
<FormattedMessage id="hello" />复制代码
当前语言为en
时,生成结果:
<span>Hello!</span>复制代码
到这里,react-intl基本的国际化就实现了。
背景:
由阿里巴巴推出的react国际化库
这个库最好地方在于使用简单方便,侵入性低
安装
使用npm安装
npm install react-intl-universal --save复制代码
在初始页面,进行该库的初始化,配置语言包,json文件根据须要支持几种语言来决定,下面的图片中仅支持中英文
于项目入口文件中配置国际化
import intl from 'react-intl-universal';
// locale data
const locales = {
"en-US": require('./locales/en-US.json'),
"zh-CN": require('./locales/zh-CN.json'),
};
class App extends Component {
state = {initDone: false}
componentDidMount() {
this.loadLocales();
}
loadLocales() {
// react-intl-universal 是单例模式, 只应该实例化一次
intl.init({
currentLocale: 'en-US', // TODO: determine locale here
locales,
})
.then(() => {
this.setState({initDone: true});
});
}
render() {
return (
this.state.initDone &&
<div>
{intl.get('SIMPLE')}
</div>
);
}
}复制代码
语言配置文件能够是json或者js,json格式以下:
英语配置文件 ./locales/en-US.json
{
"SIMPLE": "Simple Sentence",
"LANG_TYPE": "paas-us",
"INPUT_MOBILE": "Mobile Number",
"HELLO": "Hello, {name}. Welcome to {where}!"
}复制代码
中文配置文件 ./locales/zh-CN.json
{
"SIMPLE": "简单的句子",
"LANG_TYPE": "paas-cn",
"INPUT_MOBILE": "手机号",
"HELLO": "你好, {name}。欢迎来到{where}!"
}复制代码
在刚才的初始化代码中,render函数里面已经进行了调用了。在整个项目的其余地方,因为已经进行了初始化了,因此能够直接调用了。调用的例子以下:
import intl from 'react-intl-universal';
class Test extends Component {
render() {
return (
<div>
{intl.get('INPUT_MOBILE')}
</div>
);
}
}复制代码
再来看一下初始化函数
intl.init({
currentLocale: 'en-US', // TODO: determine locale here
locales,
})复制代码
初始化的时候,除了直接指定语言外,还能够由函数determineLocale根据如下配置进行指定:
这些配置的生效以下面代码所示:
let currentLocale = intl.determineLocale({
urlLocaleKey: "lang",
cookieLocaleKey: "lang"
});
intl.init({
currentLocale, // determine locale here
locales,
})复制代码
那么,咱们能够利用以下方式进行切换:当选择相应语言时,触发回调函数,在函数内,修改url或者cookie,而后进行页面刷新,从新初始化,便可以切换语言了。
下面我给出一个根据cookie切换的例子:
handleClick = (lang) => {
Cookies.set('lang', lang, { expires: '1Y' });
window.location.reload(true);
}复制代码
react-intl-universal库在语言处理上,还有不少其余功能,如:
- 带HTML标签的HTML 文本
- 变量
- 单复数形式
- 货币
- 日期
a.纯文字,使用intl.get()
<div> {intl.get('SIMPLE')} </div>复制代码
b.带html模板的文字,使用intl.getHTML()方法
例如资源包里是这样定义的
{
"SIMPLE": "This is <span style='color:red'>HTML</span>"
}复制代码
引用时需使用getHTML()方法获取文字
<div>{intl.getHTML('SIMPLE')}</div>
复制代码
下例中的变量为num,给它标记为plural后,它的值只能为数字。当num值为0时,显示"no photos.";当值为1时,显示"one photo.";当值为其余数字好比25000时,显示“25,000 photos.”,这里的'#'表示给num的值添加千分位分隔符后显示
{
"PHOTO": "You have {num, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}"
}复制代码
引用结果以下:
intl.get('PHOTO', {num:0}); // "You have no photos."
intl.get('PHOTO', {num:1}); // "You have one photo."
intl.get('PHOTO', {num:1000000}); // "You have 1,000,000 photos."复制代码
具体语法为{变量名, 类型, 格式化},下例中变量名为"price",它的类型是number,"USD"表示在值前面加上美圆符号($)
{
"SALE_PRICE": "The price is {price, number, USD}"
}复制代码
引用及显示结果以下:
intl.get('SALE_PRICE', {price:123456.78}); // The price is $123,456.78复制代码
语法同上:{变量名, 类型, 格式化},当类型为"date"时,格式化有如下几个选项:short,medium,long,full,也可不格式化
{
"SALE_START": "Sale begins {start, date}",
"SALE_END": "Sale ends {end, date, long}"
}复制代码
引用及显示:
intl.get('SALE_START', {start:new Date()}); // Sale begins 4/19/2017
intl.get('SALE_END', {end:new Date()}); // Sale ends April 19, 2017复制代码
当遇到好比因拼写错误致使没法匹配到资源包里的文字时,能够事先配置默认的message,这时当没法匹配的资源包时会显示默认message
//"defaultMessage()"可简写为"d()"
intl.get('not-exist-key').defaultMessage('没有找到这句话');复制代码
同理亦可配置带html模板的默认message
intl.getHTML('not-exist-key').d(<h2>没有找到这句话</h2>)复制代码
资源包里的配置以下
{
"HELLO": "Hello, {name}. Welcome to {where}!"
}复制代码
在html中引用时
<div> intl.get('HELLO', {name:'banana', where:'China'}) </div>复制代码
显示的结果为:Hello, banana. Welcome to China!
到此react-intl-universal
基本的使用方法介绍完毕了,若是以上达不到你的需求请前往git翻看更多readme文档和api文档。
git地址:github.com/alibaba/rea…
组件 LocaleProvider 用于全局配置国际化文案
为组件内建文案提供统一的国际化支持
使用
LocaleProvider 使用 React 的 context 特性,只需在应用外围包裹一次便可全局生效。
import { LocaleProvider } from 'antd';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';
moment.locale('zh-cn');
...
return <LocaleProvider locale={zh_CN}><App /></LocaleProvider>;复制代码
提供了英语,中文,俄语,法语,德语等多种语言支持,全部语言包能够在 这里 找到。
注意:若是你须要使用 UMD 版的 dist 文件,应该引入 antd/dist/antd-with-locales.js
,同时引入 moment 对应的 locale,而后按如下方式使用:
const { LocaleProvider, locales } = window.antd;
...
return <LocaleProvider locale={locales.en_US}><App /></LocaleProvider>;复制代码
到此今天的国际化分享大全就结束了,我我的感受仍是react-intl-universal
比较好用,若是对你有帮助记得点点关注哦,
案例已上传到github,有相关需求的能够去看看,第一次写勿喷,若是有问题请指正!