UNPKG

i18n-transform-cli

Version:

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

314 lines (313 loc) 12.8 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const fs_extra_1 = __importDefault(require("fs-extra")); const chalk_1 = __importDefault(require("chalk")); const path_1 = __importDefault(require("path")); const prettier_1 = __importDefault(require("prettier")); const cli_progress_1 = __importDefault(require("cli-progress")); const glob_1 = __importDefault(require("glob")); const merge_1 = __importDefault(require("lodash/merge")); const cloneDeep_1 = __importDefault(require("lodash/cloneDeep")); const transform_1 = __importDefault(require("./transform")); const log_1 = __importDefault(require("./utils/log")); const getAbsolutePath_1 = require("./utils/getAbsolutePath"); const collector_1 = __importDefault(require("./collector")); const translate_1 = __importDefault(require("./translate")); const getLang_1 = __importDefault(require("./utils/getLang")); const constants_1 = require("./utils/constants"); const stateManager_1 = __importDefault(require("./utils/stateManager")); const exportExcel_1 = __importStar(require("./exportExcel")); const initConfig_1 = require("./utils/initConfig"); const saveLocaleFile_1 = require("./utils/saveLocaleFile"); const assertType_1 = require("./utils/assertType"); function isValidInput(input) { const inputPath = (0, getAbsolutePath_1.getAbsolutePath)(process.cwd(), input); if (!fs_extra_1.default.existsSync(inputPath)) { log_1.default.error(`路径${inputPath}不存在,请重新设置input参数`); process.exit(1); } if (!fs_extra_1.default.statSync(inputPath).isDirectory()) { log_1.default.error(`路径${inputPath}不是一个目录,请重新设置input参数`); process.exit(1); } return true; } function getSourceFilePaths(input, exclude) { if (isValidInput(input)) { return glob_1.default.sync(`${input}/**/*.{cjs,mjs,js,ts,tsx,jsx,vue}`, { ignore: exclude, }); } else { return []; } } function saveLocale(localePath) { const keyMap = collector_1.default.getKeyMap(); console.log('keyMap', keyMap); const localeAbsolutePath = (0, getAbsolutePath_1.getAbsolutePath)(process.cwd(), localePath); if (!fs_extra_1.default.existsSync(localeAbsolutePath)) { fs_extra_1.default.ensureFileSync(localeAbsolutePath); } if (!fs_extra_1.default.statSync(localeAbsolutePath).isFile()) { log_1.default.error(`路径${localePath}不是一个文件,请重新设置localePath参数`); process.exit(1); } (0, saveLocaleFile_1.saveLocaleFile)(keyMap, localeAbsolutePath); log_1.default.verbose(`输出中文语言包到指定位置:`, localeAbsolutePath); } function getPrettierParser(ext) { switch (ext) { case 'vue': return 'vue'; case 'ts': case 'tsx': return 'babel-ts'; default: return 'babel'; } } function getOutputPath(input, output, sourceFilePath) { let outputPath; if (output) { const filePath = sourceFilePath.replace(input + '/', ''); outputPath = (0, getAbsolutePath_1.getAbsolutePath)(process.cwd(), output, filePath); fs_extra_1.default.ensureFileSync(outputPath); } else { outputPath = (0, getAbsolutePath_1.getAbsolutePath)(process.cwd(), sourceFilePath); } return outputPath; } function formatInquirerResult(answers) { if (answers.translator === constants_1.YOUDAO) { return { translator: answers.translator, youdao: { key: answers.key, secret: answers.secret, }, }; } else if (answers.translator === constants_1.BAIDU) { return { translator: answers.translator, baidu: { key: answers.key, secret: answers.secret, }, }; } else { return { translator: answers.translator, google: { proxy: answers.proxy, }, }; } } async function getTranslationConfig() { const cachePath = (0, getAbsolutePath_1.getAbsolutePath)(__dirname, '../.cache/configCache.json'); fs_extra_1.default.ensureFileSync(cachePath); const cache = fs_extra_1.default.readFileSync(cachePath, 'utf8') || '{}'; const oldConfigCache = JSON.parse(cache); // const answers = await inquirer.prompt([ // { // type: 'list', // name: 'translator', // message: '请选择翻译接口', // default: YOUDAO, // choices: [ // { name: '有道翻译', value: YOUDAO }, // { name: '谷歌翻译', value: GOOGLE }, // { name: '百度翻译', value: BAIDU }, // ], // when(answers) { // return !answers.skipTranslate // }, // }, // { // type: 'input', // name: 'proxy', // message: '使用谷歌服务需要翻墙,请输入代理地址', // default: oldConfigCache.proxy || '', // when(answers) { // return answers.translator === GOOGLE // }, // validate(input) { // return input.length === 0 ? '代理地址不能为空' : true // }, // }, // { // type: 'input', // name: 'key', // message: '请输入有道翻译appKey', // default: oldConfigCache.key || '', // when(answers) { // return answers.translator === YOUDAO // }, // validate(input) { // return input.length === 0 ? 'appKey不能为空' : true // }, // }, // { // type: 'input', // name: 'secret', // message: '请输入有道翻译appSecret', // default: oldConfigCache.secret || '', // when(answers) { // return answers.translator === YOUDAO // }, // validate(input) { // return input.length === 0 ? 'appSecret不能为空' : true // }, // }, // { // type: 'input', // name: 'key', // message: '请输入百度翻译appId', // default: oldConfigCache.key || '', // when(answers) { // return answers.translator === BAIDU // }, // validate(input) { // return input.length === 0 ? 'appKey不能为空' : true // }, // }, // { // type: 'input', // name: 'secret', // message: '请输入百度翻译appSecret', // default: oldConfigCache.secret || '', // when(answers) { // return answers.translator === BAIDU // }, // validate(input) { // return input.length === 0 ? 'appSecret不能为空' : true // }, // }, // ]) const answers = { translator: 'youdao', key: '5b2194113e67d35a', secret: 'ZQ78pgasKncCNBjzDryKAsoeBPpd4o19', }; const newConfigCache = Object.assign(oldConfigCache, answers); fs_extra_1.default.writeFileSync(cachePath, JSON.stringify(newConfigCache), 'utf8'); const result = formatInquirerResult(answers); return result; } function formatCode(code, ext, prettierConfig) { let stylizedCode = code; if ((0, assertType_1.isObject)(prettierConfig)) { stylizedCode = prettier_1.default.format(code, { ...prettierConfig, parser: getPrettierParser(ext), }); log_1.default.verbose(`格式化代码完成`); } return stylizedCode; } async function default_1(options) { let i18nConfig = (0, initConfig_1.getI18nConfig)(options); if (!i18nConfig.skipTranslate) { const translationConfig = await getTranslationConfig(); i18nConfig = (0, merge_1.default)(i18nConfig, translationConfig); } // 全局缓存脚手架配置 stateManager_1.default.setToolConfig(i18nConfig); const { input, exclude, output, rules, localePath, locales, skipExtract, skipTranslate, adjustKeyMap, localeFileType, } = i18nConfig; log_1.default.debug(`命令行配置信息:`, i18nConfig); let oldPrimaryLang = {}; const primaryLangPath = (0, getAbsolutePath_1.getAbsolutePath)(process.cwd(), localePath); oldPrimaryLang = (0, getLang_1.default)(primaryLangPath); if (!skipExtract) { log_1.default.info('正在转换中文,请稍等...'); const sourceFilePaths = getSourceFilePaths(input, exclude); const bar = new cli_progress_1.default.SingleBar({ format: `${chalk_1.default.cyan('提取进度:')} [{bar}] {percentage}% {value}/{total}`, }, cli_progress_1.default.Presets.shades_classic); const startTime = new Date().getTime(); bar.start(sourceFilePaths.length, 0); sourceFilePaths.forEach((sourceFilePath) => { log_1.default.verbose(`正在提取文件中的中文:`, sourceFilePath); const sourceCode = fs_extra_1.default.readFileSync(sourceFilePath, 'utf8'); const ext = path_1.default.extname(sourceFilePath).replace('.', ''); collector_1.default.resetCountOfAdditions(); collector_1.default.setCurrentCollectorPath(sourceFilePath); const { code } = (0, transform_1.default)(sourceCode, ext, rules, sourceFilePath); log_1.default.verbose(`完成中文提取和语法转换:`, sourceFilePath); // 只有文件提取过中文,或文件规则forceImport为true时,才重新写入文件 if (collector_1.default.getCountOfAdditions() > 0 || rules[ext].forceImport) { const stylizedCode = formatCode(code, ext, i18nConfig.prettier); const outputPath = getOutputPath(input, output, sourceFilePath); fs_extra_1.default.writeFileSync(outputPath, stylizedCode, 'utf8'); log_1.default.verbose(`生成文件:`, outputPath); } // 自定义当前文件的keyMap if (adjustKeyMap) { const newkeyMap = adjustKeyMap((0, cloneDeep_1.default)(collector_1.default.getKeyMap()), collector_1.default.getCurrentFileKeyMap(), sourceFilePath); collector_1.default.setKeyMap(newkeyMap); collector_1.default.resetCurrentFileKeyMap(); } bar.increment(); }); // 增量转换时,保留之前的提取的中文结果 if (i18nConfig.incremental) { const newkeyMap = (0, merge_1.default)(oldPrimaryLang, collector_1.default.getKeyMap()); collector_1.default.setKeyMap(newkeyMap); } const extName = path_1.default.extname(localePath); const savePath = localePath.replace(extName, `.${localeFileType}`); console.log('savePath', savePath); saveLocale(savePath); bar.stop(); const endTime = new Date().getTime(); log_1.default.info(`耗时${((endTime - startTime) / 1000).toFixed(2)}s`); } console.log(''); // 空一行 console.log('localePath', localePath); if (!skipTranslate) { await (0, translate_1.default)(localePath, locales, oldPrimaryLang, { translator: i18nConfig.translator, google: i18nConfig.google, youdao: i18nConfig.youdao, baidu: i18nConfig.baidu, }); } log_1.default.success('转换完毕!'); if (i18nConfig.exportExcel) { log_1.default.info(`正在导出excel翻译文件`); (0, exportExcel_1.exportFieldExcel)(); (0, exportExcel_1.default)(); log_1.default.success(`导出完毕!`); } } exports.default = default_1;