I18n与React和i18next

来自菜鸟教程
(重定向自I18n与React和i18next
跳转至:导航、​搜索

越来越多的应用程序正在为全球市场设计,这意味着您的应用程序需要为使用各种语言和方言的受众工作。 React 没有内置国际化 (i18n),但国际化应用程序并不难,尤其是在 i18next 的帮助下。

i18next 是一个用 JavaScript 编写的 i18n 框架。 它提供了标准的 i18n 插值、格式化和处理复数和上下文功能。

一个 30,000 英尺的 i18next 视图将是它提供了一个函数,该函数接受一个键、一些选项并返回当前语言的值。

以下是使用上述功能的简单示例,只需一个简单的按键,没有任何选项。

i18n.t('error') // 'An error occurred' in English and
                // 'Ocurrió un error' in Spanish.

因为该函数可能会在应用程序中被多次调用,所以 i18next 的创建者选择了一个短名称:t – 是翻译的缩写。 在 i18next 文档中经常会看到 t 函数,您将在本文中看到它的使用。

尽管 i18next 旨在与许多框架一起使用,但本文将重点介绍如何使用 i18next 国际化 React 应用程序。

为了在 React 中使用 i18next,需要将 t 函数提供给需要国际化的组件。 这可以通过各种方式来完成。 我们将在下面演示几个。

手动集成

在使用 i18next 之前,需要对其进行配置。 这是本文中的示例使用的配置。 它关闭了值转义,因为 React 已经为我们处理了这个问题,它将当前语言设置为英语,并将两种语言(英语和西班牙语)的翻译硬编码。 有关更多选项,请参阅 i18next 配置

模块:i18n.js

import i18next from 'i18next';

i18next
  .init({
    interpolation: {
      // React already does escaping
      escapeValue: false,
    },
    lng: 'en', // 'en' | 'es'
    // Using simple hardcoded resources for simple example
    resources: {
      en: {
        translation: {
          age: { label: 'Age', },
          home: { label: 'Home', },
          name: { label: 'Name', },
        },
      },
      es: {
        translation: {
          age: { label: 'Años', },
          home: { label: 'Casa', },
          name: { label: 'Nombre', },
        },
      },
    },
  })

export default i18next

手动集成从导入我们预配置的 i18next 实例开始,该实例将提供 t 功能。

import React from 'react';

// Import a pre-configured instance of i18next
import i18n from './i18n';

function Gator({ gator }) {
  return (
    <div className="Gator">
      <label>i18n.t('name.label')</label>
      <span>{ gator.name } 🐊</span>
      <label>i18n.t('age.label')</label>
      <span>{ gator.age }</span>
      <label>i18n.t('home.label')</label>
      <span>{ gator.home }</span>
    </div>
  )
}

尽管上面的示例将使用当前语言(英语)呈现标签,但在语言更改后标签不会更新,因为 React 尚不知道如何确定语言何时更改。 因此,让我们调整代码以在语言更改时重新渲染组件。

import React from 'react';

// Import a pre-configured instance of i18next
import i18n from './i18n';

class Gator extends React.Component {

  constructor(props) {
    super(props)
    this.state = {
      lng: 'en'
    }
    this.onLanguageChanged = this.onLanguageChanged.bind(this)
  }

  componentDidMount() {
    i18n.on('languageChanged', this.onLanguageChanged)
  }

  componentWillUnmount() {
    i18n.off('languageChanged', this.onLanguageChanged)
  }

  onLanguageChanged(lng) {
    this.setState({
      lng: lng
    })
  }

  render() {
    let gator = this.props.gator,
        lng = this.state.lng

    return (
      <div>
        <label>{ i18n.t('name.label', { lng }) }</label>
        <span>{ gator.name } 🐊</span>
        <label>{ i18n.t('age.label', { lng }) }</label>
        <span>{ gator.age }</span>
        <label>{ i18n.t('home.label', { lng }) }</label>
        <span>{ gator.home }</span>
      </div>
    )
  }
}

请参阅上述代码的 工作示例

虽然我们修复了语言更改后组件不重新渲染的问题,但我们引入了很多样板代码:

  1. 添加了两个生命周期方法(componentDidMountcomponentWillUnmount)。 (这意味着我们必须从功能组件切换到类组件。)
  2. 添加了一个事件监听器,因此我们可以通知 React 语言已更改。
  3. 引入了一种机制来导致组件重新渲染。 在上面的示例中,正在使用状态。 另一种选择是在语言更改后调用 forceUpdate

有没有更简单的方法? 就在这里!

react-i18next 绑定

幸运的是,有一种更简单的绑定方法:react-i18next

import React from 'react';
import { I18n } from 'react-i18next';

// Import a pre-configured instance of i18next
import i18n_unused from './i18n';

function Gator({ gator }) {
  return (
    <I18n>
      {
        (t) => {
          return (
            <div>
              <label>{ t('name.label') }</label>
              <span>{ gator.name } 🐊</span>
              <label>{ t('age.label') }</label>
              <span>{ gator.age }</span>
              <label>{ t('home.label') }</label>
              <span>{ gator.home }</span>
            </div>
          )
        }
      }
    </I18n>
  )
}

i18next 的 React 绑定提供了 I18n 组件。 它期望单个函数表达式作为其子项。 此函数将传递给 t 函数。 (将函数表达式用作组件的子项称为 函数作为子项模式 。)

轻松很多! 请参阅上述代码的 工作示例

因此,请查看 i18nextreact-i18next 以获取有关配置、更高级翻译和其他绑定选项的更多详细信息。