前言

之前写过一篇关于React的国际化文章,主要是用react-intl库,雅虎开源的。react-intl是用高阶组件包装一层来做国际化。
基于组件化会有一些问题,比如在一些工具方法中需要国际化,就需要自己去实现了。在umi-react快速开发框架我们采用
react-intl-universal库来实现,不仅支持组件化调用,也支持动态调用,实现国际化。

react-intl-universal 用法

  1. 安装
```
  npm install react-intl-universal --save
```
  1. 初始化
    在以下示例中,我们intl使用app locale data(locales)初始化并确定动态使用哪个区域设置(currentLocale).
    然后intl.get(…)用来获取国际化的消息

      import intl from \'react-intl-universal\';
      const locales = {
        "en-US": require(\'./locales/en-US.js\'),
        "zh-CN": require(\'./locales/zh-CN.js\'),
      };
    
      class App extends Component {
    
        state = {initDone: false}
    
        componentDidMount() {
          this.loadLocales();
        }
    
        loadLocales() {
          // init method will load CLDR locale data according to currentLocale
          // react-intl-universal is singleton, so you should init it only once in your app
          intl.init({
            currentLocale: \'en-US\', // TODO: determine locale here
            locales,
          })
          .then(() => {
            // After loading CLDR locale data, start to render
          this.setState({initDone: true});
          });
        }
    
        render() {
          return (
            this.state.initDone &&
            <div>
              {intl.get(\'SIMPLE\')}
            </div>
          );
        }
    
      }
    
  2. 调用

    • HTML Message (HTML 消息)

      locale data:

      { "TIP": "This is <span style=\'color:red\'>HTML</span>" }
      

      js code:

      intl.getHTML(\'TIP\');
      
    • Default Message (设置默认消息)
      js code:

      intl.get(\'not-exist-key\').defaultMessage(\'default message\') 
      

      也可以用简写设置默认值

      intl.get(\'not-exist-key\').d(\'default message\')
      

      getHTML 也支持默认值

      intl.getHTML(\'not-exist-key\').d(<div>hello</div>)
      
    • Message With Variables (消息添加变量)

      locale data:

      { "HELLO": "Hello, {name}. Welcome to {where}!" }
      

      js code:

      intl.get(\'HELLO\', {name:\'Tony\', where:\'Alibaba\'})
      

在umi-react项目中加入国际化

  1. 在根目录新建locales文件夹, 添加locale描述文件
    en_US.js 文件

      export default {
        user: {
          login: {
            loginBtn: \'login\',
            placeholderName: \'Please input user name\',
            placeholderPws: \'Please input password\',
            forgetPwd: \'Forget password\',
            remember: \'Remember me\',
          },
          logout: \'logout\'
        }
      }
    

zh_CN.JS 文件

  ```
    export default {
      user: {
        login: {
          loginBtn: \'登录\',
          placeholderName: \'请输入用户名\',
          placeholderPws: \'请输入密码\',
          forgetPwd: \'忘记密码\',
          remember: \'记住我\',
        },
        logout: \'退出登录\'
      }
    }
  ```
  1. 在global modle中添加初始化state和Effect(changeLocale)和reducers(setLocale)

      import intl from \'react-intl-universal\';
      import locales from \'../locales\';
      import storage from \'utils/localStorage\';
    
      const defaultState = {
        currLocale: storage.get(\'locale\') || \'zh_CN\',
        localeLoad: false,
      }
    
      export default {
        namespace: \'global\',
    
        state: defaultState,
    
        effects: {
          *changeLocale({ payload }, { call, put }) {
            const params = {
              currentLocale: payload,
              locales
            };
            // 初始化国际化
            yield intl.init(params);
    
            yield put({
              type: \'setLocale\',
              payload: {
                currLocale: payload,
                localeLoad: true,
              }
            });
            // 把当前国际化持久化到 localstorage 中
            storage.add(\'locale\', payload);
          },
        },
    
        reducers: {
          setLocale(state, { payload }) {
            return {
              ...state,
              ...payload,
            };
          },
        },
      };
    
    
  2. 在layouts index.js 中掉用changeLocale初始化国际化和antd组件国际化

    import React, { Component } from \'react\'
    import BaseLayout from \'./baseLayout\';
    import { LocaleProvider } from \'antd\';
    import { connect } from \'dva\';
    import zh_CN from \'antd/lib/locale-provider/zh_CN\';
    import en_US from \'antd/lib/locale-provider/en_US\';
    import { init } from \'./init\';
    
    @connect(({global}) => {
      return {
        currLocale: global.currLocale,
        localeLoad: global.localeLoad,
      }
    })
    class Index extends Component {
      constructor() {
        super();
        init();
        this.state = {
          initDone: false,
        }
      }
    
      componentDidMount() {
        const {dispatch, currLocale} = this.props;
        // 更改国际化
        dispatch({
          type: \'global/changeLocale\',
          payload: currLocale,
        });
      }
      /**
      * 初始intl国际化和antd组件国际化
      */
      renderBody = () => {
        const {location: {pathname}, children, currLocale, localeLoad } = this.props;
        if (pathname === \'/login\') {
          return localeLoad && <React.Fragment>
            {children}
          </React.Fragment>;
        }
        return (
          localeLoad && (<LocaleProvider locale={ currLocale === \'zh_CN\' ? zh_CN : en_US }>
            <BaseLayout {...this.props} />
          </LocaleProvider>)
        );
      }
    
      render() {
        return (
          <React.Fragment>
            {this.renderBody()}
          </React.Fragment>
        )
      }
    }
    
    export default Index;
    
  3. 在 src/baseLayout/header.js 添加更改国际化的 select

    import React, { Component } from \'react\';
    import { Avatar, Dropdown, Menu, Icon, Select } from \'antd\';
    import { connect } from \'dva\';
    import intl from \'react-intl-universal\';
    import styles from \'./baseLayout.less\';
    
    const Option = Select.Option;
    
    @connect(({user}) => {
      return {
        user: user.user
      }
    })
    class Header extends Component {
      /**
      * 切换语言
      */
      onLocaleChange = (value) => {
        this.props.dispatch({
          type: \'global/changeLocale\',
          payload: value,
        })
      }
    
      render() {
        const {currLocale, user} = this.props;
        return (
          <div className={styles.header}>
            <div className={styles.headerButton}>
              <Select
                defaultValue={currLocale}
                style={{ width: 100 }}
                onChange={this.onLocaleChange}>
                <Option value=\'zh_CN\'>中文</Option>
                <Option value=\'en_US\'>English</Option>
              </Select>
            </div>
          </div>
        )
      }
    }
    
    export default Header;
    
    
  4. 到此我们的系统国际化就可以用了。我们把登陆页面国际化完善起来。这要调用intl.get方法

    import intl from \'react-intl-universal\';
    @connect(({user}) => ({
      loginErr: user.loginErr,
    }))
    @Form.create()
    class Login extends React.Component {
      render() {
        const { loginErr, form:{ getFieldDecorator } } = this.props;
        const intlLogin = intl.get(\'user.login.loginBtn\');
        const intlUsername = intl.get(\'user.login.placeholderName\');
        const intlPwd = intl.get(\'user.login.placeholderPws\');
        const intlforgetPwd = intl.get(\'user.login.forgetPwd\');
        const intlRemember = intl.get(\'user.login.remember\');
        return (
          <div className={styles.login}>
            { loginErr && <Alert style={{ marginBottom: \'20px\' }} message=\'用户名密码错误\' type=\'error\' showIcon />}
            <Form onSubmit={this.handleSubmit} className=\'login-form\'>
              <FormItem>
                {getFieldDecorator(\'name\', {
                  rules: [
                    FormValid.require(intlUsername),
                  ],
                })(
                  <Input
                    prefix={<Icon type=\'user\' style={{ color: \'rgba(0,0,0,.25)\' }} />}
                    placeholder={intlUsername}
                  />
                )}
              </FormItem>
              <FormItem>
                {getFieldDecorator(\'password\', {
                  rules: [
                    FormValid.require(intlPwd),
                  ],
                })(
                  <Input
                    prefix={<Icon type=\'lock\' style={{ color: \'rgba(0,0,0,.25)\' }} />}
                    type=\'password\'
                    placeholder={intlPwd}
                  />
                )}
              </FormItem>
              <FormItem>
                {getFieldDecorator(\'remember\', {
                  valuePropName: \'checked\',
                  initialValue: true,
                })(
                  <Checkbox>{intlRemember}</Checkbox>
                )}
                <a className=\'login-form-forgot\' href=\'\'>{intlforgetPwd}</a>
                <Button type=\'primary\' htmlType=\'submit\' className=\'login-form-button\'>
                  {intlLogin}
                </Button>
              </FormItem>
            </Form>
          </div>
        );
      }
    }
    export default Login;
    



结束语

国际化已经完成, 代码已放到github上,大家可以自行查看umi-react。如果觉得不错,请 start 一下
我建了一个QQ群,大家加进来,可以一起交流。群号 787846148

版权声明:本文为qiaojie原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/qiaojie/p/9673609.html