发布于 2026-01-06 14 阅读
0

如何实现 React 应用国际化?DEV 的全球展示挑战赛,由 Mux 呈现:展示你的项目!

如何将 React 应用国际化

由 Mux 主办的 DEV 全球展示挑战赛:展示你的项目!

本文最初发表于我的个人博客。

国际化(或称 i18n)是指在您的网站或应用程序中支持不同的语言。它可以帮助您吸引来自世界各地的用户,从而提升网站流量。

在本教程中,我们将学习如何将 React 网站国际化,包括翻译内容以及根据所选语言更改布局方向。

您可以在此 GitHub 存储库中找到本教程的完整代码

设置网站

首先,我们将使用Create React App (CRA)设置 React 网站

运行以下命令:

npx create-react-app react-i18n-tutorial
Enter fullscreen mode Exit fullscreen mode

完成上述步骤后,将目录切换到项目目录:

cd react-i18n-tutorial
Enter fullscreen mode Exit fullscreen mode

然后就可以启动服务器了:

npm start
Enter fullscreen mode Exit fullscreen mode

安装依赖项

将 React 应用国际化的最简单方法是使用i18next库。i18next 是一个用 Javascript 编写的国际化框架,可以与多种语言和框架一起使用,但最重要的是可以与React一起使用。

运行以下命令安装 i18next:

npm install react-i18next i18next --save
Enter fullscreen mode Exit fullscreen mode

此外,我们还需要安装i18next-http-backend,它允许我们从目录中获取翻译,以及i18next-browser-languagedetector,它允许我们检测用户的语言:

npm i i18next-http-backend i18next-browser-languagedetector
Enter fullscreen mode Exit fullscreen mode

最后,我们将安装React Bootstrap来进行简单的样式设置:

npm install react-bootstrap@next bootstrap@5.1.0
Enter fullscreen mode Exit fullscreen mode

创建主页

我们将在进行国际化工作之前,先创建网站的主页。

导航栏

我们首先需要导航组件。创建src/components/Navigation.js时请使用以下内容:

import { Container, Nav, Navbar, NavDropdown } from "react-bootstrap";

function Navigation () {

  return (
    <Navbar bg="light" expand="lg">
      <Container>
        <Navbar.Brand href="#">React i18n</Navbar.Brand>
        <Navbar.Toggle aria-controls="basic-navbar-nav" />
        <Navbar.Collapse id="basic-navbar-nav">
          <Nav className="me-auto">
            <NavDropdown title="Language" id="basic-nav-dropdown">
              <NavDropdown.Item href="#">English</NavDropdown.Item>
              <NavDropdown.Item href="#">العربية</NavDropdown.Item>
            </NavDropdown>
          </Nav>
        </Navbar.Collapse>
      </Container>
    </Navbar>
  );
}

export default Navigation;
Enter fullscreen mode Exit fullscreen mode

标题

然后,我们将创建src/components/Greeting.js以下内容:

function Greeting () {

  return (
    <h1>Hello</h1>
  );
}

export default Greeting;
Enter fullscreen mode Exit fullscreen mode

文本

接下来,我们将创建src/components/Text.js以下内容:

function Text () {

  return (
    <p>Thank you for visiting our website.</p>
  )
}

export default Text;
Enter fullscreen mode Exit fullscreen mode

最后,我们需要在网站上显示这些组件。请更改以下内容src/App.js

import React from 'react';
import { Container } from 'react-bootstrap';
import 'bootstrap/dist/css/bootstrap.min.css';
import Greeting from './components/Greeting';
import Loading from './components/Loading';
import Navigation from './components/Navigation';
import Text from './components/Text';

function App() {

  return (
    <>
      <Navigation />
      <Container>
        <Greeting />
        <Text />
      </Container>
    </>
  );
}

export default App;

Enter fullscreen mode Exit fullscreen mode

如果服务器尚未运行,请立即运行。您将看到一个带有导航栏和一些文本的简单网站。

如何将 React 应用国际化

配置 i18next

使用 i18next 对 React 进行国际化的第一步是配置和初始化它。

src/i18n.js使用以下内容创建:

import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import Backend from 'i18next-http-backend';
import I18nextBrowserLanguageDetector from "i18next-browser-languagedetector";

i18n
  .use(Backend)
  .use(I18nextBrowserLanguageDetector)
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    fallbackLng: 'en',
    debug: true,

    interpolation: {
      escapeValue: false // react already safes from xss
    }
  });

  export default i18n;
Enter fullscreen mode Exit fullscreen mode

我们首先i18n从导入i18next。然后,我们将i18next-http-backendi18next-browser-languagedetector作为插件添加到i18n。我们还添加了initReactI18next作为插件,以确保i18next与 React 兼容。

接下来,我们i18n通过传递一个选项对象来初始化它。你可以向初始化器传递很多选项,但我们只传递了 3 个。

fallbackLng如果未检测到任何语言,则该语言将作为 i18n 的默认语言。语言的检测依据是用户的首选语言,或用户之前使用网站时选择的语言。

debug启用控制台中的调试信息。此功能不应用于生产环境。

至于escapeValuein interpolation,我们将其设置为 false,因为 React 已经转义了所有字符串,可以防止跨站脚本攻击 (XSS)

添加翻译文件

默认情况下,i18next-http-backend程序会在 `<language_code>` 目录中查找翻译文件public/locales/{language}/translation.json,其中 ` {language}<language_code>` 是所选语言的代码。例如,`en` 代表英语。

在本教程中,我们的网站将支持两种语言:英语和阿拉伯语。因此,我们将创建一个目录locales并在其中创建两个子目录enar

translation.json然后,在以下位置创建文件en

{
  "greeting": "Hello",
  "text": "Thank you for visiting our website.",
  "language": "Language"
}
Enter fullscreen mode Exit fullscreen mode

这将创建 3 个翻译键。使用这些键时,将根据所选语言输出与该键对应的字符串值。因此,每个语言文件都应该具有相同的键,但其值已翻译成该语言。

translation.json接下来,我们将在以下位置创建文件ar

{
  "greeting": "مرحبا",
  "text": "شكرا لزيارة موقعنا",
  "language": " اللغة"
}
Enter fullscreen mode Exit fullscreen mode

使用 i18n 实例

下一步是将我们刚刚创建的设置文件导入到以下位置App.js

import i18n from './i18n';
Enter fullscreen mode Exit fullscreen mode

接下来,为了确保在 i18next 和翻译文件加载完毕后组件能够正确渲染,我们需要使用React 的 Suspense 组件来包裹我们的组件:

<Suspense fallback={<Loading />}>
    <Navigation />
    <Container>
        <Greeting />
        <Text />
    </Container>
</Suspense>
Enter fullscreen mode Exit fullscreen mode

如您所见,我们传递了一个新的组件Loading作为备用方案,同时 i18next 会加载翻译文件。因此,我们需要创建src/components/Loading.js包含以下内容的组件:

import { Spinner } from "react-bootstrap";

function Loading () {
  return (
    <Spinner animation="border" role="status">
      <span className="visually-hidden">Loading...</span>
    </Spinner>
  )
}

export default Loading;
Enter fullscreen mode Exit fullscreen mode

现在,我们可以翻译App组件及其子组件中的字符串了。

使用 useTranslation 翻译字符串

在 i18next 中,翻译字符串的方法有很多种,其中一种是使用useTranslationhook。通过这个 hook,你可以获取到翻译函数,并用它来翻译字符串。

我们先来翻译这个Greeting组件。在组件开头添加以下内容:

function Greeting () {
  const { t } = useTranslation();
    ...
}
Enter fullscreen mode Exit fullscreen mode

然后,在返回的 JSX 中,我们不再直接放置文本“Hello”,而是将其替换为t我们从以下位置收到的翻译函数useTranslation

return (
    <h1>{t('greeting')}</h1>
  );
Enter fullscreen mode Exit fullscreen mode

请注意,我们将添加到每种语言文件中的键传递给了翻译函数translation.json。i18next 将根据当前语言获取该值。

我们对组件也做同样的处理Text

import { useTranslation } from "react-i18next";

function Text () {
  const { t } = useTranslation();

  return (
    <p>{t('text')}</p>
  )
}

export default Text;
Enter fullscreen mode Exit fullscreen mode

最后,我们将翻译组件内部的文本“Language” Navigation

<NavDropdown title={t('language')} id="basic-nav-dropdown">
Enter fullscreen mode Exit fullscreen mode

如果你现在打开这个网站,你会发现一切都没有变化。文字仍然是英文的。

虽然从技术上讲没有什么变化,但考虑到我们使用翻译函数时传递的是键而不是实际的字符串,并且它输出的是正确的字符串,这意味着 i18next 正在加载翻译并显示正确的语言。

如果我们尝试使用导航栏中的下拉菜单更改语言,则不会发生任何变化。我们需要根据用户点击的语言来更改语言。

更改网站语言

用户应该能够更改网站的语言。为了管理和更改网站的当前语言,我们需要创建一个应用程序所有部分都可以访问的上下文。

创建上下文可以消除在不同组件和层级之间传递状态的需要。

src/LocaleContext.js创建包含以下内容的文件:

import React from "react";

const defaultValue = {
  locale: 'en',
  setLocale: () => {} 
}

export default React.createContext(defaultValue);
Enter fullscreen mode Exit fullscreen mode

locale然后,在内部创建状态src/App.js

function App() {
  const [locale, setLocale] = useState(i18n.language);
Enter fullscreen mode Exit fullscreen mode

如您所见,我们传递的i18n.language是一个初始值。该language属性表示当前选择的语言。

然而,由于 i18n 需要时间加载翻译,初始值将为undefined0。因此,我们需要监听语言首次加载和更改时触发的languageChanged事件:i18n

i18n.on('languageChanged', (lng) => setLocale(i18n.language));
Enter fullscreen mode Exit fullscreen mode

最后,我们需要用上下文提供程序将返回的 JSX 包裹起来:

<LocaleContext.Provider value={{locale, setLocale}}>
      <Suspense fallback={<Loading />}>
        <Navigation />
          <Container>
            <Greeting />
            <Text />
          </Container>
    </Suspense>
</LocaleContext.Provider>
Enter fullscreen mode Exit fullscreen mode

现在,我们可以从任何子组件访问区域设置及其设置器。

要更改语言,我们需要为下拉链接的点击事件添加一个监听函数。

src/components/Navigation.js函数开头从上下文中获取区域设置状态:

const { locale } = useContext(LocaleContext);
Enter fullscreen mode Exit fullscreen mode

然后,添加一个监听器组件,用于更改语言i18n

  function changeLocale (l) {
    if (locale !== l) {
      i18n.changeLanguage(l);
    }
  }
Enter fullscreen mode Exit fullscreen mode

最后,我们将监听器绑定到两个下拉链接的点击事件:

<NavDropdown.Item href="#" onClick={() => changeLocale('en')}>English</NavDropdown.Item>
              <NavDropdown.Item href="#" onClick={() => changeLocale('ar')}>العربية</NavDropdown.Item>
Enter fullscreen mode Exit fullscreen mode

如果您访问该网站并尝试更改语言,您会发现语言会根据您的选择成功更改。此外,如果您尝试更改语言后刷新页面,您会发现所选语言会保持不变。

如何将 React 应用国际化

更改翻译文件的位置

如前所述,翻译文件的默认位置在[此处] public/locales/{language}/translation.json。但是,这是可以更改的。

要更改默认位置,请更改以下行src/i18n.js

.use(Backend)
Enter fullscreen mode Exit fullscreen mode

致以下人员:

.use(new Backend(null, {
    loadPath: '/translations/{{lng}}/{{ns}}.json'
  }))
Enter fullscreen mode Exit fullscreen mode

其中,loadPath是相对于的public。因此,如果您使用上述路径,则表示翻译文件应该位于名为的目录中translations

{{lng}}指的是语言,例如,en{{ns}}指的是命名空间,默认情况下为translation

您还可以提供一个函数作为值,loadPath该函数以语言作为第一个参数,以命名空间作为第二个参数。

更改文档方向

国际化和本地化的下一个重要部分是根据你支持的语言来支持不同的方向。

如果您使用的是从右到左 (RTL) 的语言,那么在选择 RTL 语言时,您应该能够更改文档的方向。

以我们的网站为例,你会发现,虽然选择阿拉伯语时文本会被翻译,但方向仍然是从左到右(LTR)。

这与 i18next 无关,因为这是使用 CSS 实现的。在本教程中,我们将学习如何在 Bootstrap 5 中使用RTL来支持 RTL 语言。

首先,我们需要给文档的标签添加 `<head>`dir和 `<body> lang` 属性<html>。为此,我们需要安装React Helmet

npm i react-helmet
Enter fullscreen mode Exit fullscreen mode

然后,在组件Suspense返回的 JSX 代码中App添加以下内容:

<Helmet htmlAttributes={{
          lang: locale,
          dir: locale === 'en' ? 'ltr' : 'rtl'
        }} />
Enter fullscreen mode Exit fullscreen mode

这将根据区域设置的值更改langdir属性。<html>

接下来我们需要做的是用ThemeProvider以下组件包裹 Bootstrap 组件react-bootstrap

<ThemeProvider dir={locale === 'en' ? 'ltr' : 'rtl'}>
    <Navigation />
    <Container>
        <Greeting />
        <Text />
    </Container>
</ThemeProvider>
Enter fullscreen mode Exit fullscreen mode

如您所见,我们dir根据区域设置传递了方向属性。这是必要的,因为react-bootstrap它会根据当前方向是左上角rtl还是右上角来加载相应的样式表ltr

最后,我们需要更改组件Nav中的类名Navigation

<Nav className={locale === 'en' ? 'ms-auto' : 'me-auto'}>
Enter fullscreen mode Exit fullscreen mode

之所以需要这样做,是因为切换到 RTL 语言时似乎存在支持问题ms-auto

如果您现在尝试打开该网站并将语言更改为阿拉伯语,您会发现文档的方向也发生了变化。

如何将 React 应用国际化

结论

i18next 可以帮助您轻松实现 React 应用以及其他框架和语言的国际化。通过国际化您的应用或网站,您可以吸引来自世界各地的更多用户。

国际化的主要部分包括翻译内容、在网站样式表中支持所选语言的方向,以及记住用户的选择。使用 i18next,您可以轻松翻译内容并记住用户的选择。

文章来源:https://dev.to/shahednasser/how-to-internationalize-a-react-app-28ca