1. 首页
  2. React

Vite6+React18+Ts项目-16.国际化进阶之 i18next 多语言

ant 支持的语言

地址:https://ant.design/docs/react/i18n-cn

语言

文件名

阿拉伯语

ar_EG

阿塞拜疆语

az_AZ

保加利亚语

bg_BG

孟加拉语(孟加拉国)

bn_BD

白俄罗斯语

by_BY

加泰罗尼亚语

ca_ES

捷克语

cs_CZ

丹麦语

da_DK

德语

de_DE

希腊语

el_GR

英语

en_GB

英语(美式)

en_US

西班牙语

es_ES

巴斯克语

eu_ES

爱沙尼亚语

et_EE

波斯语

fa_IR

芬兰语

fi_FI

法语(比利时)

fr_BE

法语(加拿大)

fr_CA

法语(法国)

fr_FR

爱尔兰语

ga_IE

加利西亚语(西班牙)

gl_ES

希伯来语

he_IL

印地语

hi_IN

克罗地亚语

hr_HR

匈牙利语

hu_HU

亚美尼亚

hy_AM

印度尼西亚语

id_ID

意大利语

it_IT

冰岛语

is_IS

日语

ja_JP

格鲁吉亚语

ka_GE

高棉语

km_KH

北库尔德语

kmr_IQ

卡纳达语

kn_IN

哈萨克语

kk_KZ

韩语/朝鲜语

ko_KR

立陶宛语

lt_LT

拉脱维亚语

lv_LV

马其顿语

mk_MK

马拉雅拉姆语

ml_IN

蒙古语

mn_MN

马来语 (马来西亚)

ms_MY

缅甸语

my_MM

挪威语

nb_NO

尼泊尔语

ne_NP

荷兰语(比利时)

nl_BE

荷兰语

nl_NL

波兰语

pl_PL

葡萄牙语(巴西)

pt_BR

葡萄牙语

pt_PT

罗马尼亚语

ro_RO

俄罗斯语

ru_RU

僧伽罗语

si_LK

斯洛伐克语

sk_SK

塞尔维亚语

sr_RS

斯洛文尼亚语

sl_SI

瑞典语

sv_SE

泰米尔语

ta_IN

泰语

th_TH

土耳其语

tr_TR

土库曼

tk_TK

乌尔都语 (巴基斯坦)

ur_PK

乌克兰语

uk_UA

乌兹别克语(拉丁字母)

uz_UZ

越南语

vi_VN

简体中文

zh_CN

繁体中文(中国香港)

zh_HK

繁体中文(中国台湾)

zh_TW

dayjs支持的语言

地址:https://github.com/iamkun/dayjs/tree/dev/src/locale

af

am

ar-dz

ar-iq

ar-kw

ar-ly

ar-ma

ar-sa

ar-tn

ar

az

be

bg

bi

bm

bn-bd

bn

bo

br

bs

ca

cs

cv

cy

da

de-at

de-ch

de

dv

el

en-au

en-ca

en-gb

en-ie

en-il

en-in

en-nz

en-sg

en-tt

en

eo

es-do

es-mx

es-pr

es-us

es

et

eu

fa

fi

fo

fr-ca

fr-ch

fr

fy

ga

gd

gl

gom-latn

gu

he

hi

hr

ht

hu

hy-am

id

is

it-ch

it

ja

jv

ka

kk

km

kn

ko

ku

ky

lb

lo

lt

lv

me

mi

mk

ml

mn

mr

ms-my

ms

mt

my

nb

ne

nl-be

nl

nn

oc-lnc

pa-in

pl

pt-br

pt

rn

ro

ru

rw

sd

se

si

sk

sl

sq

sr-cyrl

sr

ss

sv-fi

sv

sw

ta

te

tet

tg

th

tk

tl-ph

tlh

tr

tzl

tzm-latn

tzm

ug-cn

uk

ur

uz-latn

uz

vi

x-pseudo

yo

zh-cn

zh-hk

zh-tw

zh

ant,dayjs和后端语言对照表

Ant 实现的语言

Ant 语言编码

dayjs语言编码(后缀.js)

dayjs语言编码备注

浏览器语言编码

浏览器语言编码备注

后端语言

阿拉伯语

ar_EG

ar

ar

ar

阿塞拜疆语

az_AZ

az

az

az

保加利亚语

bg_BG

bg

bg

bg

孟加拉语(孟加拉国)

bn_BD

bn-bd

存在 bn 翻译

bn

存在 bn-IN

bn

白俄罗斯语

by_BY

加泰罗尼亚语

ca_ES

ca

ca

存在 ca-Es-VALENCIA

ca

捷克语

cs_CZ

cs

cs

cs

丹麦语

da_DK

da

da

da

德语

de_DE

de

de

存在 de-AT de-DE de-LI de-CH

de

希腊语

el_GR

el

el

el

英语

en_GB

en-gb

en-GB-oxendict

存在 en-IE en-AU en-CA en-ZA en-NZ en-IN

en-GB

英语(美式)

en_US

en

en

en

西班牙语

es_ES

es

es

存在 es-AR es-CO es-CR 等多个

es

巴斯克语

eu_ES

eu

eu

eu

爱沙尼亚语

et_EE

et

et

et

波斯语

fa_IR

fa

fa

fa

芬兰语

fi_FI

fi

fi

fi

法语(比利时)

fr_BE

fr

fr-BE

存在 fr-BE fr-FR fr-CA fr-CH 等多个

fr-BE

法语(加拿大)

fr_CA

fr-ca

fr-CA

fr-CA

法语(法国)

fr_FR

fr

fr-FR

fr

爱尔兰语

ga_IE

ga

ga

ga

加利西亚语(西班牙)

gl_ES

gl

gl

gl

希伯来语

he_IL

he

he

he

印地语

hi_IN

hi

hi

hi

克罗地亚语

hr_HR

hr

hr

hr

匈牙利语

hu_HU

hu

hu

hu

亚美尼亚

hy_AM

hy-am

hy

hy

印度尼西亚语

id_ID

id

id

id

意大利语

it_IT

it

it-IT

存在 it it-CH

it

冰岛语

is_IS

is

is

is

日语

ja_JP

ja

ja

ja

格鲁吉亚语

ka_GE

ka

ka

ka

高棉语

km_KH

km

km

km

北库尔德语

kmr_IQ

卡纳达语

kn_IN

kn

kn

kn

哈萨克语

kk_KZ

kk

kk

kk

韩语/朝鲜语

ko_KR

ko

ko

ko

立陶宛语

lt_LT

lt

lt

lt

拉脱维亚语

lv_LV

lv

lv

lv

马其顿语

mk_MK

mk

mk

mk

马拉雅拉姆语

ml_IN

ml

ml

ml

蒙古语

mn_MN

mn

mn

mn

马来语 (马来西亚)

ms_MY

ms-my

存在 ms 翻译

ms

ms

缅甸语

my_MM

my

my

my

挪威语

nb_NO

nb

nb

nb

尼泊尔语

ne_NP

ne

ne

ne

荷兰语(比利时)

nl_BE

nl-be

存在 nl 翻译

nl-BE

存在 nl

nl-BE

荷兰语

nl_NL

nl

nl

nl

波兰语

pl_PL

pl

pl

pl

葡萄牙语(巴西)

pt_BR

pt-br

存在 pt 翻译

pt-BR

存在 pt

pt-BR

葡萄牙语

pt_PT

pt

pt-PT

存在 pt

pt

罗马尼亚语

ro_RO

ro

ro

ro

俄罗斯语

ru_RU

ru

ru

ru

僧伽罗语

si_LK

si

si

si

斯洛伐克语

sk_SK

sk

sk

sk

塞尔维亚语

sr_RS

sr

sr

存在 sr-Latn-RS sr-Cyrl-BA sr-Cyrl-RS

sr

斯洛文尼亚语

sl_SI

sl

sl

sl

瑞典语

sv_SE

sv

sv

sv

泰米尔语

ta_IN

ta

ta

ta

泰语

th_TH

th

th

th

土耳其语

tr_TR

tr

tr

tr

土库曼

tk_TK

tk

tk

tk

乌尔都语 (巴基斯坦)

ur_PK

ur

ur

ur

乌克兰语

uk_UA

uk

uk

uk

乌兹别克语(拉丁字母)

uz_UZ

uz

uz-Latn

uz

越南语

vi_VN

vi

vi

vi

简体中文

zh_CN

zh-cn

存在 zh 翻译

zh-CN

存在 zh

zh

繁体中文(中国香港)

zh_HK

zh-hk

存在 zh 翻译

zh-HK

存在 zh

zh-HK

繁体中文(中国台湾)

zh_TW

zh-tw

存在 zh 翻译

zh-TW

存在 zh

zh-TW

如何在react,ant项目中使用语言切换

首先,定义 util.ts 用来将浏览器语言代码转为后端语言代码 src\langs\util.ts

export interface LangType {
  /**
   * 语言名称
   */
  name: string;
  /**
   * 浏览器语言
   */
  browser: string;
  /**
   * Ant 支持的语言
   */
  ant: string;
  /**
   * DayJS 支持的语言
   */
  dayjs: string;
  /**
   * 后端语言
   */
  backend: string;
}

/**
 * 支持的语言列表,可以从后端获取
 *
 */
const support = new Map<string, LangType>([
  /**
   * 英语
   */
  ['en-GB', { name: '英语', browser: 'en-GB', ant: 'enGB', dayjs: 'en-gb', backend: 'en-GB' }],
  /**
   * 英语(美式)
   */
  ['en', { name: '英语(美式)', browser: 'en', ant: 'enUS', dayjs: 'en', backend: 'en' }],
  /**
   * 中文
   */
  ['zh', { name: '中文', browser: 'zh', ant: 'zhCN', dayjs: 'zh-cn', backend: 'zh' }],
  /**
   * 简体中文
   */
  ['zh-CN', { name: '简体中文', browser: 'zh-CN', ant: 'zhCN', dayjs: 'zh-cn', backend: 'zh' }],
  /**
   * 繁体中文(中国台湾)
   */
  ['zh-TW', { name: '繁体中文(中国台湾)', browser: 'zh-TW', ant: 'zhTW', dayjs: 'zh-tw', backend: 'zh-TW' }],
  /**
   * 泰语
   */
  ['th', { name: '泰语', browser: 'th', ant: 'thTH', dayjs: 'th', backend: 'th' }],
]);

/**
 * 将浏览器语言代码进行转换
 * @param code
 */
export function getLangType(code: string): LangType {
  if (code == undefined || code == null || code == '') {
    return defaultLangType;
  }
  // 转换几个特殊编码
  switch (code) {
    case 'en-GB-oxendict':
      code = 'en-GB';
      break;
    case 'fr-FR':
      code = 'fr';
      break;
    case 'pt-PT':
      code = 'pt';
      break;
    case 'zh-CN':
      code = 'zh';
      break;
    case 'uz-Latn':
      code = 'uz';
      break;
    default:
      break;
  }
  // 返回转换后的语言
  if (support.has(code)) {
    return support.get(code)!;
  }
  code = code.split('-')[0];
  return support.has(code) ? support.get(code)! : defaultLangType;
}

/**
 * 默认语言
 */
export const defaultLangType = support.get('en')!;

其中支持的语言列表变量 support 可以通过加载js文件从后端获取,比如

https://demo.com/lang-support.js

可通过下面代码声明变量,以免报错

// 声明全局类型(防止TS报错)
declare global {
  interface Window {
    languageSupport: Map<string, LangConvert>;
  }
}
// 使用变量
const support = window.languageSupport;

然后,在 i18n.ts 文件中使用 getLangType函数,src\langs\i18n.ts

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

import { setLang } from '@/stores/lang/lang-store';
import { getLangType } from './util';

i18n
  .use(Backend) // 启用从后端加载翻译文件
  .use(LanguageDetector) // 启用浏览器语言检测
  .use(initReactI18next) // 绑定 React
  .init({
    fallbackLng: 'en-GB', // 默认语言,初次加载时,首先会加载默认语言,然后加载当前语言,也就是说初次加载时会加载两种语言
    load: 'currentOnly', // 仅加载当前语言
    interpolation: {
      escapeValue: false, // React 已经处理了 XSS 防护
    },
    backend: {
      loadPath: 'http://demo.com/lang.php?code={{lng}}', // 从后端加载翻译文件的路径
    },
    detection: {
      // 自定义 localStorage 的 key,这里面存的是当前语言类型,不是语言翻译内容
      lookupLocalStorage: 'my_custom_lng_key',
      // 自定义 cookie 的 key,这里面存的是当前语言类型,不是语言翻译内容
      lookupCookie: 'my_custom_lng_cookie_key',
      // 语言检测的选项,当前语言会按照顺序依次从以下选择中查询当前语言
      order: ['localStorage', 'cookie', 'navigator'],
      // 缓存检测到的语言
      caches: ['localStorage', 'cookie'],
      // 语言代码转换,可以将当前语言代码进行转换,比如将 en 转换为 en-GB
      convertDetectedLanguage: (code) => {
        return getLangType(code).browser;
      },
    },
  });

// 大多数场景不建议将i18n的语言保存到状态管理,因为 i18n 自身已有管理状态,避免重复,微前端架构可能需要保存到状态管理,也看具体情况
i18n.on('initialized', () => {
  setLang(getLangType(i18n.language));
});

export default i18n;

在状态管理 lang-store.ts 里保存文件,并在语言切换的方法里处理其它逻辑,比如字典的重新获取

import i18n from '@/langs/i18n';
import { LangType, defaultLangType, getLangType } from '@/langs/util';
import { create } from 'zustand';
import { createJSONStorage, persist } from 'zustand/middleware';
import { immer } from 'zustand/middleware/immer';


// define the initial state
const init: LangType = defaultLangType;

// 存储store的key
const storeKey = 'store-lang';

// create your store
const useLangStore = create<LangType>()(
  immer(
    persist(
      () => ({
        ...init,
      }),
      {
        // name of the item in the storage (must be unique)
        name: storeKey,
        // (optional) by default, 'localStorage' is used
        storage: createJSONStorage(() => localStorage),
      }
    )
  )
);

export default useLangStore;

// 设置语言
export const setLang = (state: LangType) => {
  useLangStore.setState(state);
  // 这里可以处理其它逻辑,比如切换语言后,需要重新获取字典数据,需要修改i18n缓存在浏览器的语言代码等...
  i18n.changeLanguage(state.browser)
};

在项目中使用 ant 和 dayjs,并进行语言切换

import { ConfigProvider, Calendar, Radio, RadioChangeEvent } from 'antd';

import { Locale } from 'antd/lib/locale';
import { getLangType } from './langs/util';

import useLangStore, { setLang } from '@/stores/lang/lang-store';

import dayjs from 'dayjs';

// 引入 Ant Design 中文语言包,这里不一一引入了,支持哪些语言,引用哪些语言即可
import zhCN from 'antd/locale/zh_CN';
import enUS from 'antd/locale/en_US';
import enGB from 'antd/locale/en_GB';
import zhTW from 'antd/locale/zh_TW';
import thTH from 'antd/locale/th_TH';

// 引入 dayjs 的语言包,这里不一一引入了,支持哪些语言,按需引入即可
import 'dayjs/locale/zh-cn';
import 'dayjs/locale/zh-tw';
import 'dayjs/locale/th';

// 方便演示,简单列出几种语言
const antLangMap = new Map<string, Locale>([
  ['enGB', enGB],
  ['enUS', enUS],
  ['zhCN', zhCN],
  ['zhTW', zhTW],
  ['thTH', thTH],
]);

function App() {
  const lang = useLangStore((state) => state);

  const onChange = (e: RadioChangeEvent) => {
    // 这里应该单独抽离出一个方法,在 i18n initialized 事件时同步调用该方法
    const v = getLangType(e.target.value);
    setLang(v);
    dayjs.locale(v.dayjs);
  };

  console.log(lang);

  return (
    <>
      <ConfigProvider locale={antLangMap.get(lang.ant)}>
        <Radio.Group
          onChange={onChange}
          value={lang.backend}
          options={[
            { value: 'en', label: '英语(美式)' },
            { value: 'zh', label: '中文' },
            { value: 'zh-TW', label: '繁体中文(中国台湾)' },
            { value: 'th', label: '泰语' },
          ]}
        />
        <div
          style={{
            width: '500px',
            margin: '50px auto',
            padding: '10px',
            border: '1px solid #eee',
          }}
        >
          <Calendar></Calendar>
        </div>
      </ConfigProvider>
    </>
  );
}

export default App;

TOP