UNPKG

@voerkai18n/cli

Version:

命令行工具,用来初始化/提取/编译/自动翻译等工具链

132 lines (109 loc) 4.44 kB
const { t } = require("../../i18n"); const glob = require("fast-glob"); const { extractMessages, extractParagraphs } = require("@voerkai18n/utils"); const logsets = require("logsets"); const path = require("path"); const { readFile } = require("flex-tools/fs/nodefs"); const { getProjectContext } = require("@voerkai18n/utils"); const { updateMessages, formatMessages, getMessageIds } = require("./messages"); const { updateParagraphs } = require("./paragraphs") /** * * @param {*} settings * @returns */ /** * 异步函数 `extractTexts` 用于从指定文件中提取需要翻译的文本。 * * @param {Object} ctx - 设置对象,包含提取文本的相关配置。 * @param {string} ctx.langDir - 语言目录的路径。 * @param {string} ctx.langRelDir - 相对于项目根目录的语言目录路径。 * @param {Array<string>} [ctx.patterns] - 可选的文件匹配模式数组,用于扩展默认的匹配规则。 * @returns {Promise<{ text,rang,args,options,file }>} 返回一个包含提取出的翻译文本的数组。 * * 该函数首先定义了一组默认的文件匹配模式,然后合并了用户自定义的模式。 * 使用 fastGlob 函数查找匹配的文件,并逐个读取文件内容。 * 对每个文件的内容调用 extractMessages 函数来提取翻译文本。 * 提取过程中会记录任务进度和结果。 * 最终返回所有提取出的翻译文本的数组。 */ async function scanSourceFiles(ctx) { const { langRelDir, patterns, tasks } = ctx; tasks.addGroup(t("提取参数:")); tasks.create(t("更新模式: {}"), ctx.mode); tasks.create(t("提取方式: {}"), ctx.regex ? "regex" : "ast"); tasks.create(t("提取范围: {}"), patterns.join(", ")); tasks.create(t("通过{}参数增加文件匹配规则"), "--patterns"); tasks.create( t("您可以通过修改{}文件的{}参数来调整提取范围"), `${langRelDir}/settings.json`, "patterns" ); const files = await glob(patterns, { cwd: process.cwd(), absolute: true, }); const messages = []; const paragraphs = []; let msgCount = 0, paragraphCount = 0; tasks.addGroup(t("开始提取:")); for (let file of files) { try { const relFile = path.relative(process.cwd(), file); const codeLang = path.extname(file).slice(1); tasks.add(t("提取 {}"), relFile); const code = await readFile(file, { encoding: "utf-8" }); // 提取文本 const msgs = await extractMessages(code, { namespaces: ctx.namespaces, file : file, language : codeLang || "ts", extractor : ctx.ast ? "ast" : "regex", }); if (msgs && msgs.length > 0) messages.push(...msgs); // 提取段落 const pghs = await extractParagraphs(code, { file : file }) if (pghs && pghs.length > 0) paragraphs.push(...pghs); if (msgs.length === 0 && pghs.length === 0) { tasks.skip(); } else { tasks.complete([ t("文本{}, 段落{}"), msgs.length, pghs.length ]); } msgCount += msgs.length; paragraphCount += pghs.length; } catch (e) { tasks.error(e); } } tasks.addGroup(t("提取结果:")); tasks.addMemo(t("名称空间:{}"),[ "default", ...Object.keys(ctx.namespaces || [])].join(",") ); tasks.addMemo(t("共提取{}个文本"), msgCount); tasks.addMemo(t("共提取{}个段落"), paragraphCount); return [ messages, paragraphs ] } async function extractor(options) { const ctx = await getProjectContext(options); const tasks = logsets.tasklist({ width: 88, grouped: true }); ctx.tasks = tasks; await getMessageIds(ctx); // 1. 提取文本 const [ messages, paragraphs ] = await scanSourceFiles(ctx); // 2. 将提取到的文本进行预处理:按名称空间分组 const formattedMessages = formatMessages(messages, ctx); // 3. 保存文本 await updateMessages(formattedMessages, ctx); // 4. 保存段落 await updateParagraphs(paragraphs, ctx); tasks.addGroup(t("下一步:")); tasks.addMemo(t("翻译{}文件"), "translates/messages/*.json"); tasks.addMemo(t("翻译段落{}文件"), "translates/paragraphs/*.json"); tasks.addMemo(t("运行<{}>编译语言包"), "voerkai18n compile"); tasks.addMemo(t("在源码中从<{}>导入编译后的语言包"), ctx.langRelDir); tasks.done(); } module.exports = extractor;