ArcoDesign 组件库国际化踩坑记录

940 阅读5分钟

背景

最近有一个我负责的项目需要开源,彻彻底底地支持国际化。项目本身的业务代码有做国际化配置,但是引入的组件库不支持国际化,会出现如图所示的情况。

image.png

在业务站点切换成英文后,业务站点自身的文案会替换成英文,但是“请选择筛选条件并搜索”这个输入框就没有展示英文。原先这个英文版只有美国同事内部使用,比较随意没有做处理。但现在作为开源的问题点提出来,就必须要做处理。需要达到下面的效果。

image.png

思考

组件库现状分析

  1. 组件库有8人协同维护,已经有几十个组件,新增的逻辑需要考虑到对原有代码的影响。
  2. 如果要对所有组件进行国际化需要自动化方案,不然维护不动。
  3. 组件库是基于ArcoDesign提供的脚手架创建的,需要考虑到Arco的一些规则。

最简单,但意义最小的方案

业务方指对这个搜索框提出了问题,希望我能修改。最简单的方案就是我给搜索框组件增加一组参数customTips: {inputTip?:string; guideTip?:string},如果业务代码内想要国际化那么重新给组件赋值就行。但问题在于后续持续维护,如果用到了更多组件,需要给所有组件新增一组参数。如果customTips参数并没有形成一个规范,那后续所有组件自己维护自己的国际化,也会带来混乱。

相对复杂,但更健康的方案

参考Arco官方,其实已经给出了答案。通过一个组件ConfigProvider来统一控制组件库的国际化。在根组件使用ConfigProvider把实际业务代码以及组件包裹起来,组件就可以获取ConfigProvider的参数。

Arco支持多种语言国际化,所以也做了按需引入,需要手动引入所需的语言包。不过因为考虑到我的文案可能也就几十条,并且只支持英语这个国际化语言,暂时就没什么必要做按需引入了。

image.png

import { useState } from 'react';
import {
  ConfigProvider,
} from '@arco-design/web-react';
import zhCN from '@arco-design/web-react/es/locale/zh-CN';
import enUS from '@arco-design/web-react/es/locale/en-US';

function App() {
  const [locale, setLocale] = useState('zh-CN');

  function getLocale() {
    switch (locale) {
      case 'zh-CN':
        return zhCN;

      case 'en-US':
        return enUS;

      default:
        return zhCN;
    }
  }

  return (
    <ConfigProvider locale={getLocale()}>
         // 你的代码
    </ConfigProvider>
  );
}

export default App;

参考Arco的ConfigProvider,我设计了TobConfigProvider。

踩坑记录

别名坑

ArcoDesign的组件库会将/components目录打包成dist、es、lib三个文件夹,分别对应了umd、es、commonjs三种产物。除dist是使用webpack进行打包,es与lib是直接用tsc进行打包。

image.png

一开始我在项目里创建了一个文件夹/locales,里面放了与国际化有关的内容。为了让组件库的每个文件都能以相同的名字引入/locales/i18n.tsx,我设置了别名。最后实现的效果是import useTrans from '@locales/i18'

还有一个考虑就是用到了批量替换代码的脚本。这个脚本会将代码中的中文替换成trans(中文内容),并自动插入import useTrans from '@locales/i18'到代码里。目前这个脚本自动插入固定字符串,没有办法根据ts文件的路径去动态生成一个相对路径。

一般来说你用webpack打包一个东西,打包的产物直接放浏览器里跑完全没问题,因为webpack帮你处理好了依赖关系,不管是通过别名还是相对路径引入的,最后都会得到一个moduleID。然而组件库不同,它的打包产物不是直接放在浏览器运行,而是要经过使用者的二次打包。

image.png image.png

从上面的两张图可以看出来,第一张图是ts文件,导入了别名路径@code2/test。图2是tsc的打包产物,导入的内容依旧是别名。最后发包的时候只会上传dist/code/index.js,而保留了别名映射关系的tsconfig.js是不会被上传的。所以业务代码其实不知道你这个@code2/test对应的原来是./src/code2/test,就会报错。

image.png

其实也蛮奇怪的,找了半天,没有找到让TypeScript把打包产物的别名更正为相对路径的配置。所以这边ArcoDesign用tsc来打包是否合理呢?如果用rollup打包就还能用插件把路径处理一下,否则这在组件库的开发中就没有办法使用别名。

tsc打包坑

一开始我把/locales放到根目录,和/components同级,结果打包出来的东西使用者找不到模块。原先tsc会将/components目录内的东西直接输出到/es目录中。但是如果/components目录内的文件引用了/locales则会导致/es的目录下变更为/components+/locales,那使用者自然是无法引入组件了。

正常的

/es
    /TagInput
    /Ellipsis
    ……

异常的

/es
    /components
    /locales

webpack配置坑

ArcoDesign的组件库可以将我们编写的组件库直接在一个网站预览。里面就有一个./arco-team-site/.config/webpack.config.js来配置预览站点的打包配置。还有一个输出UMD产物的配置文件.config/webpack.config.js。印象中会影响到webpack配置的地方有4处,可能都得改改,这边也有点麻烦。