前言
本文主要介绍在项目中如何加入多语言的环境和开发规范,主要依赖 react-intl
这个包,外部打包依赖 babel-plugin-react-intl
抽取 id 来实现高效注入和便携开发。
用友云平台战略项目交付团队
第一章 快速开始
1.1 准备多语环境
安装 react-intl
后在项目页面的主入口注入多语对象,如下示例编写通用多语组件,该组件可放在 common
目录中。
import React from 'react';
import ReactDOM from 'react-dom';
import mirror, { connect,withRouter } from 'mirrorx';
import { Locale } from 'tinper-bee';
import { IntlProvider, addLocaleData } from 'react-intl';
const chooseLocale = (locale) => {
let lang;
switch (locale) {
case 'en_US':
//两个默认的语言包
lang = require('./lang/en_US.js').default
break;
default:
lang = require('./lang/zh_CN.js').default
}
return lang;
}
let intlModel = {
name: "intl",
initialState: {
locale: 'zh_CN',
localeData: chooseLocale('zh_CN') || {}
},
reducers: {
setLocale(state, locale) {
return {
...state,
locale,
localeData: chooseLocale(locale)
};
}
}
}
//使用mirror切换语言包,也可采用静态的。
mirror.model(intlModel);
export default connect(state => state.intl)((props) => {
let { children, localeData } = props;
let { tinperLocale, locale, messages } = localeData;
return (
<Locale locale={tinperLocale}>
<IntlProvider
key={locale}
locale={locale}
messages={messages}
defaultLocale={locale}
onError={(error) =>{}}
>
<div>
{children}
</div>
</IntlProvider>
</Locale>
)
});
1.2 注入多语环境
在页面的主入口使用上面编写的组件包裹,如在路由中使用或者在统一门户组件中使用
- 门户组件 ```javascript import React, { Component } from ‘react’; import ReactDOM from ‘react-dom’; import { actions } from ‘mirrorx’; import { FormattedMessage} from ‘react-intl’;
import LocalePortal from ‘components/LocalePortal’;
import ‘./index.less’
class MainLayout extends Component {
constructor(props){
super(props)
this.state = {
value: ‘zh_CN’
}
}
handleChange = value => {
this.setState({value}, () => {
actions.intl.setLocale(value);
});
};
render() {
let { children } = this.props;
return (
</div>
)
}
}
export default MainLayout;
- 使用门户组件包裹业务界面,如下包裹路由
```javascript
import 'core-js'
import React from 'react';
import mirror, {
render,
Router,
Route
} from 'mirrorx';
import MainLayout from 'components/MainLayout';
import Routers from "./routes";
mirror.defaults({
historyMode: "hash"
});
render(
<MainLayout >
<Router>
<Route path={`/`} component={Routers}/>
</Router>
</MainLayout>
,
document.getElementById('app')
);
1.3 在业务组件中使用多语
通过上述过程做好准备工作后,业务开发人员就可以在业务界面中加入多语言的代码,且不用操心维护外部如何操作,如下:
import { FormattedMessage, defineMessages, injectIntl} from 'react-intl';
/**
* 实际使用的时候有两周方式如下
* */
//1.标签使用
<FormattedMessage
id = 'Demo.text'
defaultMessage = '我是文本'
/>
//2.API使用
const locales = defineMessages({
content: {
id: 'Demo.context',
defaultMessage: '我是文本',
}
});
class App extends Component {
render() {
const _this = this;
//调取 intl 对象
let { intl:{formatMessage} } = _this.props;
return (
<div className="form-panel">
{
formatMessage(locales.content)
}
</div>
)
}
}
//注入 intl 对象
export default injectIntl(App);
第二章 项目规约
2.1 项目结构
在自己的模块中增加 lang 目录,这里建议使用 injectIntl API方式使用 intl。之后再每一个组件中通过高阶方法增加 intl 对象。
├── components
├── lang
│ └── index.js #国际化脚本
├── routes
├── app.js
├── container.js
├── index.html
├── model.js
└── service.js
- lang/index.js
import { defineMessages} from 'react-intl';
//不同的组件单独命名
export const orderGridLang = defineMessages({
content: {
id: 'js.context',
defaultMessage: '我是{name}'
},
text: {
id: 'js.lib.test.text',
defaultMessage: '一段字符'
},
});
export const sreachPanelLang = defineMessages({
name: {
id: 'js.item.test.name',
defaultMessage: '我不是{name}'
},
});
- 注入对象
export default injectIntl(App);
- 使用定义的语言对象
import { FormattedMessage, defineMessages, injectIntl} from 'react-intl';
import { sreachPanelLang } from './lang'
class App extends Component {
render() {
const _this = this;
//调取 intl 对象
let { intl:{formatMessage} } = _this.props;
return (
<div className="form-panel">
{
formatMessage(sreachPanelLang.name)
}
</div>
)
}
}
//注入 intl 对象
export default injectIntl(App);
2.2 命名规范
为避免 id 重复我们强约束字符的 id 命名规范。
- 1.模块中
js.[项目名].[模块名].[ID名]
- 2.通用字符命名
通用字符如:确认、取消等,常用字符我们会提炼出来生成通用语言包,他的命名规范是
js.common.[ID名]
第三章 自动化构建抽取ID
文章最开始提到了 babel-plugin-react-intl
,这个插件是用来抽取项目中定义的多语变量 ID 的,在 ucf.config.js 中添加配置到 babel_plugins 配置中即可,需要抽取时执行一次即可,不要在开发态下开启此功能。
babel_plugins: [
[require.resolve("babel-plugin-react-intl"), {
"messagesDir": "./intl/"
}]
],