@lingui/cli 4.11.1 → 5.0.0-next.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/catalog/extractFromFiles.js +14 -1
- package/dist/api/catalog.js +1 -1
- package/dist/api/compile.js +4 -5
- package/dist/api/extractors/babel.d.ts +4 -3
- package/dist/api/extractors/babel.js +41 -39
- package/dist/extract-experimental/bundleSource.d.ts +2 -2
- package/dist/extract-experimental/bundleSource.js +5 -21
- package/dist/extract-experimental/linguiEsbuildPlugin.d.ts +5 -0
- package/dist/extract-experimental/linguiEsbuildPlugin.js +45 -0
- package/dist/lingui-extract-experimental.js +15 -1
- package/dist/lingui-extract.d.ts +1 -1
- package/dist/lingui-extract.js +13 -5
- package/dist/services/translationIO.js +39 -5
- package/package.json +10 -10
- package/dist/extract-experimental/buildExternalizeFilter.d.ts +0 -13
- package/dist/extract-experimental/buildExternalizeFilter.js +0 -47
|
@@ -8,6 +8,18 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
8
8
|
const path_1 = __importDefault(require("path"));
|
|
9
9
|
const extractors_1 = __importDefault(require("../extractors"));
|
|
10
10
|
const utils_1 = require("../utils");
|
|
11
|
+
function mergePlaceholders(prev, next) {
|
|
12
|
+
const res = Object.assign({}, prev);
|
|
13
|
+
Object.entries(next).forEach(([key, value]) => {
|
|
14
|
+
if (!res[key]) {
|
|
15
|
+
res[key] = [];
|
|
16
|
+
}
|
|
17
|
+
if (!res[key].includes(value)) {
|
|
18
|
+
res[key].push(value);
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return res;
|
|
22
|
+
}
|
|
11
23
|
async function extractFromFiles(paths, config) {
|
|
12
24
|
const messages = {};
|
|
13
25
|
let catalogSuccess = true;
|
|
@@ -18,6 +30,7 @@ async function extractFromFiles(paths, config) {
|
|
|
18
30
|
messages[next.id] = {
|
|
19
31
|
message: next.message,
|
|
20
32
|
context: next.context,
|
|
33
|
+
placeholders: {},
|
|
21
34
|
comments: [],
|
|
22
35
|
origin: [],
|
|
23
36
|
};
|
|
@@ -35,7 +48,7 @@ async function extractFromFiles(paths, config) {
|
|
|
35
48
|
}
|
|
36
49
|
messages[next.id] = Object.assign(Object.assign({}, prev), { message: (_a = prev.message) !== null && _a !== void 0 ? _a : next.message, comments: next.comment
|
|
37
50
|
? [...prev.comments, next.comment]
|
|
38
|
-
: prev.comments, origin: [...prev.origin, [filename, next.origin[1]]] });
|
|
51
|
+
: prev.comments, origin: [...prev.origin, [filename, next.origin[1]]], placeholders: mergePlaceholders(prev.placeholders, next.placeholders) });
|
|
39
52
|
}, config, {
|
|
40
53
|
extractors: config.extractors,
|
|
41
54
|
});
|
package/dist/api/catalog.js
CHANGED
|
@@ -70,7 +70,7 @@ class Catalog {
|
|
|
70
70
|
// Sort messages
|
|
71
71
|
order(options.orderBy)));
|
|
72
72
|
const sortedCatalogs = cleanAndSort(catalogs);
|
|
73
|
-
const locales = options.locale ?
|
|
73
|
+
const locales = options.locale ? options.locale : this.locales;
|
|
74
74
|
await Promise.all(locales.map((locale) => this.write(locale, sortedCatalogs[locale])));
|
|
75
75
|
return sortedCatalogs;
|
|
76
76
|
}
|
package/dist/api/compile.js
CHANGED
|
@@ -57,12 +57,11 @@ function buildExportStatement(expression, namespace) {
|
|
|
57
57
|
// import type { Messages } from "@lingui/core";
|
|
58
58
|
const importMessagesTypeDeclaration = t.importDeclaration([t.importSpecifier(t.identifier("Messages"), t.identifier("Messages"))], t.stringLiteral("@lingui/core"));
|
|
59
59
|
importMessagesTypeDeclaration.importKind = "type";
|
|
60
|
-
//
|
|
61
|
-
const
|
|
62
|
-
|
|
63
|
-
// export const messages:Messages = { message: "Translation" }
|
|
60
|
+
// Cast the expression to `Messages`
|
|
61
|
+
const castExpression = t.tsAsExpression(expression, t.tsTypeReference(t.identifier("Messages")));
|
|
62
|
+
// export const messages = ({ message: "Translation" } as Messages)
|
|
64
63
|
const exportDeclaration = t.exportNamedDeclaration(t.variableDeclaration("const", [
|
|
65
|
-
t.variableDeclarator(
|
|
64
|
+
t.variableDeclarator(t.identifier("messages"), castExpression),
|
|
66
65
|
]));
|
|
67
66
|
return t.program([importMessagesTypeDeclaration, exportDeclaration]);
|
|
68
67
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ParserOptions } from "@babel/core";
|
|
2
|
-
import
|
|
3
|
-
|
|
2
|
+
import { ExtractorType, LinguiConfig, ExtractedMessage, ExtractorCtx } from "@lingui/conf";
|
|
3
|
+
export declare const babelRe: RegExp;
|
|
4
4
|
/**
|
|
5
5
|
* @public
|
|
6
6
|
*
|
|
@@ -26,6 +26,7 @@ import { ExtractedMessage, ExtractorCtx } from "@lingui/conf";
|
|
|
26
26
|
* }
|
|
27
27
|
* ```
|
|
28
28
|
*/
|
|
29
|
-
export declare function extractFromFileWithBabel(filename: string, code: string, onMessageExtracted: (msg: ExtractedMessage) => void, ctx: ExtractorCtx, parserOpts: ParserOptions): Promise<void>;
|
|
29
|
+
export declare function extractFromFileWithBabel(filename: string, code: string, onMessageExtracted: (msg: ExtractedMessage) => void, ctx: ExtractorCtx, parserOpts: ParserOptions, skipMacroPlugin?: boolean): Promise<void>;
|
|
30
|
+
export declare function getBabelParserOptions(filename: string, parserOptions: LinguiConfig["extractorParserOptions"]): (import("@babel/parser").ParserPluginWithOptions | ("decimal" | "placeholders" | "asyncDoExpressions" | "asyncGenerators" | "bigInt" | "classPrivateMethods" | "classPrivateProperties" | "classProperties" | "classStaticBlock" | "decorators-legacy" | "decoratorAutoAccessors" | "destructuringPrivate" | "doExpressions" | "dynamicImport" | "explicitResourceManagement" | "exportDefaultFrom" | "exportNamespaceFrom" | "flow" | "flowComments" | "functionBind" | "functionSent" | "importMeta" | "jsx" | "logicalAssignment" | "importAssertions" | "importReflection" | "moduleBlocks" | "moduleStringNames" | "nullishCoalescingOperator" | "numericSeparator" | "objectRestSpread" | "optionalCatchBinding" | "optionalChaining" | "partialApplication" | "privateIn" | "regexpUnicodeSets" | "throwExpressions" | "topLevelAwait" | "v8intrinsic" | "decorators" | "estree" | "moduleAttributes" | "pipelineOperator" | "recordAndTuple" | "typescript"))[];
|
|
30
31
|
declare const extractor: ExtractorType;
|
|
31
32
|
export default extractor;
|
|
@@ -3,10 +3,11 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
3
3
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
4
|
};
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.extractFromFileWithBabel = void 0;
|
|
6
|
+
exports.getBabelParserOptions = exports.extractFromFileWithBabel = exports.babelRe = void 0;
|
|
7
7
|
const core_1 = require("@babel/core");
|
|
8
8
|
const babel_plugin_extract_messages_1 = __importDefault(require("@lingui/babel-plugin-extract-messages"));
|
|
9
|
-
const
|
|
9
|
+
const babel_plugin_lingui_macro_1 = __importDefault(require("@lingui/babel-plugin-lingui-macro"));
|
|
10
|
+
exports.babelRe = new RegExp("\\.(" +
|
|
10
11
|
[...core_1.DEFAULT_EXTENSIONS, ".ts", ".mts", ".cts", ".tsx"]
|
|
11
12
|
.map((ext) => ext.slice(1))
|
|
12
13
|
.join("|") +
|
|
@@ -76,7 +77,7 @@ async function createSourceMapper(code, sourceMaps) {
|
|
|
76
77
|
* }
|
|
77
78
|
* ```
|
|
78
79
|
*/
|
|
79
|
-
async function extractFromFileWithBabel(filename, code, onMessageExtracted, ctx, parserOpts) {
|
|
80
|
+
async function extractFromFileWithBabel(filename, code, onMessageExtracted, ctx, parserOpts, skipMacroPlugin = false) {
|
|
80
81
|
const mapper = await createSourceMapper(code, ctx === null || ctx === void 0 ? void 0 : ctx.sourceMaps);
|
|
81
82
|
await (0, core_1.transformAsync)(code, {
|
|
82
83
|
// don't generate code
|
|
@@ -87,20 +88,17 @@ async function extractFromFileWithBabel(filename, code, onMessageExtracted, ctx,
|
|
|
87
88
|
inputSourceMap: ctx === null || ctx === void 0 ? void 0 : ctx.sourceMaps,
|
|
88
89
|
parserOpts,
|
|
89
90
|
plugins: [
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
},
|
|
102
|
-
},
|
|
103
|
-
],
|
|
91
|
+
...(!skipMacroPlugin
|
|
92
|
+
? [
|
|
93
|
+
[
|
|
94
|
+
babel_plugin_lingui_macro_1.default,
|
|
95
|
+
{
|
|
96
|
+
extract: true,
|
|
97
|
+
linguiConfig: ctx.linguiConfig,
|
|
98
|
+
},
|
|
99
|
+
],
|
|
100
|
+
]
|
|
101
|
+
: []),
|
|
104
102
|
[
|
|
105
103
|
babel_plugin_extract_messages_1.default,
|
|
106
104
|
{
|
|
@@ -114,34 +112,38 @@ async function extractFromFileWithBabel(filename, code, onMessageExtracted, ctx,
|
|
|
114
112
|
mapper.destroy();
|
|
115
113
|
}
|
|
116
114
|
exports.extractFromFileWithBabel = extractFromFileWithBabel;
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
const parserPlugins = [];
|
|
125
|
-
if ([/\.ts$/, /\.mts$/, /\.cts$/, /\.tsx$/].some((r) => filename.match(r))) {
|
|
126
|
-
parserPlugins.push("typescript");
|
|
127
|
-
if (parserOptions.tsExperimentalDecorators) {
|
|
128
|
-
parserPlugins.push("decorators-legacy");
|
|
129
|
-
}
|
|
130
|
-
else {
|
|
131
|
-
parserPlugins.push("decorators");
|
|
132
|
-
}
|
|
115
|
+
function getBabelParserOptions(filename, parserOptions) {
|
|
116
|
+
// https://babeljs.io/docs/en/babel-parser#latest-ecmascript-features
|
|
117
|
+
const parserPlugins = [];
|
|
118
|
+
if ([/\.ts$/, /\.mts$/, /\.cts$/, /\.tsx$/].some((r) => filename.match(r))) {
|
|
119
|
+
parserPlugins.push("typescript");
|
|
120
|
+
if (parserOptions.tsExperimentalDecorators) {
|
|
121
|
+
parserPlugins.push("decorators-legacy");
|
|
133
122
|
}
|
|
134
123
|
else {
|
|
135
124
|
parserPlugins.push("decorators");
|
|
136
|
-
if (parserOptions === null || parserOptions === void 0 ? void 0 : parserOptions.flow) {
|
|
137
|
-
parserPlugins.push("flow");
|
|
138
|
-
}
|
|
139
125
|
}
|
|
140
|
-
|
|
141
|
-
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
parserPlugins.push("decorators");
|
|
129
|
+
if (parserOptions === null || parserOptions === void 0 ? void 0 : parserOptions.flow) {
|
|
130
|
+
parserPlugins.push("flow");
|
|
142
131
|
}
|
|
132
|
+
}
|
|
133
|
+
if ([/\.js$/, /\.jsx$/, /\.tsx$/].some((r) => filename.match(r))) {
|
|
134
|
+
parserPlugins.push("jsx");
|
|
135
|
+
}
|
|
136
|
+
return parserPlugins;
|
|
137
|
+
}
|
|
138
|
+
exports.getBabelParserOptions = getBabelParserOptions;
|
|
139
|
+
const extractor = {
|
|
140
|
+
match(filename) {
|
|
141
|
+
return exports.babelRe.test(filename);
|
|
142
|
+
},
|
|
143
|
+
async extract(filename, code, onMessageExtracted, ctx) {
|
|
144
|
+
const parserOptions = ctx.linguiConfig.extractorParserOptions;
|
|
143
145
|
return extractFromFileWithBabel(filename, code, onMessageExtracted, ctx, {
|
|
144
|
-
plugins:
|
|
146
|
+
plugins: getBabelParserOptions(filename, parserOptions),
|
|
145
147
|
});
|
|
146
148
|
},
|
|
147
149
|
};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export declare function bundleSource(
|
|
1
|
+
import { LinguiConfigNormalized } from "@lingui/conf";
|
|
2
|
+
export declare function bundleSource(linguiConfig: LinguiConfigNormalized, entryPoints: string[], outDir: string, rootDir: string): Promise<import("esbuild").BuildResult<any>>;
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.bundleSource = void 0;
|
|
4
|
-
const
|
|
4
|
+
const linguiEsbuildPlugin_1 = require("./linguiEsbuildPlugin");
|
|
5
5
|
function createExtRegExp(extensions) {
|
|
6
6
|
return new RegExp("\\.(?:" + extensions.join("|") + ")(?:\\?.*)?$");
|
|
7
7
|
}
|
|
8
|
-
async function bundleSource(
|
|
8
|
+
async function bundleSource(linguiConfig, entryPoints, outDir, rootDir) {
|
|
9
9
|
const esbuild = await import("esbuild");
|
|
10
|
+
const config = linguiConfig.experimental.extractor;
|
|
10
11
|
const excludeExtensions = config.excludeExtensions || [
|
|
11
12
|
"ico",
|
|
12
13
|
"pot",
|
|
@@ -26,7 +27,6 @@ async function bundleSource(config, entryPoints, outDir, rootDir) {
|
|
|
26
27
|
"less",
|
|
27
28
|
"jpg",
|
|
28
29
|
];
|
|
29
|
-
const packageJson = await (0, buildExternalizeFilter_1.getPackageJson)(rootDir);
|
|
30
30
|
const esbuildOptions = {
|
|
31
31
|
entryPoints: entryPoints,
|
|
32
32
|
outExtension: { ".js": ".jsx" },
|
|
@@ -41,27 +41,11 @@ async function bundleSource(config, entryPoints, outDir, rootDir) {
|
|
|
41
41
|
sourcemap: "inline",
|
|
42
42
|
sourceRoot: outDir,
|
|
43
43
|
sourcesContent: false,
|
|
44
|
+
packages: "external",
|
|
44
45
|
outbase: rootDir,
|
|
45
46
|
metafile: true,
|
|
46
47
|
plugins: [
|
|
47
|
-
{
|
|
48
|
-
name: "externalize-deps",
|
|
49
|
-
setup(build) {
|
|
50
|
-
const isExternal = (0, buildExternalizeFilter_1.buildExternalizeFilter)({
|
|
51
|
-
includeDeps: config.includeDeps || [],
|
|
52
|
-
excludeDeps: config.excludeDeps || [],
|
|
53
|
-
packageJson,
|
|
54
|
-
});
|
|
55
|
-
// externalize bare imports
|
|
56
|
-
build.onResolve({ filter: /^[^.].*/ }, async ({ path: id }) => {
|
|
57
|
-
if (isExternal(id)) {
|
|
58
|
-
return {
|
|
59
|
-
external: true,
|
|
60
|
-
};
|
|
61
|
-
}
|
|
62
|
-
});
|
|
63
|
-
},
|
|
64
|
-
},
|
|
48
|
+
(0, linguiEsbuildPlugin_1.pluginLinguiMacro)({ linguiConfig }),
|
|
65
49
|
{
|
|
66
50
|
name: "externalize-files",
|
|
67
51
|
setup(build) {
|
|
@@ -0,0 +1,45 @@
|
|
|
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.pluginLinguiMacro = void 0;
|
|
7
|
+
const core_1 = require("@babel/core");
|
|
8
|
+
const fs_1 = __importDefault(require("fs"));
|
|
9
|
+
const path_1 = __importDefault(require("path"));
|
|
10
|
+
const babel_1 = require("../api/extractors/babel");
|
|
11
|
+
const babel_plugin_lingui_macro_1 = __importDefault(require("@lingui/babel-plugin-lingui-macro"));
|
|
12
|
+
const pluginLinguiMacro = (options) => ({
|
|
13
|
+
name: "linguiMacro",
|
|
14
|
+
setup(build) {
|
|
15
|
+
build.onLoad({ filter: babel_1.babelRe, namespace: "" }, async (args) => {
|
|
16
|
+
const filename = path_1.default.relative(process.cwd(), args.path);
|
|
17
|
+
const contents = await fs_1.default.promises.readFile(args.path, "utf8");
|
|
18
|
+
const hasMacroRe = /from ["']@lingui(\/.+)?\/macro["']/g;
|
|
19
|
+
if (!hasMacroRe.test(contents)) {
|
|
20
|
+
// let esbuild process file as usual
|
|
21
|
+
return undefined;
|
|
22
|
+
}
|
|
23
|
+
const result = await (0, core_1.transformAsync)(contents, {
|
|
24
|
+
babelrc: false,
|
|
25
|
+
configFile: false,
|
|
26
|
+
filename: filename,
|
|
27
|
+
sourceMaps: "inline",
|
|
28
|
+
parserOpts: {
|
|
29
|
+
plugins: (0, babel_1.getBabelParserOptions)(filename, options.linguiConfig.extractorParserOptions),
|
|
30
|
+
},
|
|
31
|
+
plugins: [
|
|
32
|
+
[
|
|
33
|
+
babel_plugin_lingui_macro_1.default,
|
|
34
|
+
{
|
|
35
|
+
extract: true,
|
|
36
|
+
linguiConfig: options.linguiConfig,
|
|
37
|
+
},
|
|
38
|
+
],
|
|
39
|
+
],
|
|
40
|
+
});
|
|
41
|
+
return { contents: result.code, loader: "jsx" };
|
|
42
|
+
});
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
exports.pluginLinguiMacro = pluginLinguiMacro;
|
|
@@ -16,6 +16,7 @@ const bundleSource_1 = require("./extract-experimental/bundleSource");
|
|
|
16
16
|
const writeCatalogs_1 = require("./extract-experimental/writeCatalogs");
|
|
17
17
|
const getEntryPoints_1 = require("./extract-experimental/getEntryPoints");
|
|
18
18
|
const chalk_1 = __importDefault(require("chalk"));
|
|
19
|
+
const babel_1 = require("./api/extractors/babel");
|
|
19
20
|
async function command(linguiConfig, options) {
|
|
20
21
|
var _a;
|
|
21
22
|
options.verbose && console.log("Extracting messages from source files…");
|
|
@@ -31,10 +32,23 @@ async function command(linguiConfig, options) {
|
|
|
31
32
|
].join("\n")));
|
|
32
33
|
const tempDir = await promises_1.default.mkdtemp(path_1.default.join(os_1.default.tmpdir(), "js-lingui-extract-"));
|
|
33
34
|
await promises_1.default.rm(tempDir, { recursive: true, force: true });
|
|
34
|
-
const bundleResult = await (0, bundleSource_1.bundleSource)(
|
|
35
|
+
const bundleResult = await (0, bundleSource_1.bundleSource)(linguiConfig, (0, getEntryPoints_1.getEntryPoints)(config.entries), tempDir, linguiConfig.rootDir);
|
|
35
36
|
const stats = [];
|
|
36
37
|
let commandSuccess = true;
|
|
37
38
|
const format = await (0, formats_1.getFormat)(linguiConfig.format, linguiConfig.formatOptions, linguiConfig.sourceLocale);
|
|
39
|
+
linguiConfig.extractors = [
|
|
40
|
+
{
|
|
41
|
+
match(_filename) {
|
|
42
|
+
return true;
|
|
43
|
+
},
|
|
44
|
+
async extract(filename, code, onMessageExtracted, ctx) {
|
|
45
|
+
const parserOptions = ctx.linguiConfig.extractorParserOptions;
|
|
46
|
+
return (0, babel_1.extractFromFileWithBabel)(filename, code, onMessageExtracted, ctx, {
|
|
47
|
+
plugins: (0, babel_1.getBabelParserOptions)(filename, parserOptions),
|
|
48
|
+
}, true);
|
|
49
|
+
},
|
|
50
|
+
},
|
|
51
|
+
];
|
|
38
52
|
for (const outFile of Object.keys(bundleResult.metafile.outputs)) {
|
|
39
53
|
const messages = await (0, extractFromFiles_1.extractFromFiles)([outFile], linguiConfig);
|
|
40
54
|
const { entryPoint } = bundleResult.metafile.outputs[outFile];
|
package/dist/lingui-extract.d.ts
CHANGED
package/dist/lingui-extract.js
CHANGED
|
@@ -61,7 +61,12 @@ exports.default = command;
|
|
|
61
61
|
if (require.main === module) {
|
|
62
62
|
commander_1.program
|
|
63
63
|
.option("--config <path>", "Path to the config file")
|
|
64
|
-
.option("--locale <locale>", "Only extract the specified
|
|
64
|
+
.option("--locale <locale, [...]>", "Only extract the specified locales", (value) => {
|
|
65
|
+
return value
|
|
66
|
+
.split(",")
|
|
67
|
+
.map((s) => s.trim())
|
|
68
|
+
.filter(Boolean);
|
|
69
|
+
})
|
|
65
70
|
.option("--overwrite", "Overwrite translations for source locale")
|
|
66
71
|
.option("--clean", "Remove obsolete translations")
|
|
67
72
|
.option("--debounce <delay>", "Debounces extraction for given amount of milliseconds")
|
|
@@ -85,10 +90,13 @@ if (require.main === module) {
|
|
|
85
90
|
console.log(chalk_1.default.yellow((0, help_1.helpRun)(`extract --convert-from lingui`)));
|
|
86
91
|
process.exit(1);
|
|
87
92
|
}
|
|
88
|
-
if (options.locale
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
93
|
+
if (options.locale) {
|
|
94
|
+
const missingLocale = options.locale.find((l) => !config.locales.includes(l));
|
|
95
|
+
if (missingLocale) {
|
|
96
|
+
hasErrors = true;
|
|
97
|
+
console.error(`Locale ${chalk_1.default.bold(missingLocale)} does not exist.`);
|
|
98
|
+
console.error();
|
|
99
|
+
}
|
|
92
100
|
}
|
|
93
101
|
if (hasErrors)
|
|
94
102
|
process.exit(1);
|
|
@@ -9,6 +9,8 @@ const pofile_1 = __importDefault(require("pofile"));
|
|
|
9
9
|
const https_1 = __importDefault(require("https"));
|
|
10
10
|
const glob_1 = __importDefault(require("glob"));
|
|
11
11
|
const date_fns_1 = require("date-fns");
|
|
12
|
+
const EXPLICIT_ID_FLAG = "js-lingui-explicit-id";
|
|
13
|
+
const EXPLICIT_ID_AND_CONTEXT_FLAG = "js-lingui-explicit-id-and-context";
|
|
12
14
|
const getCreateHeaders = (language) => ({
|
|
13
15
|
"POT-Creation-Date": (0, date_fns_1.format)(new Date(), "yyyy-MM-dd HH:mmxxxx"),
|
|
14
16
|
"MIME-Version": "1.0",
|
|
@@ -141,32 +143,64 @@ function sync(config, options, successCallback, failCallback) {
|
|
|
141
143
|
});
|
|
142
144
|
}
|
|
143
145
|
function createSegmentFromPoItem(item) {
|
|
144
|
-
const
|
|
146
|
+
const itemHasExplicitId = item.extractedComments.includes(EXPLICIT_ID_FLAG);
|
|
147
|
+
const itemHasContext = item.msgctxt != null;
|
|
145
148
|
const segment = {
|
|
146
149
|
type: "source",
|
|
147
|
-
source:
|
|
150
|
+
source: "",
|
|
148
151
|
context: "",
|
|
149
152
|
references: [],
|
|
150
153
|
comment: "",
|
|
151
154
|
};
|
|
152
|
-
|
|
155
|
+
// For segment.source & segment.context, we must remain compatible with projects created/synced before Lingui V4
|
|
156
|
+
if (itemHasExplicitId) {
|
|
157
|
+
segment.source = item.msgstr[0];
|
|
153
158
|
segment.context = item.msgid;
|
|
154
159
|
}
|
|
160
|
+
else {
|
|
161
|
+
segment.source = item.msgid;
|
|
162
|
+
if (itemHasContext) {
|
|
163
|
+
segment.context = item.msgctxt;
|
|
164
|
+
}
|
|
165
|
+
}
|
|
155
166
|
if (item.references.length) {
|
|
156
167
|
segment.references = item.references;
|
|
157
168
|
}
|
|
169
|
+
// Since Lingui v4, when using explicit IDs, Lingui automatically adds 'js-lingui-explicit-id' to the extractedComments array
|
|
158
170
|
if (item.extractedComments.length) {
|
|
159
171
|
segment.comment = item.extractedComments.join(" | ");
|
|
172
|
+
if (itemHasExplicitId && itemHasContext) {
|
|
173
|
+
// segment.context is already used for the explicit ID, so we need to pass the context (for translators) in segment.comment
|
|
174
|
+
segment.comment = `${item.msgctxt} | ${segment.comment}`;
|
|
175
|
+
// Replace the flag to let us know how to recompose a target PO Item that is consistent with the source PO Item
|
|
176
|
+
segment.comment = segment.comment.replace(EXPLICIT_ID_FLAG, EXPLICIT_ID_AND_CONTEXT_FLAG);
|
|
177
|
+
}
|
|
160
178
|
}
|
|
161
179
|
return segment;
|
|
162
180
|
}
|
|
163
181
|
function createPoItemFromSegment(segment) {
|
|
182
|
+
var _a, _b;
|
|
183
|
+
const segmentHasExplicitId = (_a = segment.comment) === null || _a === void 0 ? void 0 : _a.includes(EXPLICIT_ID_FLAG);
|
|
184
|
+
const segmentHasExplicitIdAndContext = (_b = segment.comment) === null || _b === void 0 ? void 0 : _b.includes(EXPLICIT_ID_AND_CONTEXT_FLAG);
|
|
164
185
|
const item = new pofile_1.default.Item();
|
|
165
|
-
|
|
186
|
+
if (segmentHasExplicitId || segmentHasExplicitIdAndContext) {
|
|
187
|
+
item.msgid = segment.context;
|
|
188
|
+
}
|
|
189
|
+
else {
|
|
190
|
+
item.msgid = segment.source;
|
|
191
|
+
item.msgctxt = segment.context;
|
|
192
|
+
}
|
|
166
193
|
item.msgstr = [segment.target];
|
|
167
194
|
item.references =
|
|
168
195
|
segment.references && segment.references.length ? segment.references : [];
|
|
169
|
-
|
|
196
|
+
if (segment.comment) {
|
|
197
|
+
segment.comment = segment.comment.replace(EXPLICIT_ID_AND_CONTEXT_FLAG, EXPLICIT_ID_FLAG);
|
|
198
|
+
item.extractedComments = segment.comment ? segment.comment.split(" | ") : [];
|
|
199
|
+
// We recompose a target PO Item that is consistent with the source PO Item
|
|
200
|
+
if (segmentHasExplicitIdAndContext) {
|
|
201
|
+
item.msgctxt = item.extractedComments.shift();
|
|
202
|
+
}
|
|
203
|
+
}
|
|
170
204
|
return item;
|
|
171
205
|
}
|
|
172
206
|
function saveSegmentsToTargetPos(config, paths, segmentsPerLocale) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lingui/cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "5.0.0-next.0",
|
|
4
4
|
"description": "CLI for working wit message catalogs",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"cli",
|
|
@@ -53,11 +53,12 @@
|
|
|
53
53
|
"@babel/parser": "^7.21.2",
|
|
54
54
|
"@babel/runtime": "^7.21.0",
|
|
55
55
|
"@babel/types": "^7.21.2",
|
|
56
|
-
"@lingui/babel-plugin-extract-messages": "
|
|
57
|
-
"@lingui/
|
|
58
|
-
"@lingui/
|
|
59
|
-
"@lingui/
|
|
60
|
-
"@lingui/
|
|
56
|
+
"@lingui/babel-plugin-extract-messages": "^5.0.0-next.0",
|
|
57
|
+
"@lingui/babel-plugin-lingui-macro": "^5.0.0-next.0",
|
|
58
|
+
"@lingui/conf": "^5.0.0-next.0",
|
|
59
|
+
"@lingui/core": "^5.0.0-next.0",
|
|
60
|
+
"@lingui/format-po": "^5.0.0-next.0",
|
|
61
|
+
"@lingui/message-utils": "^5.0.0-next.0",
|
|
61
62
|
"babel-plugin-macros": "^3.0.1",
|
|
62
63
|
"chalk": "^4.1.0",
|
|
63
64
|
"chokidar": "3.5.1",
|
|
@@ -65,7 +66,7 @@
|
|
|
65
66
|
"commander": "^10.0.0",
|
|
66
67
|
"convert-source-map": "^2.0.0",
|
|
67
68
|
"date-fns": "^3.6.0",
|
|
68
|
-
"esbuild": "^0.
|
|
69
|
+
"esbuild": "^0.21.5",
|
|
69
70
|
"glob": "^7.1.4",
|
|
70
71
|
"inquirer": "^7.3.3",
|
|
71
72
|
"micromatch": "4.0.2",
|
|
@@ -79,8 +80,7 @@
|
|
|
79
80
|
"source-map": "^0.8.0-beta.0"
|
|
80
81
|
},
|
|
81
82
|
"devDependencies": {
|
|
82
|
-
"@lingui/jest-mocks": "
|
|
83
|
-
"@lingui/macro": "4.11.1",
|
|
83
|
+
"@lingui/jest-mocks": "^3.0.3",
|
|
84
84
|
"@types/convert-source-map": "^2.0.0",
|
|
85
85
|
"@types/glob": "^8.1.0",
|
|
86
86
|
"@types/micromatch": "^4.0.1",
|
|
@@ -88,5 +88,5 @@
|
|
|
88
88
|
"mock-fs": "^5.2.0",
|
|
89
89
|
"mockdate": "^3.0.5"
|
|
90
90
|
},
|
|
91
|
-
"gitHead": "
|
|
91
|
+
"gitHead": "2192f8d54699a3846ff8fe6f3992697be2da68a8"
|
|
92
92
|
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
type PackageJson = {
|
|
2
|
-
dependencies?: Record<string, string>;
|
|
3
|
-
devDependencies?: Record<string, string>;
|
|
4
|
-
peerDependencies?: Record<string, string>;
|
|
5
|
-
optionalDependencies?: Record<string, string>;
|
|
6
|
-
};
|
|
7
|
-
export declare function buildExternalizeFilter({ includeDeps, excludeDeps, packageJson, }: {
|
|
8
|
-
includeDeps: string[];
|
|
9
|
-
excludeDeps: string[];
|
|
10
|
-
packageJson: PackageJson;
|
|
11
|
-
}): (id: string) => boolean;
|
|
12
|
-
export declare function getPackageJson(rootDir: string): Promise<PackageJson>;
|
|
13
|
-
export {};
|
|
@@ -1,47 +0,0 @@
|
|
|
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.getPackageJson = exports.buildExternalizeFilter = void 0;
|
|
7
|
-
const node_fs_1 = __importDefault(require("node:fs"));
|
|
8
|
-
function createPackageRegExp(packageName) {
|
|
9
|
-
return new RegExp("^" + packageName + "(?:\\/.+)?");
|
|
10
|
-
}
|
|
11
|
-
function packages(packages, includeDeps) {
|
|
12
|
-
return Object.keys(packages || {})
|
|
13
|
-
.filter((packageName) => {
|
|
14
|
-
return !includeDeps.some((incl) => packageName.startsWith(incl));
|
|
15
|
-
})
|
|
16
|
-
.map(createPackageRegExp);
|
|
17
|
-
}
|
|
18
|
-
function buildExternalizeFilter({ includeDeps, excludeDeps, packageJson, }) {
|
|
19
|
-
const external = [
|
|
20
|
-
...packages(packageJson.dependencies, includeDeps),
|
|
21
|
-
...packages(packageJson.devDependencies, includeDeps),
|
|
22
|
-
...packages(packageJson.peerDependencies, includeDeps),
|
|
23
|
-
...packages(packageJson.optionalDependencies, includeDeps),
|
|
24
|
-
...excludeDeps.map(createPackageRegExp),
|
|
25
|
-
];
|
|
26
|
-
return (id) => external.some((regExp) => {
|
|
27
|
-
return regExp.test(id);
|
|
28
|
-
});
|
|
29
|
-
}
|
|
30
|
-
exports.buildExternalizeFilter = buildExternalizeFilter;
|
|
31
|
-
async function getPackageJson(rootDir) {
|
|
32
|
-
const { default: pkgUp } = await import("pkg-up");
|
|
33
|
-
const packageJsonPath = await pkgUp({
|
|
34
|
-
cwd: rootDir,
|
|
35
|
-
});
|
|
36
|
-
if (!packageJsonPath) {
|
|
37
|
-
throw new Error("We could not able to find your package.json file. " +
|
|
38
|
-
"Check that `rootDir` is pointing to the folder with package.json");
|
|
39
|
-
}
|
|
40
|
-
try {
|
|
41
|
-
return JSON.parse(await node_fs_1.default.promises.readFile(packageJsonPath, "utf-8"));
|
|
42
|
-
}
|
|
43
|
-
catch (e) {
|
|
44
|
-
throw new Error(`Unable to read package.json file at path ${packageJsonPath}. \n\n Error: ${e.message}`);
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
exports.getPackageJson = getPackageJson;
|