@lingui/cli 5.4.1 → 5.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/ProgramExit.d.ts +3 -0
- package/dist/api/ProgramExit.js +10 -0
- package/dist/api/catalog/extractFromFiles.d.ts +4 -1
- package/dist/api/catalog/extractFromFiles.js +56 -29
- package/dist/api/catalog/getCatalogs.d.ts +1 -1
- package/dist/api/catalog/getCatalogs.js +6 -9
- package/dist/api/catalog/getTranslationsForCatalog.d.ts +4 -2
- package/dist/api/catalog/getTranslationsForCatalog.js +18 -6
- package/dist/api/catalog.d.ts +16 -9
- package/dist/api/catalog.js +29 -29
- package/dist/api/compile/compileLocale.d.ts +5 -0
- package/dist/api/compile/compileLocale.js +84 -0
- package/dist/api/extractWorkerPool.d.ts +1 -0
- package/dist/api/extractWorkerPool.js +8 -0
- package/dist/api/extractors/babel.js +1 -0
- package/dist/api/extractors/index.d.ts +2 -6
- package/dist/api/extractors/index.js +2 -2
- package/dist/api/logger.d.ts +3 -0
- package/dist/api/logger.js +2 -0
- package/dist/api/resolveWorkersOptions.d.ts +6 -0
- package/dist/api/resolveWorkersOptions.js +21 -0
- package/dist/api/stats.js +9 -1
- package/dist/api/workerLogger.d.ts +9 -0
- package/dist/api/workerLogger.js +19 -0
- package/dist/extract-experimental/extractFromBundleAndWrite.d.ts +19 -0
- package/dist/extract-experimental/extractFromBundleAndWrite.js +63 -0
- package/dist/extract-experimental/workers/extractWorker.d.ts +6 -0
- package/dist/extract-experimental/workers/extractWorker.js +32 -0
- package/dist/lingui-compile.d.ts +2 -0
- package/dist/lingui-compile.js +48 -84
- package/dist/lingui-extract-experimental.d.ts +4 -2
- package/dist/lingui-extract-experimental.js +48 -46
- package/dist/lingui-extract-template.d.ts +2 -0
- package/dist/lingui-extract-template.js +23 -6
- package/dist/lingui-extract.d.ts +2 -0
- package/dist/lingui-extract.js +32 -8
- package/dist/workers/compileWorker.d.ts +11 -0
- package/dist/workers/compileWorker.js +39 -0
- package/dist/workers/extractWorker.d.ts +7 -0
- package/dist/workers/extractWorker.js +24 -0
- package/package.json +14 -10
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { LinguiConfigNormalized } from "@lingui/conf";
|
|
2
|
+
import { FormatterWrapper } from "../api/formats";
|
|
3
|
+
export declare function extractFromBundleAndWrite(params: {
|
|
4
|
+
entryPoint: string;
|
|
5
|
+
bundleFile: string;
|
|
6
|
+
linguiConfig: LinguiConfigNormalized;
|
|
7
|
+
outputPattern: string;
|
|
8
|
+
format: FormatterWrapper;
|
|
9
|
+
template: boolean;
|
|
10
|
+
locales: string[];
|
|
11
|
+
clean: boolean;
|
|
12
|
+
overwrite: boolean;
|
|
13
|
+
}): Promise<{
|
|
14
|
+
success: boolean;
|
|
15
|
+
stat?: undefined;
|
|
16
|
+
} | {
|
|
17
|
+
success: boolean;
|
|
18
|
+
stat: string;
|
|
19
|
+
}>;
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.extractFromBundleAndWrite = extractFromBundleAndWrite;
|
|
7
|
+
const extractFromFiles_1 = require("../api/catalog/extractFromFiles");
|
|
8
|
+
const writeCatalogs_1 = require("./writeCatalogs");
|
|
9
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
|
10
|
+
const babel_1 = require("../api/extractors/babel");
|
|
11
|
+
async function extractFromBundle(filename, linguiConfig) {
|
|
12
|
+
const messages = {};
|
|
13
|
+
let success;
|
|
14
|
+
try {
|
|
15
|
+
const file = await promises_1.default.readFile(filename);
|
|
16
|
+
const parserOptions = linguiConfig.extractorParserOptions;
|
|
17
|
+
await (0, babel_1.extractFromFileWithBabel)(filename, file.toString(), (msg) => {
|
|
18
|
+
(0, extractFromFiles_1.mergeExtractedMessage)(msg, messages, linguiConfig);
|
|
19
|
+
}, {
|
|
20
|
+
linguiConfig,
|
|
21
|
+
}, {
|
|
22
|
+
plugins: (0, babel_1.getBabelParserOptions)(filename, parserOptions),
|
|
23
|
+
}, true);
|
|
24
|
+
success = true;
|
|
25
|
+
}
|
|
26
|
+
catch (e) {
|
|
27
|
+
console.error(`Cannot process file ${filename} ${e.message}`);
|
|
28
|
+
console.error(e.stack);
|
|
29
|
+
success = false;
|
|
30
|
+
}
|
|
31
|
+
return { success, messages };
|
|
32
|
+
}
|
|
33
|
+
async function extractFromBundleAndWrite(params) {
|
|
34
|
+
const { linguiConfig, entryPoint, format, outputPattern, locales, overwrite, clean, template, } = params;
|
|
35
|
+
const { messages, success } = await extractFromBundle(params.bundleFile, params.linguiConfig);
|
|
36
|
+
if (!success) {
|
|
37
|
+
return { success: false };
|
|
38
|
+
}
|
|
39
|
+
let stat;
|
|
40
|
+
if (template) {
|
|
41
|
+
stat = (await (0, writeCatalogs_1.writeTemplate)({
|
|
42
|
+
linguiConfig,
|
|
43
|
+
clean,
|
|
44
|
+
format,
|
|
45
|
+
messages,
|
|
46
|
+
entryPoint,
|
|
47
|
+
outputPattern,
|
|
48
|
+
})).statMessage;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
stat = (await (0, writeCatalogs_1.writeCatalogs)({
|
|
52
|
+
locales,
|
|
53
|
+
linguiConfig,
|
|
54
|
+
clean,
|
|
55
|
+
format,
|
|
56
|
+
messages,
|
|
57
|
+
entryPoint,
|
|
58
|
+
overwrite,
|
|
59
|
+
outputPattern,
|
|
60
|
+
})).statMessage;
|
|
61
|
+
}
|
|
62
|
+
return { success: true, stat };
|
|
63
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type ExtractWorkerFunction = typeof extractWorker;
|
|
2
|
+
declare const extractWorker: (linguiConfigPath: string, entryPoint: string, bundleFile: string, outputPattern: string, template: boolean, locales: string[], clean: boolean, overwrite: boolean) => Promise<{
|
|
3
|
+
success: boolean;
|
|
4
|
+
stat?: string;
|
|
5
|
+
}>;
|
|
6
|
+
export {};
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const worker_1 = require("threads/worker");
|
|
4
|
+
const conf_1 = require("@lingui/conf");
|
|
5
|
+
const extractFromBundleAndWrite_1 = require("../extractFromBundleAndWrite");
|
|
6
|
+
const formats_1 = require("../../api/formats");
|
|
7
|
+
let linguiConfig;
|
|
8
|
+
let format;
|
|
9
|
+
const extractWorker = async (linguiConfigPath, entryPoint, bundleFile, outputPattern, template, locales, clean, overwrite) => {
|
|
10
|
+
if (!linguiConfig) {
|
|
11
|
+
// initialize config once per worker, speed up workers follow execution
|
|
12
|
+
linguiConfig = (0, conf_1.getConfig)({
|
|
13
|
+
configPath: linguiConfigPath,
|
|
14
|
+
skipValidation: true,
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
if (!format) {
|
|
18
|
+
format = await (0, formats_1.getFormat)(linguiConfig.format, linguiConfig.formatOptions, linguiConfig.sourceLocale);
|
|
19
|
+
}
|
|
20
|
+
return await (0, extractFromBundleAndWrite_1.extractFromBundleAndWrite)({
|
|
21
|
+
entryPoint,
|
|
22
|
+
bundleFile,
|
|
23
|
+
outputPattern,
|
|
24
|
+
format,
|
|
25
|
+
linguiConfig,
|
|
26
|
+
locales,
|
|
27
|
+
overwrite,
|
|
28
|
+
clean,
|
|
29
|
+
template,
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
(0, worker_1.expose)(extractWorker);
|
package/dist/lingui-compile.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LinguiConfigNormalized } from "@lingui/conf";
|
|
2
|
+
import { WorkersOptions } from "./api/resolveWorkersOptions";
|
|
2
3
|
export type CliCompileOptions = {
|
|
3
4
|
verbose?: boolean;
|
|
4
5
|
allowEmpty?: boolean;
|
|
@@ -6,5 +7,6 @@ export type CliCompileOptions = {
|
|
|
6
7
|
typescript?: boolean;
|
|
7
8
|
watch?: boolean;
|
|
8
9
|
namespace?: string;
|
|
10
|
+
workersOptions: WorkersOptions;
|
|
9
11
|
};
|
|
10
12
|
export declare function command(config: LinguiConfigNormalized, options: CliCompileOptions): Promise<boolean>;
|
package/dist/lingui-compile.js
CHANGED
|
@@ -8,111 +8,75 @@ const picocolors_1 = __importDefault(require("picocolors"));
|
|
|
8
8
|
const chokidar_1 = __importDefault(require("chokidar"));
|
|
9
9
|
const commander_1 = require("commander");
|
|
10
10
|
const conf_1 = require("@lingui/conf");
|
|
11
|
-
const compile_1 = require("./api/compile");
|
|
12
11
|
const help_1 = require("./api/help");
|
|
13
12
|
const api_1 = require("./api");
|
|
14
|
-
const
|
|
15
|
-
const
|
|
16
|
-
const
|
|
17
|
-
|
|
18
|
-
}
|
|
13
|
+
const compileLocale_1 = require("./api/compile/compileLocale");
|
|
14
|
+
const threads_1 = require("threads");
|
|
15
|
+
const resolveWorkersOptions_1 = require("./api/resolveWorkersOptions");
|
|
16
|
+
const ms_1 = __importDefault(require("ms"));
|
|
19
17
|
async function command(config, options) {
|
|
20
|
-
const
|
|
18
|
+
const startTime = Date.now();
|
|
21
19
|
// Check config.compile.merge if catalogs for current locale are to be merged into a single compiled file
|
|
22
20
|
const doMerge = !!config.catalogsMergePath;
|
|
23
21
|
console.log("Compiling message catalogs…");
|
|
24
22
|
let errored = false;
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
errored = true;
|
|
32
|
-
}
|
|
33
|
-
else {
|
|
34
|
-
throw err;
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
}));
|
|
38
|
-
return !errored;
|
|
39
|
-
}
|
|
40
|
-
async function compileLocale(locale, catalogs, options, config, doMerge) {
|
|
41
|
-
let mergedCatalogs = {};
|
|
42
|
-
await Promise.all(catalogs.map(async (catalog) => {
|
|
43
|
-
const { messages, missing: missingMessages } = await catalog.getTranslations(locale, {
|
|
44
|
-
fallbackLocales: config.fallbackLocales,
|
|
45
|
-
sourceLocale: config.sourceLocale,
|
|
46
|
-
});
|
|
47
|
-
if (!options.allowEmpty &&
|
|
48
|
-
locale !== config.pseudoLocale &&
|
|
49
|
-
missingMessages.length > 0) {
|
|
50
|
-
console.error(picocolors_1.default.red(`Error: Failed to compile catalog for locale ${picocolors_1.default.bold(locale)}!`));
|
|
51
|
-
if (options.verbose) {
|
|
52
|
-
console.error(picocolors_1.default.red("Missing translations:"));
|
|
53
|
-
missingMessages.forEach((missing) => {
|
|
54
|
-
const source = missing.source || missing.source === missing.id
|
|
55
|
-
? `: (${missing.source})`
|
|
56
|
-
: "";
|
|
57
|
-
console.error(`${missing.id}${source}`);
|
|
58
|
-
});
|
|
23
|
+
if (!options.workersOptions.poolSize) {
|
|
24
|
+
// single threaded
|
|
25
|
+
const catalogs = await (0, api_1.getCatalogs)(config);
|
|
26
|
+
for (const locale of config.locales) {
|
|
27
|
+
try {
|
|
28
|
+
await (0, compileLocale_1.compileLocale)(catalogs, locale, options, config, doMerge, console);
|
|
59
29
|
}
|
|
60
|
-
|
|
61
|
-
|
|
30
|
+
catch (err) {
|
|
31
|
+
if (err.name === "ProgramExit") {
|
|
32
|
+
errored = true;
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw err;
|
|
36
|
+
}
|
|
62
37
|
}
|
|
63
|
-
console.error();
|
|
64
|
-
throw new ProgramExit();
|
|
65
38
|
}
|
|
66
|
-
|
|
67
|
-
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
if (!config.resolvedConfigPath) {
|
|
42
|
+
throw new Error("Multithreading is only supported when lingui config loaded from file system, not passed by API");
|
|
68
43
|
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
44
|
+
options.verbose &&
|
|
45
|
+
console.log(`Use worker pool of size ${options.workersOptions.poolSize}`);
|
|
46
|
+
const pool = (0, threads_1.Pool)(() => (0, threads_1.spawn)(new threads_1.Worker("./workers/compileWorker")), { size: options.workersOptions.poolSize });
|
|
47
|
+
try {
|
|
48
|
+
for (const locale of config.locales) {
|
|
49
|
+
pool.queue(async (worker) => {
|
|
50
|
+
const { logs, error, exitProgram } = await worker.compileLocale(locale, options, doMerge, config.resolvedConfigPath);
|
|
51
|
+
if (logs.errors) {
|
|
52
|
+
console.error(logs.errors);
|
|
53
|
+
}
|
|
54
|
+
if (exitProgram) {
|
|
55
|
+
errored = true;
|
|
56
|
+
return;
|
|
57
|
+
}
|
|
58
|
+
if (error) {
|
|
59
|
+
throw error;
|
|
60
|
+
}
|
|
61
|
+
});
|
|
72
62
|
}
|
|
63
|
+
await pool.completed(true);
|
|
73
64
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const result = await compileAndWrite(locale, config, options, await (0, getCatalogs_1.getCatalogForMerge)(config), mergedCatalogs);
|
|
77
|
-
if (!result) {
|
|
78
|
-
throw new ProgramExit();
|
|
65
|
+
finally {
|
|
66
|
+
await pool.terminate();
|
|
79
67
|
}
|
|
80
68
|
}
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const namespace = options.typescript
|
|
84
|
-
? "ts"
|
|
85
|
-
: options.namespace || config.compileNamespace;
|
|
86
|
-
const { source: compiledCatalog, errors } = (0, compile_1.createCompiledCatalog)(locale, messages, {
|
|
87
|
-
strict: false,
|
|
88
|
-
namespace,
|
|
89
|
-
pseudoLocale: config.pseudoLocale,
|
|
90
|
-
compilerBabelOptions: config.compilerBabelOptions,
|
|
91
|
-
});
|
|
92
|
-
if (errors.length) {
|
|
93
|
-
let message = (0, api_1.createCompilationErrorMessage)(locale, errors);
|
|
94
|
-
if (options.failOnCompileError) {
|
|
95
|
-
message += `These errors fail command execution because \`--strict\` option passed`;
|
|
96
|
-
console.error(picocolors_1.default.red(message));
|
|
97
|
-
return false;
|
|
98
|
-
}
|
|
99
|
-
else {
|
|
100
|
-
message += `You can fail command execution on these errors by passing \`--strict\` option`;
|
|
101
|
-
console.error(picocolors_1.default.red(message));
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
let compiledPath = await catalogToWrite.writeCompiled(locale, compiledCatalog, namespace);
|
|
105
|
-
compiledPath = (0, normalize_path_1.default)(path_1.default.relative(config.rootDir, compiledPath));
|
|
106
|
-
options.verbose && console.error(picocolors_1.default.green(`${locale} ⇒ ${compiledPath}`));
|
|
107
|
-
return true;
|
|
69
|
+
console.log(`Done in ${(0, ms_1.default)(Date.now() - startTime)}`);
|
|
70
|
+
return !errored;
|
|
108
71
|
}
|
|
109
72
|
if (require.main === module) {
|
|
110
73
|
commander_1.program
|
|
111
|
-
.description("
|
|
74
|
+
.description("Compile message catalogs to compiled bundle.")
|
|
112
75
|
.option("--config <path>", "Path to the config file")
|
|
113
76
|
.option("--strict", "Disable defaults for missing translations")
|
|
114
77
|
.option("--verbose", "Verbose output")
|
|
115
78
|
.option("--typescript", "Create Typescript definition for compiled bundle")
|
|
79
|
+
.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")
|
|
116
80
|
.option("--namespace <namespace>", "Specify namespace for compiled bundle. Ex: cjs(default) -> module.exports, es -> export, window.test -> window.test")
|
|
117
81
|
.option("--watch", "Enables Watch Mode")
|
|
118
82
|
.option("--debounce <delay>", "Debounces compilation for given amount of milliseconds")
|
|
@@ -135,6 +99,7 @@ if (require.main === module) {
|
|
|
135
99
|
verbose: options.watch || options.verbose || false,
|
|
136
100
|
allowEmpty: !options.strict,
|
|
137
101
|
failOnCompileError: !!options.strict,
|
|
102
|
+
workersOptions: (0, resolveWorkersOptions_1.resolveWorkersOptions)(options),
|
|
138
103
|
typescript: options.typescript || config.compileNamespace === "ts" || false,
|
|
139
104
|
namespace: options.namespace, // we want this to be undefined if user does not specify so default can be used
|
|
140
105
|
}));
|
|
@@ -180,7 +145,6 @@ if (require.main === module) {
|
|
|
180
145
|
if (!results) {
|
|
181
146
|
process.exit(1);
|
|
182
147
|
}
|
|
183
|
-
console.log("Done!");
|
|
184
148
|
});
|
|
185
149
|
}
|
|
186
150
|
}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { LinguiConfigNormalized } from "@lingui/conf";
|
|
2
|
+
import { WorkersOptions } from "./api/resolveWorkersOptions";
|
|
2
3
|
export type CliExtractTemplateOptions = {
|
|
3
|
-
verbose
|
|
4
|
+
verbose?: boolean;
|
|
4
5
|
files?: string[];
|
|
5
6
|
template?: boolean;
|
|
6
7
|
locales?: string[];
|
|
7
8
|
overwrite?: boolean;
|
|
8
9
|
clean?: boolean;
|
|
10
|
+
workersOptions: WorkersOptions;
|
|
9
11
|
};
|
|
10
|
-
export default function command(linguiConfig: LinguiConfigNormalized, options:
|
|
12
|
+
export default function command(linguiConfig: LinguiConfigNormalized, options: CliExtractTemplateOptions): Promise<boolean>;
|
|
@@ -10,13 +10,13 @@ const conf_1 = require("@lingui/conf");
|
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
11
11
|
const formats_1 = require("./api/formats");
|
|
12
12
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
13
|
-
const extractFromFiles_1 = require("./api/catalog/extractFromFiles");
|
|
14
13
|
const normalize_path_1 = __importDefault(require("normalize-path"));
|
|
15
14
|
const bundleSource_1 = require("./extract-experimental/bundleSource");
|
|
16
|
-
const writeCatalogs_1 = require("./extract-experimental/writeCatalogs");
|
|
17
15
|
const getEntryPoints_1 = require("./extract-experimental/getEntryPoints");
|
|
18
16
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
19
|
-
const
|
|
17
|
+
const threads_1 = require("threads");
|
|
18
|
+
const resolveWorkersOptions_1 = require("./api/resolveWorkersOptions");
|
|
19
|
+
const extractFromBundleAndWrite_1 = require("./extract-experimental/extractFromBundleAndWrite");
|
|
20
20
|
async function command(linguiConfig, options) {
|
|
21
21
|
var _a;
|
|
22
22
|
options.verbose && console.log("Extracting messages from source files…");
|
|
@@ -43,58 +43,58 @@ async function command(linguiConfig, options) {
|
|
|
43
43
|
const bundleResult = await (0, bundleSource_1.bundleSource)(linguiConfig, (0, getEntryPoints_1.getEntryPoints)(config.entries), tempDir, linguiConfig.rootDir);
|
|
44
44
|
const stats = [];
|
|
45
45
|
let commandSuccess = true;
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
match(_filename) {
|
|
50
|
-
return true;
|
|
51
|
-
},
|
|
52
|
-
async extract(filename, code, onMessageExtracted, ctx) {
|
|
53
|
-
const parserOptions = ctx.linguiConfig.extractorParserOptions;
|
|
54
|
-
return (0, babel_1.extractFromFileWithBabel)(filename, code, onMessageExtracted, ctx, {
|
|
55
|
-
plugins: (0, babel_1.getBabelParserOptions)(filename, parserOptions),
|
|
56
|
-
}, true);
|
|
57
|
-
},
|
|
58
|
-
},
|
|
59
|
-
];
|
|
60
|
-
for (const outFile of Object.keys(bundleResult.metafile.outputs)) {
|
|
61
|
-
const messages = await (0, extractFromFiles_1.extractFromFiles)([outFile], linguiConfig);
|
|
62
|
-
const { entryPoint } = bundleResult.metafile.outputs[outFile];
|
|
63
|
-
let output;
|
|
64
|
-
if (!messages) {
|
|
65
|
-
commandSuccess = false;
|
|
66
|
-
continue;
|
|
46
|
+
if (options.workersOptions.poolSize) {
|
|
47
|
+
if (!linguiConfig.resolvedConfigPath) {
|
|
48
|
+
throw new Error("Multithreading is only supported when lingui config loaded from file system, not passed by API");
|
|
67
49
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
50
|
+
options.verbose &&
|
|
51
|
+
console.log(`Use worker pool of size ${options.workersOptions.poolSize}`);
|
|
52
|
+
const pool = (0, threads_1.Pool)(() => (0, threads_1.spawn)(new threads_1.Worker("./extract-experimental/workers/extractWorker")), { size: options.workersOptions.poolSize });
|
|
53
|
+
try {
|
|
54
|
+
for (const outFile of Object.keys(bundleResult.metafile.outputs)) {
|
|
55
|
+
const { entryPoint } = bundleResult.metafile.outputs[outFile];
|
|
56
|
+
pool.queue(async (extractFromBundleAndWrite) => {
|
|
57
|
+
const { success, stat } = await extractFromBundleAndWrite(linguiConfig.resolvedConfigPath, entryPoint, outFile, config.output, options.template, options.locales || linguiConfig.locales, options.clean, options.overwrite);
|
|
58
|
+
commandSuccess && (commandSuccess = success);
|
|
59
|
+
stats.push({
|
|
60
|
+
entry: (0, normalize_path_1.default)(path_1.default.relative(linguiConfig.rootDir, entryPoint)),
|
|
61
|
+
content: stat,
|
|
62
|
+
});
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
await pool.completed();
|
|
66
|
+
}
|
|
67
|
+
finally {
|
|
68
|
+
await pool.terminate();
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else {
|
|
72
|
+
const format = await (0, formats_1.getFormat)(linguiConfig.format, linguiConfig.formatOptions, linguiConfig.sourceLocale);
|
|
73
|
+
for (const outFile of Object.keys(bundleResult.metafile.outputs)) {
|
|
74
|
+
const { entryPoint } = bundleResult.metafile.outputs[outFile];
|
|
75
|
+
const { success, stat } = await (0, extractFromBundleAndWrite_1.extractFromBundleAndWrite)({
|
|
74
76
|
entryPoint,
|
|
77
|
+
bundleFile: outFile,
|
|
75
78
|
outputPattern: config.output,
|
|
76
|
-
})).statMessage;
|
|
77
|
-
}
|
|
78
|
-
else {
|
|
79
|
-
output = (await (0, writeCatalogs_1.writeCatalogs)({
|
|
80
|
-
locales: options.locales || linguiConfig.locales,
|
|
81
|
-
linguiConfig,
|
|
82
|
-
clean: options.clean,
|
|
83
79
|
format,
|
|
84
|
-
|
|
85
|
-
|
|
80
|
+
linguiConfig,
|
|
81
|
+
locales: options.locales || linguiConfig.locales,
|
|
86
82
|
overwrite: options.overwrite,
|
|
87
|
-
|
|
88
|
-
|
|
83
|
+
clean: options.clean,
|
|
84
|
+
template: options.template,
|
|
85
|
+
});
|
|
86
|
+
commandSuccess && (commandSuccess = success);
|
|
87
|
+
stats.push({
|
|
88
|
+
entry: (0, normalize_path_1.default)(path_1.default.relative(linguiConfig.rootDir, entryPoint)),
|
|
89
|
+
content: stat,
|
|
90
|
+
});
|
|
89
91
|
}
|
|
90
|
-
stats.push({
|
|
91
|
-
entry: (0, normalize_path_1.default)(path_1.default.relative(linguiConfig.rootDir, entryPoint)),
|
|
92
|
-
content: output,
|
|
93
|
-
});
|
|
94
92
|
}
|
|
95
93
|
// cleanup temp directory
|
|
96
94
|
await promises_1.default.rm(tempDir, { recursive: true, force: true });
|
|
97
|
-
stats
|
|
95
|
+
stats
|
|
96
|
+
.sort((a, b) => a.entry.localeCompare(b.entry))
|
|
97
|
+
.forEach(({ entry, content }) => {
|
|
98
98
|
console.log([`Catalog statistics for ${entry}:`, content, ""].join("\n"));
|
|
99
99
|
});
|
|
100
100
|
return commandSuccess;
|
|
@@ -107,6 +107,7 @@ if (require.main === module) {
|
|
|
107
107
|
.option("--clean", "Remove obsolete translations")
|
|
108
108
|
.option("--locale <locale, [...]>", "Only extract the specified locales")
|
|
109
109
|
.option("--verbose", "Verbose output")
|
|
110
|
+
.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")
|
|
110
111
|
.parse(process.argv);
|
|
111
112
|
const options = commander_1.program.opts();
|
|
112
113
|
const config = (0, conf_1.getConfig)({
|
|
@@ -118,6 +119,7 @@ if (require.main === module) {
|
|
|
118
119
|
locales: (_a = options.locale) === null || _a === void 0 ? void 0 : _a.split(","),
|
|
119
120
|
overwrite: options.overwrite,
|
|
120
121
|
clean: options.clean,
|
|
122
|
+
workersOptions: (0, resolveWorkersOptions_1.resolveWorkersOptions)(options),
|
|
121
123
|
}).then(() => {
|
|
122
124
|
if (!result)
|
|
123
125
|
process.exit(1);
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { LinguiConfigNormalized } from "@lingui/conf";
|
|
2
|
+
import { WorkersOptions } from "./api/resolveWorkersOptions";
|
|
2
3
|
export type CliExtractTemplateOptions = {
|
|
3
4
|
verbose: boolean;
|
|
4
5
|
files?: string[];
|
|
6
|
+
workersOptions: WorkersOptions;
|
|
5
7
|
};
|
|
6
8
|
export default function command(config: LinguiConfigNormalized, options: Partial<CliExtractTemplateOptions>): Promise<boolean>;
|
|
@@ -10,18 +10,33 @@ const conf_1 = require("@lingui/conf");
|
|
|
10
10
|
const api_1 = require("./api");
|
|
11
11
|
const path_1 = __importDefault(require("path"));
|
|
12
12
|
const normalize_path_1 = __importDefault(require("normalize-path"));
|
|
13
|
+
const extractWorkerPool_1 = require("./api/extractWorkerPool");
|
|
14
|
+
const resolveWorkersOptions_1 = require("./api/resolveWorkersOptions");
|
|
13
15
|
async function command(config, options) {
|
|
14
16
|
options.verbose && console.log("Extracting messages from source files…");
|
|
15
17
|
const catalogs = await (0, api_1.getCatalogs)(config);
|
|
16
18
|
const catalogStats = {};
|
|
17
19
|
let commandSuccess = true;
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
20
|
+
let workerPool;
|
|
21
|
+
if (options.workersOptions.poolSize) {
|
|
22
|
+
options.verbose &&
|
|
23
|
+
console.log(`Use worker pool of size ${options.workersOptions.poolSize}`);
|
|
24
|
+
workerPool = (0, extractWorkerPool_1.createExtractWorkerPool)(options.workersOptions);
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
await Promise.all(catalogs.map(async (catalog) => {
|
|
28
|
+
const result = await catalog.makeTemplate(Object.assign(Object.assign({}, options), { orderBy: config.orderBy, workerPool }));
|
|
29
|
+
if (result) {
|
|
30
|
+
catalogStats[(0, normalize_path_1.default)(path_1.default.relative(config.rootDir, catalog.templateFile))] = Object.keys(result).length;
|
|
31
|
+
}
|
|
32
|
+
commandSuccess && (commandSuccess = Boolean(result));
|
|
33
|
+
}));
|
|
34
|
+
}
|
|
35
|
+
finally {
|
|
36
|
+
if (workerPool) {
|
|
37
|
+
await workerPool.terminate();
|
|
22
38
|
}
|
|
23
|
-
|
|
24
|
-
}));
|
|
39
|
+
}
|
|
25
40
|
Object.entries(catalogStats).forEach(([key, value]) => {
|
|
26
41
|
console.log(`Catalog statistics for ${picocolors_1.default.bold(key)}: ${picocolors_1.default.green(value)} messages`);
|
|
27
42
|
console.log();
|
|
@@ -32,6 +47,7 @@ if (require.main === module) {
|
|
|
32
47
|
commander_1.program
|
|
33
48
|
.option("--config <path>", "Path to the config file")
|
|
34
49
|
.option("--verbose", "Verbose output")
|
|
50
|
+
.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")
|
|
35
51
|
.parse(process.argv);
|
|
36
52
|
const options = commander_1.program.opts();
|
|
37
53
|
const config = (0, conf_1.getConfig)({
|
|
@@ -39,6 +55,7 @@ if (require.main === module) {
|
|
|
39
55
|
});
|
|
40
56
|
const result = command(config, {
|
|
41
57
|
verbose: options.verbose || false,
|
|
58
|
+
workersOptions: (0, resolveWorkersOptions_1.resolveWorkersOptions)(options),
|
|
42
59
|
}).then(() => {
|
|
43
60
|
if (!result)
|
|
44
61
|
process.exit(1);
|
package/dist/lingui-extract.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { LinguiConfigNormalized } from "@lingui/conf";
|
|
2
|
+
import { WorkersOptions } from "./api/resolveWorkersOptions";
|
|
2
3
|
export type CliExtractOptions = {
|
|
3
4
|
verbose: boolean;
|
|
4
5
|
files?: string[];
|
|
@@ -7,5 +8,6 @@ export type CliExtractOptions = {
|
|
|
7
8
|
locale: string[];
|
|
8
9
|
prevFormat: string | null;
|
|
9
10
|
watch?: boolean;
|
|
11
|
+
workersOptions: WorkersOptions;
|
|
10
12
|
};
|
|
11
13
|
export default function command(config: LinguiConfigNormalized, options: Partial<CliExtractOptions>): Promise<boolean>;
|
package/dist/lingui-extract.js
CHANGED
|
@@ -14,22 +14,44 @@ const stats_1 = require("./api/stats");
|
|
|
14
14
|
const help_1 = require("./api/help");
|
|
15
15
|
const ora_1 = __importDefault(require("ora"));
|
|
16
16
|
const normalize_path_1 = __importDefault(require("normalize-path"));
|
|
17
|
+
const resolveWorkersOptions_1 = require("./api/resolveWorkersOptions");
|
|
18
|
+
const extractWorkerPool_1 = require("./api/extractWorkerPool");
|
|
19
|
+
const ms_1 = __importDefault(require("ms"));
|
|
17
20
|
async function command(config, options) {
|
|
21
|
+
const startTime = Date.now();
|
|
18
22
|
options.verbose && console.log("Extracting messages from source files…");
|
|
19
23
|
const catalogs = await (0, api_1.getCatalogs)(config);
|
|
20
24
|
const catalogStats = {};
|
|
21
25
|
let commandSuccess = true;
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
26
|
+
let workerPool;
|
|
27
|
+
// important to initialize ora before worker pool, otherwise it cause
|
|
28
|
+
// MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 unpipe listeners added to [WriteStream]. MaxListeners is 10. Use emitter.setMaxListeners() to increase limit
|
|
29
|
+
// when workers >= 10
|
|
30
|
+
const spinner = (0, ora_1.default)();
|
|
31
|
+
if (options.workersOptions.poolSize) {
|
|
32
|
+
options.verbose &&
|
|
33
|
+
console.log(`Use worker pool of size ${options.workersOptions.poolSize}`);
|
|
34
|
+
workerPool = (0, extractWorkerPool_1.createExtractWorkerPool)(options.workersOptions);
|
|
35
|
+
}
|
|
36
|
+
spinner.start();
|
|
37
|
+
try {
|
|
38
|
+
await Promise.all(catalogs.map(async (catalog) => {
|
|
39
|
+
const result = await catalog.make(Object.assign(Object.assign({}, options), { orderBy: config.orderBy, workerPool }));
|
|
40
|
+
catalogStats[(0, normalize_path_1.default)(path_1.default.relative(config.rootDir, catalog.path))] = result || {};
|
|
41
|
+
commandSuccess && (commandSuccess = Boolean(result));
|
|
42
|
+
}));
|
|
43
|
+
}
|
|
44
|
+
finally {
|
|
45
|
+
if (workerPool) {
|
|
46
|
+
await workerPool.terminate();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
const doneMsg = `Done in ${(0, ms_1.default)(Date.now() - startTime)}`;
|
|
28
50
|
if (commandSuccess) {
|
|
29
|
-
spinner.succeed();
|
|
51
|
+
spinner.succeed(doneMsg);
|
|
30
52
|
}
|
|
31
53
|
else {
|
|
32
|
-
spinner.fail();
|
|
54
|
+
spinner.fail(doneMsg);
|
|
33
55
|
}
|
|
34
56
|
Object.entries(catalogStats).forEach(([key, value]) => {
|
|
35
57
|
console.log(`Catalog statistics for ${key}: `);
|
|
@@ -67,6 +89,7 @@ if (require.main === module) {
|
|
|
67
89
|
.map((s) => s.trim())
|
|
68
90
|
.filter(Boolean);
|
|
69
91
|
})
|
|
92
|
+
.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")
|
|
70
93
|
.option("--overwrite", "Overwrite translations for source locale")
|
|
71
94
|
.option("--clean", "Remove obsolete translations")
|
|
72
95
|
.option("--debounce <delay>", "Debounces extraction for given amount of milliseconds")
|
|
@@ -109,6 +132,7 @@ if (require.main === module) {
|
|
|
109
132
|
watch: options.watch || false,
|
|
110
133
|
files: (filePath === null || filePath === void 0 ? void 0 : filePath.length) ? filePath : undefined,
|
|
111
134
|
prevFormat,
|
|
135
|
+
workersOptions: (0, resolveWorkersOptions_1.resolveWorkersOptions)(options),
|
|
112
136
|
});
|
|
113
137
|
};
|
|
114
138
|
const changedPaths = new Set();
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { CliCompileOptions } from "../lingui-compile";
|
|
2
|
+
import { SerializedLogs } from "../api/workerLogger";
|
|
3
|
+
declare const compileWorker: {
|
|
4
|
+
compileLocale: (locale: string, options: CliCompileOptions, doMerge: boolean, linguiConfigPath: string) => Promise<{
|
|
5
|
+
logs?: SerializedLogs;
|
|
6
|
+
error?: unknown;
|
|
7
|
+
exitProgram?: boolean;
|
|
8
|
+
}>;
|
|
9
|
+
};
|
|
10
|
+
export type CompileWorker = typeof compileWorker;
|
|
11
|
+
export {};
|