UNPKG

@l10nmonster/cli

Version:

Continuous localization for the rest of us

690 lines (675 loc) 31.4 kB
var __create = Object.create; var __defProp = Object.defineProperty; var __getOwnPropDesc = Object.getOwnPropertyDescriptor; var __getOwnPropNames = Object.getOwnPropertyNames; var __getProtoOf = Object.getPrototypeOf; var __hasOwnProp = Object.prototype.hasOwnProperty; var __export = (target, all) => { for (var name in all) __defProp(target, name, { get: all[name], enumerable: true }); }; var __copyProps = (to, from, except, desc) => { if (from && typeof from === "object" || typeof from === "function") { for (let key of __getOwnPropNames(from)) if (!__hasOwnProp.call(to, key) && key !== except) __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); } return to; }; var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps( // If the importer is in node compatibility mode or this is not an ESM // file that has been converted to a CommonJS file using a Babel- // compatible transform (i.e. "__esModule" has not been set), then set // "default" to the CommonJS "module.exports" for node compatibility. isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target, mod )); var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); // l10nCommands.js var l10nCommands_exports = {}; __export(l10nCommands_exports, { builtInCmds: () => builtInCmds, runL10nMonster: () => runL10nMonster }); module.exports = __toCommonJS(l10nCommands_exports); var path = __toESM(require("path"), 1); var util = __toESM(require("node:util"), 1); var winston = __toESM(require("winston"), 1); var import_core8 = require("@l10nmonster/core"); // analyze.js var import_fs = require("fs"); var import_core = require("@l10nmonster/core"); // shared.js var import_helpers = require("@l10nmonster/helpers"); var consoleColor = { red: "\x1B[31m", yellow: "\x1B[33m", green: "\x1B[32m", reset: "\x1B[0m", dim: "\x1B[2m", bright: "\x1B[1m" }; function printContent(contentPairs) { for (const [prj, uc] of Object.entries(contentPairs)) { console.log(`Project: ${prj}`); for (const [rid, content] of Object.entries(uc)) { console.log(` \u2023 ${rid}`); for (const [sid, str] of Object.entries(content)) { console.log(` \u2219 ${consoleColor.dim}${sid}:${consoleColor.reset} ${str.color}${str.confidence ? `[${str.confidence.toFixed(2)}] ` : ""}${sid === str.txt ? "\u2263" : str.txt}${consoleColor.reset}`); } } } } function printRequest(req) { const untranslatedContent = {}; for (const tu of req.tus) { const prj = tu.prj || "default"; untranslatedContent[prj] ??= {}; untranslatedContent[prj][tu.rid] ??= {}; const confidence = 1; untranslatedContent[prj][tu.rid][tu.sid] = { confidence, txt: import_helpers.utils.flattenNormalizedSourceV1(tu.nsrc)[0], // eslint-disable-next-line no-nested-ternary color: confidence <= 0.1 ? consoleColor.red : confidence <= 0.2 ? consoleColor.yellow : consoleColor.green }; } printContent(untranslatedContent); } function printResponse(req, res, showPair) { const translations = res.tus.reduce((p, c) => (p[c.guid] = c.ntgt, p), {}); let matchedTranslations = 0; const translatedContent = {}; for (const tu of req.tus) { const prj = tu.prj || "default"; translatedContent[prj] ??= {}; translatedContent[prj][tu.rid] ??= {}; if (translations[tu.guid]) { const key = showPair ? import_helpers.utils.flattenNormalizedSourceV1(tu.nsrc)[0] : tu.sid; translatedContent[prj][tu.rid][key] = { txt: import_helpers.utils.flattenNormalizedSourceV1(translations[tu.guid])[0], color: consoleColor.green }; matchedTranslations++; } } if (req.tus.length !== res.tus.length || req.tus.length !== matchedTranslations) { console.log(`${consoleColor.red}${req.tus.length} TU in request, ${res.tus.length} TU in response, ${matchedTranslations} matching translations${consoleColor.reset}`); } printContent(translatedContent); } // analyze.js var analyze = class { static help = { description: "content reports and validation.", arguments: [ ["[analyzer]", "name of the analyzer to run"], ["[params...]", "optional parameters to the analyzer"] ], options: [ ["-l, --lang <language>", "target language to analyze (if TM analyzer)"], ["--filter <filter>", "use the specified tu filter"], ["--output <filename>", "filename to write the analysis to)"] ] }; static async action(monsterManager, options) { try { if (options.analyzer) { const analysis = await (0, import_core.analyzeCmd)(monsterManager, options.analyzer, options.params, options.lang, options.filter); const header = analysis.head; if (options.output) { const rows = header ? [header, ...analysis.body].map((row) => row.join(",")) : analysis.body; rows.push("\n"); (0, import_fs.writeFileSync)(options.output, rows.join("\n")); } else { if (header) { const groups = analysis.groupBy; let previousGroup; for (const row of analysis.body) { const columns = row.map((col, idx) => [col, idx]); if (groups) { const currentGroup = columns.filter(([col, idx]) => groups.includes(header[idx])); const currentGroupSmashed = currentGroup.map(([col, idx]) => col).join("|"); if (currentGroupSmashed !== previousGroup) { previousGroup = currentGroupSmashed; console.log(currentGroup.map(([col, idx]) => `${consoleColor.dim}${header[idx]}: ${consoleColor.reset}${consoleColor.bright}${col}${consoleColor.reset}`).join(" ")); } } const currentData = columns.filter(([col, idx]) => (!groups || !groups.includes(header[idx])) && col !== null && col !== void 0); console.log(currentData.map(([col, idx]) => ` ${consoleColor.dim}${header[idx]}: ${consoleColor.reset}${col}`).join("")); } } else { console.log(analysis.body.join("\n")); } } } else { console.log("Available analyzers:"); for (const [name, analyzer] of Object.entries(monsterManager.analyzers)) { console.log(` ${typeof analyzer.prototype.processSegment === "function" ? "(src)" : " (tu)"} ${consoleColor.bright}${name} ${analyzer.helpParams ?? ""}${consoleColor.reset} ${analyzer.help}`); } } } catch (e) { console.error(`Failed to analyze: ${e.stack || e}`); } } }; // job.js var import_core2 = require("@l10nmonster/core"); var job = class { static help = { description: "show request/response/pairs of a job or push/delete jobs.", arguments: [ ["<operation>", "operation to perform on job", ["req", "res", "pairs", "push", "delete"]] ], requiredOptions: [ ["-g, --jobGuid <guid>", "guid of job"] ] }; static async action(monsterManager, options) { const op = options.operation; const jobGuid = options.jobGuid; if (op === "req") { const req = await monsterManager.jobStore.getJobRequest(jobGuid); if (req) { console.log(`Showing request of job ${jobGuid} ${req.sourceLang} -> ${req.targetLang}`); printRequest(req); } else { console.error("Could not fetch the specified job"); } } else if (op === "res") { const req = await monsterManager.jobStore.getJobRequest(jobGuid); const res = await monsterManager.jobStore.getJob(jobGuid); if (req && res) { console.log(`Showing response of job ${jobGuid} ${req.sourceLang} -> ${req.targetLang} (${res.translationProvider}) ${res.status}`); printResponse(req, res); } else { console.error("Could not fetch the specified job"); } } else if (op === "pairs") { const req = await monsterManager.jobStore.getJobRequest(jobGuid); const res = await monsterManager.jobStore.getJob(jobGuid); if (req && res) { console.log(`Showing source-target pairs of job ${jobGuid} ${req.sourceLang} -> ${req.targetLang} (${res.translationProvider}) ${res.status}`); printResponse(req, res, true); } else { console.error("Could not fetch the specified job"); } } else if (op === "push") { console.log(`Pushing job ${jobGuid}...`); try { const pushResponse = await (0, import_core2.jobPushCmd)(monsterManager, jobGuid); console.log(`${pushResponse.num.toLocaleString()} translations units requested -> status: ${pushResponse.status}`); } catch (e) { console.error(`Failed to push job: ${e.stack ?? e}`); } } else if (op === "delete") { console.log(`Deleting job ${jobGuid}...`); try { const res = await monsterManager.jobStore.getJob(jobGuid); if (res) { console.error(`Can only delete blocked/failed jobs. This job has status: ${res.status}`); } else { await monsterManager.jobStore.deleteJobRequest(jobGuid); } } catch (e) { console.error(`Failed to push job: ${e.stack ?? e}`); } } else { console.error(`Invalid operation: ${op}`); } } }; // jobs.js var import_core3 = require("@l10nmonster/core"); var jobs = class { static help = { description: "unfinished jobs status.", options: [ ["-l, --lang <language>", "only get jobs for the target language"] ] }; static async action(monsterManager, options) { const limitToLang = options.lang; const jobs2 = await (0, import_core3.jobsCmd)(monsterManager, { limitToLang }); for (const [lang, jobManifests] of Object.entries(jobs2)) { if (jobManifests.length > 0) { console.log(`Target language ${consoleColor.bright}${lang}${consoleColor.reset}:`); for (const mf of jobManifests) { const numUnits = mf.inflight?.length ?? mf.tus?.length ?? 0; const lastModified = new Date(mf.updatedAt); console.log(` Job ${mf.jobGuid}: status ${consoleColor.bright}${mf.status}${consoleColor.reset} ${numUnits.toLocaleString()} ${mf.sourceLang} units with ${mf.translationProvider} - ${lastModified.toDateString()} ${lastModified.toLocaleTimeString()}`); } } } } }; // monster.js var monster = class { static help = { description: "test configuration and warm up caches", options: [ ["-l, --lang <language>", "target languages to warm up"] ] }; static async action(monsterManager, options) { console.log( " _.------. .----.__\n / \\_. ._ /---.__ \\\n | O O |\\\\___ //| / `\\ |\n | .vvvvv. | ) `(/ | | o o \\|\n / | | |/ \\ | /| ./| .vvvvv. |\\\n / `^^^^^' / _ _ `|_ || / /| | | | \\\n ./ /| | O) O ) \\|| //' | `^vvvv' |/\\\\\n / / | \\ / | | ~ \\ | \\\\\n \\ / | / \\ Y /' | \\ | | ~\n `' | _ | `._/' | | \\ 7 /\n _.-'-' `-'-'| |`-._/ / \\ _ / . |\n __.-' \\ \\ . / \\_. \\ -|_/\\/ `--.|_\n --' \\ \\ | / | | `-\n \\uU \\UU/ | / :F_P:" ); console.time("Initialization time"); const resourceHandles = await monsterManager.rm.getResourceHandles(); const targetLangs = monsterManager.getTargetLangs(options.lang); console.log(`Resources: ${resourceHandles.length}`); console.log(`Possible languages: ${targetLangs.join(", ")}`); console.log("Translation Memories:"); const availableLangPairs = (await monsterManager.jobStore.getAvailableLangPairs()).sort(); for (const [sourceLang, targetLang] of availableLangPairs) { const tm = await monsterManager.tmm.getTM(sourceLang, targetLang); console.log(` - ${sourceLang} / ${targetLang} (${tm.guids.length} entries)`); } console.timeEnd("Initialization time"); const printCapabilities = (cap) => `${Object.entries(cap).map(([cmd, available]) => `${available ? consoleColor.green : consoleColor.red}${cmd}`).join(" ")}${consoleColor.reset}`; console.log(` Your config allows the following commands: ${printCapabilities(monsterManager.capabilities)}`); if (Object.keys(monsterManager.capabilitiesByChannel).length > 1) { Object.entries(monsterManager.capabilitiesByChannel).forEach(([channel, cap]) => console.log(` - ${channel}: ${printCapabilities(cap)}`)); } } }; // pull.js var import_core4 = require("@l10nmonster/core"); var pull = class { static help = { description: "receive outstanding translation jobs.", options: [ ["--partial", "commit partial deliveries"], ["-l, --lang <language>", "only get jobs for the target language"] ] }; static async action(monsterManager, options) { const limitToLang = options.lang; const partial = options.partial; console.log(`Pulling pending translations...`); const stats = await (0, import_core4.pullCmd)(monsterManager, { limitToLang, partial }); console.log(`Checked ${stats.numPendingJobs.toLocaleString()} pending jobs, ${stats.doneJobs.toLocaleString()} done jobs, ${stats.newPendingJobs.toLocaleString()} pending jobs created, ${stats.translatedStrings.toLocaleString()} translated strings found`); } }; // push.js var import_core5 = require("@l10nmonster/core"); var push = class { static help = { description: "push source content upstream (send to translation).", options: [ ["-l, --lang <language>", "target language to push"], ["--filter <filter>", "use the specified tu filter"], ["--driver <untranslated|source|tm|job:jobGuid>", "driver of translations need to be pushed (default: untranslated)"], ["--leverage", "eliminate internal repetitions from untranslated driver"], ["--refresh", "refresh existing translations without requesting new ones"], ["--provider <name,...>", "use the specified translation providers"], ["--instructions <instructions>", "send the specified translation instructions"], ["--dryrun", "simulate translating and compare with existing translations"] ] }; static async action(monsterManager, options) { const limitToLang = options.lang; const tuFilter = options.filter; const driverOption = options.driver ?? "untranslated"; const driver = {}; if (driverOption.indexOf("job:") === 0) { driver.jobGuid = driverOption.split(":")[1]; } else if (["untranslated", "source", "tm"].includes(driverOption)) { driver[driverOption] = true; } else { throw `invalid ${driverOption} driver`; } const refresh = options.refresh; const leverage = options.leverage; const dryRun = options.dryrun; const instructions = options.instructions; console.log(`Pushing content upstream...${dryRun ? " (dry run)" : ""}`); try { if (dryRun) { const status2 = await (0, import_core5.pushCmd)(monsterManager, { limitToLang, tuFilter, driver, refresh, leverage, dryRun, instructions }); for (const langStatus of status2) { console.log(` Dry run of ${langStatus.sourceLang} -> ${langStatus.targetLang} push:`); printRequest(langStatus); } } else { const providerList = (options.provider ?? "default").split(","); for (const provider of providerList) { const translationProviderName = provider.toLowerCase() === "default" ? void 0 : provider; const status2 = await (0, import_core5.pushCmd)(monsterManager, { limitToLang, tuFilter, driver, refresh, translationProviderName, leverage, dryRun, instructions }); if (status2.length > 0) { for (const ls of status2) { if (ls.minimumJobSize === void 0) { console.log(`job ${ls.jobGuid} with ${ls.num.toLocaleString()} translations received for language ${consoleColor.bright}${ls.targetLang}${consoleColor.reset} from provider ${consoleColor.bright}${ls.provider}${consoleColor.reset} -> status: ${consoleColor.bright}${ls.status}${consoleColor.reset}`); } else { console.log(`${ls.num.toLocaleString()} translations units for language ${ls.targetLang} not sent to provider ${consoleColor.bright}${ls.provider}${consoleColor.reset} because you need at least ${ls.minimumJobSize}`); } } } else { console.log("Nothing to push!"); break; } } } } catch (e) { console.error(`Failed to push: ${e.stack || e}`); } } }; // snap.js var import_core6 = require("@l10nmonster/core"); var snap = class { static help = { description: "commits a snapshot of sources in normalized format.", options: [ ["--maxSegments <number>", "threshold to break up snapshots into chunks"] ] }; static async action(monsterManager, options) { console.log(`Taking a snapshot of sources...`); const numSources = await (0, import_core6.snapCmd)(monsterManager, options); console.log(`${numSources} sources committed`); } }; // status.js var import_fs2 = require("fs"); var import_core7 = require("@l10nmonster/core"); function computeTotals(totals, partial) { for (const [k, v] of Object.entries(partial)) { if (typeof v === "object") { totals[k] ??= {}; computeTotals(totals[k], v); } else { totals[k] ??= 0; totals[k] += v; } } } function printLeverage(leverage, detailed) { const totalStrings = leverage.translated + leverage.pending + leverage.untranslated + leverage.internalRepetitions; detailed && console.log(` - total strings for target language: ${totalStrings.toLocaleString()} (${leverage.translatedWords.toLocaleString()} translated words)`); for (const [q, num] of Object.entries(leverage.translatedByQ).sort((a, b) => b[1] - a[1])) { detailed && console.log(` - translated strings @ quality ${q}: ${num.toLocaleString()}`); } leverage.pending && console.log(` - strings pending translation: ${leverage.pending.toLocaleString()} (${leverage.pendingWords.toLocaleString()} words)`); leverage.untranslated && console.log(` - untranslated unique strings: ${leverage.untranslated.toLocaleString()} (${leverage.untranslatedChars.toLocaleString()} chars - ${leverage.untranslatedWords.toLocaleString()} words - $${(leverage.untranslatedWords * 0.2).toFixed(2)})`); leverage.internalRepetitions && console.log(` - untranslated repeated strings: ${leverage.internalRepetitions.toLocaleString()} (${leverage.internalRepetitionWords.toLocaleString()} words)`); } var status = class { static help = { description: "translation status of content.", options: [ ["-l, --lang <language>", "only get status of target language"], ["-a, --all", "show information for all projects, not just untranslated ones"], ["--output <filename>", "write status to the specified file"] ] }; static async action(monsterManager, options) { const limitToLang = options.lang; const all = Boolean(options.all); const output = options.output; const status2 = await (0, import_core7.statusCmd)(monsterManager, { limitToLang }); if (output) { (0, import_fs2.writeFileSync)(output, JSON.stringify(status2, null, " "), "utf8"); } else { console.log(`${consoleColor.reset}${status2.numSources.toLocaleString()} translatable resources`); for (const [lang, langStatus] of Object.entries(status2.lang)) { console.log(` ${consoleColor.bright}Language ${lang}${consoleColor.reset} (minimum quality: ${langStatus.leverage.minimumQuality})`); const totals = {}; const prjLeverage = Object.entries(langStatus.leverage.prjLeverage).sort((a, b) => a[0] > b[0] ? 1 : -1); for (const [prj, leverage] of prjLeverage) { computeTotals(totals, leverage); const untranslated = leverage.pending + leverage.untranslated + leverage.internalRepetitions; if (leverage.translated + untranslated > 0) { (all || untranslated > 0) && console.log(` Project: ${consoleColor.bright}${prj}${consoleColor.reset}`); printLeverage(leverage, all); } } if (prjLeverage.length > 1) { console.log(` Total:`); printLeverage(totals, true); } } } return status2; } }; // tmexport.js var fs = __toESM(require("fs/promises"), 1); var import_helpers2 = require("@l10nmonster/helpers"); var tmexport = class { static help = { description: "export translation memory as a json job.", options: [ ["-l, --lang <language>", "target language to export"], ["--filter <filter>", "use the specified tu filter"], ["--prjsplit", "split target files by project"] ] }; static async action(monsterManager, options) { const prjsplit = options.prjsplit; console.log(`Exporting TM for ${consoleColor.bright}${options.lang ? options.lang : "all languages"}${consoleColor.reset}...`); let tuFilterFunction; if (options.filter) { tuFilterFunction = monsterManager.tuFilters[import_helpers2.utils.fixCaseInsensitiveKey(monsterManager.tuFilters, options.filter)]; if (!tuFilterFunction) { throw `Couldn't find ${options.filter} tu filter`; } } const files = []; const desiredTargetLangs = new Set(monsterManager.getTargetLangs(options.lang)); const availableLangPairs = (await monsterManager.jobStore.getAvailableLangPairs()).filter((pair) => desiredTargetLangs.has(pair[1])); for (const [sourceLang, targetLang] of availableLangPairs) { const tusByPrj = {}; const tm = await monsterManager.tmm.getTM(sourceLang, targetLang); tm.guids.forEach((guid) => { const tu = tm.getEntryByGuid(guid); if (!tuFilterFunction || tuFilterFunction(tu)) { if (!prjsplit || !l10nmonster.prj || l10nmonster.prj.includes(tu.prj)) { const prj = prjsplit && tu?.prj || "default"; tusByPrj[prj] ??= []; tusByPrj[prj].push(tu); } } }); for (const [prj, tus] of Object.entries(tusByPrj)) { const jobGuid = `tmexport_${prjsplit ? `${prj}_` : ""}${sourceLang}_${targetLang}`; const jobReq = { sourceLang, targetLang, jobGuid, updatedAt: (l10nmonster.regression ? /* @__PURE__ */ new Date("2022-05-30T00:00:00.000Z") : /* @__PURE__ */ new Date()).toISOString(), status: "created", tus: [] }; const jobRes = { ...jobReq, translationProvider: "TMExport", status: "done", tus: [] }; for (const tu of tus) { try { jobReq.tus.push(l10nmonster.TU.asSource(tu)); } catch (e) { l10nmonster.logger.info(e.stack ?? e); } if (tu.inflight) { l10nmonster.logger.info(`Warning: in-flight translation unit ${tu.guid} can't be exported`); } else { try { jobRes.tus.push(l10nmonster.TU.asTarget(tu)); } catch (e) { l10nmonster.logger.info(e.stack ?? e); } } } const filename = `TMExport_${sourceLang}_${targetLang}_job_${jobGuid}`; await fs.writeFile(`${filename}-req.json`, JSON.stringify(jobReq, null, " "), "utf8"); await fs.writeFile(`${filename}-done.json`, JSON.stringify(jobRes, null, " "), "utf8"); files.push(filename); } } console.log(`Generated files: ${files.join(", ")}`); } }; // translate.js function computeDelta(currentTranslations, newTranslations) { const delta = []; const newGstrMap = Object.fromEntries(newTranslations.segments.map((seg) => [seg.sid, seg.gstr])); const seenIds = /* @__PURE__ */ new Set(); for (const seg of currentTranslations.segments) { seenIds.add(seg.sid); const newGstr = newGstrMap[seg.sid]; if (seg.gstr !== newGstr) { delta.push({ id: seg.sid, l: seg.gstr, r: newGstr }); } } newTranslations.segments.filter((seg) => !seenIds.has(seg.sid)).forEach((seg) => delta.push({ id: seg.sid, r: seg.gstr })); return delta; } async function compareToExisting(monsterManager, resHandle, targetLang, translatedRes) { let currentTranslations; let delta; const channel = monsterManager.rm.getChannel(resHandle.channel); try { currentTranslations = await channel.getExistingTranslatedResource(resHandle, targetLang); if (translatedRes) { const newTranslations = await channel.makeResourceHandleFromObject(resHandle).loadResourceFromRaw(translatedRes, { isSource: false }); delta = computeDelta(currentTranslations, newTranslations); } } catch (e) { l10nmonster.logger.verbose(`Couldn't fetch ${targetLang} resource for ${resHandle.channel}:${resHandle.id}: ${e.stack ?? e}`); } const bundleChanges = currentTranslations ? translatedRes ? delta.length > 0 ? "changed" : "unchanged" : "deleted" : translatedRes ? "new" : "void"; return [bundleChanges, delta]; } function printChanges(resHandle, targetLang, bundleChanges, delta) { if (bundleChanges === "changed") { console.log(` ${consoleColor.yellow}Changed translated bundle ${resHandle.channel}:${resHandle.id} for ${targetLang}${consoleColor.reset}`); for (const change of delta) { change.l !== void 0 && console.log(`${consoleColor.red}- ${change.id}: ${change.l}${consoleColor.reset}`); change.r !== void 0 && console.log(`${consoleColor.green}+ ${change.id}: ${change.r}${consoleColor.reset}`); } } else if (bundleChanges === "new") { console.log(` ${consoleColor.green}New translated bundle ${resHandle.channel}:${resHandle.id} for ${targetLang}${consoleColor.reset}`); } else if (bundleChanges === "deleted") { console.log(` ${consoleColor.green}Deleted translated bundle ${resHandle.channel}:${resHandle.id} for ${targetLang}${consoleColor.reset}`); } } function printSummary(response) { console.log("Translation summary:"); for (const [lang, langStatus] of Object.entries(response.lang)) { const summary = {}; for (const resourceStatus of langStatus.resourceStatus) { summary[resourceStatus.status] = (summary[resourceStatus.status] ?? 0) + 1; } console.log(` - ${lang}: ${Object.entries(summary).sort().map(([k, v]) => `${k}(${v})`).join(", ")}`); } } var translate = class { static help = { description: "generate translated resources based on latest source and translations.", arguments: [ ["[mode]", "commit all/changed/none of the translations", ["all", "delta", "dryrun"]] ], options: [ ["-l, --lang <language>", "target language to translate"] ] }; static async action(monsterManager, options) { const mode = (options.mode ?? "all").toLowerCase(); console.log(`Generating translated resources for ${consoleColor.bright}${options.lang ? options.lang : "all languages"}${consoleColor.reset}... (${mode} mode)`); const response = { lang: {} }; const targetLangs = monsterManager.getTargetLangs(options.lang); const allResources = await monsterManager.rm.getAllResources({ keepRaw: true }); for await (const resHandle of allResources) { for (const targetLang of targetLangs) { if (resHandle.targetLangs.includes(targetLang) && (l10nmonster.prj === void 0 || l10nmonster.prj.includes(resHandle.prj))) { const resourceStatus = { id: resHandle.id }; const tm = await monsterManager.tmm.getTM(resHandle.sourceLang, targetLang); const translatedRes = await resHandle.generateTranslatedRawResource(tm); let bundleChanges, delta; if (mode === "delta" || mode === "dryrun") { [bundleChanges, delta] = await compareToExisting(monsterManager, resHandle, targetLang, translatedRes); resourceStatus.status = bundleChanges; resourceStatus.delta = delta; } if (mode === "dryrun") { printChanges(resHandle, targetLang, bundleChanges, delta); } else if (mode === "all" || bundleChanges === "changed" || bundleChanges === "new" || bundleChanges === "deleted") { const translatedResourceId = await monsterManager.rm.getChannel(resHandle.channel).commitTranslatedResource(targetLang, resHandle.id, translatedRes); resourceStatus.status = translatedRes === null ? "deleted" : "generated"; resourceStatus.translatedId = translatedResourceId; l10nmonster.logger.verbose(`Committed translated resource: ${translatedResourceId}`); } else { l10nmonster.logger.verbose(`Delta mode skipped translation of bundle ${resHandle.channel}:${resHandle.id} for ${targetLang}`); resourceStatus.status = "skipped"; } response.lang[targetLang] ??= { resourceStatus: [] }; response.lang[targetLang].resourceStatus.push(resourceStatus); } } } printSummary(response); return response; } }; // l10nCommands.js function createLogger2(verboseOption) { const verboseLevel = verboseOption === void 0 || verboseOption === 0 ? "error" : ( // eslint-disable-next-line no-nested-ternary verboseOption === 1 ? "warn" : verboseOption === true || verboseOption === 2 ? "info" : "verbose" ); return winston.createLogger({ level: verboseLevel, transports: [ new winston.transports.Console({ format: winston.format.combine( winston.format.ms(), winston.format.timestamp(), winston.format.printf(({ level, message, timestamp, ms }) => `${consoleColor.green}${timestamp.substr(11, 12)} (${ms}) [${Math.round(process.memoryUsage().heapUsed / 1024 / 1024)}MB] ${level}: ${typeof message === "string" ? message : util.inspect(message)}${consoleColor.reset}`) ) }) ] }); } function createHandler(mm, globalOptions, action) { return (opts) => action(mm, { ...globalOptions, ...opts }); } var builtInCmds = [analyze, job, jobs, monster, pull, push, snap, status, tmexport, translate]; async function runL10nMonster(relativePath, globalOptions, cb) { const configPath = path.resolve(".", relativePath); global.l10nmonster ??= {}; l10nmonster.logger = createLogger2(globalOptions.verbose); l10nmonster.env = process.env; const mm = await (0, import_core8.createMonsterManager)(configPath, globalOptions); const l10n = { withMonsterManager: (cb2) => cb2(mm) }; [...builtInCmds, ...mm.extensionCmds].forEach((Cmd) => l10n[Cmd.name] = createHandler(mm, globalOptions, Cmd.action)); let response; try { response = await cb(l10n); } catch (e) { response = { error: e.stack ?? e }; } finally { mm && await mm.shutdown(); } if (response?.error) { throw response.error; } return response; } // Annotate the CommonJS export names for ESM import in node: 0 && (module.exports = { builtInCmds, runL10nMonster }); //# sourceMappingURL=l10nCommands.cjs.map