前端国际化实践总结

Posted by Qz on January 13, 2022

“Yeah It’s on. ”

i18n

https://www.npmjs.com/package/i18n

i18next

https://www.i18next.com/overview/getting-started

https://www.npmjs.com/package/i18next

i18next is a very popular internationalization framework for browser or any other javascript environment (eg. Node.js, Deno).

I18next是一个非常流行的国际化框架,适用于浏览器或任何其他javascript环境。node . js, Deno)。

i18next is an i18n framework written in and for JavaScript. It provides the standard i18n features of interpolation, formatting, and handling plurals and context.

国际化方案选型

前端国际化一般需要同时处理文案翻译、语言检测、语言包加载、日期数字格式化、复数和插值。简单项目可以直接把 resources 打进包里;中大型项目更推荐按语言和命名空间拆分,通过 i18next-http-backend 按需加载语言包。

常见目录结构如下:

public/locales/
  zh-CN/
    common.json
    user.json
  en-US/
    common.json
    user.json

命名空间拆分的好处是可以避免首屏加载所有业务文案,也方便多人协作维护。公共按钮、表单校验、菜单等通用文案放在 common,业务模块文案按模块拆分。

常用配置说明

  • fallbackLng:兜底语言,避免当前语言缺失时页面直接展示 key。
  • ns / defaultNS:命名空间配置,适合大型项目拆分语言包。
  • load:控制语言匹配方式,例如 languageOnly 会把 zh-CN 归一到 zh
  • debug:只建议在开发环境开启。
  • interpolation.escapeValue:React 默认会做 XSS 转义,通常可以设置为 false

react-i18next

import i18n from "i18next"
import Backend from "i18next-http-backend"
import LanguageDetector from "i18next-browser-languagedetector"
import { initReactI18next } from "react-i18next"
import { name } from "../../package.json"

const env = process.env.NODE_ENV
let loadPath = ""
let addPath = ""

if (env === "production") {
  loadPath = `/${name}/locales//.json`
  addPath = `/${name}/locales/add//`
} else {
  loadPath = "/locales//.json"
  addPath = "/locales/add//"
}

i18n
  // load translation using http -> see /public/locales
  // learn more: https://github.com/i18next/i18next-http-backend
  .use(Backend)
  // detect user language
  // learn more: https://github.com/i18next/i18next-browser-languageDetector
  .use(LanguageDetector)
  // pass the i18n instance to react-i18next.
  .use(initReactI18next)
  // init i18next
  // for all options read: https://www.i18next.com/overview/configuration-options
  .init({
    load: "languageOnly",
    fallbackLng: "en",
    backend: {
      // 根据不同环境加载不同路径
      loadPath,
      addPath,
    },
    debug: env !== "production", // 调试模式只在开发环境开启
    interpolation: {
      escapeValue: false, // React 默认会做转义,避免重复转义
    },
    react: {
      useSuspense: true,
    },
  })

export default i18n

问题

need to pass in an i18next instance

react-i18next

需要使用 I18nextProvider

解决:

import { I18nextProvider } from "react-i18next"

import i18n from "./i18n"

<I18nextProvider i18n={i18n}>
  <Suspense fallback={"loading..."}>
    <App />
  </Suspense>
</I18nextProvider>

changeLanguage is not a function

react-i18next

大概率是 translation.json 请求的路径有问题,设置好 loadPath/addPath