国际化探索:颗粒化方案

date
Mar 10, 2025
slug
i18n-1
status
Published
tags
i18n
Technology
summary
最近公司平台需国际化改造,以适配不同语言环境。基于特定需求,展开了一系列技术探索与实践。
type
Post
最近公司平台需国际化改造,以适配不同语言环境。基于特定需求,展开了一系列技术探索与实践。
但是平台的国际化需满足以下前提:
  • 不需要支持站内实时切换语言,需刷新页面完成切换。
  • 平台包含大量业务页面,导致语言包体积庞大且各页面语言包独立性高;故尽可能的切割语言包,如按路由拆分,按需获取。
  • 考虑到部分页面内容需要提前就需确定,无法采用异步加载语言包的方式。

颗粒化方案

方案核心

方案的核心是将国际化颗粒度细化到极致,通过以下步骤实现:
  1. 极致颗粒度国际化:将每个文本片段都独立处理。
  1. 利用 Tree Shaking:通过 TypeScript 的特性,移除未使用的 i18n 变量,减少体积。
  1. vite 插件提取 i18n 内容:将语言包按需拆分。
  1. 打包压缩:通过变量压缩等手段进一步减小语言包体积。

调研

i18n
fnandoUpdated Mar 9, 2025
在调研过程中,我们发现大多数 i18n 实现库都侧重于站内切换语言,这会导致同时加载多个语言包,随着页面增多,语言包体积膨胀,不符合我们的需求。
 
不过,我们注意到了 I18nextProvider,它通过提供不同的 i18n 实例来加载不同的语言包,能在一定程度上实现路由间的分片加载,这启发了我们在第二版方案中实现类似的功能。
 
i18next-http-backend
i18nextUpdated Mar 3, 2025
此外,对于异步加载语言包的方案,如将语言包放在 public 目录下,根据语言动态加载,虽然可行,但因一些限制,我们无法采用这种方式。

i18n 实现

以取浏览器语言为例

使用

语言包定义

组件中使用

打包优化

  1. Tree Shaking:利用 TypeScript 的特性,过滤掉未使用的 i18n 变量,减少打包体积。
  1. 变量压缩:通过压缩工具,将变量名进行压缩,进一步减小体积。例如:

    语言拆分

    利用 vite 配置和插件,将 i18n 语言包内容进行提炼和拆分。首先,通过 rollup 的 manualChunks 提取所有 i18n.ts 文件,并为其生成唯一的 chunk 名称。
    vite.config.js
    打包之后,我们就能看到生成的 i18n 的文件:
    notion image
     
    然后,利用 vite 插件对这些 chunk 进行处理,将其中的语言包内容拆解成单独的语言文件,如 i18n-zh-*.jsi18n-en-*.js,实现单语言加载。
    i18nPlugin.js
    利用之前 manualChunks 打包好的 i18n 文件标识,取找到所有的文件并通过 AST 进行语言提炼,生成单独语言的新文件。
    notion image
     

    单语言映射

    index.html 中加入一个标识,然后在 vite 插件中,通过 transformIndexHtml 方法,将提炼后的语言包文件进行载入并替换该标识,从而实现单语言映射。
    index.html
    i18nPlugin.js
    拆除了单独看这个替换的函数部分:
     
    这里的 map 是关系,建立映射关系,将原本的语言包映射到单一语言包上。
    比如原本引入的是 i18n-1abc4c9b-d12e7f4b.js 文件,通过映射之后,假设现在加载的是中文,那么就会变成 i18n-1abc4c9b-d12e7f4b.jsi18n-zh-1abc4c9b-d12e7f4b.js,从而节省了一半的体积。
     
    该方案的主要优化逻辑是在打包阶段实现的,通过颗粒化处理和打包优化,显著减少了语言包的体积。然而,这种方式对开发者来说并不友好,开发体验较差。
    在后续的方案中,我们将重点优化开发体验,通过单语言拆分和路由拆分等方向来改进。
     

    © JinSo 2021 - 2025