import fs from 'fs'; import path from 'path'; import { fileURLToPath } from 'url'; import { dirname } from 'path'; const __filename = fileURLToPath(import.meta.url); const __dirname = dirname(__filename); /** * Vite 插件:构建时直接读取 CSV,替换代码中的 t('xxx') 为翻译文本 * 无需生成任何中间文件,直接从 CSV 读取并替换 * @param {object} options - 插件选项 * @param {string} options.locale - 目标语言代码,从 vite.config.ts 传递 */ function vitePluginTranslate(options = {}) { let translations = {}; let locale = options.locale || 'en'; return { name: 'vite-plugin-translate', enforce: 'pre', // 在 Vue 插件之前执行,处理原始模板 configResolved(config) { // 直接读取 CSV 翻译文件(与后端共享同一数据源) if (locale && locale !== 'en') { const csvPath = path.resolve(__dirname, `../jcloud/translations/${locale}.csv`); if (fs.existsSync(csvPath)) { translations = parseCSV(csvPath); console.log(`[translate] Loaded ${Object.keys(translations).length} translations from ${csvPath}`); } else { console.warn(`[translate] CSV file not found: ${csvPath}, translations will not be replaced`); } } }, transform(code, id) { // 只处理 .vue, .js, .ts 文件 if (!/\.(vue|js|ts|jsx|tsx)$/.test(id)) { return null; } // 如果是英文,不替换 if (locale === 'en') { return null; } // 如果翻译为空,警告但不阻止(可能 CSV 文件不存在,使用原文) if (Object.keys(translations).length === 0) { console.warn(`[translate] No translations loaded for locale: ${locale}, skipping replacement`); return null; } let replaced = code; const isVueFile = id.endsWith('.vue'); if (isVueFile) { // 分离