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; } } // 获取 .jar 文件列表 function getJarFiles(dirPath) { const files = fs.readdirSync(dirPath); return files.filter((file) => file.endsWith(".jar")); } // 从字符串中提取所有符合 %+字母 格式的标签 function extractTags(str) { const tagRegex = /%[a-zA-Z]/g; return (str.match(tagRegex) || []).sort(); } function removeJsonLineBreak(str) { const regex = /"([^"]*)"/g; return str.replace(regex, (match, p1) => { return `"${p1.replace(/[\r\n]+/g, "")}"`; }); } // 获取 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 {}; } // 处理 mods_translated 目录下的 .jar 文件 function processMods() { const modsTranslatedDir = "./mods_translated"; const errorMods = []; const jarFiles = getJarFiles(modsTranslatedDir); jarFiles.forEach((jarFile) => { const jarPath = path.join(modsTranslatedDir, jarFile); console.log(`正在读取 ${jarPath}`); // 解压 jar 包并读取 fabric.mod.json 文件 const zip = new AdmZip(jarPath); const modJsonEntry = zip.getEntry("fabric.mod.json"); if (!modJsonEntry) { console.log(`未找到 fabric.mod.json: ${jarPath}`); return; } const modJsonContent = zip.readAsText(modJsonEntry); const modJson = JSON.parse(removeJsonLineBreak(modJsonContent)); const modId = modJson.id; // 检查是否存在 en_us.json 和 zh_cn.json 文件 const enLangEntry = zip.getEntry(`assets/${modId}/lang/en_us.json`); if (enLangEntry) { const enLangContent = zip.readAsText(enLangEntry); const enLang = JSON.parse(enLangContent); const zhLang = getZhLang(modId, jarPath); // 对比 enLang 和 zhLang 的 keys 是否相同 const enKeys = Object.keys(enLang); const zhKeys = Object.keys(zhLang); const keysDifference = enKeys.filter( (key) => !zhKeys.includes(key) ); if (keysDifference.length > 0) { errorMods.push(jarFile + " " + keysDifference.toString()); } // 遍历 enLang 和 zhLang 的每一个 key enKeys.forEach((key) => { if (zhLang[key] !== undefined) { const enTags = extractTags(enLang[key]); const zhTags = extractTags(zhLang[key]); // 比较 enTags 和 zhTags 是否相同 if (enTags.sort().join(",") !== zhTags.sort().join(",")) { errorMods.push(jarFile + " key=" + key); } } }); } }); console.log("有错误的 Mods:"); console.log(errorMods); } processMods();