@lingui/babel-plugin-extract-messages 3.17.0 → 3.17.2
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/CHANGELOG.md +16 -0
- package/build/index.js +31 -90
- package/package.json +5 -5
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,22 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
## [3.17.2](https://github.com/lingui/js-lingui/compare/v3.17.1...v3.17.2) (2023-02-24)
|
|
7
|
+
|
|
8
|
+
**Note:** Version bump only for package @lingui/babel-plugin-extract-messages
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
## [3.17.1](https://github.com/lingui/js-lingui/compare/v3.17.0...v3.17.1) (2023-02-07)
|
|
15
|
+
|
|
16
|
+
**Note:** Version bump only for package @lingui/babel-plugin-extract-messages
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
|
|
6
22
|
# [3.17.0](https://github.com/lingui/js-lingui/compare/v3.16.1...v3.17.0) (2023-02-01)
|
|
7
23
|
|
|
8
24
|
**Note:** Version bump only for package @lingui/babel-plugin-extract-messages
|
package/build/index.js
CHANGED
|
@@ -4,27 +4,21 @@ Object.defineProperty(exports, "__esModule", {
|
|
|
4
4
|
value: true
|
|
5
5
|
});
|
|
6
6
|
exports.default = _default;
|
|
7
|
-
|
|
8
7
|
var _fs = _interopRequireDefault(require("fs"));
|
|
9
|
-
|
|
10
8
|
var _path = _interopRequireDefault(require("path"));
|
|
11
|
-
|
|
12
9
|
var _mkdirp = _interopRequireDefault(require("mkdirp"));
|
|
13
|
-
|
|
14
10
|
var _generator = _interopRequireDefault(require("@babel/generator"));
|
|
15
|
-
|
|
16
11
|
var _conf = require("@lingui/conf");
|
|
17
|
-
|
|
18
12
|
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
|
|
13
|
+
const CONFIG = Symbol("I18nConfig");
|
|
19
14
|
|
|
20
|
-
|
|
15
|
+
// Map of messages
|
|
16
|
+
const MESSAGES = Symbol("I18nMessages");
|
|
21
17
|
|
|
22
|
-
|
|
18
|
+
// We need to remember all processed nodes. When JSX expressions are
|
|
23
19
|
// replaced with CallExpressions, all children are traversed for each CallExpression.
|
|
24
20
|
// Then, i18n._ methods are visited multiple times for each parent CallExpression.
|
|
25
|
-
|
|
26
21
|
const VISITED = Symbol("I18nVisited");
|
|
27
|
-
|
|
28
22
|
function addMessage(path, messages, {
|
|
29
23
|
id,
|
|
30
24
|
message: newDefault,
|
|
@@ -36,31 +30,27 @@ function addMessage(path, messages, {
|
|
|
36
30
|
// prevent from adding undefined msgid
|
|
37
31
|
if (id === undefined) return;
|
|
38
32
|
const extractedComments = comment ? [comment] : [];
|
|
39
|
-
|
|
40
33
|
if (context) {
|
|
41
34
|
if (messages.has(context)) {
|
|
42
35
|
const existingContext = messages.get(context);
|
|
43
|
-
|
|
44
36
|
if (existingContext.has(id)) {
|
|
45
|
-
const message = messages.get(id);
|
|
46
|
-
|
|
37
|
+
const message = messages.get(id);
|
|
38
|
+
// only set/check default language when it's defined.
|
|
47
39
|
if (message.message && newDefault && message.message !== newDefault) {
|
|
48
40
|
throw path.buildCodeFrameError("Different defaults for the same message ID.");
|
|
49
41
|
}
|
|
50
|
-
|
|
51
42
|
if (newDefault) {
|
|
52
43
|
message.message = newDefault;
|
|
53
44
|
}
|
|
54
|
-
|
|
55
45
|
;
|
|
56
46
|
[].push.apply(message.origin, origin);
|
|
57
|
-
|
|
58
47
|
if (comment) {
|
|
59
48
|
;
|
|
60
49
|
[].push.apply(message.extractedComments, [comment]);
|
|
61
50
|
}
|
|
62
51
|
} else {
|
|
63
|
-
existingContext.set(id, {
|
|
52
|
+
existingContext.set(id, {
|
|
53
|
+
...props,
|
|
64
54
|
message: newDefault,
|
|
65
55
|
origin,
|
|
66
56
|
extractedComments
|
|
@@ -69,7 +59,8 @@ function addMessage(path, messages, {
|
|
|
69
59
|
}
|
|
70
60
|
} else {
|
|
71
61
|
const newContext = new Map();
|
|
72
|
-
newContext.set(id, {
|
|
62
|
+
newContext.set(id, {
|
|
63
|
+
...props,
|
|
73
64
|
message: newDefault,
|
|
74
65
|
origin,
|
|
75
66
|
extractedComments
|
|
@@ -78,25 +69,24 @@ function addMessage(path, messages, {
|
|
|
78
69
|
}
|
|
79
70
|
} else {
|
|
80
71
|
if (messages.has(id)) {
|
|
81
|
-
const message = messages.get(id);
|
|
72
|
+
const message = messages.get(id);
|
|
82
73
|
|
|
74
|
+
// only set/check default language when it's defined.
|
|
83
75
|
if (message.message && newDefault && message.message !== newDefault) {
|
|
84
76
|
throw path.buildCodeFrameError("Different defaults for the same message ID.");
|
|
85
77
|
}
|
|
86
|
-
|
|
87
78
|
if (newDefault) {
|
|
88
79
|
message.message = newDefault;
|
|
89
80
|
}
|
|
90
|
-
|
|
91
81
|
;
|
|
92
82
|
[].push.apply(message.origin, origin);
|
|
93
|
-
|
|
94
83
|
if (comment) {
|
|
95
84
|
;
|
|
96
85
|
[].push.apply(message.extractedComments, [comment]);
|
|
97
86
|
}
|
|
98
87
|
} else {
|
|
99
|
-
messages.set(id, {
|
|
88
|
+
messages.set(id, {
|
|
89
|
+
...props,
|
|
100
90
|
message: newDefault,
|
|
101
91
|
origin,
|
|
102
92
|
extractedComments
|
|
@@ -104,14 +94,13 @@ function addMessage(path, messages, {
|
|
|
104
94
|
}
|
|
105
95
|
}
|
|
106
96
|
}
|
|
97
|
+
|
|
107
98
|
/**
|
|
108
99
|
* An ES6 Map type is not possible to encode with JSON.stringify,
|
|
109
|
-
* so we can instead use a replacer function as an argument to
|
|
100
|
+
* so we can instead use a replacer function as an argument to
|
|
110
101
|
* tell the JSON parser how to serialize / deserialize the Maps
|
|
111
102
|
* it encounters.
|
|
112
103
|
*/
|
|
113
|
-
|
|
114
|
-
|
|
115
104
|
function mapReplacer(key, value) {
|
|
116
105
|
if (value instanceof Map) {
|
|
117
106
|
const object = {};
|
|
@@ -120,10 +109,8 @@ function mapReplacer(key, value) {
|
|
|
120
109
|
});
|
|
121
110
|
return object;
|
|
122
111
|
}
|
|
123
|
-
|
|
124
112
|
return value;
|
|
125
113
|
}
|
|
126
|
-
|
|
127
114
|
function extractStringContatentation(t, node, error) {
|
|
128
115
|
if (t.isStringLiteral(node)) {
|
|
129
116
|
return node.value;
|
|
@@ -133,51 +120,42 @@ function extractStringContatentation(t, node, error) {
|
|
|
133
120
|
throw error;
|
|
134
121
|
}
|
|
135
122
|
}
|
|
136
|
-
|
|
137
123
|
function extractCommentString(t, path, valuePath, valueObj) {
|
|
138
124
|
if (t.isStringLiteral(valueObj)) {
|
|
139
125
|
// Comment is a single line string
|
|
140
126
|
return valueObj.value;
|
|
141
|
-
}
|
|
142
|
-
|
|
127
|
+
}
|
|
143
128
|
|
|
129
|
+
// Comment is a multi-line string.
|
|
144
130
|
const errorIfNotAString = path.get(valuePath).buildCodeFrameError("Only strings are supported as comments.");
|
|
145
|
-
|
|
146
131
|
if (t.isBinaryExpression(valueObj)) {
|
|
147
132
|
return extractStringContatentation(t, valueObj, errorIfNotAString);
|
|
148
133
|
} else {
|
|
149
134
|
throw errorIfNotAString;
|
|
150
135
|
}
|
|
151
136
|
}
|
|
152
|
-
|
|
153
137
|
function _default({
|
|
154
138
|
types: t
|
|
155
139
|
}) {
|
|
156
140
|
let localTransComponentName;
|
|
157
|
-
|
|
158
141
|
function isTransComponent(node) {
|
|
159
142
|
return t.isJSXElement(node) && t.isJSXIdentifier(node.openingElement.name, {
|
|
160
143
|
name: localTransComponentName
|
|
161
144
|
});
|
|
162
145
|
}
|
|
163
|
-
|
|
164
146
|
const isI18nMethod = node => t.isMemberExpression(node) && t.isIdentifier(node.object, {
|
|
165
147
|
name: "i18n"
|
|
166
148
|
}) && t.isIdentifier(node.property, {
|
|
167
149
|
name: "_"
|
|
168
150
|
});
|
|
169
|
-
|
|
170
151
|
function collectMessage(path, file, props) {
|
|
171
152
|
const messages = file.get(MESSAGES);
|
|
172
153
|
const rootDir = file.get(CONFIG).rootDir;
|
|
173
|
-
|
|
174
154
|
const filename = _path.default.relative(rootDir, file.opts.filename).replace(/\\/g, "/");
|
|
175
|
-
|
|
176
155
|
const line = path.node.loc ? path.node.loc.start.line : null;
|
|
177
156
|
props.origin = [[filename, line]];
|
|
178
157
|
addMessage(path, messages, props);
|
|
179
158
|
}
|
|
180
|
-
|
|
181
159
|
return {
|
|
182
160
|
visitor: {
|
|
183
161
|
// Get the local name of Trans component. Usually it's just `Trans`, but
|
|
@@ -190,21 +168,19 @@ function _default({
|
|
|
190
168
|
const moduleName = node.source.value;
|
|
191
169
|
if (!["@lingui/react", "@lingui/macro", "@lingui/core"].includes(moduleName)) return;
|
|
192
170
|
const importDeclarations = {};
|
|
193
|
-
|
|
194
171
|
if (moduleName === "@lingui/react" || moduleName === "@lingui/macro") {
|
|
195
172
|
node.specifiers.forEach(specifier => {
|
|
196
173
|
importDeclarations[specifier.imported.name] = specifier.local.name;
|
|
197
|
-
});
|
|
198
|
-
// If there's no alias, consider it was imported as Trans.
|
|
174
|
+
});
|
|
199
175
|
|
|
176
|
+
// Trans import might be missing if there's just Plural or similar macro.
|
|
177
|
+
// If there's no alias, consider it was imported as Trans.
|
|
200
178
|
localTransComponentName = importDeclarations["Trans"] || "Trans";
|
|
201
179
|
}
|
|
202
|
-
|
|
203
180
|
if (!node.specifiers.length) {
|
|
204
181
|
path.remove();
|
|
205
182
|
}
|
|
206
183
|
},
|
|
207
|
-
|
|
208
184
|
// Extract translation from <Trans /> component.
|
|
209
185
|
JSXElement(path, {
|
|
210
186
|
file
|
|
@@ -216,7 +192,6 @@ function _default({
|
|
|
216
192
|
const attrs = node.openingElement.attributes || [];
|
|
217
193
|
const props = attrs.reduce((acc, item) => {
|
|
218
194
|
const key = item.name.name;
|
|
219
|
-
|
|
220
195
|
if (key === "id" || key === "message" || key === "comment" || key === "context") {
|
|
221
196
|
if (item.value.value) {
|
|
222
197
|
acc[key] = item.value.value;
|
|
@@ -224,25 +199,19 @@ function _default({
|
|
|
224
199
|
acc[key] = item.value.expression.value;
|
|
225
200
|
}
|
|
226
201
|
}
|
|
227
|
-
|
|
228
202
|
return acc;
|
|
229
203
|
}, {});
|
|
230
|
-
|
|
231
204
|
if (!props.id) {
|
|
232
205
|
// <Trans id={message} /> is valid, don't raise warning
|
|
233
206
|
const idProp = attrs.filter(item => item.name.name === "id")[0];
|
|
234
|
-
|
|
235
207
|
if (idProp === undefined || t.isLiteral(props.id)) {
|
|
236
208
|
console.warn("Missing message ID, skipping.");
|
|
237
209
|
console.warn((0, _generator.default)(node).code);
|
|
238
210
|
}
|
|
239
|
-
|
|
240
211
|
return;
|
|
241
212
|
}
|
|
242
|
-
|
|
243
213
|
collectMessage(path, file, props);
|
|
244
214
|
},
|
|
245
|
-
|
|
246
215
|
CallExpression(path, {
|
|
247
216
|
file
|
|
248
217
|
}) {
|
|
@@ -258,15 +227,12 @@ function _default({
|
|
|
258
227
|
const props = {
|
|
259
228
|
id: path.node.arguments[0].value
|
|
260
229
|
};
|
|
261
|
-
|
|
262
230
|
if (!props.id) {
|
|
263
231
|
console.warn("Missing message ID, skipping.");
|
|
264
232
|
console.warn((0, _generator.default)(path.node).code);
|
|
265
233
|
return;
|
|
266
234
|
}
|
|
267
|
-
|
|
268
235
|
const copyOptions = ["message", "comment", "context"];
|
|
269
|
-
|
|
270
236
|
if (t.isObjectExpression(path.node.arguments[2])) {
|
|
271
237
|
path.node.arguments[2].properties.forEach(({
|
|
272
238
|
key,
|
|
@@ -274,54 +240,43 @@ function _default({
|
|
|
274
240
|
}, i) => {
|
|
275
241
|
if (!copyOptions.includes(key.name)) return;
|
|
276
242
|
let valueToExtract = value.value;
|
|
277
|
-
|
|
278
243
|
if (key.name === "comment") {
|
|
279
244
|
valueToExtract = extractCommentString(t, path, `arguments.2.properties.${i}.value`, value);
|
|
280
245
|
}
|
|
281
|
-
|
|
282
246
|
props[key.name] = valueToExtract;
|
|
283
247
|
});
|
|
284
248
|
}
|
|
285
|
-
|
|
286
249
|
visited.add(path.node);
|
|
287
250
|
collectMessage(path, file, props);
|
|
288
251
|
},
|
|
289
|
-
|
|
290
252
|
StringLiteral(path, {
|
|
291
253
|
file
|
|
292
254
|
}) {
|
|
293
255
|
const visited = file.get(VISITED);
|
|
294
256
|
const comment = path.node.leadingComments && path.node.leadingComments.filter(node => node.value.match(/^\s*i18n/))[0];
|
|
295
|
-
|
|
296
257
|
if (!comment || visited.has(path.node)) {
|
|
297
258
|
return;
|
|
298
259
|
}
|
|
299
|
-
|
|
300
260
|
visited.add(path.node);
|
|
301
261
|
const props = {
|
|
302
262
|
id: path.node.value
|
|
303
263
|
};
|
|
304
|
-
|
|
305
264
|
if (!props.id) {
|
|
306
265
|
console.warn("Missing message ID, skipping.");
|
|
307
266
|
console.warn((0, _generator.default)(path.node).code);
|
|
308
267
|
return;
|
|
309
268
|
}
|
|
310
|
-
|
|
311
269
|
collectMessage(path, file, props);
|
|
312
270
|
},
|
|
313
|
-
|
|
314
271
|
// Extract message descriptors
|
|
315
272
|
ObjectExpression(path, {
|
|
316
273
|
file
|
|
317
274
|
}) {
|
|
318
275
|
const visited = file.get(VISITED);
|
|
319
276
|
const comment = path.node.leadingComments && path.node.leadingComments.filter(node => node.value.match(/^\s*i18n/))[0];
|
|
320
|
-
|
|
321
277
|
if (!comment || visited.has(path.node)) {
|
|
322
278
|
return;
|
|
323
279
|
}
|
|
324
|
-
|
|
325
280
|
visited.add(path.node);
|
|
326
281
|
const props = {};
|
|
327
282
|
const copyProps = ["id", "message", "comment", "context"];
|
|
@@ -333,43 +288,39 @@ function _default({
|
|
|
333
288
|
}, i) => {
|
|
334
289
|
// By default, the value is just the string value of the object property.
|
|
335
290
|
let valueToExtract = value.value;
|
|
336
|
-
|
|
337
291
|
if (key.name === "comment") {
|
|
338
292
|
valueToExtract = extractCommentString(t, path, `properties.${i}.value`, value);
|
|
339
293
|
} else if (key.name === "id") {
|
|
340
294
|
const isIdLiteral = !value.value && t.isTemplateLiteral(value);
|
|
341
|
-
|
|
342
295
|
if (isIdLiteral) {
|
|
343
|
-
|
|
296
|
+
var _value$quasis$, _value$quasis$$value;
|
|
297
|
+
valueToExtract = value === null || value === void 0 ? void 0 : (_value$quasis$ = value.quasis[0]) === null || _value$quasis$ === void 0 ? void 0 : (_value$quasis$$value = _value$quasis$.value) === null || _value$quasis$$value === void 0 ? void 0 : _value$quasis$$value.cooked;
|
|
344
298
|
}
|
|
345
299
|
}
|
|
346
|
-
|
|
347
300
|
props[key.name] = valueToExtract;
|
|
348
301
|
});
|
|
349
302
|
collectMessage(path, file, props);
|
|
350
303
|
}
|
|
351
|
-
|
|
352
304
|
},
|
|
353
|
-
|
|
354
305
|
pre(file) {
|
|
355
|
-
localTransComponentName = null;
|
|
356
|
-
// Config was already validated in CLI.
|
|
306
|
+
localTransComponentName = null;
|
|
357
307
|
|
|
308
|
+
// Skip validation because config is loaded for each file.
|
|
309
|
+
// Config was already validated in CLI.
|
|
358
310
|
file.set(CONFIG, (0, _conf.getConfig)({
|
|
359
311
|
cwd: file.opts.filename,
|
|
360
312
|
skipValidation: true,
|
|
361
313
|
configPath: this.opts.configPath
|
|
362
|
-
}));
|
|
314
|
+
}));
|
|
315
|
+
|
|
316
|
+
// Ignore else path for now. Collision is possible if other plugin is
|
|
363
317
|
// using the same Symbol('I18nMessages').
|
|
364
318
|
// istanbul ignore else
|
|
365
|
-
|
|
366
319
|
if (!file.has(MESSAGES)) {
|
|
367
320
|
file.set(MESSAGES, new Map());
|
|
368
321
|
}
|
|
369
|
-
|
|
370
322
|
file.set(VISITED, new WeakSet());
|
|
371
323
|
},
|
|
372
|
-
|
|
373
324
|
post(file) {
|
|
374
325
|
/* Write catalog to directory `localeDir`/_build/`path.to.file`/`filename`.json
|
|
375
326
|
* e.g: if file is src/components/App.js (relative to package.json), then
|
|
@@ -381,36 +332,26 @@ function _default({
|
|
|
381
332
|
filename
|
|
382
333
|
} = file.opts;
|
|
383
334
|
const rootDir = config.rootDir;
|
|
384
|
-
|
|
385
335
|
const baseDir = _path.default.dirname(_path.default.relative(rootDir, filename));
|
|
386
|
-
|
|
387
336
|
const targetDir = _path.default.join(localeDir, "_build", baseDir);
|
|
388
|
-
|
|
389
337
|
const messages = file.get(MESSAGES);
|
|
390
338
|
const catalog = {};
|
|
391
|
-
|
|
392
339
|
const baseName = _path.default.basename(filename);
|
|
393
|
-
|
|
394
340
|
const catalogFilename = _path.default.join(targetDir, `${baseName}.json`);
|
|
341
|
+
_mkdirp.default.sync(targetDir);
|
|
395
342
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
343
|
+
// no messages, skip file
|
|
399
344
|
if (!messages.size) {
|
|
400
345
|
// clean any existing catalog
|
|
401
346
|
if (_fs.default.existsSync(catalogFilename)) {
|
|
402
347
|
_fs.default.writeFileSync(catalogFilename, JSON.stringify({}));
|
|
403
348
|
}
|
|
404
|
-
|
|
405
349
|
return;
|
|
406
350
|
}
|
|
407
|
-
|
|
408
351
|
messages.forEach((value, key) => {
|
|
409
352
|
catalog[key] = value;
|
|
410
353
|
});
|
|
411
|
-
|
|
412
354
|
_fs.default.writeFileSync(catalogFilename, JSON.stringify(catalog, mapReplacer, 2));
|
|
413
355
|
}
|
|
414
|
-
|
|
415
356
|
};
|
|
416
357
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lingui/babel-plugin-extract-messages",
|
|
3
|
-
"version": "3.17.
|
|
3
|
+
"version": "3.17.2",
|
|
4
4
|
"description": "Babel plugin for collecting messages from source code for internationalization",
|
|
5
5
|
"main": "./build/index.js",
|
|
6
6
|
"author": {
|
|
@@ -33,10 +33,10 @@
|
|
|
33
33
|
"node": ">=14.0.0"
|
|
34
34
|
},
|
|
35
35
|
"dependencies": {
|
|
36
|
-
"@babel/generator": "^7.
|
|
37
|
-
"@babel/runtime": "^7.
|
|
38
|
-
"@lingui/conf": "3.17.
|
|
36
|
+
"@babel/generator": "^7.20.14",
|
|
37
|
+
"@babel/runtime": "^7.20.13",
|
|
38
|
+
"@lingui/conf": "3.17.2",
|
|
39
39
|
"mkdirp": "^1.0.4"
|
|
40
40
|
},
|
|
41
|
-
"gitHead": "
|
|
41
|
+
"gitHead": "31dcab5a9a8f88bfa8b3a2c7cd12aa2d908a1d80"
|
|
42
42
|
}
|