UNPKG

@lingui/cli

Version:

CLI for working wit message catalogs

128 lines (127 loc) 6.59 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; var _a; Object.defineProperty(exports, "__esModule", { value: true }); exports.default = command; const commander_1 = require("commander"); const conf_1 = require("@lingui/conf"); const path_1 = __importDefault(require("path")); const formats_1 = require("./api/formats"); const promises_1 = __importDefault(require("fs/promises")); const normalize_path_1 = __importDefault(require("normalize-path")); const bundleSource_1 = require("./extract-experimental/bundleSource"); const getEntryPoints_1 = require("./extract-experimental/getEntryPoints"); const picocolors_1 = __importDefault(require("picocolors")); const threads_1 = require("threads"); const resolveWorkersOptions_1 = require("./api/resolveWorkersOptions"); const extractFromBundleAndWrite_1 = require("./extract-experimental/extractFromBundleAndWrite"); async function command(linguiConfig, options) { var _a; options.verbose && console.log("Extracting messages from source files…"); const config = (_a = linguiConfig.experimental) === null || _a === void 0 ? void 0 : _a.extractor; if (!config) { throw new Error("The configuration for experimental extractor is empty. Please read the docs."); } console.log(picocolors_1.default.yellow([ "You have using an experimental feature", "Experimental features are not covered by semver, and may cause unexpected or broken application behavior." + " Use at your own risk.", "", ].join("\n"))); // unfortunately we can't use os.tmpdir() in this case // on windows it might create a folder on a different disk then source code is stored // (tmpdir would be always on C: but code could be stored on D:) // and then relative path in sourcemaps produced by esbuild will be broken. // sourcemaps itself doesn't allow to have absolute windows path, because they are not URL compatible. // that's why we store esbuild bundles in .lingui folder const tmpPrefix = ".lingui/"; await promises_1.default.mkdir(tmpPrefix, { recursive: true }); const tempDir = await promises_1.default.mkdtemp(tmpPrefix); await promises_1.default.rm(tempDir, { recursive: true, force: true }); const bundleResult = await (0, bundleSource_1.bundleSource)(linguiConfig, (0, getEntryPoints_1.getEntryPoints)(config.entries), tempDir, linguiConfig.rootDir); const stats = []; let commandSuccess = true; if (options.workersOptions.poolSize) { if (!linguiConfig.resolvedConfigPath) { throw new Error("Multithreading is only supported when lingui config loaded from file system, not passed by API"); } options.verbose && console.log(`Use worker pool of size ${options.workersOptions.poolSize}`); const pool = (0, threads_1.Pool)(() => (0, threads_1.spawn)(new threads_1.Worker("./extract-experimental/workers/extractWorker")), { size: options.workersOptions.poolSize }); try { for (const outFile of Object.keys(bundleResult.metafile.outputs)) { const { entryPoint } = bundleResult.metafile.outputs[outFile]; pool.queue(async (extractFromBundleAndWrite) => { const { success, stat } = await extractFromBundleAndWrite(linguiConfig.resolvedConfigPath, entryPoint, outFile, config.output, options.template, options.locales || linguiConfig.locales, options.clean, options.overwrite); commandSuccess && (commandSuccess = success); stats.push({ entry: (0, normalize_path_1.default)(path_1.default.relative(linguiConfig.rootDir, entryPoint)), content: stat, }); }); } await pool.completed(); } finally { await pool.terminate(true); } } else { const format = await (0, formats_1.getFormat)(linguiConfig.format, linguiConfig.formatOptions, linguiConfig.sourceLocale); for (const outFile of Object.keys(bundleResult.metafile.outputs)) { const { entryPoint } = bundleResult.metafile.outputs[outFile]; const { success, stat } = await (0, extractFromBundleAndWrite_1.extractFromBundleAndWrite)({ entryPoint, bundleFile: outFile, outputPattern: config.output, format, linguiConfig, locales: options.locales || linguiConfig.locales, overwrite: options.overwrite, clean: options.clean, template: options.template, }); commandSuccess && (commandSuccess = success); stats.push({ entry: (0, normalize_path_1.default)(path_1.default.relative(linguiConfig.rootDir, entryPoint)), content: stat, }); } } // cleanup temp directory await promises_1.default.rm(tempDir, { recursive: true, force: true }); stats .sort((a, b) => a.entry.localeCompare(b.entry)) .forEach(({ entry, content }) => { console.log([`Catalog statistics for ${entry}:`, content, ""].join("\n")); }); return commandSuccess; } if (require.main === module) { commander_1.program .option("--config <path>", "Path to the config file") .option("--template", "Extract to template") .option("--overwrite", "Overwrite translations for source locale") .option("--clean", "Remove obsolete translations") .option("--locale <locale, [...]>", "Only extract the specified locales") .option("--verbose", "Verbose output") .option("--workers <n>", "Number of worker threads to use (default: CPU count - 1, capped at 8). Pass `--workers 1` to disable worker threads and run everything in a single process") .parse(process.argv); const options = commander_1.program.opts(); const config = (0, conf_1.getConfig)({ configPath: options.config, }); const result = command(config, { verbose: options.verbose || false, template: options.template, locales: (_a = options.locale) === null || _a === void 0 ? void 0 : _a.split(","), overwrite: options.overwrite, clean: options.clean, workersOptions: (0, resolveWorkersOptions_1.resolveWorkersOptions)(options), }).then(() => { if (!result) process.exit(1); }); }