• react-intl国际化在项目中的使用


    前言

    使用成熟的第三方库的国际化,可以直接使用封装好的方法,这个国际化的原理其实是使用了react 的第三方库react-intl ,感觉主要比较好的就是使用其中的模版,它的本质还是通过了Provider的形式

    第一步新建文件夹,计划把所有的国际化相关的代码统统放到 src/locale 中以下是目录结构

    src
      -local
        -languages (所有的翻译文件)
        -Provider (国际化包裹组件,其中调用国际化接口并合并最后注入)
        -index.ts(到处一些公共的语言相关的变量和方法)
    

    1、项目入口 js文件

    从入口 js 文件开始我们的工作,可以看到只使用了 IntlProvider 组件,并传入了当前的模块名字,在组件中通过模块名去请求后端的国际化内容

    // 以下是 vite 的入口文件 main.tsx
    import ReactDOM from 'react-dom/client'
    import { Suspense } from 'react'
    import 'amfe-flexible'
    
    import App from './App'
    
    // 国际的 Provider (包含 react-intl antd)
    import IntlProvider from '@/locale/Provider'
    
    ReactDOM.createRoot(document.getElementById('root') as HTMLElement).render(
      <IntlProvider moduleCodes='baseline'>
        <Suspense>
          <App />
        </Suspense>
      </IntlProvider>
    )
    

    2、locale/index.ts文件

    1. 定义了当前的语言

    2. 定义了当前的 languages 翻译内容

    3. 导出了非组件中使用intl的方法(简写了一些代码,其他组件中都使用了hooks的国际化写法,这里导出是为了方便组件外面使用)

    import { createIntl, createIntlCache } from "react-intl";
    
    import en_us from "./languages/en-us";
    import zh_cn from "./languages/zh-cn";
    import zh_tw from "./languages/zh-tw";
    
    // 所有的语言map
    let languages = {
      "en-us": en_us,
      "zh-cn": zh_cn,
      "zh-tw": zh_tw,
    };
    
    // 当前的语言
    const lang = localStorage.getItem("language") || "zh-cn";
    
    // 非组件中使用intl
    const intl = createIntl(
      {
        locale: localStorage.getItem("language") || "zh-cn",
        messages: languages[lang],
      },
      createIntlCache()
    );
    
    // 简写 intl.formatMessage(使得业务中少些代码)
    const i18n = (
      id: string,
      defaultMessage?: string,
      description?: string | object
    ) => {
      return intl.formatMessage({ id, defaultMessage, description });
    };
    
    export { languages, lang, intl, i18n };
    

    3、locale/Provider组件

    入口的使用的 IntlProvider 定义如下,可以看到该组件做了以下操作

    1. 引入locale/index.ts文件中的 当前语言、所有的语言翻译

    2. 组件挂载后立马通过 moduleCodes 获取后端国际化内容然后合并本地的国际化内容(具体每个项目不同),成功合并后渲染所有的子页面 {init && children}

    3. 处理UI库的国际化(这里是antd)

    import { useEffect, useState } from 'react';
    import { ConfigProvider } from 'antd'
    import { IntlProvider } from 'react-intl'
    import 'dayjs/locale/zh-cn'
    import dayjs from 'dayjs'
    import enUS from 'antd/locale/en_US';
    import zhCN from 'antd/locale/zh_CN';
    
    import { getIntl } from '@/api/user'
    import { languages, lang } from '../index'
    
    dayjs.locale(lang )
    
    export default function Index(props: {
      children?: any,
      moduleCodes: string | Array<string>,
    }) {
      let { children, moduleCodes } = props
      const [init, setInit] = useState(false)
      const [intl, setInel] = useState({})
    
      useEffect(() => {
        initData()
      }, [])
    
      const initData = async () => {
        // 接口请求获取国际化,并合并本地默认值
        let res = await getIntl(moduleCodes)
        let map = {}
        res.list.forEach((module: { [key: string]: string }) => {
          Object.keys(module).forEach(key => {
            Object.assign(map, module[key])
          })
        })
        setInel({ ...languages[lang], ...map })
        setInit(true)
      }
    
      return (
        <IntlProvider defaultLocale="zh-cn" locale={lang} messages={intl}>
          <ConfigProvider locale={lang === 'en-us' ? enUS : zhCN}>
            {init && children}
          </ConfigProvider>
        </IntlProvider>
      )
    }
    

    3、locale/languages

    目前有两种语言文件 en-us.ts zh-cn.ts,导出一个键值对的对象

    // en-us.ts
    export default {
      "baseline.common.index": "No.",
    };
    
    //zh-cn.ts
    export default {
      "baseline.common.index": "序号",
    };
    

    4、国际化的使用

    这是函数组的使用,类组件的使用可以使用上面locale/index.ts导出的的 intl,具体的使用可以点进去看 react-intl 的定义

    import { useIntl } from 'react-intl';
    
    function Component(){
        const intl = useIntl();
    
        useEffect(() => {
            // 测试
            intl.formatMessage({ id: 'baseline.common.index'});
        }, [])
    }
    
  • 相关阅读:
    Linux的目录管理
    C基础练习(学生管理系统)
    【杂记】Windows首页挟持病毒查杀过程记录
    C# 将PDF转为Excel
    认识线程,初始并发
    Linux下通过开源软件fail2ban进行远程登录防护
    Linux虚拟机和开发板scp命令互传文件
    Spring Boot面试题解析
    微信小程序之console.log()使用
    使用Selenium进行元素定位的全面指南
  • 原文地址:https://blog.csdn.net/qq_41064597/article/details/139400985