原创 奈德丽 2025-10-15 08:31 重庆
点击关注公众号,技术干货及时达。

💡 **痛点与背景分析**:在国际机票业务中,多语言管理主要依赖 Excel,面临 Key 命名混乱、缺乏模块化、更新流程繁琐等问题。数千条 Key 的维护工作量巨大,尤其是在 AI 辅助翻译后,频繁修改成本高昂。由于机票项目历史包袱重,短期内难以彻底改造。
🚀 **新方案的设计目标与实现**:针对酒店新项目,作者搭建了一套高效的 i18n 管理方案,核心目标是统一 Key 规则(模块.内容_内容)、实现多语言 JSON 文件的自动化生成并集成到项目内,以及通过一条命令完成更新,彻底告别手动查找脚本和复制粘贴。通过编写 `excel-to-json.js` 脚本并配置 `package.json`,实现了 `pnpm i18n:excel-to-json` 一键操作。
⚙️ **核心脚本逻辑与成果展示**:脚本核心流程为“读取 Excel 内容 → 转换为 JSON → 输出到项目 i18n 目录”,提供了完整的 Node.js 代码实现。改造后的工作流大幅简化,操作效率显著提升,实现了自动输出、自动提示缺失翻译、统一 Key 命名和模块化管理,团队反馈积极,为未来机票项目重构提供了平滑迁移的方案。
原创 奈德丽 2025-10-15 08:31 重庆
点击关注公众号,技术干货及时达。
node 跑脚本;生成后再「手动复制」到项目中。下面是一个实际的 Excel 片段,可以感受一下当时的混乱程度:scripts 目录,并编写了一个 excel-to-json.js 脚本。在 package.json 中添加如下命令:以后,只需要运行下面一行命令,就能完成所有工作:{"scripts": {"i18n:excel-to-json": "node scripts/excel-to-json.js"}}
pnpm i18n:excel-to-json再也不用手动寻找脚本路径,也不用手动复制粘贴,「效率直接起飞 🚀」。脚本实现核心逻辑就是:「从 Excel 读取内容 → 转换为 JSON → 输出到项目 i18n 目录」。完整代码如下:成果展示这是在线语言原文档import fs from 'node:fs'import os from 'node:os'import path from 'node:path'import XLSX from 'xlsx'/*** 语言映射表:Excel 表头 -> 标准语言码*/const languageMap = {'English': 'en','简中': 'zh-CN','Chinese (Traditional)': 'zh-TW','Korean': 'ko','Spanish': 'es','German Edited': 'de','Italian': 'it','Norwegian': 'no','French': 'fr','Arabic': 'ar','Thailandese': 'th','Malay': 'ms',}// 读取 Excel 文件function readExcel(filePath) {if (!fs.existsSync(filePath)) {throw new Error(`❌ Excel 文件未找到: ${filePath}`)}const workbook = XLSX.readFile(filePath)const sheet = workbook.Sheets[workbook.SheetNames[0]]return XLSX.utils.sheet_to_json(sheet)}/*** 清空输出目录*/function clearOutputDir(dirPath) {if (fs.existsSync(dirPath)) {fs.readdirSync(dirPath).forEach(file => fs.unlinkSync(path.join(dirPath, file)))console.log(`🧹 已清空目录: ${dirPath}`)} else {fs.mkdirSync(dirPath, { recursive: true })console.log(`📂 创建目录: ${dirPath}`)}}/*** 生成 JSON 文件*/function generateLocales(rows, outputDir) {const locales = {}rows.forEach(row => {const key = row.Keyif (!key) return// 遍历语言列Object.entries(languageMap).forEach(([columnName, langCode]) => {if (!locales[langCode]) locales[langCode] = {}const value = row[columnName] || ''const keys = key.split('.')let current = locales[langCode]keys.forEach((k, idx) => {if (idx === keys.length - 1) {current[k] = value} else {current[k] = current[k] || {}current = current[k]}})})})// 输出文件Object.entries(locales).forEach(([lang, data]) => {const filePath = path.join(outputDir, `${lang}.json`)fs.writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf-8')console.log(`✅ 生成文件: ${filePath}`)})}/*** 检测缺失翻译*/function detectMissingTranslations(rows) {const missing = []rows.forEach(row => {const key = row.Keyif (!key) returnObject.entries(languageMap).forEach(([columnName, langCode]) => {const value = row[columnName]if (!value?.trim()) {missing.push({ key, lang: langCode })}})})return missing}function logMissingTranslations(missingList) {if (missingList.length === 0) {console.log('\n🎉 所有 key 的翻译完整!')return}console.warn('\n⚠️ 以下 key 缺少翻译:')missingList.forEach(item => {console.warn(` - key: "${item.key}" 缺少语言: ${item.lang}`)})}function main() {const desktopPath = path.join(os.homedir(), 'Desktop', 'hotel多语言.xlsx')const outputDir = path.resolve('src/i18n/locales')const rows = readExcel(desktopPath)clearOutputDir(outputDir)generateLocales(rows, outputDir)logMissingTranslations(detectMissingTranslations(rows))}main()
操作
旧流程
新流程
运行脚本
手动找脚本路径
pnpm i18n:excel-to-json文件生成位置
生成后手动拷贝
自动输出到项目
检测缺失翻译
无
自动提示
key 命名管理
无统一规则
模块化、规范化
这套机制目前在「酒店项目」中运行良好,团队反馈也很积极。总结这次改造让我最大的感触是:❝「旧项目难以推翻重来,但新项目一定要趁早做好架构设计。」❞通过这次优化,我们不仅解决了多语言维护的痛点,还提升了团队整体开发效率。而这套方案在未来如果机票项目有机会重构,也可以直接平滑迁移过去。点击"阅读原文"了解详情~
AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。
鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑