i18n-auto-react
Version:
基于百度翻译API服务的自动翻译插件
143 lines (140 loc) • 4.85 kB
JavaScript
import fs from 'fs';
import path from 'path';
import { l as logger } from './log.js';
import ignore from 'ignore';
import prettier from 'prettier';
import { parse } from '@babel/parser';
import t from '@babel/types';
import crypto from 'crypto';
import _traverse from '@babel/traverse';
import { cosmiconfigSync } from 'cosmiconfig';
const traverse = getDefault(_traverse);
const tplRegexp = /(?<!\\)\$\{([\s\S]+?)\}/g;
function getDefault(data) {
return typeof data === 'function' ? data : data.default;
}
const explorerSync = cosmiconfigSync('i18n');
// 获取配置文件
const getConfiguration = () => {
const searchedFor = explorerSync.search(process.cwd());
if (!searchedFor?.config) {
logger.error(`配置文件不存在,请执行 npx i18n init`);
process.exit(0);
}
let config = searchedFor.config;
if (config.__esModule && config['default']) {
config = config['default'];
}
config.__rootPath = process.cwd();
config.include = Array.isArray(config.include)
? config.include
: [config.include];
config.exclude = Array.isArray(config.exclude)
? config.exclude
: [config.exclude];
return config;
};
// 创建文件夹
const mkdir = (dir) => {
if (!fs.existsSync(dir)) {
mkdir(path.dirname(dir));
fs.mkdirSync(dir);
}
};
// 创建文件
const createLanguageFile = async (filePath, template, data = {}) => {
mkdir(path.dirname(filePath));
const fileName = path.basename(filePath, path.extname(filePath));
const file = template
.replace('$name', `'${fileName}'`)
.replace('$data', () => JSON.stringify(data));
let code = await prettierJs(file);
fs.writeFileSync(filePath, code, { encoding: 'utf-8' });
};
async function prettierJs(code) {
const filePath = await prettier.resolveConfigFile();
const prettierConfig = (await prettier.resolveConfig(filePath)) || {};
return prettier.format(code, { parser: 'babel-ts', ...prettierConfig });
}
// 获取需要翻译的列表
function scanFile(dirPath, config, fn) {
const dirOrFiles = fs.readdirSync(dirPath, { encoding: 'utf8' });
let fileRegex = config.test;
if (typeof fileRegex === 'string')
fileRegex = new RegExp(fileRegex);
const ig = ignore().add(config.exclude);
const includes = ignore().add(config.include);
for (let item of dirOrFiles) {
const relativePath = path.relative(config.__rootPath, path.resolve(dirPath, item));
if (!ig.ignores(relativePath) || includes.ignores(relativePath)) {
const filePath = path.resolve(dirPath, item);
if (fs.lstatSync(filePath).isFile()) {
if (fileRegex.test(item))
fn(filePath);
}
else {
scanFile(filePath, config, fn);
}
}
}
}
function babelParse(code) {
try {
const ast = parse(code, {
sourceType: 'module',
errorRecovery: true,
plugins: ['jsx', 'typescript', 'decorators-legacy'].filter((n) => n)
});
if (ast.errors && ast.errors.length > 0) {
ast.errors.forEach((err) => logger.error(err));
return;
}
return ast;
}
catch (error) {
logger.error(error);
}
}
function isCallExpression(path, importInfo) {
let { imported, local } = importInfo;
if (t.isCallExpression(path.parent)) {
let name = path.parent.callee.name;
if (name === imported || local === name)
return true;
}
return false;
}
function md5Hash(str, secretKey) {
let md5;
{
md5 = crypto.createHash('md5');
}
return md5.update(str).digest('hex');
}
function sleep(ms) {
return new Promise((resolve) => setTimeout(resolve, ms));
}
function readLanguages(name, config, isExit = false) {
const { output } = config;
const { dir: outputPath, ext = 'js' } = output;
let curFilePath = path.resolve(config.__rootPath, outputPath, `${name}.${ext}`);
if (!fs.existsSync(curFilePath) && isExit) {
logger.error(`${curFilePath} 文件不存在!`);
// process.exit(0)
}
const file = fs.readFileSync(curFilePath, { encoding: 'utf-8' });
const ast = parse(file, {
sourceType: 'module',
plugins: ['typescript']
});
const res = {};
traverse(ast, {
ObjectProperty(path) {
const key = path.node.key.value || path.node.key.name;
const value = path.node.value.value || path.node.value.name;
res[key] = value || '';
}
});
return res;
}
export { sleep as a, babelParse as b, createLanguageFile as c, getConfiguration as d, getDefault as g, isCallExpression as i, md5Hash as m, prettierJs as p, readLanguages as r, scanFile as s, tplRegexp as t };