UNPKG

i18n-management-cli

Version:

CLI tool for i18n management platform - import, export, and sync translations

159 lines (133 loc) 4.09 kB
const fs = require('fs-extra'); const path = require('path'); const { glob } = require('glob'); class FileUtils { static async readJsonFile(filePath) { try { const fullPath = path.resolve(filePath); if (!await fs.pathExists(fullPath)) { throw new Error(`File not found: ${filePath}`); } return await fs.readJson(fullPath); } catch (error) { throw new Error(`Failed to read JSON file ${filePath}: ${error.message}`); } } static async writeJsonFile(filePath, data) { try { const fullPath = path.resolve(filePath); await fs.ensureDir(path.dirname(fullPath)); await fs.writeJson(fullPath, data, { spaces: 2 }); return true; } catch (error) { throw new Error(`Failed to write JSON file ${filePath}: ${error.message}`); } } static async findJsonFiles(dir, pattern = '**/*.json') { try { const fullPath = path.resolve(dir); if (!await fs.pathExists(fullPath)) { return []; } const files = await glob(pattern, { cwd: fullPath }); return files.map(file => path.join(fullPath, file)); } catch (error) { throw new Error(`Failed to find JSON files in ${dir}: ${error.message}`); } } static extractLanguageFromPath(filePath) { // 匹配 /zh/, /en/, /tw/ 等模式 const match = filePath.match(/\/([a-z]{2,3})(?:[-_][A-Z]{2})?\/[^\/]*\.json$/i); return match ? match[1].toLowerCase() : null; } static generateModuleName(filePath) { const fileName = path.basename(filePath, path.extname(filePath)); // 如果文件名是 index,使用父目录名 if (fileName === 'index') { const parentDir = path.basename(path.dirname(filePath)); return parentDir || 'common'; } return fileName; } static flattenObject(obj, prefix = '') { const result = {}; 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(result, this.flattenObject(obj[key], newKey)); } else { result[newKey] = String(obj[key]); } } } return result; } static unflattenObject(obj) { const result = {}; for (const key in obj) { if (obj.hasOwnProperty(key)) { const keys = key.split('.'); let current = result; for (let i = 0; i < keys.length - 1; i++) { if (!current[keys[i]]) { current[keys[i]] = {}; } current = current[keys[i]]; } current[keys[keys.length - 1]] = obj[key]; } } return result; } static compareObjects(local, remote) { const localKeys = new Set(Object.keys(local)); const remoteKeys = new Set(Object.keys(remote)); const added = {}; const modified = {}; const deleted = []; const unchanged = {}; // 查找新增和修改的键 for (const key of localKeys) { if (!remoteKeys.has(key)) { added[key] = local[key]; } else if (local[key] !== remote[key]) { modified[key] = { local: local[key], remote: remote[key] }; } else { unchanged[key] = local[key]; } } // 查找删除的键 for (const key of remoteKeys) { if (!localKeys.has(key)) { deleted.push(key); } } return { added, modified, deleted, unchanged }; } static async ensureDirectoryExists(dirPath) { try { await fs.ensureDir(path.resolve(dirPath)); return true; } catch (error) { throw new Error(`Failed to create directory ${dirPath}: ${error.message}`); } } static validateJsonFile(filePath) { try { require(path.resolve(filePath)); return true; } catch (error) { throw new Error(`Invalid JSON file ${filePath}: ${error.message}`); } } } module.exports = FileUtils;