入口文件(src/index.js)
import React from "react";
import ReactDOM from "react-dom";
import registerServiceWorker from "./registerServiceWorker";
import {Provider} from "react-redux";
import {createStore, applyMiddleware} from "redux";
import {rootReducer} from "./store";
import Router from "./route";
import "./assets/styles/base.less";
import "./assets/styles/antd-override.less";
import createSagaMiddleware from "redux-saga"; // 引入redux-saga中的createSagaMiddleware函数
import rootSaga from "./sagas"; // 引入saga
import {LocaleProvider} from 'antd';
import zhCN from "antd/lib/locale-provider/zh_CN";
import enUS from "antd/lib/locale-provider/en_US";
import {addLocaleData, IntlProvider} from 'react-intl';
// 引入多语言环境
import en from 'react-intl/locale-data/en';
import zh from 'react-intl/locale-data/zh';
import enMessages from '@/locales/en_US';
import zhMessages from '@/locales/zh_CN';
addLocaleData([...en, ...zh]);
// 从缓存中读取国际化语言值
// const {IMS_INF_LANG = 'en'} = localStorage;
const {IMS_INF_LANG = 'en'} = localStorage;
/*
设置缺省值,避免其他IMS_INF_LANG为其他非法值("en"/"zh"之外的值,如"null"、"undefined")时
locale、antLocale、messages均为undefined,导致页面国际化异常
* */
let locale = "en";
let antLocale = enUS;
let messages = enMessages;
if (IMS_INF_LANG === 'zh') {
locale = 'zh';
antLocale = zhCN;
messages = zhMessages;
} else if (IMS_INF_LANG === 'en') {
locale = 'en';
antLocale = enUS;
messages = enMessages;
}
const sagaMiddleware = createSagaMiddleware(); // 创建saga中间件
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware)); // 创建store
sagaMiddleware.run(rootSaga); // 运行saga中间件
ReactDOM.render(
<IntlProvider locale={locale}
messages={messages}
>
<Provider store={store}>
<LocaleProvider locale={antLocale}>
<Router/>
</LocaleProvider>
</Provider>
</IntlProvider>,
document.getElementById("root")
);
registerServiceWorker();复制代码
一般标准化的前端国际化方案,包括两个方面:
1、业务组件静态文本的国际化
2、UI组件内部的国际化
正常情况下,如果只需实现中英文国际化,前端只需要将英文内容作为key,维护一份中文对照库,但是如果在下述情况下,那么也需要维护一份英文对照库
如下:
中英文目标中包含a标签,此时无法将该文本作为key进行国际化,需要指定一个特殊的key,结合dangerouslySetInnerHTML渲染HTML字符串实现国际化
<span dangerouslySetInnerHTML={{__html: this.renderFormattedString("C_PAM")}}></span>复制代码
英文对照
const en_US = {
"C_PAM": "Please confirm your account information in <a href='/home/paymentInfo'>Payment account management</a>"
};
export default en_US;复制代码
中文对照
const zh_CN = {
"C_PAM": "请前往<a href='/home/paymentInfo'>收款账号管理</a>确认您的账号信息"
};
export default zh_CN;复制代码
在组件文件中进行国际化
首先,在组件头部引入react-intl
import {injectIntl, FormattedMessage} from 'react-intl';复制代码
组件外部包裹injectIntl
export default connect(
mapStateToProps,
mapDispatchToProps
)(withRouter(injectIntl(Comp)));复制代码
然后,利用FormattedMessage或intl.formatMessage方法实现国际化
renderFormattedMessage = (key) => {
return <FormattedMessage
id={key}
defaultMessage={key}
/>
};
renderFormattedString = (key) => {
const {intl} = this.props;
let res = intl.formatMessage({
id: key,
defaultMessage: key
});
return res;
};复制代码
主要通过两种方式实现
第1种、将key映射为span标签,如"English"=><span>English</span>(英文映射)/"English"=><span>英文</span>(英文映射)
第2种、将key映射为纯字符串,如"English"=>"English"/"English"=>"英文"
在组件文件中,通过this.props.intl.locale判断当前语言是中文还是英文
<div className="our-partner">
{
this.props.intl.locale === "en" &&
<span>
{"Participating"}
<br/>
{"Brands"}
</span>
}
{
this.props.intl.locale === "zh" &&
<span>
{
"我们的"
}
<br/>
{
"合作伙伴"
}
</span>
}
</div>复制代码
另外,前端项目多语言需要结合localStorage或cookie实现,因为多语言对于用户来说往往是一种固定偏好,不会在短时间内发生变化,所以需要浏览器通过缓存策略记住这种偏好。
在退出或会话token失效需要清空系统缓存时,切记不要清除用户语言缓存,如下:
componentWillReceiveProps(nextProps) {
if (nextProps.logout_result.success !== this.props.logout_result.success) {
if (nextProps.logout_result.success) {
message.success(nextProps.logout_result.msg);
const lang = localStorage.getItem("IMS_INF_LANG");
localStorage.clear();
localStorage.setItem("IMS_INF_LANG", lang);
this.props.history.push('/login');
}
}
}复制代码