用i18next进行React本地化的教程

2,577 阅读20分钟

对于想要提高用户满意度并通过提高转换率达到商业目标的开发者来说,构建一个符合当地市场需要的应用程序是最重要的。

对于React应用程序,有许多国际化的选项可用于瞄准这类受众。在本指南中,我们将审查其中一个最受欢迎的解决方案:i18next。

这个框架通过本地化过程(也被称为l10n)使应用程序无缝地适应特定的本地市场和文化。

本地化不仅仅是将文字从一种语言翻译成另一种语言。除了翻译之外,它还帮助我们考虑文化差异,如货币、单位位置、数字和日期格式、复数,甚至是当地的外观。

这就是一个本地化的应用程序的样子。

Final Localized Application Using i18next

在本教程中,我们一起构建这个应用程序。你可以在这里与最终的项目进行互动

为什么使用i18next框架?

i18next框架由于支持插件,所以很灵活,让我们可以添加一些功能,否则我们就必须自己构建。

我们还可以选择将翻译分成不同的文件,并在需要时加载它们。这意味着我们不需要在加载页面之前加载所有的翻译文件,减少了缓慢的加载时间。

前提条件

  • 对React有一个基本的了解
  • 在你的电脑上安装Node.js

下载启动项目

有了这个简单的React项目,让我们在电脑终端运行以下命令。

git clone https://github.com/Ibaslogic/react_i18next_starter

一旦完成,用代码编辑器打开project 文件夹。在project 目录内,运行npm install ,生成一个node_modules 文件夹。

然后,通过运行npm start ,启动开发服务器,并等待看到应用程序在浏览器中加载,http://localhost:3000/

Reacti18next Home Screen Rendered In English

project 的结构应该是这样的:

project_folder
    ├── node_modules
    ├── public
    ├── src
    │    ├── components
    │    │      ├── App.js
    │    │      ├── Content.js
    │    │      ├── Footer.js
    │    │      └── Header.js
    │    ├── index.css
    │    └── index.js
    ├── .gitignore
    ├── package-lock.json
    ├── package.json
    ├── README.md
    └── yarn.lock

我们现在的重点是在src 文件夹上。在那里,我们有所有的React组件,包含我们可以本地化的内容。

安装i18nextreact-i18next

要使用i18next对React应用程序进行本地化,我们必须将i18nextreact-i18next 包添加到我们的项目中。

i18next 提供了所有的翻译功能,而react-i18next 增加了一些额外的 React 功能,如 Hooks, HOCs, render props, 等等。

通过运行以下命令来安装它们。

npm install react-i18next i18next

设置配置文件

src 文件夹中创建一个名为i18n.js 的文件,并添加这个翻译配置。

import i18n from "i18next";
import { initReactI18next } from "react-i18next";

i18n
  .use(initReactI18next)
  .init({
    resources: {
      en: {
        translation: {
          //English translations here
        },
      },
      ja: {
        translation: {
          //Japanese translations here
        },
      },
    },
    lng: "en",
    fallbackLng: "en",
  });

export default i18n;

通过从i18next 核心中导入i18n 实例,我们可以通过模块提供的initReactI18next 对象将react-i18next 模块绑定到它。这确保了i18next框架将i18n 实例传递给react-i18next 模块。

调用use() 函数加载并绑定任何插件到i18n 实例。

然后我们通过调用init() 函数来初始化我们的配置,并定义基本的配置选项

我们还添加了resources,lng, 和fallbackLng 对象属性。在resources ,我们为两种语言提供了translation 对象,即英语和日语。

enja 是 ISO 标准代码,分别代表英语和日语。在这里可以看到所有ISO标准语言缩写。

接下来,导入src/index.js 中的配置文件,像这样:

import "./i18n";

不要忘记保存这些文件!

翻译一个简单的文本信息

首先,让我们翻译我们的启动项目中的一个简单的标题信息,"欢迎来到react-i18next教程"。

更新src/i18n.js 文件,包括英语和日语的翻译。

// ...
resources: {
  en: {
    translation: {
      //English translations here
      "welcome text": "Welcome to the react-i18next tutorial",
    },
  },
  ja: {
    translation: {
      //Japanese translations here
      "welcome text": "react-i18nextチュートリアルへようこそ",
    },
  },
},
// ...

保存该文件。

正如在translation 对象中所看到的,我们以JSON格式定义了我们的消息,给它一个跨支持的地区的唯一的键。

在这个项目中,我们使用谷歌翻译将其翻译成目标语言。

通过 实例访问翻译后的消息t()

i18next ,通过i18n 实例提供一个翻译函数,称为t() 。它接受一个查找翻译对象的键,并返回与当前语言的键匹配的字符串。

根据React组件的类型,我们可以通过不同的方式访问t() ,例如使用:

在本指南中,我们将使用useTranslation Hook。

使用useTranslation 钩子

打开components/Content.js 文件,导入useTranslation Hook,像这样:

import { useTranslation } from 'react-i18next';

然后,在return 语句的上方,添加这一行:

const { t, i18n } = useTranslation();

从Hook中,我们可以访问t 函数和i18n 实例。我们只需要t 函数来翻译我们的内容。在本指南的后面,我们将使用i18n 实例来改变应用程序的语言。现在,我们可以删除i18n

接下来,用包含翻译键的t 函数替换h1 文本,这样我们就有了以下内容。

import { useTranslation } from "react-i18next";

const Content = () => {
  const { t } = useTranslation();

  return (
    <div className="container hero">
      <h1>{t("welcome text")}</h1>
      {/* ... */}
    </div>
  );
};

export default Content;

保存该文件并重新加载前端。

没有任何变化。但是,让我们暂时将src/i18n.js 文件中的lng 属性改为日文(ja),并保存文件。

i18n
  .use(initReactI18next)
  .init({
    resources: {
      // ...
    },
    lng: "ja",
    fallbackLng: "en",
  });

现在,一旦我们重新加载页面,我们就会看到日文文本的呈现。

Rendered App Text In Japanese With Page Reload

懒惰地从服务器上加载翻译文件

目前,我们在配置文件中加载了所有的翻译。这并不理想,尤其是当我们在一个更大的项目中添加更多语言和内容时。

i18next 提供了一个更好的方法来优化我们的代码,将翻译从代码中分离出来,并在需要时加载它们。为了做到这一点,我们将安装一个插件。

安装i18next-http-backend

i18next-http-backend 包从后端服务器加载翻译文件。

npm install i18next-http-backend

接下来,更新i18n.js 配置文件以包括该插件。

import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from "i18next-http-backend";

i18n
  .use(Backend)
  .use(initReactI18next)
  .init({
    ...
  });

export default i18n;

默认情况下,这个插件希望从public/locales/{lng}/translation.json 目录中加载我们的翻译文件,其中lng 是语言代码。

虽然我们也可以把配置文件中的目录改为自定义目录,但我们将坚持使用默认目录。

让我们为我们支持的每一种语言创建translation.json 文件。在这个例子中,我们将支持英语、阿拉伯语、法语和日语。

文件的结构应该是这样的:

public
  ├── locales
  │     ├── ar
  │     │   └── translation.json 
  │     ├── en
  │     │   └── translation.json
  │     ├── fr
  │     │   └── translation.json
  │     ├── ja
  │     │   └── translation.json

en/translation.json 文件中,添加以下内容。

{
  "welcome text": "Welcome to the react-i18next tutorial"
}

ar/translation.json 文件中,添加以下内容。

{
  "welcome text": "مرحبًا بك في البرنامج التعليمي react-i18next"
}

对于其他支持的地区,使用谷歌翻译。稍后,我们将更新我们的翻译文件以适应其他文本。

记住要保存所有的文件。

我们现在可以删除src/i18n.js 文件中的resources 属性,因为我们现在可以从后台加载翻译。

现在的配置文件看起来像这样。

// ...
i18n
  .use(Backend)
  .use(initReactI18next)
  .init({
    lng: "en",
    fallbackLng: "en",
  });
// ...

如果我们保存文件并重新加载前台,我们会遇到应用中断。i18next框架希望我们在等待翻译文本从后端加载时处理应用程序的状态。

为了做到这一点,我们将把顶层组件包裹在React的Suspense 组件内。这允许我们在等待阶段显示一些回退--例如,一个加载指示器。

打开src/index.js 文件,使用Suspense 组件,像这样。

ReactDOM.render(
  <React.StrictMode>
    <Suspense fallback={<div>Loading...</div>}>
      <App />
    </Suspense>
  </React.StrictMode>,
  document.getElementById("root")
);

接下来,在文件的顶部导入Suspense 组件。

import React, { Suspense } from "react";

fallback 道具接受一个文本字符串或任何我们想呈现的React元素。保存文件,应用程序应该可以工作。

如果我们把配置文件中的lng 属性改为ar 或任何支持的语言,我们将在前端看到翻译。

Change lng Property To Update Translation In The Frontend

现在我们已经涵盖了基本原理,让我们快速翻译其他页面内容。

插值、格式化和复数化

到现在为止,我们已经涵盖了如何翻译一个简单的文本字符串。如前所述,本地化超越了语言之间的翻译。必须考虑文化差异。

往前走,我们将介绍如何格式化和翻译一个富含文本的信息。如果我们看一下我们的应用程序,我们会看到我们有数字、日期和货币的位置,以便为不同的地区设置格式。

我们还有一个随着用户点击按钮而增加的数字计数,并且必须格式化文本以尊重复数。

内插法

当文本中有一个必须被格式化的数字或日期时,我们使用内插法。这是允许在我们的翻译中插入数值的功能之一。

使用前端的文本,"在选定的语言中格式化3000",我们将把 "3000 "插值到文本中。

en/translation.json 文件中,将此添加到JSON中。

{
  ...
  "formatNumber": "Formatting {{num}} in the selected language"
}

注意我们是如何用一个占位符来替换数字的。

在阿拉伯语文件中,添加这个

{
  ...
  "formatNumber": "تنسيق {{num}} في اللغة المختارة"
}

确保为其他支持的地区添加翻译,并保存所有文件。

接下来,我们将使用翻译功能,t() ,根据当前的语言来翻译和格式化我们的信息。

components/Content.js ,找到这个元素

<p>Formatting 3,000 in the selected language</p>

用这个替换它。

<p>{t("formatNumber", { num: 3000 })}</p>

在这里,我们把要插值的数字作为t() 函数的第二个参数传递。在对象属性中使用的num ,必须与翻译文件中的占位符相匹配--在我们的例子中是{{num}}

保存文件并测试工作。

如果我们把i18n.js 文件中的lng 属性改为ar ,我们就会得到这个结果:

Interpolate The Number Translation To Update For The Arabic Format

接下来,我们必须根据当前语言对插值的数字进行格式化。

格式化

i18next默认不支持数字或日期的格式化。但是,它允许我们使用moment.js、Luxon和date-fns等库,或通过Intl API进行格式化。

在这个项目中,我们将使用Intl API为我们进行格式化;它很简单,而且与i18next配合得很好。这个Intl API通过其Intl 对象为我们提供了所需的构造函数。

对于我们的格式化,我们只需要Intl.NumberFormat()Intl.DateTimeFormat() 构造函数。

为了格式化我们之前插值的数字,我们必须在配置中添加另一个翻译选项,称为interpolation ,并定义一个处理格式化的函数。

现在的配置看起来像这样:

i18n
  .use(Backend)
  .use(initReactI18next)
  .init({
    lng: "ar",
    fallbackLng: "en",
    interpolation: {
      format: (value, format, lng) => {
        if (format === "number") {
          return new Intl.NumberFormat(lng).format(value);
        }
      },
    },
  });

重点是format 函数。在那里,我们定义了一个条件,检查我们需要格式化的值是否是一个数字。然后我们必须使用Intl API以当前语言返回格式化的值。

为了确保条件返回为真,我们必须在我们的翻译中更新占位符,{{ }} ,以包括number

对于英语,更新en ,如下所示。

"formatNumber": "Formatting {{num, number}} in the selected language"

对于阿拉伯语,更新ar ,如下所示。

"formatNumber": "تنسيق {{num, number}} في اللغة المختارة"

也为其他支持的地区更新翻译文件,并保存它们。

现在,这个应用程序应该是这样的。

Updated Arabic Number Format From Interpolated Number

使用同样的方法,让我们翻译components/Content.js 文件中的其他文本,并对日期和货币位置进行格式化。

更新en/translation.json ,包括以下内容。

{
  ...
  "formatCurrency": "Displaying {{price, currency}} in the selected locale",
  "formatDate": "Today's date: {{today, date}}"
}

ar/translation.json ,添加:

{
  ...
  "formatCurrency": "عرض {{price, currency}} دولارًا في اللغة المحددة",
  "formatDate": "تاريخ اليوم: {{today, date}}"
}

同样,为其他支持的地区添加翻译。

之后,更新components/Content.js 文件以访问这些翻译。

const Content = () => {
  // ...

  return (
    <div className="container hero">
      <h1>{t("welcome text")}</h1>
      <p>{t("formatCurrency", { price: 69.99 })}</p>
      <p>{t("formatNumber", { num: 3000 })}</p>
      <p>{t("formatDate", { today: new Date() })}</p>
    </div>
  );
};

最后,在i18n.js 文件中,更新format 函数。

format: (value, format, lng) => {
  // ...
  if (format === "date") {
    return new Intl.DateTimeFormat(lng).format(value);
  }
  if (format === "currency") {
    return new Intl.NumberFormat(lng, {
      style: "currency",
      currency: "USD",
    }).format(value);
  }
},

在这个文件中,我们正在使用Intl.DateTimeFormat() 构造函数来格式化日期。注意我们是如何向Intl.NumberFormat() 提供额外的选项来格式化货币的。在这里找到货币代码的列表。

保存所有的文件并重新加载前台。

默认情况下,i18next会转义数值以减少跨站脚本(XSS)攻击,如下图所示。

i18next Escapes Values To Reduce Cross-Site Scripting

但是,React应用程序是受XSS保护的。escapeValue 因此,让我们通过在interpolation ,并指定一个false ,防止i18next转义值。

interpolation: {
  format: (value, format, lng) => {
    // ...
  },
  escapeValue: false // react already safes from xss
},

保存并重新加载前端,它应该可以工作。

复数化

目前在我们的应用程序中,点击前台的计数按钮并不能改变计数语句。例如,当计数是单数时,语句应该是 "你点击了1次"。

所以,让我们开始在各种翻译文件中添加翻译。更新en/translation.json 文件,包括以下内容。

{
  ...
  "clickCount": "You've clicked {{count}} time",
  "clickCount_plural": "You've clicked {{count}} times"
}

在这里,我们要用一个占位符替换消息中的动态计数。这个占位符变量必须被称为count 。我们也在提供我们的翻译的复数等价物。

为了告诉i18next是渲染单数还是复数的消息,我们必须把clickCount ,而不是_plural ,连同动态计数值一起传递给渲染中的t 函数。

如果计数是1 ,就渲染单数信息,否则就渲染复数形式。

我们来更新其他地区的翻译文件。对于ja/translation.json 文件,添加以下内容。

{
  ...
  "clickCount": "{{count}}回クリックしました"
}

注意,我们没有添加复数形式。这是因为日语 (ja) 只有一种复数形式。请看每种语言的适当复数形式

和英语一样,法语也有两种复数形式。然而,有些词在单数和复数中的形式是一样的。

例如,如果我们把信息翻译成法语,我们在fr/translation.json 文件中会有以下内容。

{
  ...
  "clickCount": "Vous avez cliqué {{count}} fois",
  "clickCount_plural": "Vous avez cliqué {{count}} fois"
}

由于两者的形式相同,我们可以忽略第二个,而得到这个。

{
  ...
  "clickCount": "Vous avez cliqué {{count}} fois",
}

对于阿拉伯语来说,除了单数,还有五种复数形式,所以我们必须定义每一种形式,像这样。

clickCount_0; //c = 0 i.e zero
clickCount_1; //c = 1 i.e singular
clickCount_2; //c =2 i.e two
clickCount_3; //3 <= c <=10 i.e few
clickCount_4; //11 <= c <=99 i.e many
clickCount_5; //>= 100 i.e other

我们必须保持相同的关键名称,在我们的例子中,就是保持clickCount ,就像我们在其他翻译文件中使用的那样。

i18next会根据计数自动选择合适的形式。当计数为0,1, 或2 时,i18next会渲染分配给他们各自的键clickCount_0,clickCount_1, 和clickCount_2 的翻译。

然而,当计数在310 之间时,i18next 翻译分配给clickCount_31199 翻译分配给clickCount_4 ,而计数在100 或以上时,翻译分配给clickCount_5

如果我们把 "你已经点击了{{n}}次 "这个字符串翻译成阿拉伯语,其中 "n "是一个从0到无限大的数字,我们可以使用谷歌翻译得到以下结果。

{
  ...
  "clickCount_0": "لقد نقرت {{count}} مرة",
  "clickCount_1": "لقد نقرت مرة واحدة",
  "clickCount_2": "لقد نقرت مرتين",
  "clickCount_3": "لقد نقرت {{count}} مرات",
  "clickCount_4": "لقد نقرت {{count}} مرة",
  "clickCount_5": "لقد نقرت {{count}} مرة"
}

现在,保存这些文件。

打开components/Footer.js 文件,访问t 函数。首先,导入翻译Hook,像这样:

import { useTranslation } from "react-i18next";

return 语句的上方,从Hook中访问t 函数。

const { t } = useTranslation();

现在,我们可以用它来替换文本进行翻译;所以,找到以下元素。

<p>You've clicked {count} times</p>

然后,用这个替换它。

<p>{t("clickCount", { count: count })}</p>

保存文件,重新加载前台,并测试项目。

Trans 组件

要翻译一个用strong,i, 或br 元素格式化的字符串,或包含一个链接,我们必须使用i18next的Trans 组件。

如果我们打开components/Footer.js 文件,我们可以翻译和格式化以下元素。

<p>
  Let's <strong> click the button </strong> below:
</p>

这里的逻辑很简单,我们将把p 元素文本分解成节点,并给它们分配一个索引号,像这样。

  Let's --> index 0
  <strong> click the button </strong> --> index 1
  below: --> index 2

接下来,在Footer.js 文件中导入Trans 组件来包装文本。

// ...

import { useTranslation, Trans } from "react-i18next";

const Footer = () => {
  // ...

  return (
    <div className="container mt">
      {/* Footer content here */}
      <p>
        <Trans i18nKey="clickButtonText">
          Let's <strong> click the button </strong> below:
        </Trans>
      </p>
      {/* ... */}
    </div>
  );
};

// ...

注意我们已经把i18nKey 这个道具添加到Trans 组件中。我们将使用它的值作为翻译文件中的一个键。

我们现在可以使用这个索引号作为占位符来引用翻译文件中的内部元素。

en/translation.json 文件中,我们有以下内容。

{
  ...
  "clickButtonText": "Let's <1>click the button</1> below:"
}

该键来自于Trans i18nKey 道具。

ar/translation.json 文件中,我们有以下内容。

{
  ...
  "clickButtonText": "دعنا <1> انقر فوق الزر </ 1> أدناه: "
}

更新其他支持的翻译文件,保存它们,并重新加载前端,就可以看到变化。

翻译按钮文本

为了翻译按钮文本,让我们用t 函数替换component/Footer.js 文件中的文本。

<button onClick={onChange}>{t("click")}</button>

然后,更新翻译文件以包括键值对。

en/translation.json 文件中,添加。

"click": "Click here"

ar/translation.json 文件中,添加。

"click": "انقر هنا"

使用谷歌翻译来更新其他翻译文件。

翻译菜单项目

对于翻译菜单项,首先将其添加到en/translation.json 文件中。

"menu" : {
  "aboutProject" : "About the project",
  "contactUs": "Contact us" 
}

然后,将此添加到ar/translation.json 文件中。

"menu" : {
  "aboutProject" : "حول المشروع",
  "contactUs": "اتصل بنا" 
}

再次,使用谷歌翻译来更新其他翻译文件,并保存它们。

接下来,打开components/Header.js 文件,在顶部导入useTranslation

import { useTranslation } from "react-i18next";

然后,使用t 的功能来翻译菜单的标题。

import { useTranslation } from "react-i18next";

const Header = () => {
  const { t } = useTranslation();
  const menu = [
    {
      title: t("menu.aboutProject"),
      // ...
    },
    {
      title: t("menu.contactUs"),
      // ...
    },
  ];

  return (
    // ...
  );
};

// ...

如果我们保存该文件并重新加载前端,我们会看到菜单项和所有页面内容都被正确翻译。

Translate Menu Items Into Arabic In Frontend

检测用户的语言

我们必须提供一个选项,让用户在前台切换语言,同时在浏览器的存储中持续保存所选择的地区。这使得内容在以后的访问中能以首选的语言显示。

i18next为此提供了一个插件,让我们用这个命令来安装它。

npm install i18next-browser-languagedetector

安装完毕后,导入并添加该插件到配置文件中。

// ...
import LanguageDetector from "i18next-browser-languagedetector";

i18n
  // ...
  .use(LanguageDetector)
  .init({
    fallbackLng: "en",
    detection: {
      order: ["path", "localStorage", "htmlTag", "cookie"],
      caches: ["localStorage", "cookie"], // cache user language on
    },
    interpolation: {
      // ...
    },
  });

export default i18n;

在设置中,我们删除了lng 属性,因为现在的应用程序依赖于该插件来检测当前的语言。在detection 属性中,我们已经指定了检测用户语言的顺序。

顺序中的第一项具有最高的优先权,并按此顺序递减。这意味着该插件首先检查path ,其次是localStorage ,以此类推。

现在,我们可以从URL路径http://localhost:3000/ar,访问locale内容。

我们必须指定path 作为数组中的第一项,以通过路径访问locale内容。然而,请注意,用户的locale仍然从其他指定的存储中检测出来。

保存文件并重新加载前端;通过向URL路径http://localhost:3000/ar传递一个locale来测试该项目。

创建一个语言切换器

要创建一个语言切换器,首先打开components/Header.js 文件,在return 语句上方添加支持的语言。

// Languages
const languages = [
  { name: "English", code: "en" },
  { name: "日本語", code: "ja" },
  { name: "Français", code: "fr" },
  { name: "العربية", code: "ar" },
];

接下来,在JSX中找到这个元素。

<div className="switcher">
  {/* Language switch dropdown here */}
</div>

更新它,所以我们有以下内容。

<div className="switcher">
  {/* Language switch dropdown here */}
  <span>Languages</span>{" "}
  <select>
    {languages.map(({ name, code }) => (
      <option key={code} value={code}>
        {name}
      </option>
    ))}
  </select>
</div>

保存该文件。这些代码应该是不言自明的,因为它是基本的React

现在切换器应该在前端显示,尽管它还没有工作。我们需要使下拉元素成为受控组件

我们需要做的就是把一个value prop和onChange 传递给select 元素。

<select onChange="" value="">
  {/* ... */}
</select>

value 道具获取当前的locale,而onChange 则触发一个更新locale的函数。

我们可以通过安装一个名为js-cookie 的软件包从存储中获得当前的locale值。这使我们能够从cookie中获得locale字符串。

npm install js-cookie

接下来,在Header.js 文件的顶部导入Cookies 对象。

import Cookies from "js-cookie";

然后,在return 语句上方添加这段代码。

const currentLocale = Cookies.get("i18next") || "en";

这个包使用get() 方法从存储器中读取一个cookie,并接受cookie的名称。

对于i18next框架,cookie的名字是i18next 。我们可以在浏览器devtools的存储cookie中找到这个名字。

接下来,定义一个状态,接受当前的locale,并将其分配给我们的下拉元素的value prop。

还是在Header.js 文件中,在文件的顶部导入useState

import { useState } from "react";

然后,定义一个language 变量,并通过useState Hook 传入当前的locale。

return 语句的上方添加以下内容。

const [language, setLanguage] = useState(currentLocale);

现在,language 有了当前的locale,我们可以把它传给value 道具。

<select onChange={handleChangeLocale} value={language}>
  {/* ... */}
</select>

注意我们还添加了handleChangeLocale 处理程序来触发更新。

让我们快速创建它。在return 语句的上方添加这段代码。

const handleChangeLocale = (e) => {
  const lang = e.target.value;
  setLanguage(lang);
};

这段代码是根据用户的选择来更新语言下拉菜单。我们必须更进一步,更新应用程序的语言。

如前所述,i18n 实例是需要改变语言的。现在,我们可以用它来抓取changeLanguage() API来接受用户选择的语言。

t 函数一样,我们也可以从useTranslation() Hook中访问i18n 实例。

因此,更新Hook以包括i18n

const { t, i18n } = useTranslation();

然后,在handleChangeLocale 处理程序中使用它。

const handleChangeLocale = (e) => {
  const lang = e.target.value;
  setLanguage(lang);
  i18n.changeLanguage(lang);
};

保存并测试该应用程序。

从右到左渲染阿拉伯文内容

如果我们暂时打开浏览器devtools,并在body 元素上添加一个dir="rtl" ,我们会看到内容从右到左显示。在我们的应用程序中,我们需要找到body 元素,并在页面加载时添加dir 属性。

更新languages 数组中的阿拉伯语,在components/Header.js 文件中包括其方向。

const languages = [
  // ...
  { name: "العربية", code: "ar", dir: "rtl" },
];

之后,在return 语句上方添加以下代码。

const currentLangObj = languages.find((lang) => lang.code === currentLocale);

useEffect(() => {
  document.body.dir = currentLangObj.dir || 'ltr'
}, [currentLangObj])

在文件的顶部导入useEffect
Hook

import { useState, useEffect } from "react";

find() 方法允许我们获得所选地区的语言对象。在这个对象中,我们可以访问阿拉伯语方向,当页面加载时,我们将其分配给body.dir 属性。

翻译应用程序的标题

在这里,我们将为我们的应用程序标题和下拉菜单旁边的语言文本添加翻译。

en/translation.json ,添加。

{
  ...
  "app_title": "React-i18next tutorial",
  "languages": "Languages"  
}

为其他支持的地区添加翻译,并保存所有文件。

回到components/Header.js 文件,更新useEffect ,包括应用标题的翻译功能。

useEffect(() => {
  document.body.dir = currentLangObj.dir || "ltr";
  document.title = t("app_title");
}, [currentLangObj, t]);

最后,在JSX中找到这个元素。

<span>Languages</span>

用翻译函数替换它。

<span>{t('languages')}</span>

保存该文件并测试该应用程序。一切都应该按预期工作。

恭喜!我们完成了我们已经完成了!

总结

我很高兴你在这里。你已经学到了很多关于在React应用程序中使用i18next框架的知识。我们几乎涵盖了利用i18next所需的所有用例。现在,你知道如何使用它来实现React应用程序的本地化。

如果你喜欢这个指南,请在网络上分享它。如果你有问题或贡献,请通过评论区告诉我。