一文了解 React 国际化解决方案

484 阅读6分钟

作为一个成熟的前端开发工程师,国际化是我们必须要了解和掌握的一个技能点,我们所做的业务免不了和国际接轨,特别是在外企或者大型企业中,都需要特别注重这一点,因为我们的客户可能是全球的。如果你想提升自己,未来进入这样的企业这也是非常重要的一点。

目前的国际化方案大致分为以下两种:

  • 定义多语言词条:如react-i18nextreact-intl-universal都是去定义多语言词条,然后通过key去取值,然后进行渲染。但这里我会分别讲这两种库的使用,因为react-i18next是一个成熟且强大的库,非常适合成熟长期维护的项目,而react-intl-universal使用非常简单,且非常轻量化,很适合小型快速迭代项目使用。
  • 使用自动翻译,如我们开发时还是使用中文,然后对我们整体项目使用translate.js自动翻译功能,翻译为其他语言,这种方式适合开发时间非常紧张的项目或者老项目要快速实现国际化使用。

一、使用react-i18next实现国际化

react-i18next是目前react中使用最广泛的国际化库,也是我们最需要了解和掌握的,他本质是基于i18next封装的更适合react使用的库。

1. 创建react项目

我们首先使用vite来快速创建一个react项目

npm create vite@latest

2. 安装i18next相应依赖包

在刚创建的react项目中安装i18nextreact-i18next依赖包

npm install react-i18next i18next --save

3. 创建i18next配置文件

在项目根目录下创建i18n.js文件,并添加一下代码:

import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import zhCN from "./locales/zh-CN.json";
import enUS from "./locales/en-US.json";

// 指定词条文件,我们全放到 locales/**.json去指定
const resources = {
  zhCN: { translation: zhCN },
  enUS: { translation: enUS },
};

i18n.use(initReactI18next).init({
  resources,
  lng: "zhCN", //默认语言
  fallbackLng: "zhCN", //切换语言失败时回退语言

  interpolation: {
    escapeValue: false,
  },
});

export default i18n;

我们把词条文件全部放在了locales/**.json文件中,这里我们定义了两个词条,分别是zhCNenUS,分别对应中文和英文。

src/locales/zh-CN.json

{
  "welcome": "欢迎使用 React 和 react-i18next"
}

src/locales/en-US.json

{
  "welcome": "Welcome to React and react-i18next"
}

4. 项目中使用

src/main.tsx引入i18next配置文件

src/main.tsx

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
// 引入i18next配置文件
import "../i18n";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <App />
  </StrictMode>
);
  1. hook方式使用
import { useTranslation } from "react-i18next";

function App() {
  const { t, i18n } = useTranslation();

  const changeLanguage = () => {
    i18n.changeLanguage(i18n.language === "zhCN" ? "enUS" : "zhCN");
  };

  return (
    <>
      <h1>{t("welcome")}</h1>
      <button onClick={changeLanguage}>{i18n.language}</button>
    </>
  );
}

export default App;

通过useTranslation获取到t函数,然后通过t函数去取词条,然后通过i18n.language获取到当前语言并通过i18n.changeLanguage实现切换语言。

  1. HOC方式使用
import { withTranslation } from "react-i18next";

function App({ t, i18n }) {
  const changeLanguage = () => {
    i18n.changeLanguage(i18n.language === "zhCN" ? "enUS" : "zhCN");
  };

  return (
    <>
      <h1>{t("welcome")}</h1>
      <button onClick={changeLanguage}>{i18n.language}</button>
    </>
  );
}

export default withTranslation()(App);

这样就用react-i18next实现了国际化功能,大家如果还需要一些更高级功能,如带有参数的词条可以参考 react-i18next 官网

5. 其他推荐

  1. vsCode 插件i18n Ally,这个插件可以实现词条的文案显示,并且也可以搜索词条文案,开发时非常方便。

image-3.png

image-4.png

image-5.png

  1. Lokalise:云端管理词条

大型项目可以使用Lokalise来在云端管理词条,非常方便,可以创建分支,在项目运行时拉取一下词条即可。Lokalise 官网

二、使用react-intl-universal实现国际化

有了react-i18next,为什么还要再讲一下react-intl-universal呢?因为react-intl-universal他更加轻量,更适合小型快速迭代项目使用。我们对比一下这两个库的npm包大小:

image.png

image-1.png

1. 创建react项目

同样我们首先使用vite来快速创建一个react项目

npm create vite@latest

2. 安装react-intl-universal依赖包

npm install react-intl-universal --save

3. 创建intl配置文件

在项目根目录下创建intl.js文件,并添加一下代码:

import intl from "react-intl-universal";
import zhCN from "./src/locales/zh-CN.json";
import enUS from "./src/locales/en-US.json";

const locales = {
  "zh-CN": zhCN,
  "en-US": enUS,
};

intl.init({
  currentLocale: "zh-CN", //当前语言
  fallbackLocale: "zh-CN", //切换失败回退语言
  locales,
});

同样把所有的词条放在了src/locales/**.json,创建了zh-CNen-US两个词条。

src/locales/zh-CN.json

{
  "WELCOME": "欢迎使用 React 和 react-intl-universal",
  "HELLO": "你好, {name}. 欢迎来到 {where}!"
}

src/locales/en-US.json

{
  "WELCOME": "Welcome to React and react-intl-universal",
  "HELLO": "Hello, {name}. Welcome to {where}!"
}

4. 项目中使用

首先在src/main.tsx中引入intl配置文件

import { StrictMode } from "react";
import { createRoot } from "react-dom/client";
import "./index.css";
import App from "./App.tsx";
// 引入intl配置文件
import "../intl";

createRoot(document.getElementById("root")!).render(
  <StrictMode>
    <App />
  </StrictMode>
);

然后在组件中使用:

import intl from "react-intl-universal";

function App() {
  return (
    <>
      <h1>{intl.get("WELCOME")}</h1>
      <h2>{intl.get("HELLO", { name: "Jester", where: "juejin" })}</h2>
    </>
  );
}

export default App;

如此就使用react-intl-universal实现了国际化功能。但如果大家需要一个大而全的国际化库的话还是建议react-intl,它基本能实现国际化的所有需求,而react-intl-universal中某些功能可能还需要我们手动实现。

更详细的使用也可以参考 react-intl-universal 官网

三、使用translate.js自动翻译

在项目根目录index.html中引入translate.js相关 js 文件

src/index.html

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <link rel="icon" type="image/svg+xml" href="/vite.svg" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Vite + React + TS</title>
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/main.tsx"></script>

    // 引入translate.js
    <script src="https://cdn.staticfile.net/translate.js/3.5.1/translate.js"></script>
    // 初始化translate.js
    <script>
      translate.language.setLocal("chinese_simplified"); //设置本地语种(当前网页的语种)。如果不设置,默认自动识别当前网页显示文字的语种。 可填写如 'english'、'chinese_simplified' 等,具体参见文档下方关于此的说明。
      translate.service.use("client.edge"); //设置机器翻译服务通道,直接客户端本身,不依赖服务端 。相关说明参考 http://translate.zvo.cn/43086.html
      translate.execute(); //进行翻译
    </script>
  </body>
</html>

设置好了之后直接在项目中写文案即可,比如我App.tsx内容如下

function App() {
  return (
    <>
      <h1>欢迎使用 react 和 translate.js</h1>
      <h2>你好,我是 Jester</h2>
    </>
  );
}

export default App;

项目运行后,可看到全局有个设置语言的按钮,选择对应的语言后,即可把整体页面自动翻译对对应的语言。

image-2.png

如此就简单的实现了自动翻译,大家如果希望一些高级功能,如设置class对指定元素不翻译等,可以参考 translate.js 官网

当然自动翻译还有其他方案也可以实现,如使用google translate API等,但对网络环境要求更高,国内网络也相对没那么稳定。

这篇文章主要讲了讲目前React中常见的国际化实现方案,学习国际化也能帮助我们提升自己的技能,更容易进入更好的公司,大家如果有什么问题,也可以私信我或者评论区交流。