const fs = require("fs"); const path = require("path"); const AdmZip = require("adm-zip"); // 用于解压 .jar 文件 // 读取文件并解析为 JSON function readJson(filePath) { try { const content = fs.readFileSync(filePath, "utf8"); return JSON.parse(content); } catch (err) { console.error(`无法读取或解析文件: ${filePath}`); return null; } } // 获取文件列表 function getJarFiles(dirPath) { const files = fs.readdirSync(dirPath); return files.filter((file) => file.endsWith(".jar")); } // 检查文件是否存在 function fileExists(filePath) { return fs.existsSync(filePath); } // 获取 zhLang 数据 function getZhLang(modId, jarPath) { const zip = new AdmZip(jarPath); // 解压 jar 文件 const zhFilePath1 = `assets/${modId}/lang/zh_cn.json`; const zhFilePath2 = path.join("./i18n", modId, "lang/zh_cn.json"); // 尝试从 jar 文件内部读取 zh_cn.json const zhJsonEntry = zip.getEntry(zhFilePath1); if (zhJsonEntry) { const content = zip.readAsText(zhJsonEntry); return JSON.parse(content); } else if (fileExists(zhFilePath2)) { return readJson(zhFilePath2); } return {}; } function removeJsonLineBreak(str) { const regex = /"([^"]*)"/g; return str.replace(regex, (match, p1) => { return `"${p1.replace(/[\r\n]+/g, "")}"`; }); } // 遍历目录下所有的 .jar 文件并进行处理 function processMods() { const modsDir = "./mods"; const jarFiles = getJarFiles(modsDir); console.log(`读取了 ${jarFiles.length} 个 mod`); jarFiles.forEach((jarFile) => { const jarPath = path.join(modsDir, jarFile); const zip = new AdmZip(jarPath); console.log(`正在解析 ${jarPath}`); const modJsonEntry = zip.getEntry("fabric.mod.json"); // 读取 mod 信息 const modJson = JSON.parse(removeJsonLineBreak(zip.readAsText(modJsonEntry))); if (!modJson) return; const modId = modJson.id; const enLangPath = `assets/${modId}/lang/en_us.json`; // 尝试从 jar 文件内部读取 en_us.json const enLangEntry = zip.getEntry(enLangPath); if (!enLangEntry) { console.log(`无法读取 ${jarFile} 的 en_us.json`); return; } const enLangContent = zip.readAsText(enLangEntry); const enLang = JSON.parse(enLangContent); if (!enLang) { console.log(`${jarFile} 的 en_us.json 为空`); return; } const zhLang = getZhLang(modId, jarPath); // 找出 enLang 中有而 zhLang 中没有的 key const missingKeys = Object.keys(enLang).filter( (key) => !(key in zhLang) ); if (missingKeys.length > 0) { const newZhLang = {}; /*missingKeys.forEach(key => { newZhLang[key] = enLang[key]; });*/ for (let k in enLang) { newZhLang[k] = zhLang[k] != undefined ? zhLang[k] : enLang[k]; } // 写入文件 const outputDir = path.join("./lang/zh_cn"); if (!fs.existsSync(outputDir)) { fs.mkdirSync(outputDir, { recursive: true }); } const outputPath = path.join(outputDir, `${modId}.json`); fs.writeFileSync( outputPath, JSON.stringify(newZhLang, null, 2), "utf8" ); console.log(`写入文件: ${outputPath}`); } }); } processMods();