@lingui/format-po-gettext 5.6.1 → 5.8.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/po-gettext.cjs +157 -13
- package/dist/po-gettext.d.cts +14 -0
- package/dist/po-gettext.d.mts +14 -0
- package/dist/po-gettext.d.ts +14 -0
- package/dist/po-gettext.mjs +157 -13
- package/package.json +5 -5
package/dist/po-gettext.cjs
CHANGED
|
@@ -92,7 +92,7 @@ const ICU_PLURAL_REGEX = /^{.*, plural, .*}$/;
|
|
|
92
92
|
const ICU_SELECT_REGEX = /^{.*, select(Ordinal)?, .*}$/;
|
|
93
93
|
const LINE_ENDINGS = /\r?\n/g;
|
|
94
94
|
const DEFAULT_CTX_PREFIX = "js-lingui:";
|
|
95
|
-
function serializePlurals(item, message, id, isGeneratedId, options) {
|
|
95
|
+
function serializePlurals(item, message, id, isGeneratedId, options, formatterCtx) {
|
|
96
96
|
const icuMessage = message.message;
|
|
97
97
|
const ctxPrefix = options.customICUPrefix || DEFAULT_CTX_PREFIX;
|
|
98
98
|
if (!icuMessage) {
|
|
@@ -110,20 +110,19 @@ function serializePlurals(item, message, id, isGeneratedId, options) {
|
|
|
110
110
|
id
|
|
111
111
|
);
|
|
112
112
|
}
|
|
113
|
-
const ctx =
|
|
114
|
-
|
|
115
|
-
}
|
|
113
|
+
const ctx = {
|
|
114
|
+
pluralizeOn: [messageAst.arg]
|
|
115
|
+
};
|
|
116
116
|
if (isGeneratedId) {
|
|
117
117
|
item.msgid = stringifyICUCase(messageAst.cases[0]);
|
|
118
118
|
item.msgid_plural = stringifyICUCase(
|
|
119
119
|
messageAst.cases[messageAst.cases.length - 1]
|
|
120
120
|
);
|
|
121
|
-
ctx.
|
|
121
|
+
ctx.icu = icuMessage;
|
|
122
122
|
} else {
|
|
123
123
|
item.msgid_plural = id + "_plural";
|
|
124
124
|
}
|
|
125
|
-
|
|
126
|
-
item.extractedComments.push(ctxPrefix + ctx.toString());
|
|
125
|
+
item.extractedComments.push(ctxPrefix + serializeContextToComment(ctx));
|
|
127
126
|
if (message.translation?.length > 0) {
|
|
128
127
|
const ast = parser.parse(message.translation)[0];
|
|
129
128
|
if (ast.cases == null) {
|
|
@@ -134,6 +133,8 @@ function serializePlurals(item, message, id, isGeneratedId, options) {
|
|
|
134
133
|
} else {
|
|
135
134
|
item.msgstr = ast.cases.map(stringifyICUCase);
|
|
136
135
|
}
|
|
136
|
+
} else if (!isGeneratedId && (formatterCtx.locale === formatterCtx.sourceLocale || formatterCtx.locale === null)) {
|
|
137
|
+
item.msgstr = messageAst.cases.map(stringifyICUCase);
|
|
137
138
|
}
|
|
138
139
|
} catch (e) {
|
|
139
140
|
console.error(`Error parsing message ICU for key "${id}":`, e);
|
|
@@ -208,14 +209,13 @@ const convertPluralsToICU = (item, pluralForms, lang, ctxPrefix = DEFAULT_CTX_PR
|
|
|
208
209
|
);
|
|
209
210
|
return;
|
|
210
211
|
}
|
|
211
|
-
const
|
|
212
|
-
|
|
213
|
-
if (contextComment != null) {
|
|
212
|
+
const ctx = getContextFromComments(item.extractedComments, ctxPrefix);
|
|
213
|
+
if (ctx) {
|
|
214
214
|
item.extractedComments = item.extractedComments.filter(
|
|
215
215
|
(comment) => !comment.startsWith(ctxPrefix)
|
|
216
216
|
);
|
|
217
217
|
}
|
|
218
|
-
const storedICU = ctx
|
|
218
|
+
const storedICU = ctx?.icu;
|
|
219
219
|
if (storedICU != null) {
|
|
220
220
|
item.msgid = storedICU;
|
|
221
221
|
}
|
|
@@ -239,7 +239,7 @@ const convertPluralsToICU = (item, pluralForms, lang, ctxPrefix = DEFAULT_CTX_PR
|
|
|
239
239
|
const pluralClauses = item.msgstr.map(
|
|
240
240
|
(str, index) => pluralForms[index] ? pluralForms[index] + " {" + str + "}" : ""
|
|
241
241
|
).join(" ");
|
|
242
|
-
let pluralizeOn = ctx
|
|
242
|
+
let pluralizeOn = ctx?.pluralizeOn?.[0];
|
|
243
243
|
if (!pluralizeOn) {
|
|
244
244
|
console.warn(
|
|
245
245
|
`Unable to determine plural placeholder name for item with key "%s" in language "${lang}" (should be stored in a comment starting with "#. ${ctxPrefix}"), assuming "count".`,
|
|
@@ -249,6 +249,128 @@ const convertPluralsToICU = (item, pluralForms, lang, ctxPrefix = DEFAULT_CTX_PR
|
|
|
249
249
|
}
|
|
250
250
|
item.msgstr = ["{" + pluralizeOn + ", plural, " + pluralClauses + "}"];
|
|
251
251
|
};
|
|
252
|
+
const updateContextComment = (item, contextComment, ctxPrefix) => {
|
|
253
|
+
item.extractedComments = [
|
|
254
|
+
...item.extractedComments.filter((c) => !c.startsWith(ctxPrefix)),
|
|
255
|
+
ctxPrefix + contextComment
|
|
256
|
+
];
|
|
257
|
+
};
|
|
258
|
+
function serializeContextToComment(ctx) {
|
|
259
|
+
const urlParams = new URLSearchParams();
|
|
260
|
+
if (ctx.icu) {
|
|
261
|
+
urlParams.set("icu", ctx.icu);
|
|
262
|
+
}
|
|
263
|
+
if (ctx.pluralizeOn) {
|
|
264
|
+
urlParams.set("pluralize_on", ctx.pluralizeOn.join(","));
|
|
265
|
+
}
|
|
266
|
+
urlParams.sort();
|
|
267
|
+
return urlParams.toString();
|
|
268
|
+
}
|
|
269
|
+
function getContextFromComments(extractedComments, ctxPrefix) {
|
|
270
|
+
const contextComment = extractedComments.find(
|
|
271
|
+
(comment) => comment.startsWith(ctxPrefix)
|
|
272
|
+
);
|
|
273
|
+
if (!contextComment) {
|
|
274
|
+
return void 0;
|
|
275
|
+
}
|
|
276
|
+
const urlParams = new URLSearchParams(
|
|
277
|
+
contextComment?.substring(ctxPrefix.length)
|
|
278
|
+
);
|
|
279
|
+
return {
|
|
280
|
+
icu: urlParams.get("icu"),
|
|
281
|
+
pluralizeOn: urlParams.get("pluralize_on") ? urlParams.get("pluralize_on").split(",") : []
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
function mergeDuplicatePluralEntries(items, options) {
|
|
285
|
+
const ctxPrefix = options.customICUPrefix || DEFAULT_CTX_PREFIX;
|
|
286
|
+
const itemMap = /* @__PURE__ */ new Map();
|
|
287
|
+
for (const item of items) {
|
|
288
|
+
if (item.msgid_plural) {
|
|
289
|
+
const key = `${item.msgid}|||${item.msgid_plural}`;
|
|
290
|
+
if (!itemMap.has(key)) {
|
|
291
|
+
itemMap.set(key, []);
|
|
292
|
+
}
|
|
293
|
+
itemMap.get(key).push(item);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const mergedItems = [];
|
|
297
|
+
for (const duplicateItems of itemMap.values()) {
|
|
298
|
+
if (duplicateItems.length === 1) {
|
|
299
|
+
mergedItems.push(duplicateItems[0]);
|
|
300
|
+
} else {
|
|
301
|
+
const mergedItem = duplicateItems[0];
|
|
302
|
+
const allVariables = duplicateItems.map((item) => {
|
|
303
|
+
const ctx2 = getContextFromComments(item.extractedComments, ctxPrefix);
|
|
304
|
+
return ctx2?.pluralizeOn[0] || "count";
|
|
305
|
+
});
|
|
306
|
+
const ctx = getContextFromComments(
|
|
307
|
+
mergedItem.extractedComments,
|
|
308
|
+
ctxPrefix
|
|
309
|
+
);
|
|
310
|
+
if (!ctx) {
|
|
311
|
+
continue;
|
|
312
|
+
}
|
|
313
|
+
updateContextComment(
|
|
314
|
+
mergedItem,
|
|
315
|
+
serializeContextToComment({
|
|
316
|
+
icu: replaceArgInIcu(ctx.icu, allVariables[0], "$var"),
|
|
317
|
+
pluralizeOn: allVariables
|
|
318
|
+
}),
|
|
319
|
+
ctxPrefix
|
|
320
|
+
);
|
|
321
|
+
mergedItem.references = duplicateItems.flatMap((item) => item.references);
|
|
322
|
+
mergedItems.push(mergedItem);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
325
|
+
return mergedItems;
|
|
326
|
+
}
|
|
327
|
+
function replaceArgInIcu(icu, oldVar, newVar) {
|
|
328
|
+
return icu.replace(new RegExp(`{${oldVar}, plural,`), `{${newVar}, plural,`);
|
|
329
|
+
}
|
|
330
|
+
function expandMergedPluralEntries(items, options) {
|
|
331
|
+
const ctxPrefix = options.customICUPrefix || DEFAULT_CTX_PREFIX;
|
|
332
|
+
const expandedItems = [];
|
|
333
|
+
for (const item of items) {
|
|
334
|
+
if (!item.msgid_plural) {
|
|
335
|
+
expandedItems.push(item);
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
const ctx = getContextFromComments(item.extractedComments, ctxPrefix);
|
|
339
|
+
if (!ctx) {
|
|
340
|
+
console.warn(
|
|
341
|
+
`Plural entry with msgid "${item.msgid}" is missing context information for expansion.`
|
|
342
|
+
);
|
|
343
|
+
expandedItems.push(item);
|
|
344
|
+
continue;
|
|
345
|
+
}
|
|
346
|
+
const variableList = ctx.pluralizeOn;
|
|
347
|
+
if (variableList.length === 1) {
|
|
348
|
+
expandedItems.push(item);
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
for (const variable of variableList) {
|
|
352
|
+
const newItem = new PO__default.Item();
|
|
353
|
+
newItem.msgid = item.msgid;
|
|
354
|
+
newItem.msgid_plural = item.msgid_plural;
|
|
355
|
+
newItem.msgstr = [...item.msgstr];
|
|
356
|
+
newItem.msgctxt = item.msgctxt;
|
|
357
|
+
newItem.comments = [...item.comments];
|
|
358
|
+
updateContextComment(
|
|
359
|
+
item,
|
|
360
|
+
serializeContextToComment({
|
|
361
|
+
pluralizeOn: [variable],
|
|
362
|
+
// get icu comment, replace variable placeholder with current variable
|
|
363
|
+
icu: replaceArgInIcu(ctx.icu, "\\$var", variable)
|
|
364
|
+
}),
|
|
365
|
+
ctxPrefix
|
|
366
|
+
);
|
|
367
|
+
newItem.extractedComments = item.extractedComments;
|
|
368
|
+
newItem.flags = { ...item.flags };
|
|
369
|
+
expandedItems.push(newItem);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
return expandedItems;
|
|
373
|
+
}
|
|
252
374
|
function formatter(options = {}) {
|
|
253
375
|
options = {
|
|
254
376
|
origins: true,
|
|
@@ -261,6 +383,9 @@ function formatter(options = {}) {
|
|
|
261
383
|
templateExtension: ".pot",
|
|
262
384
|
parse(content, ctx) {
|
|
263
385
|
const po = PO__default.parse(content);
|
|
386
|
+
if (options.mergePlurals) {
|
|
387
|
+
po.items = expandMergedPluralEntries(po.items, options);
|
|
388
|
+
}
|
|
264
389
|
const pluralForms = getPluralCases(
|
|
265
390
|
po.headers.Language,
|
|
266
391
|
po.headers["Plural-Forms"]
|
|
@@ -283,8 +408,27 @@ function formatter(options = {}) {
|
|
|
283
408
|
);
|
|
284
409
|
const id = isGeneratedId ? generateMessageId.generateMessageId(item.msgid, item.msgctxt) : item.msgid;
|
|
285
410
|
const message = catalog[id];
|
|
286
|
-
return serializePlurals(item, message, id, isGeneratedId, options);
|
|
411
|
+
return serializePlurals(item, message, id, isGeneratedId, options, ctx);
|
|
287
412
|
});
|
|
413
|
+
if (options.mergePlurals) {
|
|
414
|
+
const mergedPlurals = mergeDuplicatePluralEntries(po.items, options);
|
|
415
|
+
const newItems = [];
|
|
416
|
+
const processed = /* @__PURE__ */ new Set();
|
|
417
|
+
po.items.forEach((item) => {
|
|
418
|
+
if (!item.msgid_plural) {
|
|
419
|
+
newItems.push(item);
|
|
420
|
+
} else {
|
|
421
|
+
const mergedItem = mergedPlurals.find(
|
|
422
|
+
(merged) => merged.msgid === item.msgid && merged.msgid_plural === item.msgid_plural
|
|
423
|
+
);
|
|
424
|
+
if (mergedItem && !processed.has(mergedItem)) {
|
|
425
|
+
processed.add(mergedItem);
|
|
426
|
+
newItems.push(mergedItem);
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
});
|
|
430
|
+
po.items = newItems;
|
|
431
|
+
}
|
|
288
432
|
return po.toString();
|
|
289
433
|
}
|
|
290
434
|
};
|
package/dist/po-gettext.d.cts
CHANGED
|
@@ -2,8 +2,22 @@ import { CatalogFormatter } from '@lingui/conf';
|
|
|
2
2
|
import { PoFormatterOptions } from '@lingui/format-po';
|
|
3
3
|
|
|
4
4
|
type PoGettextFormatterOptions = PoFormatterOptions & {
|
|
5
|
+
/**
|
|
6
|
+
* Disable warning about unsupported `Select` feature encountered in catalogs
|
|
7
|
+
*
|
|
8
|
+
* @default false
|
|
9
|
+
*/
|
|
5
10
|
disableSelectWarning?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Overrides the default prefix for icu and plural comments in the final PO catalog.
|
|
13
|
+
*
|
|
14
|
+
* @default "js-lingui:"
|
|
15
|
+
*/
|
|
6
16
|
customICUPrefix?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Combine plural entries that have the same content but different variables into a single PO entry
|
|
19
|
+
*/
|
|
20
|
+
mergePlurals?: boolean;
|
|
7
21
|
};
|
|
8
22
|
declare function formatter(options?: PoGettextFormatterOptions): CatalogFormatter;
|
|
9
23
|
|
package/dist/po-gettext.d.mts
CHANGED
|
@@ -2,8 +2,22 @@ import { CatalogFormatter } from '@lingui/conf';
|
|
|
2
2
|
import { PoFormatterOptions } from '@lingui/format-po';
|
|
3
3
|
|
|
4
4
|
type PoGettextFormatterOptions = PoFormatterOptions & {
|
|
5
|
+
/**
|
|
6
|
+
* Disable warning about unsupported `Select` feature encountered in catalogs
|
|
7
|
+
*
|
|
8
|
+
* @default false
|
|
9
|
+
*/
|
|
5
10
|
disableSelectWarning?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Overrides the default prefix for icu and plural comments in the final PO catalog.
|
|
13
|
+
*
|
|
14
|
+
* @default "js-lingui:"
|
|
15
|
+
*/
|
|
6
16
|
customICUPrefix?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Combine plural entries that have the same content but different variables into a single PO entry
|
|
19
|
+
*/
|
|
20
|
+
mergePlurals?: boolean;
|
|
7
21
|
};
|
|
8
22
|
declare function formatter(options?: PoGettextFormatterOptions): CatalogFormatter;
|
|
9
23
|
|
package/dist/po-gettext.d.ts
CHANGED
|
@@ -2,8 +2,22 @@ import { CatalogFormatter } from '@lingui/conf';
|
|
|
2
2
|
import { PoFormatterOptions } from '@lingui/format-po';
|
|
3
3
|
|
|
4
4
|
type PoGettextFormatterOptions = PoFormatterOptions & {
|
|
5
|
+
/**
|
|
6
|
+
* Disable warning about unsupported `Select` feature encountered in catalogs
|
|
7
|
+
*
|
|
8
|
+
* @default false
|
|
9
|
+
*/
|
|
5
10
|
disableSelectWarning?: boolean;
|
|
11
|
+
/**
|
|
12
|
+
* Overrides the default prefix for icu and plural comments in the final PO catalog.
|
|
13
|
+
*
|
|
14
|
+
* @default "js-lingui:"
|
|
15
|
+
*/
|
|
6
16
|
customICUPrefix?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Combine plural entries that have the same content but different variables into a single PO entry
|
|
19
|
+
*/
|
|
20
|
+
mergePlurals?: boolean;
|
|
7
21
|
};
|
|
8
22
|
declare function formatter(options?: PoGettextFormatterOptions): CatalogFormatter;
|
|
9
23
|
|
package/dist/po-gettext.mjs
CHANGED
|
@@ -83,7 +83,7 @@ const ICU_PLURAL_REGEX = /^{.*, plural, .*}$/;
|
|
|
83
83
|
const ICU_SELECT_REGEX = /^{.*, select(Ordinal)?, .*}$/;
|
|
84
84
|
const LINE_ENDINGS = /\r?\n/g;
|
|
85
85
|
const DEFAULT_CTX_PREFIX = "js-lingui:";
|
|
86
|
-
function serializePlurals(item, message, id, isGeneratedId, options) {
|
|
86
|
+
function serializePlurals(item, message, id, isGeneratedId, options, formatterCtx) {
|
|
87
87
|
const icuMessage = message.message;
|
|
88
88
|
const ctxPrefix = options.customICUPrefix || DEFAULT_CTX_PREFIX;
|
|
89
89
|
if (!icuMessage) {
|
|
@@ -101,20 +101,19 @@ function serializePlurals(item, message, id, isGeneratedId, options) {
|
|
|
101
101
|
id
|
|
102
102
|
);
|
|
103
103
|
}
|
|
104
|
-
const ctx =
|
|
105
|
-
|
|
106
|
-
}
|
|
104
|
+
const ctx = {
|
|
105
|
+
pluralizeOn: [messageAst.arg]
|
|
106
|
+
};
|
|
107
107
|
if (isGeneratedId) {
|
|
108
108
|
item.msgid = stringifyICUCase(messageAst.cases[0]);
|
|
109
109
|
item.msgid_plural = stringifyICUCase(
|
|
110
110
|
messageAst.cases[messageAst.cases.length - 1]
|
|
111
111
|
);
|
|
112
|
-
ctx.
|
|
112
|
+
ctx.icu = icuMessage;
|
|
113
113
|
} else {
|
|
114
114
|
item.msgid_plural = id + "_plural";
|
|
115
115
|
}
|
|
116
|
-
|
|
117
|
-
item.extractedComments.push(ctxPrefix + ctx.toString());
|
|
116
|
+
item.extractedComments.push(ctxPrefix + serializeContextToComment(ctx));
|
|
118
117
|
if (message.translation?.length > 0) {
|
|
119
118
|
const ast = parse(message.translation)[0];
|
|
120
119
|
if (ast.cases == null) {
|
|
@@ -125,6 +124,8 @@ function serializePlurals(item, message, id, isGeneratedId, options) {
|
|
|
125
124
|
} else {
|
|
126
125
|
item.msgstr = ast.cases.map(stringifyICUCase);
|
|
127
126
|
}
|
|
127
|
+
} else if (!isGeneratedId && (formatterCtx.locale === formatterCtx.sourceLocale || formatterCtx.locale === null)) {
|
|
128
|
+
item.msgstr = messageAst.cases.map(stringifyICUCase);
|
|
128
129
|
}
|
|
129
130
|
} catch (e) {
|
|
130
131
|
console.error(`Error parsing message ICU for key "${id}":`, e);
|
|
@@ -199,14 +200,13 @@ const convertPluralsToICU = (item, pluralForms, lang, ctxPrefix = DEFAULT_CTX_PR
|
|
|
199
200
|
);
|
|
200
201
|
return;
|
|
201
202
|
}
|
|
202
|
-
const
|
|
203
|
-
|
|
204
|
-
if (contextComment != null) {
|
|
203
|
+
const ctx = getContextFromComments(item.extractedComments, ctxPrefix);
|
|
204
|
+
if (ctx) {
|
|
205
205
|
item.extractedComments = item.extractedComments.filter(
|
|
206
206
|
(comment) => !comment.startsWith(ctxPrefix)
|
|
207
207
|
);
|
|
208
208
|
}
|
|
209
|
-
const storedICU = ctx
|
|
209
|
+
const storedICU = ctx?.icu;
|
|
210
210
|
if (storedICU != null) {
|
|
211
211
|
item.msgid = storedICU;
|
|
212
212
|
}
|
|
@@ -230,7 +230,7 @@ const convertPluralsToICU = (item, pluralForms, lang, ctxPrefix = DEFAULT_CTX_PR
|
|
|
230
230
|
const pluralClauses = item.msgstr.map(
|
|
231
231
|
(str, index) => pluralForms[index] ? pluralForms[index] + " {" + str + "}" : ""
|
|
232
232
|
).join(" ");
|
|
233
|
-
let pluralizeOn = ctx
|
|
233
|
+
let pluralizeOn = ctx?.pluralizeOn?.[0];
|
|
234
234
|
if (!pluralizeOn) {
|
|
235
235
|
console.warn(
|
|
236
236
|
`Unable to determine plural placeholder name for item with key "%s" in language "${lang}" (should be stored in a comment starting with "#. ${ctxPrefix}"), assuming "count".`,
|
|
@@ -240,6 +240,128 @@ const convertPluralsToICU = (item, pluralForms, lang, ctxPrefix = DEFAULT_CTX_PR
|
|
|
240
240
|
}
|
|
241
241
|
item.msgstr = ["{" + pluralizeOn + ", plural, " + pluralClauses + "}"];
|
|
242
242
|
};
|
|
243
|
+
const updateContextComment = (item, contextComment, ctxPrefix) => {
|
|
244
|
+
item.extractedComments = [
|
|
245
|
+
...item.extractedComments.filter((c) => !c.startsWith(ctxPrefix)),
|
|
246
|
+
ctxPrefix + contextComment
|
|
247
|
+
];
|
|
248
|
+
};
|
|
249
|
+
function serializeContextToComment(ctx) {
|
|
250
|
+
const urlParams = new URLSearchParams();
|
|
251
|
+
if (ctx.icu) {
|
|
252
|
+
urlParams.set("icu", ctx.icu);
|
|
253
|
+
}
|
|
254
|
+
if (ctx.pluralizeOn) {
|
|
255
|
+
urlParams.set("pluralize_on", ctx.pluralizeOn.join(","));
|
|
256
|
+
}
|
|
257
|
+
urlParams.sort();
|
|
258
|
+
return urlParams.toString();
|
|
259
|
+
}
|
|
260
|
+
function getContextFromComments(extractedComments, ctxPrefix) {
|
|
261
|
+
const contextComment = extractedComments.find(
|
|
262
|
+
(comment) => comment.startsWith(ctxPrefix)
|
|
263
|
+
);
|
|
264
|
+
if (!contextComment) {
|
|
265
|
+
return void 0;
|
|
266
|
+
}
|
|
267
|
+
const urlParams = new URLSearchParams(
|
|
268
|
+
contextComment?.substring(ctxPrefix.length)
|
|
269
|
+
);
|
|
270
|
+
return {
|
|
271
|
+
icu: urlParams.get("icu"),
|
|
272
|
+
pluralizeOn: urlParams.get("pluralize_on") ? urlParams.get("pluralize_on").split(",") : []
|
|
273
|
+
};
|
|
274
|
+
}
|
|
275
|
+
function mergeDuplicatePluralEntries(items, options) {
|
|
276
|
+
const ctxPrefix = options.customICUPrefix || DEFAULT_CTX_PREFIX;
|
|
277
|
+
const itemMap = /* @__PURE__ */ new Map();
|
|
278
|
+
for (const item of items) {
|
|
279
|
+
if (item.msgid_plural) {
|
|
280
|
+
const key = `${item.msgid}|||${item.msgid_plural}`;
|
|
281
|
+
if (!itemMap.has(key)) {
|
|
282
|
+
itemMap.set(key, []);
|
|
283
|
+
}
|
|
284
|
+
itemMap.get(key).push(item);
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
const mergedItems = [];
|
|
288
|
+
for (const duplicateItems of itemMap.values()) {
|
|
289
|
+
if (duplicateItems.length === 1) {
|
|
290
|
+
mergedItems.push(duplicateItems[0]);
|
|
291
|
+
} else {
|
|
292
|
+
const mergedItem = duplicateItems[0];
|
|
293
|
+
const allVariables = duplicateItems.map((item) => {
|
|
294
|
+
const ctx2 = getContextFromComments(item.extractedComments, ctxPrefix);
|
|
295
|
+
return ctx2?.pluralizeOn[0] || "count";
|
|
296
|
+
});
|
|
297
|
+
const ctx = getContextFromComments(
|
|
298
|
+
mergedItem.extractedComments,
|
|
299
|
+
ctxPrefix
|
|
300
|
+
);
|
|
301
|
+
if (!ctx) {
|
|
302
|
+
continue;
|
|
303
|
+
}
|
|
304
|
+
updateContextComment(
|
|
305
|
+
mergedItem,
|
|
306
|
+
serializeContextToComment({
|
|
307
|
+
icu: replaceArgInIcu(ctx.icu, allVariables[0], "$var"),
|
|
308
|
+
pluralizeOn: allVariables
|
|
309
|
+
}),
|
|
310
|
+
ctxPrefix
|
|
311
|
+
);
|
|
312
|
+
mergedItem.references = duplicateItems.flatMap((item) => item.references);
|
|
313
|
+
mergedItems.push(mergedItem);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return mergedItems;
|
|
317
|
+
}
|
|
318
|
+
function replaceArgInIcu(icu, oldVar, newVar) {
|
|
319
|
+
return icu.replace(new RegExp(`{${oldVar}, plural,`), `{${newVar}, plural,`);
|
|
320
|
+
}
|
|
321
|
+
function expandMergedPluralEntries(items, options) {
|
|
322
|
+
const ctxPrefix = options.customICUPrefix || DEFAULT_CTX_PREFIX;
|
|
323
|
+
const expandedItems = [];
|
|
324
|
+
for (const item of items) {
|
|
325
|
+
if (!item.msgid_plural) {
|
|
326
|
+
expandedItems.push(item);
|
|
327
|
+
continue;
|
|
328
|
+
}
|
|
329
|
+
const ctx = getContextFromComments(item.extractedComments, ctxPrefix);
|
|
330
|
+
if (!ctx) {
|
|
331
|
+
console.warn(
|
|
332
|
+
`Plural entry with msgid "${item.msgid}" is missing context information for expansion.`
|
|
333
|
+
);
|
|
334
|
+
expandedItems.push(item);
|
|
335
|
+
continue;
|
|
336
|
+
}
|
|
337
|
+
const variableList = ctx.pluralizeOn;
|
|
338
|
+
if (variableList.length === 1) {
|
|
339
|
+
expandedItems.push(item);
|
|
340
|
+
continue;
|
|
341
|
+
}
|
|
342
|
+
for (const variable of variableList) {
|
|
343
|
+
const newItem = new PO.Item();
|
|
344
|
+
newItem.msgid = item.msgid;
|
|
345
|
+
newItem.msgid_plural = item.msgid_plural;
|
|
346
|
+
newItem.msgstr = [...item.msgstr];
|
|
347
|
+
newItem.msgctxt = item.msgctxt;
|
|
348
|
+
newItem.comments = [...item.comments];
|
|
349
|
+
updateContextComment(
|
|
350
|
+
item,
|
|
351
|
+
serializeContextToComment({
|
|
352
|
+
pluralizeOn: [variable],
|
|
353
|
+
// get icu comment, replace variable placeholder with current variable
|
|
354
|
+
icu: replaceArgInIcu(ctx.icu, "\\$var", variable)
|
|
355
|
+
}),
|
|
356
|
+
ctxPrefix
|
|
357
|
+
);
|
|
358
|
+
newItem.extractedComments = item.extractedComments;
|
|
359
|
+
newItem.flags = { ...item.flags };
|
|
360
|
+
expandedItems.push(newItem);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return expandedItems;
|
|
364
|
+
}
|
|
243
365
|
function formatter(options = {}) {
|
|
244
366
|
options = {
|
|
245
367
|
origins: true,
|
|
@@ -252,6 +374,9 @@ function formatter(options = {}) {
|
|
|
252
374
|
templateExtension: ".pot",
|
|
253
375
|
parse(content, ctx) {
|
|
254
376
|
const po = PO.parse(content);
|
|
377
|
+
if (options.mergePlurals) {
|
|
378
|
+
po.items = expandMergedPluralEntries(po.items, options);
|
|
379
|
+
}
|
|
255
380
|
const pluralForms = getPluralCases(
|
|
256
381
|
po.headers.Language,
|
|
257
382
|
po.headers["Plural-Forms"]
|
|
@@ -274,8 +399,27 @@ function formatter(options = {}) {
|
|
|
274
399
|
);
|
|
275
400
|
const id = isGeneratedId ? generateMessageId(item.msgid, item.msgctxt) : item.msgid;
|
|
276
401
|
const message = catalog[id];
|
|
277
|
-
return serializePlurals(item, message, id, isGeneratedId, options);
|
|
402
|
+
return serializePlurals(item, message, id, isGeneratedId, options, ctx);
|
|
278
403
|
});
|
|
404
|
+
if (options.mergePlurals) {
|
|
405
|
+
const mergedPlurals = mergeDuplicatePluralEntries(po.items, options);
|
|
406
|
+
const newItems = [];
|
|
407
|
+
const processed = /* @__PURE__ */ new Set();
|
|
408
|
+
po.items.forEach((item) => {
|
|
409
|
+
if (!item.msgid_plural) {
|
|
410
|
+
newItems.push(item);
|
|
411
|
+
} else {
|
|
412
|
+
const mergedItem = mergedPlurals.find(
|
|
413
|
+
(merged) => merged.msgid === item.msgid && merged.msgid_plural === item.msgid_plural
|
|
414
|
+
);
|
|
415
|
+
if (mergedItem && !processed.has(mergedItem)) {
|
|
416
|
+
processed.add(mergedItem);
|
|
417
|
+
newItems.push(mergedItem);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
});
|
|
421
|
+
po.items = newItems;
|
|
422
|
+
}
|
|
279
423
|
return po.toString();
|
|
280
424
|
}
|
|
281
425
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lingui/format-po-gettext",
|
|
3
|
-
"version": "5.
|
|
3
|
+
"version": "5.8.0",
|
|
4
4
|
"description": "Gettext PO format with gettext-style plurals for Lingui Catalogs",
|
|
5
5
|
"main": "./dist/po-gettext.cjs",
|
|
6
6
|
"module": "./dist/po-gettext.mjs",
|
|
@@ -43,9 +43,9 @@
|
|
|
43
43
|
"dist/"
|
|
44
44
|
],
|
|
45
45
|
"dependencies": {
|
|
46
|
-
"@lingui/conf": "5.
|
|
47
|
-
"@lingui/format-po": "5.
|
|
48
|
-
"@lingui/message-utils": "5.
|
|
46
|
+
"@lingui/conf": "5.8.0",
|
|
47
|
+
"@lingui/format-po": "5.8.0",
|
|
48
|
+
"@lingui/message-utils": "5.8.0",
|
|
49
49
|
"@messageformat/parser": "^5.0.0",
|
|
50
50
|
"cldr-core": "^45.0.0",
|
|
51
51
|
"node-gettext": "^3.0.0",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"mockdate": "^3.0.5",
|
|
58
58
|
"unbuild": "2.0.0"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "83d0513bdda9ff14003a05d376c7fedf860dd7ee"
|
|
61
61
|
}
|