优化vite翻译插件
This commit is contained in:
parent
27310a009c
commit
206612e23b
@ -390,6 +390,23 @@ function replaceAttributeBindings(code, translations) {
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* 在代码片段中替换所有 $t() 调用为翻译文本
|
||||
* @param {string} content - 要处理的代码片段
|
||||
* @param {object} translations - 翻译字典
|
||||
* @param {RegExp} pattern - 可选的匹配模式,默认匹配所有 $t() 调用
|
||||
* @returns {string} 替换后的代码
|
||||
*/
|
||||
function replaceTranslationCalls(content, translations, pattern = /\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g) {
|
||||
return content.replace(pattern, (match, quote, key) => {
|
||||
const unescapedKey = unescapeString(key);
|
||||
const translation = translations[unescapedKey];
|
||||
if (!translation || !translation.trim()) return match;
|
||||
const escaped = escapeString(translation, quote);
|
||||
return `${quote}${escaped}${quote}`;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 替换属性绑定中数组字面量内的 $t('xxx')
|
||||
* 例如::items="[{ label: $t('key'), ... }]"
|
||||
@ -400,18 +417,7 @@ function replaceAttributeArrayLiterals(code, translations) {
|
||||
return code.replace(
|
||||
/([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])\[([\s\S]*?)\]\3/g,
|
||||
(match, prefix, attrName, outerQuote, arrayContent) => {
|
||||
// 在数组内容中查找并替换所有 $t() 调用,直接替换为翻译文本
|
||||
const replacedContent = arrayContent.replace(
|
||||
/\$t\((['"])((?:\\.|(?!\1).)*)\1\)/g,
|
||||
(m, quote, key) => {
|
||||
const unescapedKey = unescapeString(key);
|
||||
const translation = translations[unescapedKey];
|
||||
if (!translation || !translation.trim()) return m;
|
||||
// 直接替换为翻译文本字符串,转义引号
|
||||
const escaped = escapeString(translation, quote);
|
||||
return `${quote}${escaped}${quote}`;
|
||||
}
|
||||
);
|
||||
const replacedContent = replaceTranslationCalls(arrayContent, translations);
|
||||
return `${prefix}${attrName}=${outerQuote}[${replacedContent}]${outerQuote}`;
|
||||
}
|
||||
);
|
||||
@ -422,26 +428,76 @@ function replaceAttributeArrayLiterals(code, translations) {
|
||||
* 例如::options="{ title: $t('key'), actions: [...] }"
|
||||
*/
|
||||
function replaceAttributeObjectLiterals(code, translations) {
|
||||
// 匹配属性绑定中的对象字面量,如 :options="{ ... }"
|
||||
// 需要处理嵌套的大括号
|
||||
return code.replace(
|
||||
/([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])\{([\s\S]*?)\}\3/g,
|
||||
(match, prefix, attrName, outerQuote, objectContent) => {
|
||||
// 在对象内容中查找并替换所有 $t() 调用,直接替换为翻译文本
|
||||
const replacedContent = objectContent.replace(
|
||||
/(\w+:\s*)\$t\((['"])((?:\\.|(?!\2).)*)\2\)/g,
|
||||
(m, keyPrefix, quote, key) => {
|
||||
const unescapedKey = unescapeString(key);
|
||||
const translation = translations[unescapedKey];
|
||||
if (!translation || !translation.trim()) return m;
|
||||
// 直接替换为翻译文本字符串,转义引号
|
||||
const escaped = escapeString(translation, quote);
|
||||
return `${keyPrefix}${quote}${escaped}${quote}`;
|
||||
// 匹配属性绑定中的对象字面量,使用平衡括号匹配以正确处理嵌套
|
||||
const pattern = /([:@]|v-bind:|v-on:)([a-zA-Z0-9_-]+)=(["'])\{/g;
|
||||
const matches = [];
|
||||
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 openBraceIndex = startIndex + match[0].length - 1; // 开括号的位置
|
||||
const afterBraceIndex = openBraceIndex + 1; // 开括号之后的位置
|
||||
|
||||
// 找到匹配的闭合大括号
|
||||
let depth = 1;
|
||||
let pos = afterBraceIndex;
|
||||
let braceEnd = -1;
|
||||
|
||||
while (pos < code.length && depth > 0) {
|
||||
const char = code[pos];
|
||||
// 跳过字符串字面量中的大括号
|
||||
if (char === '"' || char === "'") {
|
||||
pos++;
|
||||
// 跳过转义的引号
|
||||
while (pos < code.length && (code[pos] !== char || code[pos - 1] === '\\')) {
|
||||
pos++;
|
||||
}
|
||||
);
|
||||
return `${prefix}${attrName}=${outerQuote}{${replacedContent}}${outerQuote}`;
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (char === '{') depth++;
|
||||
else if (char === '}') {
|
||||
depth--;
|
||||
if (depth === 0) {
|
||||
braceEnd = pos;
|
||||
break;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
);
|
||||
|
||||
if (braceEnd === -1) continue;
|
||||
|
||||
// 检查是否以相同的引号结束
|
||||
if (braceEnd + 1 < code.length && code[braceEnd + 1] === outerQuote) {
|
||||
const objectContent = code.substring(afterBraceIndex, braceEnd);
|
||||
matches.push({ startIndex, prefix, attrName, outerQuote, afterBraceIndex, braceEnd, objectContent });
|
||||
}
|
||||
}
|
||||
|
||||
// 从后往前替换,避免索引错乱
|
||||
for (let i = matches.length - 1; i >= 0; i--) {
|
||||
const m = matches[i];
|
||||
// 匹配对象属性值中的 $t(),支持键名(标识符或字符串)
|
||||
const replacedContent = m.objectContent.replace(
|
||||
/(['"]?\w+['"]?\s*:\s*)\$t\((['"])((?:\\.|(?!\2).)*)\2\)/g,
|
||||
(match, keyPrefix, quote, key) => {
|
||||
const unescapedKey = unescapeString(key);
|
||||
const translation = translations[unescapedKey];
|
||||
if (!translation || !translation.trim()) return match;
|
||||
const escaped = escapeString(translation, quote);
|
||||
return `${keyPrefix}${quote}${escaped}${quote}`;
|
||||
}
|
||||
);
|
||||
const replacement = `${m.prefix}${m.attrName}=${m.outerQuote}{${replacedContent}}${m.outerQuote}`;
|
||||
code = code.substring(0, m.startIndex) + replacement + code.substring(m.braceEnd + 2);
|
||||
}
|
||||
|
||||
return code;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user