React - Multiple languages

  • 安装依赖的包
{
  "dependencies": {
    "@babel/runtime": "^7.13.10",
    "@material-ui/core": "^4.11.3",
    "@material-ui/icons": "^4.11.2",
    "@testing-library/jest-dom": "^5.11.10",
    "@testing-library/react": "^11.2.6",
    "@testing-library/user-event": "^12.8.3",
    "i18next": "^20.2.1",
    "i18next-browser-languagedetector": "^6.1.0",
    "i18next-http-backend": "^1.2.1",
    "i18next-xhr-backend": "^3.2.2",
    "react": "^17.0.2",
    "react-dom": "^17.0.2",
    "react-i18next": "^11.8.13",
    "react-scripts": "4.0.3",
    "web-vitals": "^1.1.1"
  }
}
  • 创建 i18nconf.js
import i18n from "i18next";
import LanguageDetector from "i18next-browser-languagedetector";
import Backend from 'i18next-xhr-backend';
import { initReactI18next } from "react-i18next";
import translationEN from "./assets/locales/en/translation.json";
import translationCN from "./assets/locales/zh_CN/translation.json";

const fallbackLang = ['en'];
const availableLanguages = ['en', 'zh_CN'];

const resources = {
  en: { translation: translationEN },
  zh_CN: { translation: translationCN }
};

// load translations using http (default public/assets/locals/en/translations)

i18n.use(Backend)
  .use(LanguageDetector)        // detect user language

  .use(initReactI18next)        // pass the i18n instance to react-i18next

  .init({
    resources,
    fallbackLng: fallbackLang,  // fallback language is english.

    detection: {
      checkWhitelist: true,     // options for language detection

    },
    debug: false,
    whitelist: availableLanguages,
    interpolation: {
      escapeValue: false,       // no need for react. it escapes by default

    },
  });

export default i18n;
  • 创建 languageSelect.js
import React from "react";
import { useTranslation } from "react-i18next";
import i18next from "i18next";

import ArrowDropDown from "@material-ui/icons/ArrowDropDown";
import Button from "@material-ui/core/Button";
import Popover from "@material-ui/core/Popover";
import List from "@material-ui/core/List";
import ListItem from "@material-ui/core/ListItem";
import ListSubheader from "@material-ui/core/ListSubheader";

const languageMap = {
  en: { label: "English", dir: "ltr", active: true },
  zh_CN: { label: "中文", dir: "ltr", active: false },
};

const LanguageSelect = () => {
  const selected = localStorage.getItem("i18nextLng") || "en";
  const { t } = useTranslation();

  const [menuAnchor, setMenuAnchor] = React.useState(null);
  React.useEffect(() => {
    document.body.dir = languageMap[selected].dir;
  }, [menuAnchor, selected]);

  return (
    <div className="language-select">
      <Button onClick={({ currentTarget }) => setMenuAnchor(currentTarget)}>
        {languageMap[selected].label}
        <ArrowDropDown fontSize="small" />
      </Button>
      <Popover
        open={!!menuAnchor}
        anchorEl={menuAnchor}
        onClose={() => setMenuAnchor(null)}
        anchorOrigin={{
          vertical: "bottom",
          horizontal: "right"
        }}
        transformOrigin={{
          vertical: "top",
          horizontal: "right"
        }}
      >
        <div>
          <List>
            <ListSubheader>{t("select_language")}</ListSubheader>
            {Object.keys(languageMap)?.map(item => (
              <ListItem
                button
                key={item}
                onClick={() => {
                  i18next.changeLanguage(item);
                  setMenuAnchor(null);
                }}
              >
                {languageMap[item].label}
              </ListItem>
            ))}
          </List>
        </div>
      </Popover>
    </div>
  );
};

export default LanguageSelect;
  • 创建语言资源文件

src\assets\locales\en\translation.json

{
    "select_language": "Select Language",
    "chaos_platform": "Wuhan China"
}

src\assets\locales\zh_CN\translation.json

{
    "select_language": "选择语言",
    "chaos_platform": "中国 武汉"
}
  • 修改 App.js
import logo from './logo.svg';
import './App.css';
import { useTranslation } from "react-i18next";
import LanguageSelect from "./languageSelect";

function App() {
  const { t } = useTranslation();
  return (
    <div className="main">
      <div className="header-panel">
        <LanguageSelect />
      </div>
      <div className="App">
        <header className="App-header">
          <img src={logo} className="App-logo" alt="logo" />
          <p>
            {t("chaos_platform")}
          </p>
        </header>
      </div>
    </div>
  );
}

export default App;
  • 修改 App.css
.header-panel {
  background-color: white;
  width:100%;
  height:50px;
  position:fixed;
  z-index:100;
}

.language-select {
  float: right;
  background-color: white;
}

.main {
  background-color: red;
}
  • 效果图

react-multi-lang!