@lingui/cli 5.4.1 → 5.5.1
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/getFallbackListForLocale.js +3 -2
- 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 +32 -30
- 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
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
import type { LinguiConfigNormalized } from "@lingui/conf";
|
|
1
|
+
import type { ExtractedMessage, LinguiConfigNormalized } from "@lingui/conf";
|
|
2
2
|
import { ExtractedCatalogType } from "../types";
|
|
3
|
+
import { ExtractWorkerPool } from "../extractWorkerPool";
|
|
3
4
|
export declare function extractFromFiles(paths: string[], config: LinguiConfigNormalized): Promise<ExtractedCatalogType>;
|
|
5
|
+
export declare function mergeExtractedMessage(next: ExtractedMessage, messages: ExtractedCatalogType, config: LinguiConfigNormalized): void;
|
|
6
|
+
export declare function extractFromFilesWithWorkerPool(workerPool: ExtractWorkerPool, paths: string[], config: LinguiConfigNormalized): Promise<ExtractedCatalogType>;
|
|
@@ -4,12 +4,17 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.extractFromFiles = extractFromFiles;
|
|
7
|
+
exports.mergeExtractedMessage = mergeExtractedMessage;
|
|
8
|
+
exports.extractFromFilesWithWorkerPool = extractFromFilesWithWorkerPool;
|
|
7
9
|
const picocolors_1 = __importDefault(require("picocolors"));
|
|
8
10
|
const path_1 = __importDefault(require("path"));
|
|
9
11
|
const extractors_1 = __importDefault(require("../extractors"));
|
|
10
12
|
const utils_1 = require("../utils");
|
|
11
13
|
function mergePlaceholders(prev, next) {
|
|
12
14
|
const res = Object.assign({}, prev);
|
|
15
|
+
// Handle case where next is null or undefined
|
|
16
|
+
if (!next)
|
|
17
|
+
return res;
|
|
13
18
|
Object.entries(next).forEach(([key, value]) => {
|
|
14
19
|
if (!res[key]) {
|
|
15
20
|
res[key] = [];
|
|
@@ -24,37 +29,59 @@ function mergePlaceholders(prev, next) {
|
|
|
24
29
|
async function extractFromFiles(paths, config) {
|
|
25
30
|
const messages = {};
|
|
26
31
|
let catalogSuccess = true;
|
|
27
|
-
|
|
32
|
+
for (const filename of paths) {
|
|
28
33
|
const fileSuccess = await (0, extractors_1.default)(filename, (next) => {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
messages[next.id] = {
|
|
32
|
-
message: next.message,
|
|
33
|
-
context: next.context,
|
|
34
|
-
placeholders: {},
|
|
35
|
-
comments: [],
|
|
36
|
-
origin: [],
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
const prev = messages[next.id];
|
|
40
|
-
// there might be a case when filename was not mapped from sourcemaps
|
|
41
|
-
const filename = next.origin[0]
|
|
42
|
-
? path_1.default.relative(config.rootDir, next.origin[0]).replace(/\\/g, "/")
|
|
43
|
-
: "";
|
|
44
|
-
const origin = [filename, next.origin[1]];
|
|
45
|
-
if (prev.message && next.message && prev.message !== next.message) {
|
|
46
|
-
throw new Error(`Encountered different default translations for message ${picocolors_1.default.yellow(next.id)}` +
|
|
47
|
-
`\n${picocolors_1.default.yellow((0, utils_1.prettyOrigin)(prev.origin))} ${prev.message}` +
|
|
48
|
-
`\n${picocolors_1.default.yellow((0, utils_1.prettyOrigin)([origin]))} ${next.message}`);
|
|
49
|
-
}
|
|
50
|
-
messages[next.id] = Object.assign(Object.assign({}, prev), { message: (_a = prev.message) !== null && _a !== void 0 ? _a : next.message, comments: next.comment
|
|
51
|
-
? [...prev.comments, next.comment].sort()
|
|
52
|
-
: prev.comments, origin: [...prev.origin, [filename, next.origin[1]]].sort((a, b) => a[0].localeCompare(b[0])), placeholders: mergePlaceholders(prev.placeholders, next.placeholders) });
|
|
53
|
-
}, config, {
|
|
54
|
-
extractors: config.extractors,
|
|
55
|
-
});
|
|
34
|
+
mergeExtractedMessage(next, messages, config);
|
|
35
|
+
}, config);
|
|
56
36
|
catalogSuccess && (catalogSuccess = fileSuccess);
|
|
57
|
-
}
|
|
37
|
+
}
|
|
38
|
+
if (!catalogSuccess)
|
|
39
|
+
return undefined;
|
|
40
|
+
return messages;
|
|
41
|
+
}
|
|
42
|
+
function mergeExtractedMessage(next, messages, config) {
|
|
43
|
+
var _a;
|
|
44
|
+
if (!messages[next.id]) {
|
|
45
|
+
messages[next.id] = {
|
|
46
|
+
message: next.message,
|
|
47
|
+
context: next.context,
|
|
48
|
+
placeholders: {},
|
|
49
|
+
comments: [],
|
|
50
|
+
origin: [],
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
const prev = messages[next.id];
|
|
54
|
+
// there might be a case when filename was not mapped from sourcemaps
|
|
55
|
+
const filename = next.origin[0]
|
|
56
|
+
? path_1.default.relative(config.rootDir, next.origin[0]).replace(/\\/g, "/")
|
|
57
|
+
: "";
|
|
58
|
+
const origin = [filename, next.origin[1]];
|
|
59
|
+
if (prev.message && next.message && prev.message !== next.message) {
|
|
60
|
+
throw new Error(`Encountered different default translations for message ${picocolors_1.default.yellow(next.id)}` +
|
|
61
|
+
`\n${picocolors_1.default.yellow((0, utils_1.prettyOrigin)(prev.origin))} ${prev.message}` +
|
|
62
|
+
`\n${picocolors_1.default.yellow((0, utils_1.prettyOrigin)([origin]))} ${next.message}`);
|
|
63
|
+
}
|
|
64
|
+
messages[next.id] = Object.assign(Object.assign({}, prev), { message: (_a = prev.message) !== null && _a !== void 0 ? _a : next.message, comments: next.comment
|
|
65
|
+
? [...prev.comments, next.comment].sort()
|
|
66
|
+
: prev.comments, origin: [...prev.origin, [filename, next.origin[1]]].sort((a, b) => a[0].localeCompare(b[0])), placeholders: mergePlaceholders(prev.placeholders, next.placeholders) });
|
|
67
|
+
}
|
|
68
|
+
async function extractFromFilesWithWorkerPool(workerPool, paths, config) {
|
|
69
|
+
const messages = {};
|
|
70
|
+
let catalogSuccess = true;
|
|
71
|
+
if (!config.resolvedConfigPath) {
|
|
72
|
+
throw new Error("Multithreading is only supported when lingui config loaded from file system, not passed by API");
|
|
73
|
+
}
|
|
74
|
+
await Promise.all(paths.map((filename) => workerPool.queue(async (worker) => {
|
|
75
|
+
const result = await worker(filename, config.resolvedConfigPath);
|
|
76
|
+
if (!result.success) {
|
|
77
|
+
catalogSuccess = false;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
result.messages.forEach((message) => {
|
|
81
|
+
mergeExtractedMessage(message, messages, config);
|
|
82
|
+
});
|
|
83
|
+
}
|
|
84
|
+
})));
|
|
58
85
|
if (!catalogSuccess)
|
|
59
86
|
return undefined;
|
|
60
87
|
return messages;
|
|
@@ -7,7 +7,7 @@ export declare function getCatalogs(config: LinguiConfigNormalized): Promise<Cat
|
|
|
7
7
|
/**
|
|
8
8
|
* Create catalog for merged messages.
|
|
9
9
|
*/
|
|
10
|
-
export declare function
|
|
10
|
+
export declare function getMergedCatalogPath(config: LinguiConfigNormalized): Promise<string>;
|
|
11
11
|
export declare function getCatalogForFile(file: string, catalogs: Catalog[]): {
|
|
12
12
|
locale: string;
|
|
13
13
|
catalog: Catalog;
|
|
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.getCatalogs = getCatalogs;
|
|
7
|
-
exports.
|
|
7
|
+
exports.getMergedCatalogPath = getMergedCatalogPath;
|
|
8
8
|
exports.getCatalogForFile = getCatalogForFile;
|
|
9
9
|
const glob_1 = require("glob");
|
|
10
10
|
const path_1 = __importDefault(require("path"));
|
|
@@ -78,16 +78,10 @@ const ensureArray = (value) => {
|
|
|
78
78
|
/**
|
|
79
79
|
* Create catalog for merged messages.
|
|
80
80
|
*/
|
|
81
|
-
async function
|
|
81
|
+
async function getMergedCatalogPath(config) {
|
|
82
82
|
const format = await (0, formats_1.getFormat)(config.format, config.formatOptions, config.sourceLocale);
|
|
83
83
|
validateCatalogPath(config.catalogsMergePath, format.getCatalogExtension());
|
|
84
|
-
return
|
|
85
|
-
name: getCatalogName(config.catalogsMergePath),
|
|
86
|
-
path: (0, utils_1.normalizeRelativePath)(config.catalogsMergePath),
|
|
87
|
-
include: [],
|
|
88
|
-
exclude: [],
|
|
89
|
-
format,
|
|
90
|
-
}, config);
|
|
84
|
+
return (0, utils_1.normalizeRelativePath)(config.catalogsMergePath);
|
|
91
85
|
}
|
|
92
86
|
function getCatalogForFile(file, catalogs) {
|
|
93
87
|
for (const catalog of catalogs) {
|
|
@@ -108,6 +102,9 @@ function getCatalogForFile(file, catalogs) {
|
|
|
108
102
|
* Validate that `catalogPath` doesn't end with trailing slash
|
|
109
103
|
*/
|
|
110
104
|
function validateCatalogPath(path, extension) {
|
|
105
|
+
if (!path.includes(LOCALE_PH)) {
|
|
106
|
+
throw new Error(`Invalid catalog path: ${LOCALE_PH} variable is missing`);
|
|
107
|
+
}
|
|
111
108
|
if (!path.endsWith(utils_1.PATHSEP)) {
|
|
112
109
|
return;
|
|
113
110
|
}
|
|
@@ -7,8 +7,9 @@ function getFallbackListForLocale(fallbackLocales, locale) {
|
|
|
7
7
|
const mapping = fallbackLocales === null || fallbackLocales === void 0 ? void 0 : fallbackLocales[locale];
|
|
8
8
|
Array.isArray(mapping) ? fL.push(...mapping) : fL.push(mapping);
|
|
9
9
|
}
|
|
10
|
-
if ((fallbackLocales === null || fallbackLocales === void 0 ? void 0 : fallbackLocales.default)
|
|
11
|
-
|
|
10
|
+
if (typeof (fallbackLocales === null || fallbackLocales === void 0 ? void 0 : fallbackLocales.default) === "string" &&
|
|
11
|
+
locale !== (fallbackLocales === null || fallbackLocales === void 0 ? void 0 : fallbackLocales.default)) {
|
|
12
|
+
fL.push(fallbackLocales.default);
|
|
12
13
|
}
|
|
13
14
|
return fL;
|
|
14
15
|
}
|
|
@@ -7,8 +7,10 @@ export type TranslationMissingEvent = {
|
|
|
7
7
|
export type GetTranslationsOptions = {
|
|
8
8
|
sourceLocale: string;
|
|
9
9
|
fallbackLocales: FallbackLocales;
|
|
10
|
-
onMissing?: (message: TranslationMissingEvent) => void;
|
|
11
10
|
};
|
|
12
11
|
export declare function getTranslationsForCatalog(catalog: Catalog, locale: string, options: GetTranslationsOptions): Promise<{
|
|
13
|
-
|
|
12
|
+
missing: TranslationMissingEvent[];
|
|
13
|
+
messages: {
|
|
14
|
+
[id: string]: string;
|
|
15
|
+
};
|
|
14
16
|
}>;
|
|
@@ -3,16 +3,28 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getTranslationsForCatalog = getTranslationsForCatalog;
|
|
4
4
|
const getFallbackListForLocale_1 = require("./getFallbackListForLocale");
|
|
5
5
|
async function getTranslationsForCatalog(catalog, locale, options) {
|
|
6
|
+
const locales = new Set([
|
|
7
|
+
locale,
|
|
8
|
+
options.sourceLocale,
|
|
9
|
+
...(0, getFallbackListForLocale_1.getFallbackListForLocale)(options.fallbackLocales, locale),
|
|
10
|
+
]);
|
|
6
11
|
const [catalogs, template] = await Promise.all([
|
|
7
|
-
catalog.readAll(),
|
|
12
|
+
catalog.readAll(Array.from(locales)),
|
|
8
13
|
catalog.readTemplate(),
|
|
9
14
|
]);
|
|
10
15
|
const sourceLocaleCatalog = catalogs[options.sourceLocale] || {};
|
|
11
16
|
const input = Object.assign(Object.assign(Object.assign({}, template), sourceLocaleCatalog), catalogs[locale]);
|
|
12
|
-
|
|
13
|
-
|
|
17
|
+
const missing = [];
|
|
18
|
+
const messages = Object.keys(input).reduce((acc, key) => {
|
|
19
|
+
acc[key] = getTranslation(catalogs, input[key], locale, key, (event) => {
|
|
20
|
+
missing.push(event);
|
|
21
|
+
}, options);
|
|
14
22
|
return acc;
|
|
15
23
|
}, {});
|
|
24
|
+
return {
|
|
25
|
+
missing,
|
|
26
|
+
messages,
|
|
27
|
+
};
|
|
16
28
|
}
|
|
17
29
|
function sourceLocaleFallback(catalog, key) {
|
|
18
30
|
if (!(catalog === null || catalog === void 0 ? void 0 : catalog[key])) {
|
|
@@ -20,8 +32,8 @@ function sourceLocaleFallback(catalog, key) {
|
|
|
20
32
|
}
|
|
21
33
|
return catalog[key].translation || catalog[key].message;
|
|
22
34
|
}
|
|
23
|
-
function getTranslation(catalogs, msg, locale, key, options) {
|
|
24
|
-
const { fallbackLocales, sourceLocale
|
|
35
|
+
function getTranslation(catalogs, msg, locale, key, onMissing, options) {
|
|
36
|
+
const { fallbackLocales, sourceLocale } = options;
|
|
25
37
|
const getTranslation = (_locale) => {
|
|
26
38
|
var _a;
|
|
27
39
|
const localeCatalog = catalogs[_locale];
|
|
@@ -52,7 +64,7 @@ function getTranslation(catalogs, msg, locale, key, options) {
|
|
|
52
64
|
sourceLocale === locale &&
|
|
53
65
|
sourceLocaleFallback(catalogs[sourceLocale], key));
|
|
54
66
|
if (!translation) {
|
|
55
|
-
onMissing
|
|
67
|
+
onMissing({
|
|
56
68
|
id: key,
|
|
57
69
|
source: msg.message || sourceLocaleFallback(catalogs[sourceLocale], key),
|
|
58
70
|
});
|
package/dist/api/catalog.d.ts
CHANGED
|
@@ -1,15 +1,21 @@
|
|
|
1
1
|
import { LinguiConfigNormalized, OrderBy } from "@lingui/conf";
|
|
2
2
|
import { FormatterWrapper } from "./formats";
|
|
3
|
-
import { CliExtractOptions } from "../lingui-extract";
|
|
4
|
-
import { CliExtractTemplateOptions } from "../lingui-extract-template";
|
|
5
3
|
import { CompiledCatalogNamespace } from "./compile";
|
|
6
|
-
import { GetTranslationsOptions
|
|
4
|
+
import { GetTranslationsOptions } from "./catalog/getTranslationsForCatalog";
|
|
7
5
|
import { AllCatalogsType, CatalogType, ExtractedCatalogType } from "./types";
|
|
8
|
-
|
|
6
|
+
import { ExtractWorkerPool } from "./extractWorkerPool";
|
|
7
|
+
export type MakeOptions = {
|
|
8
|
+
files?: string[];
|
|
9
|
+
clean: boolean;
|
|
10
|
+
overwrite: boolean;
|
|
11
|
+
locale: string[];
|
|
9
12
|
orderBy?: OrderBy;
|
|
13
|
+
workerPool?: ExtractWorkerPool;
|
|
10
14
|
};
|
|
11
|
-
export type MakeTemplateOptions =
|
|
15
|
+
export type MakeTemplateOptions = {
|
|
16
|
+
files?: string[];
|
|
12
17
|
orderBy?: OrderBy;
|
|
18
|
+
workerPool?: ExtractWorkerPool;
|
|
13
19
|
};
|
|
14
20
|
export type MergeOptions = {
|
|
15
21
|
overwrite?: boolean;
|
|
@@ -40,21 +46,21 @@ export declare class Catalog {
|
|
|
40
46
|
*/
|
|
41
47
|
collect(options?: {
|
|
42
48
|
files?: string[];
|
|
49
|
+
workerPool?: ExtractWorkerPool;
|
|
43
50
|
}): Promise<ExtractedCatalogType | undefined>;
|
|
44
51
|
merge(prevCatalogs: AllCatalogsType, nextCatalog: ExtractedCatalogType, options: MergeOptions): {
|
|
45
52
|
[k: string]: CatalogType;
|
|
46
53
|
};
|
|
47
|
-
getTranslations(locale: string, options:
|
|
48
|
-
missing: TranslationMissingEvent[];
|
|
54
|
+
getTranslations(locale: string, options: GetTranslationsOptions): Promise<{
|
|
55
|
+
missing: import("./catalog/getTranslationsForCatalog").TranslationMissingEvent[];
|
|
49
56
|
messages: {
|
|
50
57
|
[id: string]: string;
|
|
51
58
|
};
|
|
52
59
|
}>;
|
|
53
60
|
write(locale: string, messages: CatalogType): Promise<[created: boolean, filename: string]>;
|
|
54
61
|
writeTemplate(messages: CatalogType): Promise<void>;
|
|
55
|
-
writeCompiled(locale: string, compiledCatalog: string, namespace?: CompiledCatalogNamespace): Promise<string>;
|
|
56
62
|
read(locale: string): Promise<CatalogType>;
|
|
57
|
-
readAll(): Promise<AllCatalogsType>;
|
|
63
|
+
readAll(locales?: string[]): Promise<AllCatalogsType>;
|
|
58
64
|
readTemplate(): Promise<CatalogType>;
|
|
59
65
|
get sourcePaths(): string[];
|
|
60
66
|
get localeDir(): string;
|
|
@@ -62,4 +68,5 @@ export declare class Catalog {
|
|
|
62
68
|
}
|
|
63
69
|
export declare function cleanObsolete<T extends ExtractedCatalogType>(messages: T): T;
|
|
64
70
|
export declare function order<T extends ExtractedCatalogType>(by: OrderBy, catalog: T): T;
|
|
71
|
+
export declare function writeCompiled(path: string, locale: string, compiledCatalog: string, namespace?: CompiledCatalogNamespace): Promise<string>;
|
|
65
72
|
export declare function orderByMessage<T extends ExtractedCatalogType>(messages: T): T;
|
package/dist/api/catalog.js
CHANGED
|
@@ -6,6 +6,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.Catalog = void 0;
|
|
7
7
|
exports.cleanObsolete = cleanObsolete;
|
|
8
8
|
exports.order = order;
|
|
9
|
+
exports.writeCompiled = writeCompiled;
|
|
9
10
|
exports.orderByMessage = orderByMessage;
|
|
10
11
|
const fs_1 = __importDefault(require("fs"));
|
|
11
12
|
const path_1 = __importDefault(require("path"));
|
|
@@ -35,7 +36,7 @@ class Catalog {
|
|
|
35
36
|
}
|
|
36
37
|
async make(options) {
|
|
37
38
|
const [nextCatalog, prevCatalogs] = await Promise.all([
|
|
38
|
-
this.collect({ files: options.files }),
|
|
39
|
+
this.collect({ files: options.files, workerPool: options.workerPool }),
|
|
39
40
|
this.readAll(),
|
|
40
41
|
]);
|
|
41
42
|
if (!nextCatalog)
|
|
@@ -57,7 +58,10 @@ class Catalog {
|
|
|
57
58
|
return sortedCatalogs;
|
|
58
59
|
}
|
|
59
60
|
async makeTemplate(options) {
|
|
60
|
-
const catalog = await this.collect({
|
|
61
|
+
const catalog = await this.collect({
|
|
62
|
+
files: options.files,
|
|
63
|
+
workerPool: options.workerPool,
|
|
64
|
+
});
|
|
61
65
|
if (!catalog)
|
|
62
66
|
return false;
|
|
63
67
|
const sorted = order(options.orderBy, catalog);
|
|
@@ -74,6 +78,9 @@ class Catalog {
|
|
|
74
78
|
const regex = new RegExp(options.files.join("|"), "i");
|
|
75
79
|
paths = paths.filter((path) => regex.test((0, normalize_path_1.default)(path)));
|
|
76
80
|
}
|
|
81
|
+
if (options.workerPool) {
|
|
82
|
+
return await (0, extractFromFiles_1.extractFromFilesWithWorkerPool)(options.workerPool, paths, this.config);
|
|
83
|
+
}
|
|
77
84
|
return await (0, extractFromFiles_1.extractFromFiles)(paths, this.config);
|
|
78
85
|
}
|
|
79
86
|
/*
|
|
@@ -103,14 +110,7 @@ class Catalog {
|
|
|
103
110
|
]));
|
|
104
111
|
}
|
|
105
112
|
async getTranslations(locale, options) {
|
|
106
|
-
|
|
107
|
-
const messages = await (0, getTranslationsForCatalog_1.getTranslationsForCatalog)(this, locale, Object.assign(Object.assign({}, options), { onMissing: (event) => {
|
|
108
|
-
missing.push(event);
|
|
109
|
-
} }));
|
|
110
|
-
return {
|
|
111
|
-
missing,
|
|
112
|
-
messages,
|
|
113
|
-
};
|
|
113
|
+
return await (0, getTranslationsForCatalog_1.getTranslationsForCatalog)(this, locale, options);
|
|
114
114
|
}
|
|
115
115
|
async write(locale, messages) {
|
|
116
116
|
const filename = this.getFilename(locale);
|
|
@@ -122,29 +122,12 @@ class Catalog {
|
|
|
122
122
|
const filename = this.templateFile;
|
|
123
123
|
await this.format.write(filename, messages, undefined);
|
|
124
124
|
}
|
|
125
|
-
async writeCompiled(locale, compiledCatalog, namespace) {
|
|
126
|
-
let ext;
|
|
127
|
-
switch (namespace) {
|
|
128
|
-
case "es":
|
|
129
|
-
ext = "mjs";
|
|
130
|
-
break;
|
|
131
|
-
case "ts":
|
|
132
|
-
case "json":
|
|
133
|
-
ext = namespace;
|
|
134
|
-
break;
|
|
135
|
-
default:
|
|
136
|
-
ext = "js";
|
|
137
|
-
}
|
|
138
|
-
const filename = `${(0, utils_1.replacePlaceholders)(this.path, { locale })}.${ext}`;
|
|
139
|
-
await (0, utils_1.writeFile)(filename, compiledCatalog);
|
|
140
|
-
return filename;
|
|
141
|
-
}
|
|
142
125
|
async read(locale) {
|
|
143
126
|
return await this.format.read(this.getFilename(locale), locale);
|
|
144
127
|
}
|
|
145
|
-
async readAll() {
|
|
128
|
+
async readAll(locales = this.locales) {
|
|
146
129
|
const res = {};
|
|
147
|
-
await Promise.all(
|
|
130
|
+
await Promise.all(locales.map(async (locale) => (res[locale] = await this.read(locale))));
|
|
148
131
|
// statement above will save locales in object in undetermined order
|
|
149
132
|
// resort here to have keys order the same as in locales definition
|
|
150
133
|
return this.locales.reduce((acc, locale) => {
|
|
@@ -240,6 +223,23 @@ function orderByOrigin(messages) {
|
|
|
240
223
|
return acc;
|
|
241
224
|
}, {});
|
|
242
225
|
}
|
|
226
|
+
async function writeCompiled(path, locale, compiledCatalog, namespace) {
|
|
227
|
+
let ext;
|
|
228
|
+
switch (namespace) {
|
|
229
|
+
case "es":
|
|
230
|
+
ext = "mjs";
|
|
231
|
+
break;
|
|
232
|
+
case "ts":
|
|
233
|
+
case "json":
|
|
234
|
+
ext = namespace;
|
|
235
|
+
break;
|
|
236
|
+
default:
|
|
237
|
+
ext = "js";
|
|
238
|
+
}
|
|
239
|
+
const filename = `${(0, utils_1.replacePlaceholders)(path, { locale })}.${ext}`;
|
|
240
|
+
await (0, utils_1.writeFile)(filename, compiledCatalog);
|
|
241
|
+
return filename;
|
|
242
|
+
}
|
|
243
243
|
function orderByMessage(messages) {
|
|
244
244
|
// hardcoded en-US locale to have consistent sorting
|
|
245
245
|
// @see https://github.com/lingui/js-lingui/pull/1808
|
|
@@ -248,7 +248,9 @@ function orderByMessage(messages) {
|
|
|
248
248
|
.sort((a, b) => {
|
|
249
249
|
const aMsg = messages[a].message || "";
|
|
250
250
|
const bMsg = messages[b].message || "";
|
|
251
|
-
|
|
251
|
+
const aCtxt = messages[a].context || "";
|
|
252
|
+
const bCtxt = messages[b].context || "";
|
|
253
|
+
return collator.compare(aMsg, bMsg) || collator.compare(aCtxt, bCtxt);
|
|
252
254
|
})
|
|
253
255
|
.reduce((acc, key) => {
|
|
254
256
|
;
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { Catalog } from "../catalog";
|
|
2
|
+
import { LinguiConfigNormalized } from "@lingui/conf";
|
|
3
|
+
import { CliCompileOptions } from "../../lingui-compile";
|
|
4
|
+
import { Logger } from "../logger";
|
|
5
|
+
export declare function compileLocale(catalogs: Catalog[], locale: string, options: CliCompileOptions, config: LinguiConfigNormalized, doMerge: boolean, logger: Logger): Promise<void>;
|
|
@@ -0,0 +1,84 @@
|
|
|
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.compileLocale = compileLocale;
|
|
7
|
+
const catalog_1 = require("../catalog");
|
|
8
|
+
const picocolors_1 = __importDefault(require("picocolors"));
|
|
9
|
+
const getCatalogs_1 = require("../catalog/getCatalogs");
|
|
10
|
+
const ProgramExit_1 = require("../ProgramExit");
|
|
11
|
+
const compile_1 = require("../compile");
|
|
12
|
+
const normalize_path_1 = __importDefault(require("normalize-path"));
|
|
13
|
+
const path_1 = __importDefault(require("path"));
|
|
14
|
+
const messages_1 = require("../messages");
|
|
15
|
+
const getTranslationsForCatalog_1 = require("../catalog/getTranslationsForCatalog");
|
|
16
|
+
async function compileLocale(catalogs, locale, options, config, doMerge, logger) {
|
|
17
|
+
let mergedCatalogs = {};
|
|
18
|
+
for (const catalog of catalogs) {
|
|
19
|
+
const { messages, missing: missingMessages } = await (0, getTranslationsForCatalog_1.getTranslationsForCatalog)(catalog, locale, {
|
|
20
|
+
fallbackLocales: config.fallbackLocales,
|
|
21
|
+
sourceLocale: config.sourceLocale,
|
|
22
|
+
});
|
|
23
|
+
if (!options.allowEmpty &&
|
|
24
|
+
locale !== config.pseudoLocale &&
|
|
25
|
+
missingMessages.length > 0) {
|
|
26
|
+
logger.error(picocolors_1.default.red(`Error: Failed to compile catalog for locale ${picocolors_1.default.bold(locale)}!`));
|
|
27
|
+
if (options.verbose) {
|
|
28
|
+
logger.error(picocolors_1.default.red("Missing translations:"));
|
|
29
|
+
missingMessages.forEach((missing) => {
|
|
30
|
+
const source = missing.source || missing.source === missing.id
|
|
31
|
+
? `: (${missing.source})`
|
|
32
|
+
: "";
|
|
33
|
+
logger.error(`${missing.id}${source}`);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
logger.error(picocolors_1.default.red(`Missing ${missingMessages.length} translation(s)`));
|
|
38
|
+
}
|
|
39
|
+
logger.error();
|
|
40
|
+
throw new ProgramExit_1.ProgramExit();
|
|
41
|
+
}
|
|
42
|
+
if (doMerge) {
|
|
43
|
+
mergedCatalogs = Object.assign(Object.assign({}, mergedCatalogs), messages);
|
|
44
|
+
}
|
|
45
|
+
else {
|
|
46
|
+
if (!(await compileAndWrite(locale, config, options, catalog.path, messages, logger))) {
|
|
47
|
+
throw new ProgramExit_1.ProgramExit();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (doMerge) {
|
|
52
|
+
const result = await compileAndWrite(locale, config, options, await (0, getCatalogs_1.getMergedCatalogPath)(config), mergedCatalogs, logger);
|
|
53
|
+
if (!result) {
|
|
54
|
+
throw new ProgramExit_1.ProgramExit();
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
async function compileAndWrite(locale, config, options, writePath, messages, logger) {
|
|
59
|
+
const namespace = options.typescript
|
|
60
|
+
? "ts"
|
|
61
|
+
: options.namespace || config.compileNamespace;
|
|
62
|
+
const { source: compiledCatalog, errors } = (0, compile_1.createCompiledCatalog)(locale, messages, {
|
|
63
|
+
strict: false,
|
|
64
|
+
namespace,
|
|
65
|
+
pseudoLocale: config.pseudoLocale,
|
|
66
|
+
compilerBabelOptions: config.compilerBabelOptions,
|
|
67
|
+
});
|
|
68
|
+
if (errors.length) {
|
|
69
|
+
let message = (0, messages_1.createCompilationErrorMessage)(locale, errors);
|
|
70
|
+
if (options.failOnCompileError) {
|
|
71
|
+
message += `These errors fail command execution because \`--strict\` option passed`;
|
|
72
|
+
logger.error(picocolors_1.default.red(message));
|
|
73
|
+
return false;
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
message += `You can fail command execution on these errors by passing \`--strict\` option`;
|
|
77
|
+
logger.error(picocolors_1.default.red(message));
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
let compiledPath = await (0, catalog_1.writeCompiled)(writePath, locale, compiledCatalog, namespace);
|
|
81
|
+
compiledPath = (0, normalize_path_1.default)(path_1.default.relative(config.rootDir, compiledPath));
|
|
82
|
+
options.verbose && logger.error(picocolors_1.default.green(`${locale} ⇒ ${compiledPath}`));
|
|
83
|
+
return true;
|
|
84
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export type ExtractWorkerPool = ReturnType<typeof createExtractWorkerPool>;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createExtractWorkerPool = createExtractWorkerPool;
|
|
4
|
+
const threads_1 = require("threads");
|
|
5
|
+
/** @internal */
|
|
6
|
+
function createExtractWorkerPool(opts) {
|
|
7
|
+
return (0, threads_1.Pool)(() => (0, threads_1.spawn)(new threads_1.Worker("../workers/extractWorker")), { size: opts.poolSize });
|
|
8
|
+
}
|
|
@@ -120,6 +120,7 @@ function getBabelParserOptions(filename, parserOptions) {
|
|
|
120
120
|
"importAttributes", // stage3
|
|
121
121
|
"explicitResourceManagement", // stage3,
|
|
122
122
|
"decoratorAutoAccessors", // stage3,
|
|
123
|
+
"deferredImportEvaluation", // stage3
|
|
123
124
|
];
|
|
124
125
|
if ([/\.ts$/, /\.mts$/, /\.cts$/, /\.tsx$/].some((r) => filename.match(r))) {
|
|
125
126
|
parserPlugins.push("typescript");
|
|
@@ -1,6 +1,2 @@
|
|
|
1
|
-
import { ExtractedMessage,
|
|
2
|
-
|
|
3
|
-
extractors?: ExtractorType[];
|
|
4
|
-
};
|
|
5
|
-
export default function extract(filename: string, onMessageExtracted: (msg: ExtractedMessage) => void, linguiConfig: LinguiConfigNormalized, options: ExtractOptions): Promise<boolean>;
|
|
6
|
-
export {};
|
|
1
|
+
import { ExtractedMessage, LinguiConfigNormalized } from "@lingui/conf";
|
|
2
|
+
export default function extract(filename: string, onMessageExtracted: (msg: ExtractedMessage) => void, linguiConfig: LinguiConfigNormalized): Promise<boolean>;
|
|
@@ -7,9 +7,9 @@ exports.default = extract;
|
|
|
7
7
|
const promises_1 = __importDefault(require("fs/promises"));
|
|
8
8
|
const babel_1 = __importDefault(require("./babel"));
|
|
9
9
|
const DEFAULT_EXTRACTORS = [babel_1.default];
|
|
10
|
-
async function extract(filename, onMessageExtracted, linguiConfig
|
|
10
|
+
async function extract(filename, onMessageExtracted, linguiConfig) {
|
|
11
11
|
var _a;
|
|
12
|
-
const extractorsToExtract = (_a =
|
|
12
|
+
const extractorsToExtract = (_a = linguiConfig.extractors) !== null && _a !== void 0 ? _a : DEFAULT_EXTRACTORS;
|
|
13
13
|
for (const ext of extractorsToExtract) {
|
|
14
14
|
if (!ext.match(filename))
|
|
15
15
|
continue;
|
|
@@ -0,0 +1,21 @@
|
|
|
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.resolveWorkersOptions = resolveWorkersOptions;
|
|
7
|
+
const node_os_1 = __importDefault(require("node:os"));
|
|
8
|
+
function resolveWorkersOptions(opts) {
|
|
9
|
+
const cores = node_os_1.default.availableParallelism();
|
|
10
|
+
if (Number(opts.workers) <= 1 || cores === 1) {
|
|
11
|
+
return { poolSize: 0 };
|
|
12
|
+
}
|
|
13
|
+
if (!opts.workers) {
|
|
14
|
+
if (cores <= 2) {
|
|
15
|
+
return { poolSize: cores }; // on tiny machines, use all
|
|
16
|
+
}
|
|
17
|
+
// on big machines cap to 8, to avoid trashing
|
|
18
|
+
return { poolSize: Math.min(cores - 1, 8) };
|
|
19
|
+
}
|
|
20
|
+
return { poolSize: Number(opts.workers) };
|
|
21
|
+
}
|
package/dist/api/stats.js
CHANGED
|
@@ -25,7 +25,15 @@ function printStats(config, catalogs) {
|
|
|
25
25
|
compact: true,
|
|
26
26
|
},
|
|
27
27
|
});
|
|
28
|
-
Object.keys(catalogs)
|
|
28
|
+
Object.keys(catalogs)
|
|
29
|
+
.sort((a, b) => {
|
|
30
|
+
if (a === config.sourceLocale && b !== config.sourceLocale)
|
|
31
|
+
return -1;
|
|
32
|
+
if (b === config.sourceLocale && a !== config.sourceLocale)
|
|
33
|
+
return 1;
|
|
34
|
+
return a.localeCompare(b);
|
|
35
|
+
})
|
|
36
|
+
.forEach((locale) => {
|
|
29
37
|
if (locale === config.pseudoLocale)
|
|
30
38
|
return; // skip pseudo locale
|
|
31
39
|
const catalog = catalogs[locale];
|