UNPKG

@c-sheep/i18n-extract-cli

Version:

这是一款能够自动将代码里的中文转成i18n国际化标记的命令行工具。当然,你也可以用它实现将中文语言包自动翻译成其他语言。适用于vue2、vue3和react

365 lines (364 loc) 14.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.startSetMergeJson = exports.mergeBothLanguageData = exports.getFullLocalJsonData = exports.handleLanguageNext = exports.getMergePmoLanguageExcel = void 0; const node_xlsx_1 = __importDefault(require("node-xlsx")); const getAbsolutePath_1 = require("../shared/getAbsolutePath"); const glob_1 = __importDefault(require("glob")); const getLoseLangaugeXlsx_1 = require("../shared/getLoseLangaugeXlsx"); const excelUtil_1 = require("../shared/excelUtil"); const fs_1 = __importDefault(require("fs")); const translateMoreLanguage_1 = require("../translate/translateMoreLanguage"); const flatObjectDeep_1 = require("../shared/flatObjectDeep"); const cloneDeep_1 = __importDefault(require("lodash/cloneDeep")); const translateMoreLanguage_2 = require("../translate/translateMoreLanguage"); const comblie_1 = require("../shared/comblie"); const util_1 = require("../shared/util"); function getLocalExcelData(str) { const xlsxData = node_xlsx_1.default.parse((0, getAbsolutePath_1.getAbsolutePath)(process.cwd(), str))[0] .data; return xlsxData; } // 把数据按照header取排序 保证所有的顺序是一致的 function handleMergeData(result, header) { const [_, ...xlsxHeader] = result.shift(); const xlsxHeaderMap = {}; xlsxHeader.forEach((irem, index) => { xlsxHeaderMap[irem] = index + 1; }); return result.map((ditem) => { // xlsxHeaderMap const langRows = header.map((item) => { const relIndex = xlsxHeaderMap[item]; if (relIndex) { return ditem[relIndex]; } return ""; // ditem[] }); return [ditem[0], ...langRows]; }); // const newSortHeader = header.map((item, index) => ) // {zh-cn: 1, en:2, zh-tw: 3} } function getAllLanguageDataArr(str, header) { const excelPath = glob_1.default.sync(`${str}/**/*.xlsx`, { ignore: [] }); const allExcelResult = [["字典 Key", ...header]]; excelPath.forEach((linkPath, index) => { const result = (0, getLoseLangaugeXlsx_1.getLocalXlsxData)(linkPath); const newResult = handleMergeData(result, header); allExcelResult.push(...newResult); }); return allExcelResult; } function getPmoExcelData(str, defaultKey, locales) { const header = [defaultKey || "zh-cn", ...locales]; const xlsxData = getAllLanguageDataArr(str, header); const [_, ...data] = xlsxData; return { xlsxData, header, data }; } function getMergePmoLanguageExcel(header, data) { const xlsxJsonData = {}; header.forEach((key, index) => { xlsxJsonData[key] = (xlsxJsonData[key] || {}); data.forEach((row) => { var _a, _b; if (!row[0] || !row[1]) { return; } const keyName = (_b = (_a = row[0]) === null || _a === void 0 ? void 0 : _a.toString()) === null || _b === void 0 ? void 0 : _b.replace(/\[|\]/g, "_"); xlsxJsonData[key][keyName] = row[index + 1]; }); }); return xlsxJsonData; } exports.getMergePmoLanguageExcel = getMergePmoLanguageExcel; const handleLanguageNext = (obj) => { for (const i in obj) { if (typeof obj[i] === "string") { obj[i] = obj[i].trim(); } } return obj; }; exports.handleLanguageNext = handleLanguageNext; function getFullLocalJsonData(localePath, dirs, regexp) { var _a; const mapData = {}; for (const language of dirs) { if (mapData[language] && ((_a = Object.values(mapData[language])) === null || _a === void 0 ? void 0 : _a.length)) continue; const result = (0, translateMoreLanguage_1.getBaseLanguageMap)(localePath, language, regexp); const flatResult = (0, flatObjectDeep_1.flatObjectDeep)(result); mapData[language] = (0, exports.handleLanguageNext)(flatResult); } return mapData; } exports.getFullLocalJsonData = getFullLocalJsonData; function transferDataToMapBykey(data, keyIndex = 0) { const map = {}; data.forEach((item) => { map[item[keyIndex].replace(/\[|\]/g, "_")] = item; }); return map; } function genreNewLocalData(headers, mapDataInfo, excelFileName, excelPath) { const excelBuffer = (0, excelUtil_1.buildExcel)(headers, mapDataInfo, excelFileName); const excelFilePath = (0, getAbsolutePath_1.getAbsolutePath)(process.cwd(), excelPath); fs_1.default.writeFileSync(excelFilePath, excelBuffer, "utf8"); } const mergeBothLanguageData = (base, compare = {}, lang) => { const result = {}; for (const i in base) { const baseValue = base[i]; const compareValue = compare[i]; if (typeof baseValue === "object") { if (typeof compareValue === "object") { result[i] = (0, exports.mergeBothLanguageData)(baseValue, compareValue, lang); } else { result[i] = (0, exports.mergeBothLanguageData)(baseValue, compare, lang); } } else { result[i] = compareValue || baseValue; } } return result; }; exports.mergeBothLanguageData = mergeBothLanguageData; function getKeyZhData(json, result = { zhToKey: {}, keyToZh: {} }) { // console.log(json, 'json') for (const i in json) { const data = json[i]; if (typeof data === "object") { getKeyZhData(data, result); } else { result.zhToKey[data] = result.zhToKey[data] || []; result.zhToKey[data].push(i); result.keyToZh[i] = data; } } return result; } function getLangDataByZhJson(json, keyZh = {}, result = {}) { for (const i in json) { const data = json[i]; if (typeof data === "object") { getLangDataByZhJson(data, keyZh, result); } else { // ;(keyZh as any).ddd() result[i] = data; } } return result; } function setSameZhDataJson(json, keyMap) { json = (0, cloneDeep_1.default)(json); const findKeyData = (key, lang) => { const jsonData = json[lang]; const zh = keyMap.keyToZh[key] || ""; // console.log(zh, 'zh') const result = []; if (zh) { const keys = keyMap.zhToKey[zh]; for (const i of keys) { const val = jsonData[i]; result.push(val); } } return result.find((i) => i) || ""; }; for (const lang in json) { const jsonData = json[lang]; for (const key in jsonData) { if (!jsonData[key]) { jsonData[key] = findKeyData(key, lang); } } } return json; } function removeAutoTranslate(pmoJsonData, translateJsonPath, locales, moduleNameRegex) { const jifanPath = (0, getAbsolutePath_1.getAbsolutePath)(process.cwd(), translateJsonPath); const autoJson = getFullLocalJsonData(translateJsonPath, locales, moduleNameRegex || /./); // console.log(autoJson, "autoJson"); const removeSameLangData = (langData, pmoLangData, lang, index = 0) => { if (Object.keys(langData).length) { const result = {}; // console.log(pmoLangData, "pmoLangData"); for (const jk in langData) { const jkJson = langData[jk.toString().trim()]; const pmoJson = pmoLangData[jk.toString().trim()]; // console.log(jk.toString(), jkJson, pmoJson); if (typeof jkJson === "object") { const jkResult = removeSameLangData(jkJson, typeof pmoJson === "object" ? pmoJson : {}, lang, index + 1); if (Object.keys(jkResult).length > 0) { result[jk] = jkResult; } else if (index === 0) { (0, util_1.deleteEmptyFileAndFolder)((0, getAbsolutePath_1.getAbsolutePath)(jifanPath, lang, jk + ".json")); } } if (!pmoJson) { result[jk] = jkJson; } } return result; } return {}; }; const genreAutoFile = (json, translateJsonPath, lang) => { const langPath = (0, getAbsolutePath_1.getAbsolutePath)(translateJsonPath, lang); const deepJson = (0, flatObjectDeep_1.genreObjectDeep)(json); // console.log(deepJson, langPath, "deepJson, langPath"); (0, translateMoreLanguage_2.setLanguageModuleSave)(deepJson, langPath, true); }; for (const lang in autoJson) { const langFullPath = (0, getAbsolutePath_1.getAbsolutePath)(jifanPath, lang); const removeLangJson = removeSameLangData((0, flatObjectDeep_1.genreObjectDeep)(autoJson[lang] || {}), (0, flatObjectDeep_1.genreObjectDeep)(pmoJsonData[lang]), lang); const removeLength = Object.keys(removeLangJson).length; // console.log(removeLangJson, translateJsonPath, lang, "removeLangJson"); if (removeLength) { genreAutoFile(removeLangJson, translateJsonPath, lang); } else if (!moduleNameRegex) { (0, comblie_1.deleteFolderRecursive)(langFullPath); } } } // function getKeyToZh(localePath: string) { // const zhDataDeep = getBaseLanguageMap(localePath, "zh-cn"); // const flatData = flatObjectDeep(zhDataDeep); // return getKeyZhData(flatData); // } function startSetMergeJson(i18nConfig) { // let pmoJsonMapData: { [k: string]: StringObject } = {}; const { locales, translateJsonPath, localePath, sortData, formatModuleName, defaultKey } = i18nConfig; const baseLang = defaultKey || "zh-cn"; const moduleNameRegex = formatModuleName ? new RegExp(formatModuleName) : /./; if (!i18nConfig.transferPath) { console.error("请先设置 transferPath"); return; } const genreArrayDataByObj = (obj) => { const headers = Object.keys(obj).filter((i) => i !== baseLang); const newObj = (0, cloneDeep_1.default)(obj); for (const lang in newObj) { newObj[lang] = (0, flatObjectDeep_1.flatObjectDeep)(newObj[lang]); } const result = []; const zhCnData = newObj[baseLang]; for (const i in zhCnData) { const temp = []; temp.push(i, zhCnData[i]); for (const j of headers) { const langData = newObj[j]; temp.push(langData[i]); } result.push((0, cloneDeep_1.default)(temp)); } return { headers: [baseLang, ...headers], result }; }; const getMapIndex = (header, buffer = 1) => { const map = {}; const mapIndexToStr = {}; header.forEach((item, index) => { map[item] = index + buffer; mapIndexToStr[index + buffer] = item; }); return { map, mapIndexToStr }; }; const { header, data: pmoArrayJsonData } = getPmoExcelData(i18nConfig.transferPath, baseLang, locales); // const fullLocales = [baseLang, ...locales]; // for (const i of fullLocales) { // if (!header.includes(i)) { // console.error(`${i} 列不存在`); // } // } const { map: pmoIndexMap, mapIndexToStr } = getMapIndex(header); const pmoJsonMapData = getMergePmoLanguageExcel(header, pmoArrayJsonData); // console.log(pmoJsonMapData, 'pmoJsonMapData'); // const excelFilePath = getAbsolutePath(process.cwd(), localePath); const projectJson = getFullLocalJsonData(localePath, [baseLang, ...locales]); const { headers: projectHeaders, result: projectArrayJsonData } = genreArrayDataByObj(projectJson); const resultDeepMap = {}; projectHeaders.forEach((lang) => { resultDeepMap[lang] = {}; }); const resultZhMap = getZhPmoData(pmoArrayJsonData); // console.log(pmoJsonMapData, 'pmoJsonMapData'); // const ddddd = getAbsolutePath(process.cwd(), 'resultZhMap.json'); // fs.writeFileSync(ddddd, JSON.stringify(resultZhMap), "utf8"); projectArrayJsonData.forEach((pData) => { // 遍历所有的数据 projectHeaders.forEach((lang, index) => { const data = setEmptyData(pData[index + 1], pData, lang, pmoJsonMapData[lang] || {}, resultZhMap, sortData); if (data) { resultDeepMap[lang][pData[0]] = data; } }); }); const langResult = {}; for (const lang in resultDeepMap) { const resultFile = {}; const file = (0, flatObjectDeep_1.genreObjectDeep)(resultDeepMap[lang]); if (langResult[lang] === null || typeof langResult[lang] !== "object") { langResult[lang] = {}; } for (const key in file) { if (moduleNameRegex.test(key)) { resultFile[key] = file[key]; langResult[lang][key] = file[key]; } } const langPath = (0, getAbsolutePath_1.getAbsolutePath)(localePath, lang); (0, translateMoreLanguage_2.setLanguageModuleSave)(resultFile, langPath); } // console.log(langResult, 'langResult'); removeAutoTranslate(langResult, translateJsonPath, locales, formatModuleName ? moduleNameRegex : false); function getZhPmoData(pmoArrayJson) { // 获取pmo给的数据 按照中文当key const _resultZhMap = {}; pmoArrayJson.forEach((item, index) => { const key = pmoIndexMap[baseLang]; if (!_resultZhMap[item[key]]) { _resultZhMap[item[key]] = []; } const next = _resultZhMap[item[key]]; const row = {}; item.forEach((ccitem, ccindex) => { row[mapIndexToStr[ccindex] || "key"] = ccitem; }); next.push(row); }); return _resultZhMap; } function setEmptyData(localData, rowData, lang, pmoJsonData, pmoResultZhMap, sort = ["key", "local", "zh"]) { // 设置数据 取pmo给的数据 const key = rowData[0]; const zhText = rowData[1]; const pmoKeyContent = pmoJsonData[key]; const findTextArr = pmoResultZhMap[zhText] || []; const pmoZhDataMap = findTextArr.find((item) => item[lang]) || { [lang]: "" }; const mapData = { key: pmoKeyContent, local: localData, zh: pmoZhDataMap[lang] }; return sort.map((i) => mapData[i]).find((i) => i) || ""; } } exports.startSetMergeJson = startSetMergeJson;