问题描述
1. 问题触发的条件
i18n 的 message key 以纯数字开头、紧跟 + 时(如 "500+ reviews"、"1000+ reviews"、"45,000+ users"),$t() 翻译失败,直接返回 key 本身。
- 触发与语言无关,由 key 的结构(数字 +
+)决定。
- 模板
{{ $t('500+ reviews') }} 和 JS this.$t('500+ reviews') 都会复现。
- 对照:
+ 不在纯数字后面时(如 "reviews 500+"、"Pro+ features")不受影响,翻译正常。
2. 期望的表现
locale = zh-CN 时,$t('500+ reviews') 返回对应译文 "500+ 条评论"。
3. 实际的表现
$t('500+ reviews') 返回 key 本身 "500+ reviews"(未翻译)。
locale = zh-CN,messages 同时定义了两个 key:
$t('hello') → "你好" ✅
$t('reviews 500+') → "评论 500+" ✅ (+ 不在数字后)
$t('500+ reviews') → "500+ reviews" ❌ (期望 "500+ 条评论")
根因分析(已定位到源码)
文件:@mpxjs/webpack-plugin/lib/runtime/i18n.wxs
key 被 parsePath 当成路径/算术表达式解析:'500+ reviews' → ['500', '+', 'reviews'],随后 outPutByPath 把 '500' 当数字字面量、'+' 当加法,算出 500 + messages['reviews'] = 500 + undefined = NaN。
而 resolve 的兜底只判断了 == null,接不住 NaN(NaN == null 为 false):
function resolve (messages, locale, key) {
if (messages && messages[locale] && key) {
var format = getPathValue(messages[locale], key)
if (format == null) { // ❌ NaN == null 为 false,兜底被跳过
format = messages[locale][key]
}
return format // 返回了 NaN → translate 见非字符串 → return key
}
}
对照 'Pro+ features'(字母 +)得到的是 undefined,能被 == null 接住,所以正常——这也是为什么"字母 +"已修好、"数字 +"仍坏。
建议修复(保守、零破坏):兜底额外接住 NaN(用 format !== format 判 NaN,wxs 环境可用):
- if (format == null) {
+ if (format == null || format !== format) {
format = messages[locale][key]
}
环境信息描述
- 系统类型:macOS
- Mpx 依赖版本:
@mpxjs/core: 2.10.24
@mpxjs/webpack-plugin: 2.10.24
@mpxjs/api-proxy: 2.10.21
- 小程序开发者工具信息:
- 小程序平台:微信小程序
- 开发者工具版本:⚠️ * 2.01.2510290 darwin-arm64*
- 基础库版本:⚠️ 3.16.1
最简复现 demo
可下载地址:https://github.com/ASkyBig/mpx-i18n-test
复现步骤:
git clone https://github.com/ASkyBig/mpx-i18n-test
cd mpx-i18n-test
npm install # 安装到 @mpxjs/webpack-plugin@2.10.24(自带此 bug)
npm run build # 产物输出到 dist/wx
用微信开发者工具打开 dist/wx,首页(pages/index)渲染三行:
| 渲染 |
期望 |
实际 |
{{ $t('hello') }} |
你好 |
你好 ✅ |
{{ $t('reviews 500+') }} |
评论 500+ |
评论 500+ ✅ |
{{ $t('500+ reviews') }} |
500+ 条评论 |
500+ reviews ❌ |
关键配置(mpx.config.js):
i18n: {
locale: "zh-CN",
messages: {
"en-US": { hello: "hello", "500+ reviews": "500+ reviews", "reviews 500+": "reviews 500+" },
"zh-CN": { hello: "你好", "500+ reviews": "500+ 条评论", "reviews 500+": "评论 500+" },
},
},
对应修复PR: #2527
问题描述
1. 问题触发的条件
i18n 的 message key 以纯数字开头、紧跟
+时(如"500+ reviews"、"1000+ reviews"、"45,000+ users"),$t()翻译失败,直接返回 key 本身。+)决定。{{ $t('500+ reviews') }}和 JSthis.$t('500+ reviews')都会复现。+不在纯数字后面时(如"reviews 500+"、"Pro+ features")不受影响,翻译正常。2. 期望的表现
locale = zh-CN时,$t('500+ reviews')返回对应译文"500+ 条评论"。3. 实际的表现
$t('500+ reviews')返回 key 本身"500+ reviews"(未翻译)。根因分析(已定位到源码)
文件:
@mpxjs/webpack-plugin/lib/runtime/i18n.wxskey 被
parsePath当成路径/算术表达式解析:'500+ reviews'→['500', '+', 'reviews'],随后outPutByPath把'500'当数字字面量、'+'当加法,算出500 + messages['reviews']=500 + undefined=NaN。而
resolve的兜底只判断了== null,接不住NaN(NaN == null为false):对照
'Pro+ features'(字母 +)得到的是undefined,能被== null接住,所以正常——这也是为什么"字母 +"已修好、"数字 +"仍坏。建议修复(保守、零破坏):兜底额外接住
NaN(用format !== format判 NaN,wxs 环境可用):环境信息描述
@mpxjs/core: 2.10.24@mpxjs/webpack-plugin: 2.10.24@mpxjs/api-proxy: 2.10.21最简复现 demo
可下载地址:https://github.com/ASkyBig/mpx-i18n-test
复现步骤:
用微信开发者工具打开
dist/wx,首页(pages/index)渲染三行:{{ $t('hello') }}{{ $t('reviews 500+') }}{{ $t('500+ reviews') }}关键配置(
mpx.config.js):对应修复PR: #2527