diff --git a/dashboard/vite-plugin-translate.mjs b/dashboard/vite-plugin-translate.mjs index 00d8854..a0db1e0 100644 --- a/dashboard/vite-plugin-translate.mjs +++ b/dashboard/vite-plugin-translate.mjs @@ -368,9 +368,60 @@ function replaceCompiledFormat(code, translations) { } /** - * 替换属性绑定中的 $t('xxx') + * 替换属性绑定中的 $t('xxx') 或 $t('xxx', { params }) */ function replaceAttributeBindings(code, translations) { + // 先处理带参数的调用::label="$t('key', { params })" + const matches = []; + const pattern = /([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])[\$]?t\((['"])((?:\\.|(?!\4).)*)\4\s*,\s*/g; + let match; + + while ((match = pattern.exec(code)) !== null) { + const startIndex = match.index; + const prefix = match[1]; + const attrName = match[2]; + const outerQuote = match[3]; + const innerQuote = match[4]; + const key = unescapeString(match[5]); + const afterKeyIndex = match.index + match[0].length; + + // 找到参数部分的结束位置(闭括号) + const paramsEnd = findBalancedBracket(code, afterKeyIndex); + if (paramsEnd === -1) continue; + + // 找到整个属性绑定的结束位置(匹配外层的引号) + let attrEnd = paramsEnd + 1; + while (attrEnd < code.length && (code[attrEnd] === ' ' || code[attrEnd] === '\t' || code[attrEnd] === '\n')) attrEnd++; + if (attrEnd < code.length && code[attrEnd] === outerQuote) { + attrEnd++; + } + + matches.push({ startIndex, prefix, attrName, outerQuote, innerQuote, key, afterKeyIndex, paramsEnd, attrEnd }); + } + + // 从后往前替换,避免索引错乱 + for (let i = matches.length - 1; i >= 0; i--) { + const m = matches[i]; + let paramsPart = code.substring(m.afterKeyIndex, m.paramsEnd); + + // 处理参数部分中的嵌套 $t() 调用 + paramsPart = processNestedTranslations( + paramsPart, + translations, + /\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g + ); + + const translation = translations[m.key]; + if (translation) { + // 转义翻译文本以适配内层引号 + let escaped = escapeString(translation, m.innerQuote); + // 保留 $t() 调用结构,只替换翻译键 + const replacement = `${m.prefix}${m.attrName}=${m.outerQuote}$t(${m.innerQuote}${escaped}${m.innerQuote}, ${paramsPart})${m.outerQuote}`; + code = code.substring(0, m.startIndex) + replacement + code.substring(m.attrEnd); + } + } + + // 再处理不带参数的调用::label="$t('key')" return code.replace( /([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])[\$]?t\((['"])((?:\\.|(?!\4).)*)\4\)\3/g, (match, prefix, attrName, outerQuote, innerQuote, key) => {