前端多语言加载优化

背景:站点具有多语言需求,用户访问站点期间需要加载相应的多语言json 文件。

  1. 如何更快响应产品变更词条需求。
  2. 如何更快让用户加载多语言文件是需要考虑的点。
痛点:
  1. 随着多语言JSON文件的词条不断增加,文件体积的增大会导致加载时间延长,进而影响用户体验。因此,优化文件加载效率对于提升用户满意度至关重要。

  2. 以前的多语言文件维护在项目中,每次产品词条更新都需经过CI/CD流程发布,这不仅耗时较长,还难以实现快速响应变更需求。

如何解决:
  1. 基于以上两点问题,全球站多语言需要解决2个问题

  2. 多语言 json文件需要热更新,即产品改动词条之后直接发布,前端不需要CI/CD,用户即可加载最新的多语言文件

  3. 分片加载: 当用户访问特定模块(如KYC页面)时,我们只会加载 kyc 相关的多语言json 文件。其余模块多语言文件并不会被加载 (比如: 用户访问kyc模块,assets 模块多语言就不会被加载)。分片加载带来的好处是: 按需加载,且请求的词条量较小,用户体验更好

项目如何接入:
  1. 初始化拿到所有的 多语言josn文件 在S3的绝对地址,形成一个[国家]+[语言模块]结构。 (类似以下结构)
ruby 复制代码
// 这里的 data 是后端返回的 多语言文件在 S3 绝对地址,只会请求一次
 const data = {
    en_US_asset: 'https://xxx/public/abc.json',    // 英文模式  资产模块    多语言json 文件
    en_US_common: 'https://xxx/public/abcd1.json', // 英文模式  common模块 多语言json 文件
    en_US_kyc: 'https://xxx/public/acb31.json',    // 英文模式  kyc模块    多语言json 文件
    
    zh_CN_asset: 'https://xxx/public/asd1.json',   // 中文简体模式  资产模块     多语言json 文件
    zh_CN_common: 'https://xxx/public/231.json',   // 中文简体模式  common模块  多语言json 文件
    zh_CN_kyc: 'https://xxx/public/12321das.json', // 中文简体模式  kyc模块     多语言json 文件
    
    zh_TW_asset: 'https://xxx/public/1fsa1dsa.json', // 中文繁体模式  资产模块    多语言json 文件
    zh_TW_common: 'https://xxx/public/asds213.json', // 中文繁体模式  common模块 多语言json 文件
    zh_TW_kyc: 'https://xxx/public/sdadasd1.json',   // 中文繁体模式  kyc模块    多语言json 文件
  };
  1. 当用户访问具体某个业务模块的时候,只加载对应模块的多语言json 文件
javascript 复制代码
import i18n from 'i18next';
import HTTPApi from 'i18next-http-backend';
import { awaitWrap } from 'cus-utils';

import {
  getLocalLang,
  EN,
  ZHCN,
  ZHHK,
  LangMapVal,
  NameSpace,
} from '@/utils/utils';
import { getS3LangUrl } from '@/service/common';
import formatS3RemoteLang, {
  type TypeFormatS3RemoteLangUnion,
} from './utils/formatS3RemoteLang';

async function getRemoteS3Url() {
  const [err, s3data] = await awaitWrap(getS3LangUrl());

  const formatS3Data = formatS3RemoteLang(
    s3data?.updateLanguageParameters ?? [],
  );
  // 后续看需要不要加统一错误处理
  if (err) {
    console.error(err, '远端多语言加载失败');
  }

  i18n.use(HTTPApi).init({
    lng: getLocalLang(),
    fallbackLng: {
      zh_CN: [ZHCN],
      zh_HK: [ZHHK],
      en_US: [EN],
      default: [EN],
    },
    ns: 'common',
    fallbackNS: ['default'],
    backend: {
      loadPath: async ([lngs]: LangMapVal[], [namespaces]: NameSpace[]) => {
        const key = (lngs +
          '_' +
          namespaces) as keyof TypeFormatS3RemoteLangUnion;

        // 本地开发模式多语言 json 文件名map
        if (import.meta.env.MODE === 'development') {
          // mock json 文件
          const data = {
            en_US_asset: 'abc',
            en_US_common: 'abcd1',
            en_US_kyc: 'acb31',
            zh_CN_asset: 'asd1',
            zh_CN_common: '231',
            zh_CN_kyc: '12321das',
            zh_TW_asset: '1fsa1dsa',
            zh_TW_common: 'asds213',
            zh_TW_kyc: 'sdadasd1',
          };
          const devModeFilename = data[key];

          return `${import.meta.env.VITE_STATIC_PUBLICPATH}locales/${devModeFilename}.json?hash=${import.meta.env.LANG_HASH}`;
        }

        // 这里控制 多语言按需加载
        const filename = formatS3Data[key].downloadUrl;
        return filename;
      },
      overrideMimeType: 'application/json',
    },
    load: 'currentOnly',
  });
}

getRemoteS3Url();

export default i18n;
  1. 业务代码如何控制多个模块多语言json文件

    1. 方式一:通过 useTranslation 自定义声明 namespace
    javascript 复制代码
    export default function Page() {
      
      const { t } = useTranslation('kyc');       // 加载 kyc 模块多语言文件
      const { t: t1 } = useTranslation('asset'); // 加载 asset 模块多语言文件
      const { t: t2 } = useTranslation('common');// 加载 common 模块多语言文件
    
      return (
        <>
          <div>kyc词条--- {t('common.overview')}</div>
          <div>asset词条 --- {t1('common.overview')}</div>
          <div>common词条 --- {t2('common.overview')}</div>
        </>
      );
    }
    1. 方式二:通过 withTranslation 高阶组件进行 提前注入 namespace
javascript 复制代码
function Page(props) {
  return (
    <>
      <div>kyc词条--- {props.t('common.overview')}</div>
      <div>asset词条 --- {props.t('common.overview', { ns: 'asset' })}</div>
      <div>common词条 --- {props.t('common.overview', { ns: 'common' })}</div>
    </>
  );
}

export default withTranslation(['kyc', 'asset', 'common'])(Page);
效果:
  1. 通过以上配置 i18n文件, 我们可以做到词条维护在 远端S3,实现词条热更新

  2. 用户按需加载多语言词条,用户体验更好

未来优化:
  1. 多语言加载一次之后,缓存在本地,当多语言文件内容 MD5 值明确发生变更之后,再次请求多语言json 文件。即用户请求一次,文件内容没发生变更,直接使用缓存过的多语言文件,避免用户每次刷新都请求多语言文件
  2. 使用 namespace 之后,开发者每次导出组件 都需要引入至少1个namespace,后续考虑使用 AST 进行动态注入每个 组件,尽可能少写 引入 namespace
  3. 目前词条是一个一个录入的,后续考虑在打包编译阶段自动识别到多语言 key,上传到多语言平台,释放开发者录入词条的时间
相关推荐
鱼樱前端1 分钟前
前端程序员集体破防!AI工具same.dev像素级抄袭你的代码,你还能高傲多久?
前端·javascript·后端
2301_764441338 分钟前
小说文本分析工具:基于streamlit实现的文本分析
前端·python·信息可视化·数据分析·nlp
jackl的科研日常23 分钟前
“个人陈述“的“十要“和“十不要“
前端
一个处女座的程序猿O(∩_∩)O27 分钟前
Vue 中 this 使用指南与注意事项
前端·javascript·vue.js
大有数据可视化1 小时前
数字孪生像魔镜,映照出无限可能的未来
前端·html·webgl
一个处女座的程序猿O(∩_∩)O1 小时前
使用 Docker 部署前端项目全攻略
前端·docker·容器
bin91531 小时前
DeepSeek 助力 Vue3 开发:打造丝滑的表格(Table)之添加列宽调整功能,示例Table14_10空状态的固定表头表格
前端·javascript·vue.js·ecmascript·deepseek
天马37981 小时前
Vue 概念、历史、发展和Vue简介
前端·javascript·vue.js
小小鸭程序员2 小时前
NPM版本管理终极指南:掌握依赖控制与最佳实践
java·前端·spring·npm·node.js
KL's pig/猪头/爱心/猪头2 小时前
lws-minimal-ws-server前端分析
前端