Node - 国际化JSON key值去重 + JSON文件转Excel
1、转excel需要用到 xlsx
转excel的方法
const XLSX = require("xlsx"); // 将 JSON 转换为适合 Excel 的数据格式(数组) /** * 将 JSON 对象转换为数组格式 * @param {Object} jsonObj - 需要转换的 JSON 对象 * @returns {Array<Object>} 转换后的数组,每个元素包含 key值 和 翻译结果 两个属性 * @description 遍历 JSON 对象的所有属性,将每个键值对转换为包含 key值 和 翻译结果 的对象,并存入数组中 */ function convertJSONToArray(jsonObj) { const result = []; for (const key in jsonObj) { if (jsonObj.hasOwnProperty(key)) { result.push({ key值: key, 翻译结果: jsonObj[key], }); } } return result; } // 将 JSON 转换为 Excel /** * 将 JSON 对象转换为 Excel 文件并保存 * @param {Object} jsonObj - 需要转换的 JSON 对象 * @param {string} outputFilePath - 输出的 Excel 文件路径 * @description 将传入的 JSON 对象转换为数组格式,然后创建 Excel 工作簿并写入数据,最后保存为指定路径的 Excel 文件 */ const workbook = XLSX.utils.book_new(); function convertJSONToExcel(jsonObj, outputFilePath, sheetName) { const dataArray = convertJSONToArray(jsonObj); const worksheet = XLSX.utils.json_to_sheet(dataArray); XLSX.utils.book_append_sheet(workbook, worksheet, sheetName); XLSX.writeFile(workbook, outputFilePath); console.log("Excel file written successfully"); } module.exports = { convertJSONToExcel, };
2、去重方法已经读写 JSON,生成新的国际化JSON文件
const fs = require("fs"); const axios = require("axios"); const convertJSONToExcel = require("./transformExcel.js"); // 读取 JSON 文件 /** * 读取并解析 JSON 文件内容 * @param {string} filePath - JSON 文件的路径 * @returns {Object|null} 返回解析后的 JSON 对象,如果读取或解析失败则返回 null */ function readJSONFile(filePath, isRepeat = false) { try { // "utf8" 参数确保返回字符串而非 buffer const data = fs.readFileSync(filePath, "utf8"); if (isRepeat) { // 做去重操作 // result 是去重后的结果 // duplicates key是国际化中重复了的值,value是国际化中重复值对应的key; 项目中如果要统一国际化JSON 需要根据这个手动全局搜索替换一下 const { result, duplicates } = transformJSON(JSON.parse(data)); return { result, duplicates }; } else { return JSON.parse(data); } } catch (error) { console.error("Error reading file:", error); return null; } } // 提取 JSON 对象中的值 function extractValues(jsonObj) { const values = []; for (const key in jsonObj) { if (jsonObj.hasOwnProperty(key)) { values.push(jsonObj[key]); } } return values; } // 调用翻译接口 /** * 将文本数组批量翻译成多种目标语言 * @param {string[]} values - 需要翻译的文本数组 * @returns {Promise<Object>} 返回包含翻译结果的对象,格式为 {de: [], fr: [], it: [], ja: [], es: [], ko: [], th: []} * @description * - 将输入文本按每批10条进行分组 * - 并行调用翻译接口进行批量翻译 * - 支持德语(de)、法语(fr)、意大利语(it)、日语(ja)、西班牙语(es)、韩语(ko)、泰语(th) * - 如果某批翻译失败,将保留原文本内容 */ async function translateValues(values) { let translatedValues = { de: [], fr: [], it: [], ja: [], es: [], ko: [], th: [], }; const batchSize = 10; const batches = []; for (let i = 0; i < values.length; i += batchSize) { const batch = values.slice(i, i + batchSize); batches.push(batch); } const results = await Promise.allSettled( batches.map((batch) => { return axios .post( "接口名", { access_token: "xxx", source_text: batch, target_language: ["de", "fr", "it", "ja", "es", "ko", "th"], } ) .then((response) => response.data.data.translate) .catch((error) => { console.log("接口错误", batch); // console.error("Error translating batch:", batch, error); // 若翻译出错,保留原内容 return batch; }); }) ); const translatedBatches = results.map((result) => result.status === "fulfilled" ? result.value : result.reason ); translatedBatches.map((item) => { if (Array.isArray(item)) { Object.keys(translatedValues).forEach((key) => { translatedValues[key] = [...translatedValues[key], ...item]; }); } else { Object.keys(item).forEach((key) => { translatedValues[key] = [...translatedValues[key], ...item[key]]; }); } }); return translatedValues; } // 更新 JSON 对象 /** * 更新 JSON 对象中的值 * @param {Object} jsonObj - 需要更新的 JSON 对象 * @param {Array} translatedValues - 新的翻译值数组 * @returns {Object} 更新后的 JSON 对象 * @description 将传入的翻译值数组按顺序替换 JSON 对象中对应 key 的值 */ function updateJSONValues(jsonObj, translatedValues) { const keys = Object.keys(jsonObj); for (let i = 0; i < keys.length; i++) { jsonObj[keys[i]] = translatedValues[i]; } return jsonObj; } // 追加更新后的 JSON 对象到原文件 /** * 将 JSON 对象写入指定文件 * @param {string} filePath - 文件路径 * @param {Object} jsonObj - 要写入的 JSON 对象 * @throws {Error} 写入文件失败时抛出错误 */ function writeJSONFile(filePath, jsonObj) { try { return new Promise((resolve, reject) => { // 将 JSON 对象格式化为带缩进(2空格)的字符串,提升可读性。 const data = JSON.stringify(jsonObj, null, 2); // fs.writeFileSync(filePath, data, "utf8"); fs.writeFile(filePath, data, (err) => { if (err) { console.error("文件写入失败:", err); } else { resolve(true); } }); }); } catch (error) { console.error("Error writing file:", error); } } /** * 转换 JSON 对象,处理重复值的情况 * @param {Object} jsonObj - 输入的 JSON 对象 * @returns {Object} 返回包含两个属性的对象: * - result: 不含重复值的对象 * - duplicates: 包含重复值的键名映射 * @example * const input = { a: 1, b: 2, c: 1 }; * transformJSON(input); * // 返回: { * // result: { a: 1, b: 2 }, * // duplicates: { '1': ['a', 'c'] } * // } */ function transformJSON(jsonObj) { const valueToKey = {}; const result = {}; const duplicates = {}; for (const key in jsonObj) { if (jsonObj.hasOwnProperty(key)) { const value = jsonObj[key]; if (valueToKey[value]) { if (!duplicates[value]) { duplicates[value] = [valueToKey[value]]; } duplicates[value].push(key); } else { valueToKey[value] = key; result[key] = value; } } } return { result, duplicates }; } // 主函数 /** * 主函数,用于处理 JSON 文件的翻译流程 * 1. 读取中文源文件 zh_CN.json * 2. 提取需要翻译的值 * 3. 调用翻译接口进行翻译 * 4. 将翻译结果更新到原 JSON 结构中 * 5. 将结果保存到不同的目标语言文件 * * @async * @function main * @returns {Promise<void>} */ async function main() { const inputFilePath = "zh_CN.json"; const { result: inputJSON, duplicates } = readJSONFile(inputFilePath, true); if (inputJSON) { const values = extractValues(inputJSON); const translatedValues = await translateValues(values); await writeJSONFile(`结果/repeat.json`, duplicates); for (let i in translatedValues) { const newTranslateValues = translatedValues[i]; const updatedJSON = updateJSONValues(inputJSON, newTranslateValues); const writeResult = await writeJSONFile(`结果/${i}.json`, updatedJSON); if (writeResult) { const transFormJSON = readJSONFile(`结果/${i}.json`); if (transFormJSON) { convertJSONToExcel.convertJSONToExcel( transFormJSON, `excel文件/全部.xlsx`, i ); } } } } } // 调用主函数 main();

浙公网安备 33010602011771号