react-i18next基本使用

4,418 阅读3分钟

配置文件

import Backend from 'i18next-http-backend';
import LanguageDetector from 'i18next-browser-languagedetector';
import i18next from 'i18next';
import { initReactI18next } from 'react-i18next';
import intervalPlural from 'i18next-intervalplural-postprocessor';

const useSuspense = process.env.JEST_WORKER_ID ? false : true;

const i18n = i18next
  .use(Backend)
  .use(LanguageDetector)
  .use(initReactI18next)
  .use(intervalPlural)
  .init(
    {
      // load的namespace
      ns: ['common', 'app'],
      // 默认会去查找的namespace
      // 相同的key值,会优先去app命名空间中查找,若没有,才去common
      defaultNS: 'app',
      // i18next-xhr-backend 配置项
      backend: {
        loadPath: '{{ns}}.{{lng}}.json',
        addPath: 'locales/add/{{ns}}.{{lng}}',
      },
      // i18next-browser-languagedetector 配置项
      detection: {
        order: ['querystring', 'localStorage', 'navigator'],
        caches: ['localStorage'],
        lookupQuerystring: 'language',
        lookupLocalStorage: 'language',
      },
      // 如果用户选择的语言不被支持,那么使用英文来渲染界面
      fallbackLng: ['en-US', 'zh-CN'],

      interpolation: {
        escapeValue: false, // not needed for react!!
        format: function(value, format, lng) {
            if (format === 'uppercase') return value.toUpperCase();
            if(value instanceof Date) return moment(value).format(format);
            return value;
        }
      },
      react: {
        wait: true,
        useSuspense: useSuspense,
      },
      whitelist: ['en-US', 'zh-CN'],
      saveMissing: true,
    },
    (error, t) => {
      if (!error) {
        document.title = t('app.document.title');
      }
    }
  );

i18n.on('languageChanged', (language) => {
  console.log(language);
  document.title = i18n.t('document.title');
});

i18n.on('missingKey', (lngs, namespace, key, res) => {
  console.log(key);
});

export default i18n;

解释

  • intervalPlural插件 用于区间的数量表示; 利用count属性可以表示复数,但若要区分某个区间,那么需要使用该插件 具体使用见官方用例即可

  • Backend插件 由于配置项缺乏resources,所以会触发backend请求,从fetch请求里拿到resources文件
    分析backend配置项,loadPath是fetch请求的url,addPath何时触发不知道

  • LanguageDetector插件 用于语言检测;可设置检测优先级

  • interpolation

  1. 设置escapeValue为false是取消转义,因为react本身有该功能
  2. 设置format格式,展示大写和Date格式
  • languageChanged 语言改变时会触发的事件,可以在这里改变document.title

  • missingKey 当代码中出现资源里没有的key时,会触发该事件;需要注意的是,如果是动态加载页面,只有该页面加载时才会检查

其他

translate使用

import { translate } from 'react-i18next';

// 组件使用
@translate()
class UsageBoard extends Component {
  ...
}

// 函数式使用
const Usage = props => {
  ...
}

export default translate()(Usage);

文字中插入组件

有时,一段文案中有些标红、可点击等功能组件

import { withTranslation, Trans } from 'react-i18next';

<Trans
  i18nKey="page.help.tips"
  components={[<br key="1" />, <br key="2" />]} //注意编码从1开始
/>

国际化json:

"page: {
  "help: {
    tips: 我是第一行,<0 />我是第二行,<1 />我是第三行
  }
}

效果:

我是第一行,

我是第二行,

我是第三行

复数

  • i18n自带复数功能,但要注意,其语言(即)为英文时才生效!中文不生效!;其他语言不知道
    这里的语言一定要是i18n里的language值,如果只是简单把resources文件里的语言写成英文,也不会生效的
  "key": "item",
  "key_plural": "items",
  
  i18next.t('key', {count: 0}); // -> "items"
  i18next.t('key', {count: 1}); // -> "item"
  i18next.t('key', {count: 5}); // -> "items"
  i18next.t('key', {count: 00}); // -> 报错

plural前的分割符默认是_,可通过pluralSeparator配置修改

  • 若想区间复数,那么使用插件intervalPlural,如2-4个item均显示a few items
{
  "key": "{{count}} item",
  "key_plural": "{{count}} items",
  "key_interval": "(1){one item};(2-7){a few items};(7-inf){a lot of items};",
}
i18next.t('key1_interval', {postProcess: 'interval', count: 1}); // -> "one item"
i18next.t('key1_interval', {postProcess: 'interval', count: 4}); // -> "a few items"
i18next.t('key1_interval', {postProcess: 'interval', count: 100}); // -> "a lot of items"

key值插入

  • 若想在翻译中,使用变量,那么使用自带功能即可
{
    "nesting1": "1 $t(nesting2)",
    "nesting2": "2 $t(nesting3)",
    "nesting3": "3",
}

i18next.t('nesting1'); // -> "1 2 3"
  • 此方法可与复数功结合使用
{
  "time": "$t(hours,{\"count\":{{hours}}}) $t(minutes, {\"count\":{{minutes}}})",
  "hours": "{{count}} hour",
  "hours_plural": "{{count}} hours",
  "minutes": "{{count}} minute",
  "minutes_plural": "{{count}} minutes",
}
i18next.t('time', { hours: 3, minutes: 2 }) // -> "3 hours 2 minutes"