ReactJS前端国际化方案 - 你也许不需要用react-intl

巫马俊力
2023-12-01

[Updated 2017-06-15] 基于这套方案,我们开源了一个库 alibaba/react-intl-universal ,可用于React.Compoent和非React.Compoent的国际化。也支持货币、日期、复数等国际化,API更简单,更容易上手。 yahoo/react-intl据悉开发团队很多人离职了,更新维护的比较慢。

一般在ReactJS的国际化都是采用react-intl。使用react-intl最大的好处是它用props的方式注入语言包,也就是可以在不刷新页面的情况下直接更改显示的语言。

  1. 国际化只能用于View层,也就是你有国际化需求的地方,只能是React.Componet的subclass。如果有一些通用型的utility就不能使用。像是一些表单效验的错误提示如下,这样单纯的js是无法使用react-intl的。

  2. rules = {
    noSpace(value) {
    if (value.includes(' ') || value.includes('t')) {
    return '不允许空白或者tab';
    }
    }
    };
  3. default rules;

  4. react-intl的实现上使用了包装器,也就是你的Componet Class,不再是原本的Class了。比如你想要取组件的instance的时候,需要改成
this.refs.mycomponent.getWrappedInstance()

react-intl有上述2个致命的缺点,但其实我们又不需要在不刷新的情况下更换显示的语言。其实根本不需要使用react-intl。

解法

所以我们改使用另一个库intl-messageformat,它支持变量的取代、复数型态的名词显示。完全遵守ECMA-402 (Internationalization API Specification)标准。这个库无关框架,也是react-intl底层使用的一个库,所以如果你原本是使用react-intl的人,不用担心语言包格式需要改写。

使用方式也很简单。首先定义语言包,例如:

// locale/zh.js
export default ({
   hello: '你好,{name}'
 })
// locale/en.js
export default ({
   hello: 'Hello,{name}'
 })

接著写个简单的业务包装,例如根据自己的业务决定语言的方法。或者想要在遗漏语言key的时候,显示的默认值:

import IntlMessageFormat from 'intl-messageformat';
import zh from '../locale/zh';
import en from '../locale/en';
const MESSAGES = { en, zh };
const LOCALE = 'en'; // -> 这里写上你的决定语言的方法,例如可以从cookie判断语言

class Intl {

  get(key, defaultMessage, options) {
    let msg = MESSAGES[LOCALE][key];
    if (msg == null) {
      if (defaultMessage != null) {
        return defaultMessage;
      }
      return key;
    }
    if (options) {
      msg = new IntlMessageFormat(msg, LOCALE);
      return msg.format(options);
    }
    return msg;

  }
}

export default Intl;

使用的时候,可以在任何js的地方,不局限于View层:

let name = 'Tony';
intl.get('hello', 'Hello', {name})

总结

自己简单包装一下intl-messageformat的好处有:

  • 通用型工具:可以适用于任何框架
  • 无侵入性:你的组件行为不会因而改变。貨幣、日期、複數等國際化
 类似资料: