前言
这两天看到一个 uniapp vue2 国际化
的bug,这里记录一下这个bug的排查过程。
准备
现在 uniapp 支持 vue2 和 vue3,不同的 vue 版本,相关的api,配置,依赖等也有所不同。
问题截图如下:
可以看到是第一个具名格式(源码里称为叫 named)的国际化内容,没有传入 key,显示异常,第二个传入 key,显示正常。
我的测试项目是通过 hbuilderx 创建的,项目中本身是不包含 node_modules 的
但是我们却可以使用国际化的相关内容,奥秘在于 hbuilderx 这个编辑器,相关的一些依赖都内置在其中,
uniapp-cli
是 vue2 版本的依赖包,uniapp-cli-vite
是 vue3 版本的依赖包,我们可以通过这里来查看依赖到 vue-i18n
的源码。
debug
由于问题是 web 平台
,所以我们要运行到浏览器中,找到用到的产物文件
这里有个笨方法,在每个产物文件开头处加日志,我这里已经确认了是 vue-i18n.esm.js
问题是源于 $t
方法
key是我们传入的要国际化的字符串,locale是现在的语言,messages是现有的国际化对象
$t
是通过内部 i18n._t
处理的,再看下这个方法
方法内部会处理一下传入的参数,比如 $t('global.pleaseInput', { key: $t('login.tenantName') })
转化出来就是 {key: '公司名称'}
,$t('global.pleaseInput')
就是 null
下面的处理方法是 _translate
,
这里的chain是适配的语言数组,['zh-Hans', 'zh', 'en-US', 'en']
,会通过循环去处理各个语言,进入 _interpolate
方法
对应的传入的 _render
的参数是
- 请输入 {key}
- string
- null
- global.pleaseInput
另外一个是
- 请输入 {key}
- string
- {key: '公司名称'}
- global.pleaseInput
不同点就在于values参数
这个函数还调用 formatter 函数,透过名字也能大概推测这里会处理国际化字符串
parse
函数用来解析 token
compile
用来处理字符串
这个就是我们说的具名格式,values是我们传入的数据 {key: '公司名称'}
,转化之后就是 ['请输入 ', '公司名称']
,而没传入就是 null,不会成功解析和转化,最后得到的是 ['请输入 {key}']
修复
至此,我们已经简单梳理了转化的整个流程,那么,如果让我们自己上手提pr修改该怎么做呢?
我的思路是,既然 values
为 null
会处理异常,那就写个函数,统一处理,有值就是默认值,无值就是空字符串。
正则那个方法是让deepseek写的,仅供参考,这个库内部有解析 token 的函数,可以拿来用那个。
这个版本是8.x的最后一个版本,目前还没看9.x是怎么处理的,等看了有空就再更新一篇文章
结语
如有疑问或想法,欢迎留言