UNPKG

i18n-translate-agent

Version:

An intelligent i18n translation agent powered by OpenAI, supporting automatic translation of JSON files with caching and progress tracking

183 lines (157 loc) 4.7 kB
import path from "path"; import fs from "fs"; import { ICreateJsonFileParams } from "../types"; /** * 不存在的文件夹则创建 * @param {string} path */ export const notExistsToCreateFile = (path: string) => { if (fs.existsSync(path)) return; fs.mkdirSync(path); }; /** * 获取json文件 并返回 [[key,value],[key,value]...]] * @param {*} path * @returns */ export const readJsonFileSync = async (path: string) => { try { if (!fs.existsSync(path)) return {}; const jsonStr = await fs.readFileSync(path, "utf8"); // 将JSON字符串解析为对象 return JSON.parse(jsonStr); } catch (error) { console.error("解析JSON时出错:", error); return {}; } }; /** * 创建json文件 * @param {string} fileName 文件名 * @param {string} folderName 文件夹名 * @param {string} language 语言环境 * @param {object} jsonData 文件数据 */ export const createJsonFile = (params: ICreateJsonFileParams) => { const { fileName, folderName, jsonData, language } = params; notExistsToCreateFile(folderName); notExistsToCreateFile(path.resolve(`${folderName}/${language}`)); fs.writeFileSync( path.resolve(`${folderName}/${language}/${fileName}`), JSON.stringify(jsonData, null, 2), "utf8" ); }; export const getRandomNumber = (min: number, max: number) => { return Math.floor(Math.random() * (max - min + 1)) + min; }; export const isDirectoryPath = (path: string) => { if (!fs.existsSync(path)) return false; return fs.statSync(path).isDirectory(); }; export const readFileOfDirSync = (dirPath: string) => { if (!isDirectoryPath(dirPath)) return []; const files = fs.readdirSync(dirPath); // 筛选出所有文件夹 return files.filter((file) => path.extname(file) === ".json"); }; export function chunkArray<T extends object>(array: T[], chunkSize: number) { const result = []; let index = 0; while (index < array.length) { result.push(array.slice(index, index + chunkSize)); index += chunkSize; } return result; } export function intersection<T>(arr1: T[], arr2: T[]): T[] { const setA = new Set(arr1); const setB = new Set(arr2); // 创建一个新的 Set 来存储交集 let intersectionSet = new Set<T>(); // 遍历较小的集合,检查每个元素是否在另一个集合中 for (let item of setA) { if (setB.has(item)) { intersectionSet.add(item); } } return [...intersectionSet]; } /** * 扁平化嵌套 JSON 对象,使用点符号作为键 * @param obj 要扁平化的对象 * @param prefix 键前缀 * @returns 扁平化后的对象 */ export const flattenJson = ( obj: any, prefix: string = "" ): Record<string, string> => { const flattened: Record<string, string> = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { const newKey = prefix ? `${prefix}.${key}` : key; if ( typeof obj[key] === "object" && obj[key] !== null && !Array.isArray(obj[key]) ) { // 递归处理嵌套对象 Object.assign(flattened, flattenJson(obj[key], newKey)); } else { // 直接赋值字符串、数字等基本类型 flattened[newKey] = String(obj[key]); } } } return flattened; }; /** * 检测扁平化JSON中是否存在路径冲突 * @param flatObj 扁平化的对象 * @returns 是否存在冲突 */ const hasPathConflicts = (flatObj: Record<string, string>): boolean => { const keys = Object.keys(flatObj); for (let i = 0; i < keys.length; i++) { for (let j = i + 1; j < keys.length; j++) { const key1 = keys[i]; const key2 = keys[j]; // 检查是否一个key是另一个key的前缀 if (key1.startsWith(key2 + ".") || key2.startsWith(key1 + ".")) { return true; } } } return false; }; /** * 将扁平化的 JSON 重构为嵌套结构 * @param flatObj 扁平化的对象 * @returns 重构后的嵌套对象 */ export const unflattenJson = (flatObj: Record<string, string>): any => { // 如果存在路径冲突,直接返回扁平化结构,不进行反扁平化 if (hasPathConflicts(flatObj)) { console.warn( "Path conflicts detected in JSON structure, returning flattened structure" ); return flatObj; } const result: any = {}; for (const key in flatObj) { if (flatObj.hasOwnProperty(key)) { const keys = key.split("."); let current = result; for (let i = 0; i < keys.length - 1; i++) { const k = keys[i]; if (!(k in current)) { current[k] = {}; } current = current[k]; } current[keys[keys.length - 1]] = flatObj[key]; } } return result; };