最近在react项目中需要解决语言国际化的问题,查看了很多资料最后选中react-intl这个库来进行处理,下面主要简述一下react-intl的使用方法以及一些注意事项
react-intl主要有两种使用方法
官方文档推荐使用组件这种方法
下面为具体使用
(1). 安装react-intl
npm install react-intl --save
(2). 在react根组件中进行配置
/*多语言支持*/
import {IntlProvider, addLocaleData} from 'react-intl';
import rootStore from './mobx/rootStore';
import zhCN from './langConfig/zh-CN.js'; //导入 i18n 配置文件,需要手动创建并填入语言转换信息
import enUS from './langConfig/en-US.js';
import en from 'react-intl/locale-data/en';
import zh from 'react-intl/locale-data/zh';
addLocaleData([...en, ...zh]);
const langMap = {
'zh': zhCN,
'en': enUS
};
//根组件的render函数中,判断当前是哪一种语言环境(全局状态管理使用mobx,根组件注入唯一的rootStore)
render() {
let locale = rootStore.uiStore.langConfig.locale;
return (
<IntlProvider locale={locale} messages={langMap[locale]}> //所有组件都可以共享到当前语言环境的配置信息
<Provider rootStore={rootStore}>
<BrowserRouter>
<App>
<Routes></Routes>
</App>
</BrowserRouter>
</Provider>
</IntlProvider>
)
}
zh-CN.js的主要内容如下
/*全局配置提示消息内容*/
const snackbars = {
'intl.NETWORK_ERROR': "网络错误,请重新尝试", //键值在组件进行国际化时对应的就是id,具体见组件如何使用
'intl.SUCCESS': '操作成功',
'intl.PHONE_EXITS': '手机号码已存在',
'intl.CODE_ERROR': '验证码错误',
'intl.LOGIN_SUCCESS': '登录成功',
'intl.NAME': '你好, 我的名字是{name}'
};
const zh_CN = {
...snackbars
};
export default zh_CN;
(3). 在其他组件中通过使用组件的方式进行国际化
import {FormattedMessage, FormattedDate, FormattedNumber} from 'react-intl';
//render中
//无需传参的使用方式
<button>
<FormattedMessage
id="intl.NETWORK_ERROR" //这个id对应的就是zh-CN.js中的配置的键值, 该组件的值就是键值对应的value
/>
</button>
//需要传参的使用方式
<button>
<FormattedMessage
id="intl.NAME" //这个id对应的就是zh-CN.js中的配置的键值, 该组件的值就是键值对应的value, 同时会用下面values提供的name对应的值替换掉zh-CN.js中对应的站位name
values={{name: '变量'}}
/>
</button>
(4). 通过使用react-intl的api进行国际化
import {injectIntl} from 'react-intl';
class Snackbars extends Component {
handleClose = (event, reason) => {
if (reason === 'clickaway') {
return;
}
this.props.rootStore.uiStore.handleSnackbars({
open: false,
message: ''
});
};
render() {
const { classes } = this.props;
let snackbars = this.props.rootStore.uiStore.snackbars;
let message = '';
if (snackbars.message) {
// 下面这句是重点, id对应的就是zh-CN的键值
//如果需要传值的话使用this.props.intl.formatMessage({id: `intl.${snackbars.message}`}, {name: '变量'})这种方式
let intlMessage = this.props.intl.formatMessage({id: `intl.${snackbars.message}`});
message = intlMessage? intlMessage : snackbars.message;
}
return (
<Snackbar
anchorOrigin={{
vertical: 'top',
horizontal: 'center',
}}
open={snackbars.open}
autoHideDuration={3000}
onClose={this.handleClose}
SnackbarContentProps={{
'aria-describedby': 'message-id',
}}
message={<span id="message-id">{message}</span>}
action={[
<IconButton
key="close"
aria-label="Close"
color="inherit"
className={classes.close}
onClick={this.handleClose}
>
<CloseIcon />
</IconButton>,
]}
/>
)
}
}
//injectIntl包裹组件执行后会返回一个高阶组件,这时会将intl以props的形式传递给Snackbar组件
//如果外部要获取对内部Snackbar组件的引用需要添加后面的配置即{withRef: true},这时高阶组件下会有一个属性wrappedComponent指向内部组件,从而可以调用内部组件的相关方法,如果这里不太熟悉的话,建议查看关于高阶组件的相关资料
export default injectIntl(Snackbars, {withRef: true});
(5). 目前在react中做国际化使用react-intl较多,他提供两种使用方式可以简化开发工作,当然最后还是推荐使用组件的形式