前言
本文主要介绍在项目中如何加入多语言的环境和开发规范,主要依赖 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').defaultbreak;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}><IntlProviderkey={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;
- 使用门户组件包裹业务界面,如下包裹路由```javascriptimport '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.标签使用<FormattedMessageid = '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/"}]],
