@intlayer/engine 9.2.0 → 9.3.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.
Files changed (64) hide show
  1. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs +14 -2
  2. package/dist/cjs/buildIntlayerDictionary/buildIntlayerDictionary.cjs.map +1 -1
  3. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs +24 -4
  4. package/dist/cjs/buildIntlayerDictionary/writeDynamicDictionary.cjs.map +1 -1
  5. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs +43 -6
  6. package/dist/cjs/buildIntlayerDictionary/writeFetchDictionary.cjs.map +1 -1
  7. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs +96 -0
  8. package/dist/cjs/buildIntlayerDictionary/writeNestedDictionary.cjs.map +1 -0
  9. package/dist/cjs/fetchDistantDictionaries.cjs +107 -13
  10. package/dist/cjs/fetchDistantDictionaries.cjs.map +1 -1
  11. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs +1 -1
  12. package/dist/cjs/init/frameworkSetup/tanstackStart/transforms.cjs.map +1 -1
  13. package/dist/cjs/loadDictionaries/loadDictionaries.cjs +4 -2
  14. package/dist/cjs/loadDictionaries/loadDictionaries.cjs.map +1 -1
  15. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs +3 -2
  16. package/dist/cjs/loadDictionaries/loadRemoteDictionaries.cjs.map +1 -1
  17. package/dist/cjs/loadDictionaries/log.cjs +28 -5
  18. package/dist/cjs/loadDictionaries/log.cjs.map +1 -1
  19. package/dist/cjs/utils/chunkArray.cjs +24 -0
  20. package/dist/cjs/utils/chunkArray.cjs.map +1 -0
  21. package/dist/cjs/utils/index.cjs +2 -0
  22. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs +153 -92
  23. package/dist/cjs/writeContentDeclaration/transformJSFile.cjs.map +1 -1
  24. package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs +15 -3
  25. package/dist/esm/buildIntlayerDictionary/buildIntlayerDictionary.mjs.map +1 -1
  26. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs +24 -4
  27. package/dist/esm/buildIntlayerDictionary/writeDynamicDictionary.mjs.map +1 -1
  28. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs +43 -6
  29. package/dist/esm/buildIntlayerDictionary/writeFetchDictionary.mjs.map +1 -1
  30. package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs +92 -0
  31. package/dist/esm/buildIntlayerDictionary/writeNestedDictionary.mjs.map +1 -0
  32. package/dist/esm/fetchDistantDictionaries.mjs +107 -13
  33. package/dist/esm/fetchDistantDictionaries.mjs.map +1 -1
  34. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs +1 -1
  35. package/dist/esm/init/frameworkSetup/tanstackStart/transforms.mjs.map +1 -1
  36. package/dist/esm/loadDictionaries/loadDictionaries.mjs +4 -2
  37. package/dist/esm/loadDictionaries/loadDictionaries.mjs.map +1 -1
  38. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs +3 -2
  39. package/dist/esm/loadDictionaries/loadRemoteDictionaries.mjs.map +1 -1
  40. package/dist/esm/loadDictionaries/log.mjs +28 -5
  41. package/dist/esm/loadDictionaries/log.mjs.map +1 -1
  42. package/dist/esm/utils/chunkArray.mjs +22 -0
  43. package/dist/esm/utils/chunkArray.mjs.map +1 -0
  44. package/dist/esm/utils/index.mjs +2 -1
  45. package/dist/esm/writeContentDeclaration/transformJSFile.mjs +153 -92
  46. package/dist/esm/writeContentDeclaration/transformJSFile.mjs.map +1 -1
  47. package/dist/types/buildIntlayerDictionary/buildIntlayerDictionary.d.ts.map +1 -1
  48. package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts +14 -2
  49. package/dist/types/buildIntlayerDictionary/writeDynamicDictionary.d.ts.map +1 -1
  50. package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts +16 -2
  51. package/dist/types/buildIntlayerDictionary/writeFetchDictionary.d.ts.map +1 -1
  52. package/dist/types/buildIntlayerDictionary/writeNestedDictionary.d.ts +54 -0
  53. package/dist/types/buildIntlayerDictionary/writeNestedDictionary.d.ts.map +1 -0
  54. package/dist/types/fetchDistantDictionaries.d.ts +26 -0
  55. package/dist/types/fetchDistantDictionaries.d.ts.map +1 -1
  56. package/dist/types/formatDictionary.d.ts +2 -0
  57. package/dist/types/formatDictionary.d.ts.map +1 -1
  58. package/dist/types/loadDictionaries/log.d.ts +16 -1
  59. package/dist/types/loadDictionaries/log.d.ts.map +1 -1
  60. package/dist/types/utils/chunkArray.d.ts +16 -0
  61. package/dist/types/utils/chunkArray.d.ts.map +1 -0
  62. package/dist/types/utils/index.d.ts +2 -1
  63. package/dist/types/writeContentDeclaration/transformJSFile.d.ts.map +1 -1
  64. package/package.json +11 -11
@@ -11,6 +11,81 @@ recast = require_runtime.__toESM(recast);
11
11
  const b = recast.types.builders;
12
12
  const n = recast.types.namedTypes;
13
13
  /**
14
+ * Every {@link NodeType} and how it is written back to a JS/TS declaration file.
15
+ *
16
+ * Typed as `Record<NodeType, NodeTypeStrategy>` so that adding a node type to
17
+ * `@intlayer/types` without registering it here becomes a compile-time error —
18
+ * the same guarantee `getNodeType` gives on the read side.
19
+ */
20
+ const nodeTypeStrategies = {
21
+ [_intlayer_types_nodeType.TRANSLATION]: {
22
+ kind: "helperRecord",
23
+ helper: "t"
24
+ },
25
+ [_intlayer_types_nodeType.ENUMERATION]: {
26
+ kind: "helperRecord",
27
+ helper: "enu"
28
+ },
29
+ [_intlayer_types_nodeType.PLURAL]: {
30
+ kind: "helperRecord",
31
+ helper: "plural"
32
+ },
33
+ [_intlayer_types_nodeType.CONDITION]: {
34
+ kind: "helperRecord",
35
+ helper: "cond"
36
+ },
37
+ [_intlayer_types_nodeType.GENDER]: {
38
+ kind: "helperRecord",
39
+ helper: "gender"
40
+ },
41
+ [_intlayer_types_nodeType.SELECT]: {
42
+ kind: "helperRecord",
43
+ helper: "select",
44
+ getExtraArguments: (node) => typeof node.variable === "string" && node.variable.length > 0 ? [b.literal(node.variable)] : []
45
+ },
46
+ [_intlayer_types_nodeType.INSERTION]: {
47
+ kind: "helperValue",
48
+ helper: "insert"
49
+ },
50
+ [_intlayer_types_nodeType.MARKDOWN]: {
51
+ kind: "helperValue",
52
+ helper: "md"
53
+ },
54
+ [_intlayer_types_nodeType.HTML]: {
55
+ kind: "helperValue",
56
+ helper: "html"
57
+ },
58
+ [_intlayer_types_nodeType.FILE]: {
59
+ kind: "helperValue",
60
+ helper: "file"
61
+ },
62
+ [_intlayer_types_nodeType.NESTED]: {
63
+ kind: "nesting",
64
+ helper: "nest"
65
+ },
66
+ [_intlayer_types_nodeType.TEXT]: { kind: "unwrap" },
67
+ [_intlayer_types_nodeType.NUMBER]: { kind: "unwrap" },
68
+ [_intlayer_types_nodeType.BOOLEAN]: { kind: "unwrap" },
69
+ [_intlayer_types_nodeType.NULL]: { kind: "unwrap" },
70
+ [_intlayer_types_nodeType.REACT_NODE]: { kind: "preserve" },
71
+ [_intlayer_types_nodeType.PREACT_NODE]: { kind: "preserve" },
72
+ [_intlayer_types_nodeType.SOLID_NODE]: { kind: "preserve" },
73
+ [_intlayer_types_nodeType.OBJECT]: { kind: "structural" },
74
+ [_intlayer_types_nodeType.ARRAY]: { kind: "structural" },
75
+ [_intlayer_types_nodeType.UNKNOWN]: { kind: "structural" }
76
+ };
77
+ /** Every `intlayer` helper the transform is allowed to rewrite. */
78
+ const helperNames = new Set(Object.values(nodeTypeStrategies).flatMap((strategy) => "helper" in strategy ? [strategy.helper] : []));
79
+ /** Helpers wrapping a single content, e.g. `md(t({ … }))`. */
80
+ const wrapperHelperNames = new Set(Object.values(nodeTypeStrategies).flatMap((strategy) => strategy.kind === "helperValue" ? [strategy.helper] : []));
81
+ /**
82
+ * Returned by {@link buildNodeForValue} when a value must not be written to the
83
+ * source file — framework elements and functions have no data representation,
84
+ * so the original expression (when there is one) is left untouched and no new
85
+ * property is created otherwise.
86
+ */
87
+ const SKIP_WRITE = Symbol("intlayer.skipWrite");
88
+ /**
14
89
  * Unwraps TypeScript/Babel expression wrappers (satisfies, as, !, <Type>).
15
90
  * Uses string fallbacks to bypass outdated ast-types definitions.
16
91
  */
@@ -65,39 +140,51 @@ const syncNumericSuffixAcrossLocales = (existingNode, fallbackLocaleCode, newFal
65
140
  };
66
141
  /**
67
142
  * Checks if a value represents a multilingual Intlayer node.
68
- * A node is multilingual if it is a Translation node, or if it is a specialized node
69
- * (Markdown, HTML, etc.) that contains a Translation node.
143
+ *
144
+ * A node is multilingual if it is a Translation node, if it wraps one
145
+ * (Markdown, HTML, Insertion…), or if any of its variants contains one
146
+ * (Enumeration, Plural, Condition, Gender, Select…).
70
147
  */
71
148
  const isMultilingualNode = (val) => {
72
149
  if (typeof val !== "object" || val === null || Array.isArray(val)) return false;
73
150
  const nodeType = (0, _intlayer_core_dictionaryManipulator.getNodeType)(val);
74
151
  if (nodeType === _intlayer_types_nodeType.TRANSLATION) return true;
75
- if (nodeType === _intlayer_types_nodeType.MARKDOWN || nodeType === _intlayer_types_nodeType.HTML || nodeType === _intlayer_types_nodeType.INSERTION) return isMultilingualNode(val[nodeType]);
76
- if (nodeType === _intlayer_types_nodeType.ENUMERATION || nodeType === _intlayer_types_nodeType.PLURAL || nodeType === _intlayer_types_nodeType.CONDITION || nodeType === _intlayer_types_nodeType.GENDER || nodeType === _intlayer_types_nodeType.SELECT) {
77
- const data = val[nodeType];
78
- if (data && typeof data === "object") return Object.values(data).some((v) => isMultilingualNode(v));
79
- }
152
+ const strategy = nodeTypeStrategies[nodeType];
153
+ const nodeData = val[nodeType];
154
+ if (strategy.kind === "helperValue" || strategy.kind === "unwrap") return isMultilingualNode(nodeData);
155
+ if (strategy.kind === "helperRecord" && nodeData && typeof nodeData === "object") return Object.values(nodeData).some((variant) => isMultilingualNode(variant));
80
156
  return false;
81
157
  };
82
158
  /**
159
+ * Checks whether two AST nodes are literals holding the same value.
160
+ */
161
+ const isEquivalentLiteral = (left, right) => {
162
+ const isLiteral = (node) => n.Literal.check(node) || n.StringLiteral.check(node) || n.NumericLiteral.check(node) || n.BooleanLiteral.check(node);
163
+ return isLiteral(left) && isLiteral(right) && left.value === right.value;
164
+ };
165
+ /**
166
+ * Aligns the arguments of an existing call expression with the desired ones.
167
+ *
168
+ * Mutates the call only when the arguments actually differ, so Recast keeps the
169
+ * original formatting (and quote style) of calls that did not change.
170
+ */
171
+ const syncCallArguments = (callNode, desiredArguments) => {
172
+ if (!(callNode.arguments.length === desiredArguments.length && desiredArguments.every((desired, index) => {
173
+ const current = callNode.arguments[index];
174
+ return current === desired || isEquivalentLiteral(current, desired);
175
+ }))) callNode.arguments = desiredArguments;
176
+ };
177
+ /**
83
178
  * Recursively builds or updates an AST node for a given dictionary value.
179
+ *
180
+ * Returns {@link SKIP_WRITE} when the value cannot be represented in source and
181
+ * no existing expression can be kept.
84
182
  */
85
183
  const buildNodeForValue = (val, existingNode, fallbackLocale, requiredImports) => {
184
+ if (val === void 0 || typeof val === "function") return existingNode ?? SKIP_WRITE;
86
185
  const unwrappedExisting = unwrap(existingNode);
87
186
  if (unwrappedExisting) {
88
- if (!(n.Literal.check(unwrappedExisting) || n.StringLiteral.check(unwrappedExisting) || n.NumericLiteral.check(unwrappedExisting) || n.BooleanLiteral.check(unwrappedExisting) || n.TemplateLiteral.check(unwrappedExisting) || n.ObjectExpression.check(unwrappedExisting) || n.ArrayExpression.check(unwrappedExisting) || n.CallExpression.check(unwrappedExisting) && n.Identifier.check(unwrappedExisting.callee) && [
89
- "t",
90
- "enu",
91
- "plural",
92
- "cond",
93
- "gender",
94
- "select",
95
- "insert",
96
- "md",
97
- "html",
98
- "file",
99
- "nest"
100
- ].includes(unwrappedExisting.callee.name))) return existingNode;
187
+ if (!(n.Literal.check(unwrappedExisting) || n.StringLiteral.check(unwrappedExisting) || n.NumericLiteral.check(unwrappedExisting) || n.BooleanLiteral.check(unwrappedExisting) || n.TemplateLiteral.check(unwrappedExisting) || n.ObjectExpression.check(unwrappedExisting) || n.ArrayExpression.check(unwrappedExisting) || n.CallExpression.check(unwrappedExisting) && n.Identifier.check(unwrappedExisting.callee) && helperNames.has(unwrappedExisting.callee.name))) return existingNode;
101
188
  }
102
189
  if (fallbackLocale && !existingNode && !isMultilingualNode(val)) {
103
190
  if (val === null) return b.literal(null);
@@ -119,14 +206,15 @@ const buildNodeForValue = (val, existingNode, fallbackLocale, requiredImports) =
119
206
  return existingNode;
120
207
  }
121
208
  }
122
- if ((!val || typeof val !== "object") && n.CallExpression.check(existingNode) && n.Identifier.check(existingNode.callee) && existingNode.callee.name === "md") {
209
+ if ((!val || typeof val !== "object") && n.CallExpression.check(existingNode) && n.Identifier.check(existingNode.callee) && wrapperHelperNames.has(existingNode.callee.name)) {
210
+ const wrapperName = existingNode.callee.name;
123
211
  const innerArg = existingNode.arguments[0];
124
212
  if (n.CallExpression.check(innerArg) && n.Identifier.check(innerArg.callee) && innerArg.callee.name === "t") {
125
213
  const tArg = unwrap(innerArg.arguments[0]);
126
214
  if (n.ObjectExpression.check(tArg)) {
127
215
  if (typeof val === "string") syncNumericSuffixAcrossLocales(tArg, fallbackLocale, val);
128
216
  updateObjectLiteral(tArg, { [fallbackLocale]: val }, fallbackLocale, requiredImports);
129
- requiredImports.add("md");
217
+ requiredImports.add(wrapperName);
130
218
  requiredImports.add("t");
131
219
  return existingNode;
132
220
  }
@@ -136,7 +224,7 @@ const buildNodeForValue = (val, existingNode, fallbackLocale, requiredImports) =
136
224
  if (val === null) return b.literal(null);
137
225
  if (typeof val === "string" || typeof val === "number" || typeof val === "boolean") {
138
226
  if (unwrappedExisting) {
139
- if (n.TemplateLiteral.check(unwrappedExisting) && unwrappedExisting.expressions.length === 0) {
227
+ if (n.TemplateLiteral.check(unwrappedExisting) && unwrappedExisting.quasis[0] && unwrappedExisting.expressions.length === 0) {
140
228
  unwrappedExisting.quasis[0].value.raw = String(val);
141
229
  unwrappedExisting.quasis[0].value.cooked = String(val);
142
230
  return existingNode;
@@ -155,83 +243,53 @@ const buildNodeForValue = (val, existingNode, fallbackLocale, requiredImports) =
155
243
  if (Array.isArray(val)) if (unwrappedExisting && n.ArrayExpression.check(unwrappedExisting)) {
156
244
  const elements = [...unwrappedExisting.elements];
157
245
  val.forEach((item, i) => {
158
- elements[i] = buildNodeForValue(item, elements[i], fallbackLocale, requiredImports);
246
+ const elementNode = buildNodeForValue(item, elements[i], fallbackLocale, requiredImports);
247
+ elements[i] = elementNode === SKIP_WRITE ? elements[i] ?? b.literal(null) : elementNode;
159
248
  });
160
249
  if (elements.length > val.length) elements.length = val.length;
161
250
  unwrappedExisting.elements = elements;
162
251
  return existingNode;
163
- } else return b.arrayExpression(val.map((item) => buildNodeForValue(item, null, fallbackLocale, requiredImports)));
252
+ } else return b.arrayExpression(val.map((item) => {
253
+ const elementNode = buildNodeForValue(item, null, fallbackLocale, requiredImports);
254
+ return elementNode === SKIP_WRITE ? b.literal(null) : elementNode;
255
+ }));
164
256
  const nodeType = val && typeof val === "object" && !Array.isArray(val) ? (0, _intlayer_core_dictionaryManipulator.getNodeType)(val) : null;
165
- if (nodeType && [
166
- _intlayer_types_nodeType.TRANSLATION,
167
- _intlayer_types_nodeType.ENUMERATION,
168
- _intlayer_types_nodeType.PLURAL,
169
- _intlayer_types_nodeType.CONDITION,
170
- _intlayer_types_nodeType.GENDER,
171
- _intlayer_types_nodeType.SELECT,
172
- _intlayer_types_nodeType.INSERTION,
173
- _intlayer_types_nodeType.MARKDOWN,
174
- _intlayer_types_nodeType.HTML,
175
- _intlayer_types_nodeType.FILE,
176
- _intlayer_types_nodeType.NESTED,
177
- _intlayer_types_nodeType.ARRAY,
178
- _intlayer_types_nodeType.OBJECT,
179
- _intlayer_types_nodeType.REACT_NODE,
180
- _intlayer_types_nodeType.NUMBER,
181
- _intlayer_types_nodeType.BOOLEAN,
182
- _intlayer_types_nodeType.NULL,
183
- _intlayer_types_nodeType.UNKNOWN
184
- ].includes(nodeType) && nodeType !== _intlayer_types_nodeType.TEXT) {
257
+ if (nodeType) {
258
+ const strategy = nodeTypeStrategies[nodeType];
259
+ if (strategy.kind === "preserve") return existingNode ?? SKIP_WRITE;
260
+ const hasNodeData = Object.hasOwn(val, nodeType);
185
261
  const nodeData = val[nodeType];
186
- let calleeName = "";
187
- if (nodeType === _intlayer_types_nodeType.TRANSLATION) calleeName = "t";
188
- else if (nodeType === _intlayer_types_nodeType.ENUMERATION) calleeName = "enu";
189
- else if (nodeType === _intlayer_types_nodeType.PLURAL) calleeName = "plural";
190
- else if (nodeType === _intlayer_types_nodeType.CONDITION) calleeName = "cond";
191
- else if (nodeType === _intlayer_types_nodeType.GENDER) calleeName = "gender";
192
- else if (nodeType === _intlayer_types_nodeType.SELECT) calleeName = "select";
193
- else if (nodeType === _intlayer_types_nodeType.INSERTION) calleeName = "insert";
194
- else if (nodeType === _intlayer_types_nodeType.MARKDOWN) calleeName = "md";
195
- else if (nodeType === _intlayer_types_nodeType.HTML) calleeName = "html";
196
- else if (nodeType === _intlayer_types_nodeType.FILE) calleeName = "file";
197
- else if (nodeType === _intlayer_types_nodeType.NESTED) calleeName = "nest";
198
- if (calleeName) requiredImports.add(calleeName);
199
- const isMatchingCall = existingNode && n.CallExpression.check(existingNode) && n.Identifier.check(existingNode.callee) && existingNode.callee.name === calleeName;
200
- if ([
201
- "t",
202
- "enu",
203
- "plural",
204
- "cond",
205
- "gender",
206
- "select"
207
- ].includes(calleeName)) {
208
- let objArg = null;
209
- if (isMatchingCall && existingNode.arguments.length > 0 && n.ObjectExpression.check(existingNode.arguments[0])) objArg = existingNode.arguments[0];
210
- else objArg = b.objectExpression([]);
211
- updateObjectLiteral(objArg, nodeData, fallbackLocale, requiredImports);
212
- return isMatchingCall ? existingNode : b.callExpression(b.identifier(calleeName), [objArg]);
213
- }
214
- if ([
215
- "md",
216
- "html",
217
- "insert",
218
- "file"
219
- ].includes(calleeName)) {
220
- const argNode = buildNodeForValue(nodeData, isMatchingCall && existingNode.arguments.length > 0 ? existingNode.arguments[0] : null, fallbackLocale, requiredImports);
221
- if (isMatchingCall) {
222
- existingNode.arguments[0] = argNode;
223
- return existingNode;
262
+ if (strategy.kind !== "structural" && hasNodeData) {
263
+ if (strategy.kind === "unwrap") return buildNodeForValue(nodeData, existingNode, fallbackLocale, requiredImports);
264
+ const { helper } = strategy;
265
+ requiredImports.add(helper);
266
+ const isMatchingCall = existingNode && n.CallExpression.check(existingNode) && n.Identifier.check(existingNode.callee) && existingNode.callee.name === helper;
267
+ if (strategy.kind === "helperRecord") {
268
+ const recordArgument = isMatchingCall && existingNode.arguments.length > 0 && n.ObjectExpression.check(existingNode.arguments[0]) ? existingNode.arguments[0] : b.objectExpression([]);
269
+ updateObjectLiteral(recordArgument, nodeData ?? {}, fallbackLocale, requiredImports);
270
+ const callArguments = [recordArgument, ...strategy.getExtraArguments?.(val) ?? []];
271
+ if (isMatchingCall) {
272
+ syncCallArguments(existingNode, callArguments);
273
+ return existingNode;
274
+ }
275
+ return b.callExpression(b.identifier(helper), callArguments);
224
276
  }
225
- return b.callExpression(b.identifier(calleeName), [argNode]);
226
- }
227
- if (calleeName === "nest") {
228
- const args = [b.literal(nodeData.dictionaryKey)];
229
- if (nodeData.path) args.push(b.literal(nodeData.path));
277
+ if (strategy.kind === "helperValue") {
278
+ const contentArgument = buildNodeForValue(nodeData, isMatchingCall && existingNode.arguments.length > 0 ? existingNode.arguments[0] : null, fallbackLocale, requiredImports);
279
+ if (contentArgument === SKIP_WRITE) return existingNode ?? SKIP_WRITE;
280
+ if (isMatchingCall) {
281
+ syncCallArguments(existingNode, [contentArgument, ...existingNode.arguments.slice(1)]);
282
+ return existingNode;
283
+ }
284
+ return b.callExpression(b.identifier(helper), [contentArgument]);
285
+ }
286
+ const callArguments = [b.literal(nodeData?.dictionaryKey ?? "")];
287
+ if (nodeData?.path) callArguments.push(b.literal(nodeData.path));
230
288
  if (isMatchingCall) {
231
- existingNode.arguments = args;
289
+ syncCallArguments(existingNode, callArguments);
232
290
  return existingNode;
233
291
  }
234
- return b.callExpression(b.identifier("nest"), args);
292
+ return b.callExpression(b.identifier(helper), callArguments);
235
293
  }
236
294
  }
237
295
  const objNode = unwrappedExisting && n.ObjectExpression.check(unwrappedExisting) ? unwrappedExisting : b.objectExpression([]);
@@ -245,10 +303,13 @@ const updateObjectLiteral = (node, data, fallbackLocale, requiredImports) => {
245
303
  for (const [key, val] of Object.entries(data)) {
246
304
  if (val === void 0) continue;
247
305
  const existingProp = getMatchingProperty(node, key);
248
- if (existingProp) existingProp.value = buildNodeForValue(val, existingProp.value, fallbackLocale, requiredImports);
249
- else {
306
+ if (existingProp) {
307
+ const valueNode = buildNodeForValue(val, existingProp.value, fallbackLocale, requiredImports);
308
+ if (valueNode !== SKIP_WRITE) existingProp.value = valueNode;
309
+ } else {
250
310
  const keyNode = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? b.identifier(key) : b.literal(key);
251
311
  const valueNode = buildNodeForValue(val, null, fallbackLocale, requiredImports);
312
+ if (valueNode === SKIP_WRITE) continue;
252
313
  node.properties.push(b.property("init", keyNode, valueNode));
253
314
  }
254
315
  }
@@ -1 +1 @@
1
- {"version":3,"file":"transformJSFile.cjs","names":["NodeTypes","babelTsParser"],"sources":["../../../src/writeContentDeclaration/transformJSFile.ts"],"sourcesContent":["import { getNodeType } from '@intlayer/core/dictionaryManipulator';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { ContentNode, Dictionary } from '@intlayer/types/dictionary';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport * as recast from 'recast';\nimport { babelTsParser } from '../utils/babelParser';\n\nconst b = recast.types.builders;\nconst n = recast.types.namedTypes;\n\n/**\n * Unwraps TypeScript/Babel expression wrappers (satisfies, as, !, <Type>).\n * Uses string fallbacks to bypass outdated ast-types definitions.\n */\nconst unwrap = (node: any) => {\n while (\n node &&\n (n.TSSatisfiesExpression?.check(node) ||\n n.TSAsExpression?.check(node) ||\n n.TSTypeAssertion?.check(node) ||\n n.TSNonNullExpression?.check(node) ||\n [\n 'TSSatisfiesExpression',\n 'TSAsExpression',\n 'TSTypeAssertion',\n 'TSNonNullExpression',\n ].includes(node.type))\n ) {\n node = node.expression;\n }\n return node;\n};\n\n/**\n * Robustly finds a property in a recast ObjectExpression.\n * Handles quoted (\"key\") or unquoted (key) properties.\n */\nconst getMatchingProperty = (node: any, key: string) => {\n return node.properties.find((prop: any) => {\n if (n.Property.check(prop) || n.ObjectProperty.check(prop)) {\n if (n.Identifier.check(prop.key) && prop.key.name === key) return true;\n\n if (n.StringLiteral.check(prop.key) && prop.key.value === key)\n return true;\n\n if (n.Literal.check(prop.key) && prop.key.value === key) return true;\n }\n\n return false;\n });\n};\n\n/**\n * Synchronizes numeric suffixes across locales.\n * E.g. \"Hello 1\" -> \"Hello 3\" updates \"Bonjour 1\" to \"Bonjour 3\".\n */\nconst syncNumericSuffixAcrossLocales = (\n existingNode: any,\n fallbackLocaleCode: string,\n newFallbackValue: string\n) => {\n const trailingNumberMatch = newFallbackValue.match(/\\d+(?!.*\\d)/);\n if (!trailingNumberMatch) return;\n const newTrailingNumber = trailingNumberMatch[0];\n\n if (n.ObjectExpression.check(existingNode)) {\n for (const prop of existingNode.properties) {\n if (n.Property.check(prop) || n.ObjectProperty.check(prop)) {\n let propName = '';\n\n if (n.Identifier.check(prop.key)) propName = prop.key.name;\n else if (\n n.Literal.check(prop.key) &&\n typeof prop.key.value === 'string'\n )\n propName = prop.key.value;\n else if (n.StringLiteral.check(prop.key)) propName = prop.key.value;\n\n if (propName && propName !== fallbackLocaleCode) {\n if (\n n.Literal.check(prop.value) &&\n typeof prop.value.value === 'string'\n ) {\n const currentValue = prop.value.value;\n const currentTrailingNumberMatch =\n currentValue.match(/\\d+(?!.*\\d)/);\n\n if (currentTrailingNumberMatch) {\n prop.value = b.literal(\n currentValue.replace(/(\\d+)(?!.*\\d)/, newTrailingNumber)\n );\n }\n } else if (n.StringLiteral.check(prop.value)) {\n const currentValue = prop.value.value;\n const currentTrailingNumberMatch =\n currentValue.match(/\\d+(?!.*\\d)/);\n\n if (currentTrailingNumberMatch) {\n prop.value = b.stringLiteral(\n currentValue.replace(/(\\d+)(?!.*\\d)/, newTrailingNumber)\n );\n }\n }\n }\n }\n }\n }\n};\n\n/**\n * Checks if a value represents a multilingual Intlayer node.\n * A node is multilingual if it is a Translation node, or if it is a specialized node\n * (Markdown, HTML, etc.) that contains a Translation node.\n */\nconst isMultilingualNode = (val: any): boolean => {\n if (typeof val !== 'object' || val === null || Array.isArray(val)) {\n return false;\n }\n\n const nodeType = getNodeType(val as ContentNode);\n\n if (nodeType === NodeTypes.TRANSLATION) {\n return true;\n }\n\n if (\n nodeType === NodeTypes.MARKDOWN ||\n nodeType === NodeTypes.HTML ||\n nodeType === NodeTypes.INSERTION\n ) {\n return isMultilingualNode((val as any)[nodeType]);\n }\n\n if (\n nodeType === NodeTypes.ENUMERATION ||\n nodeType === NodeTypes.PLURAL ||\n nodeType === NodeTypes.CONDITION ||\n nodeType === NodeTypes.GENDER ||\n nodeType === NodeTypes.SELECT\n ) {\n const data = (val as any)[nodeType];\n\n if (data && typeof data === 'object') {\n return Object.values(data).some((v) => isMultilingualNode(v));\n }\n }\n\n return false;\n};\n\n/**\n * Recursively builds or updates an AST node for a given dictionary value.\n */\nconst buildNodeForValue = (\n val: any,\n existingNode: any,\n fallbackLocale: string | undefined, // In per-locale mode, this is the locale of the file\n requiredImports: Set<string>\n): any => {\n const unwrappedExisting = unwrap(existingNode);\n\n // --- CRITICAL GUARD: STRICT AST PRESERVATION ---\n // If the existing node is code (JSX, Variables, standard functions), leave it alone.\n // Only allow updates to literals, plain objects, arrays, and Intlayer helpers.\n if (unwrappedExisting) {\n const isUpdatableNode =\n n.Literal.check(unwrappedExisting) ||\n n.StringLiteral.check(unwrappedExisting) ||\n n.NumericLiteral.check(unwrappedExisting) ||\n n.BooleanLiteral.check(unwrappedExisting) ||\n n.TemplateLiteral.check(unwrappedExisting) ||\n n.ObjectExpression.check(unwrappedExisting) ||\n n.ArrayExpression.check(unwrappedExisting) ||\n (n.CallExpression.check(unwrappedExisting) &&\n n.Identifier.check(unwrappedExisting.callee) &&\n [\n 't',\n 'enu',\n 'plural',\n 'cond',\n 'gender',\n 'select',\n 'insert',\n 'md',\n 'html',\n 'file',\n 'nest',\n ].includes(unwrappedExisting.callee.name));\n\n if (!isUpdatableNode) {\n return existingNode;\n }\n }\n\n // If we are in per-locale mode (fallbackLocale is set)\n // and the value is not already a complex translation node,\n // we want to store it as a simple literal, NOT wrapped in t().\n if (fallbackLocale && !existingNode && !isMultilingualNode(val)) {\n if (val === null) return b.literal(null);\n if (\n typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean'\n ) {\n if (typeof val === 'string' && val.includes('\\n')) {\n return b.templateLiteral(\n [b.templateElement({ raw: val, cooked: val }, true)],\n []\n );\n }\n return b.literal(val);\n }\n }\n\n if (fallbackLocale && existingNode && !isMultilingualNode(val)) {\n if (\n n.CallExpression.check(existingNode) &&\n n.Identifier.check(existingNode.callee) &&\n existingNode.callee.name === 't'\n ) {\n const arg = unwrap(existingNode.arguments[0]);\n\n if (n.ObjectExpression.check(arg)) {\n if (typeof val === 'string') {\n syncNumericSuffixAcrossLocales(arg, fallbackLocale, val);\n }\n updateObjectLiteral(\n arg,\n { [fallbackLocale]: val },\n fallbackLocale,\n requiredImports\n );\n\n if (!fallbackLocale) {\n requiredImports.add('t');\n }\n\n return existingNode;\n }\n }\n\n if (\n (!val || typeof val !== 'object') &&\n n.CallExpression.check(existingNode) &&\n n.Identifier.check(existingNode.callee) &&\n existingNode.callee.name === 'md'\n ) {\n const innerArg = existingNode.arguments[0];\n\n if (\n n.CallExpression.check(innerArg) &&\n n.Identifier.check(innerArg.callee) &&\n innerArg.callee.name === 't'\n ) {\n const tArg = unwrap(innerArg.arguments[0]);\n\n if (n.ObjectExpression.check(tArg)) {\n if (typeof val === 'string') {\n syncNumericSuffixAcrossLocales(tArg, fallbackLocale, val);\n }\n updateObjectLiteral(\n tArg,\n { [fallbackLocale]: val },\n fallbackLocale,\n requiredImports\n );\n requiredImports.add('md');\n requiredImports.add('t');\n\n return existingNode;\n }\n }\n }\n }\n\n // 1. Primitives\n if (val === null) return b.literal(null);\n if (\n typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean'\n ) {\n if (unwrappedExisting) {\n // Preserve existing template literals (backticks)\n if (\n n.TemplateLiteral.check(unwrappedExisting) &&\n unwrappedExisting.expressions.length === 0\n ) {\n unwrappedExisting.quasis[0].value.raw = String(val);\n unwrappedExisting.quasis[0].value.cooked = String(val);\n return existingNode;\n }\n // Preserve existing standard literals (keeps quote styling)\n if (\n n.Literal.check(unwrappedExisting) ||\n n.StringLiteral.check(unwrappedExisting)\n ) {\n unwrappedExisting.value = val;\n return existingNode;\n }\n }\n\n // Force multiline strings to use Template Literals\n if (typeof val === 'string' && val.includes('\\n')) {\n return b.templateLiteral(\n [b.templateElement({ raw: val, cooked: val }, true)],\n []\n );\n }\n return b.literal(val);\n }\n\n // 2. Arrays\n if (Array.isArray(val)) {\n if (unwrappedExisting && n.ArrayExpression.check(unwrappedExisting)) {\n const elements = [...unwrappedExisting.elements];\n val.forEach((item, i) => {\n elements[i] = buildNodeForValue(\n item,\n elements[i],\n fallbackLocale,\n requiredImports\n );\n });\n\n if (elements.length > val.length) elements.length = val.length;\n unwrappedExisting.elements = elements as any;\n\n return existingNode;\n } else {\n return b.arrayExpression(\n val.map((item) =>\n buildNodeForValue(item, null, fallbackLocale, requiredImports)\n )\n );\n }\n }\n\n // 3. Intlayer Specialized Nodes\n const nodeType =\n val && typeof val === 'object' && !Array.isArray(val)\n ? getNodeType(val as ContentNode)\n : null;\n\n if (\n nodeType &&\n [\n NodeTypes.TRANSLATION,\n NodeTypes.ENUMERATION,\n NodeTypes.PLURAL,\n NodeTypes.CONDITION,\n NodeTypes.GENDER,\n NodeTypes.SELECT,\n NodeTypes.INSERTION,\n NodeTypes.MARKDOWN,\n NodeTypes.HTML,\n NodeTypes.FILE,\n NodeTypes.NESTED,\n NodeTypes.ARRAY,\n NodeTypes.OBJECT,\n NodeTypes.REACT_NODE,\n NodeTypes.NUMBER,\n NodeTypes.BOOLEAN,\n NodeTypes.NULL,\n NodeTypes.UNKNOWN,\n ].includes(nodeType as any) &&\n nodeType !== NodeTypes.TEXT\n ) {\n const nodeData = (val as any)[nodeType];\n let calleeName = '';\n\n if (nodeType === NodeTypes.TRANSLATION) calleeName = 't';\n else if (nodeType === NodeTypes.ENUMERATION) calleeName = 'enu';\n else if (nodeType === NodeTypes.PLURAL) calleeName = 'plural';\n else if (nodeType === NodeTypes.CONDITION) calleeName = 'cond';\n else if (nodeType === NodeTypes.GENDER) calleeName = 'gender';\n else if (nodeType === NodeTypes.SELECT) calleeName = 'select';\n else if (nodeType === NodeTypes.INSERTION) calleeName = 'insert';\n else if (nodeType === NodeTypes.MARKDOWN) calleeName = 'md';\n else if (nodeType === NodeTypes.HTML) calleeName = 'html';\n else if (nodeType === NodeTypes.FILE) calleeName = 'file';\n else if (nodeType === NodeTypes.NESTED) calleeName = 'nest';\n\n if (calleeName) requiredImports.add(calleeName);\n\n const isMatchingCall =\n existingNode &&\n n.CallExpression.check(existingNode) &&\n n.Identifier.check(existingNode.callee) &&\n existingNode.callee.name === calleeName;\n\n if (\n ['t', 'enu', 'plural', 'cond', 'gender', 'select'].includes(calleeName)\n ) {\n let objArg: any = null;\n\n if (\n isMatchingCall &&\n existingNode.arguments.length > 0 &&\n n.ObjectExpression.check(existingNode.arguments[0])\n ) {\n objArg = existingNode.arguments[0];\n } else {\n objArg = b.objectExpression([]);\n }\n updateObjectLiteral(objArg, nodeData, fallbackLocale, requiredImports);\n\n return isMatchingCall\n ? existingNode\n : b.callExpression(b.identifier(calleeName), [objArg]);\n }\n\n if (['md', 'html', 'insert', 'file'].includes(calleeName)) {\n const argNode = buildNodeForValue(\n nodeData,\n isMatchingCall && existingNode.arguments.length > 0\n ? existingNode.arguments[0]\n : null,\n fallbackLocale,\n requiredImports\n );\n\n if (isMatchingCall) {\n existingNode.arguments[0] = argNode;\n\n return existingNode;\n }\n\n return b.callExpression(b.identifier(calleeName), [argNode]);\n }\n\n if (calleeName === 'nest') {\n const args = [b.literal(nodeData.dictionaryKey)];\n\n if (nodeData.path) args.push(b.literal(nodeData.path));\n\n if (isMatchingCall) {\n existingNode.arguments = args;\n\n return existingNode;\n }\n\n return b.callExpression(b.identifier('nest'), args);\n }\n }\n\n // 4. Plain Object\n const objNode =\n unwrappedExisting && n.ObjectExpression.check(unwrappedExisting)\n ? unwrappedExisting\n : b.objectExpression([]);\n\n updateObjectLiteral(objNode, val, fallbackLocale, requiredImports);\n\n return existingNode && unwrappedExisting === existingNode\n ? objNode\n : existingNode || objNode;\n};\n\n/**\n * Recursively updates the AST object literal properties.\n */\nconst updateObjectLiteral = (\n node: recast.types.namedTypes.ObjectExpression,\n data: Record<string, any>,\n fallbackLocale: string | undefined,\n requiredImports: Set<string>\n) => {\n for (const [key, val] of Object.entries(data)) {\n if (val === undefined) continue;\n\n const existingProp = getMatchingProperty(node, key);\n\n if (existingProp) {\n existingProp.value = buildNodeForValue(\n val,\n existingProp.value,\n fallbackLocale,\n requiredImports\n );\n } else {\n const isValidId = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);\n const keyNode = isValidId ? b.identifier(key) : b.literal(key);\n const valueNode = buildNodeForValue(\n val,\n null,\n fallbackLocale,\n requiredImports\n );\n node.properties.push(b.property('init', keyNode, valueNode));\n }\n }\n};\n\n/**\n * Modifies the AST's top-level imports to inject dynamically needed helper utilities seamlessly.\n */\nconst addImports = (ast: any, requiredImports: Set<string>, isESM: boolean) => {\n if (requiredImports.size === 0) return;\n\n const existingCoreImports = new Set<string>();\n let coreImportPath: any = null;\n\n recast.visit(ast, {\n visitImportDeclaration(path) {\n const source = path.node.source.value;\n\n if (source === 'intlayer') {\n coreImportPath = path;\n path.node.specifiers?.forEach((spec) => {\n if (\n n.ImportSpecifier.check(spec) &&\n typeof spec.imported.name === 'string'\n ) {\n existingCoreImports.add(spec.imported.name);\n }\n });\n }\n\n return false;\n },\n visitVariableDeclaration(path) {\n path.node.declarations.forEach((decl) => {\n if (\n n.VariableDeclarator.check(decl) &&\n n.CallExpression.check(decl.init) &&\n n.Identifier.check(decl.init.callee) &&\n decl.init.callee.name === 'require'\n ) {\n const arg = decl.init.arguments[0];\n\n if (n.Literal.check(arg)) {\n if (arg.value === 'intlayer') {\n if (n.ObjectPattern.check(decl.id)) {\n decl.id.properties.forEach((prop) => {\n if (\n n.Property.check(prop) &&\n (n.Identifier.check(prop.key) ||\n n.Identifier.check(prop.value))\n ) {\n const name = n.Identifier.check(prop.key)\n ? prop.key.name\n : (prop.value as any).name;\n existingCoreImports.add(name);\n }\n });\n } else if (n.Identifier.check(decl.id)) {\n // Handle const intlayer = require('intlayer')\n existingCoreImports.add(decl.id.name);\n }\n }\n }\n }\n });\n\n return false;\n },\n });\n\n const missingCore = Array.from(requiredImports).filter(\n (imp) => !existingCoreImports.has(imp)\n );\n\n if (missingCore.length === 0) return;\n\n if (isESM) {\n if (coreImportPath) {\n missingCore.forEach((imp) => {\n coreImportPath.node.specifiers.push(\n b.importSpecifier(b.identifier(imp))\n );\n });\n coreImportPath.node.specifiers.sort((a: any, b: any) =>\n a.imported.name.localeCompare(b.imported.name)\n );\n } else {\n const specifiers = missingCore\n .sort()\n .map((imp) => b.importSpecifier(b.identifier(imp)));\n const newImport = b.importDeclaration(specifiers, b.literal('intlayer'));\n ast.program.body.unshift(newImport);\n }\n } else {\n let insertIndex = 0;\n\n if (\n ast.program.body.length > 0 &&\n n.ExpressionStatement.check(ast.program.body[0]) &&\n n.Literal.check(ast.program.body[0].expression)\n ) {\n insertIndex = 1; // Insert after 'use strict'\n }\n const cjsLines: any[] = [];\n\n const properties = missingCore.sort().map((imp) => {\n const prop = b.property('init', b.identifier(imp), b.identifier(imp));\n prop.shorthand = true;\n\n return prop;\n });\n cjsLines.push(\n b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern(properties),\n b.callExpression(b.identifier('require'), [b.literal('intlayer')])\n ),\n ])\n );\n\n ast.program.body.splice(insertIndex, 0, ...cjsLines);\n }\n};\n\n/**\n * Updates a JS/TS file seamlessly to map new localization keys, arrays, complex nodes and nested dictionaries gracefully using AST updates via Recast parser.\n */\nexport const transformJSFile = async (\n fileContent: string,\n dictionary: Dictionary,\n fallbackLocale?: Locale,\n noMetadata?: boolean\n): Promise<string> => {\n if (!dictionary || typeof dictionary !== 'object') return fileContent;\n\n let ast: any;\n try {\n ast = recast.parse(fileContent, {\n parser: babelTsParser,\n });\n } catch (error) {\n console.error({ error });\n return fileContent;\n }\n\n let rootObject: any = null;\n let isESM = false;\n\n recast.visit(ast, {\n visitExportDefaultDeclaration() {\n isESM = true;\n\n return false;\n },\n visitImportDeclaration() {\n isESM = true;\n\n return false;\n },\n });\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const decl = path.node.declaration;\n const unwrappedDecl = unwrap(decl);\n\n if (n.ObjectExpression.check(unwrappedDecl)) {\n rootObject = unwrappedDecl;\n } else if (n.Identifier.check(unwrappedDecl)) {\n const varName = unwrappedDecl.name;\n recast.visit(ast, {\n visitVariableDeclarator(vp) {\n const unwrappedInit = unwrap(vp.node.init);\n\n if (\n n.Identifier.check(vp.node.id) &&\n vp.node.id.name === varName &&\n n.ObjectExpression.check(unwrappedInit)\n ) {\n rootObject = unwrappedInit;\n }\n\n return false;\n },\n });\n }\n\n return false;\n },\n visitAssignmentExpression(path) {\n const left = path.node.left;\n\n if (n.MemberExpression.check(left)) {\n if (\n n.Identifier.check(left.object) &&\n left.object.name === 'module' &&\n n.Identifier.check(left.property) &&\n left.property.name === 'exports'\n ) {\n const unwrappedRight = unwrap(path.node.right);\n\n if (n.ObjectExpression.check(unwrappedRight)) {\n rootObject = unwrappedRight;\n }\n }\n\n if (\n n.Identifier.check(left.object) &&\n left.object.name === 'exports' &&\n n.Identifier.check(left.property) &&\n left.property.name === 'default'\n ) {\n const unwrappedRight = unwrap(path.node.right);\n\n if (n.ObjectExpression.check(unwrappedRight)) {\n rootObject = unwrappedRight;\n }\n }\n }\n this.traverse(path);\n },\n });\n\n if (!rootObject) {\n recast.visit(ast, {\n visitVariableDeclarator(path) {\n const unwrappedInit = unwrap(path.node.init);\n\n if (!rootObject && n.ObjectExpression.check(unwrappedInit)) {\n rootObject = unwrappedInit;\n }\n\n return false;\n },\n });\n }\n\n if (!rootObject) return fileContent;\n\n const requiredImports = new Set<string>();\n const effectiveFallbackLocale = (fallbackLocale as string) ?? 'en';\n\n const metadataProperties = [\n 'id',\n 'locale',\n 'filled',\n 'fill',\n 'title',\n 'description',\n 'tags',\n 'version',\n 'priority',\n 'contentAutoTransformation',\n ];\n\n if (noMetadata) {\n // Remove key, content and metadata properties if they exist\n rootObject.properties = rootObject.properties.filter((prop: any) => {\n if (n.Property.check(prop) || n.ObjectProperty.check(prop)) {\n let propName = '';\n if (n.Identifier.check(prop.key)) propName = prop.key.name;\n else if (n.StringLiteral.check(prop.key)) propName = prop.key.value;\n else if (n.Literal.check(prop.key)) propName = String(prop.key.value);\n\n return !['key', 'content', ...metadataProperties].includes(propName);\n }\n return true;\n });\n\n // Update satisfies type if exists\n recast.visit(ast, {\n visitNode(path) {\n const node = path.node;\n if (\n (n.TSSatisfiesExpression?.check(node) ||\n node.type === 'TSSatisfiesExpression') &&\n (node as any).typeAnnotation &&\n n.TSTypeReference.check((node as any).typeAnnotation) &&\n n.Identifier.check((node as any).typeAnnotation.typeName) &&\n (node as any).typeAnnotation.typeName.name === 'Dictionary'\n ) {\n (node as any).typeAnnotation = b.tsIndexedAccessType(\n b.tsTypeReference(b.identifier('Dictionary')),\n b.tsLiteralType(b.stringLiteral('content'))\n );\n }\n this.traverse(path);\n },\n });\n } else {\n for (const prop of metadataProperties) {\n if ((dictionary as any)[prop] !== undefined) {\n updateObjectLiteral(\n rootObject,\n { [prop]: (dictionary as any)[prop] },\n undefined,\n requiredImports\n );\n }\n }\n }\n\n if (dictionary.content !== undefined) {\n updateObjectLiteral(\n rootObject,\n noMetadata\n ? (dictionary.content as Record<string, any>)\n : { content: dictionary.content },\n effectiveFallbackLocale,\n requiredImports\n );\n }\n\n addImports(ast, requiredImports, isESM);\n\n return recast.print(ast).code;\n};\n"],"mappings":"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"}
1
+ {"version":3,"file":"transformJSFile.cjs","names":["NodeTypes","babelTsParser"],"sources":["../../../src/writeContentDeclaration/transformJSFile.ts"],"sourcesContent":["import { getNodeType } from '@intlayer/core/dictionaryManipulator';\nimport type { Locale } from '@intlayer/types/allLocales';\nimport type { ContentNode, Dictionary } from '@intlayer/types/dictionary';\nimport type { NodeType } from '@intlayer/types/nodeType';\nimport * as NodeTypes from '@intlayer/types/nodeType';\nimport * as recast from 'recast';\nimport { babelTsParser } from '../utils/babelParser';\n\nconst b = recast.types.builders;\nconst n = recast.types.namedTypes;\n\n/**\n * Name of an `intlayer` helper function a node type is printed as.\n *\n * Mirrors the transpiler helpers re-exported by the `intlayer` package\n * (`@intlayer/core/transpiler`).\n */\ntype HelperName =\n | 't'\n | 'enu'\n | 'plural'\n | 'cond'\n | 'gender'\n | 'select'\n | 'insert'\n | 'md'\n | 'html'\n | 'file'\n | 'nest';\n\n/**\n * How a {@link NodeType} is materialized back into source code.\n *\n * - `helperRecord` — printed as `helper({ … })`. The node data is a record of\n * variants (locales, plural categories, conditions, cases…) whose values are\n * rebuilt recursively and merged into the existing object literal.\n * - `helperValue` — printed as `helper(value)`. The node data is a single\n * content, itself possibly another node (e.g. `md(t({ … }))`).\n * - `nesting` — printed as `nest(dictionaryKey, path?)`.\n * - `unwrap` — not a source-level helper: the wrapped value replaces the node,\n * so `{ nodeType: 'text', text: 'Hello' }` is printed as `\"Hello\"`.\n * - `preserve` — framework elements have no data representation, so the\n * existing source expression is kept untouched and nothing is written when\n * there is none.\n * - `structural` — plain objects, arrays and unrecognized nodes, rebuilt by the\n * generic object/array branches.\n */\ntype NodeTypeStrategy =\n | {\n kind: 'helperRecord';\n helper: HelperName;\n /**\n * Extra arguments appended after the record argument, rebuilt from the\n * node attributes (e.g. the variable name carried by a `select` node).\n */\n getExtraArguments?: (\n node: Record<string, unknown>\n ) => recast.types.namedTypes.Literal[];\n }\n | { kind: 'helperValue'; helper: HelperName }\n | { kind: 'nesting'; helper: HelperName }\n | { kind: 'unwrap' }\n | { kind: 'preserve' }\n | { kind: 'structural' };\n\n/**\n * Every {@link NodeType} and how it is written back to a JS/TS declaration file.\n *\n * Typed as `Record<NodeType, NodeTypeStrategy>` so that adding a node type to\n * `@intlayer/types` without registering it here becomes a compile-time error —\n * the same guarantee `getNodeType` gives on the read side.\n */\nconst nodeTypeStrategies: Record<NodeType, NodeTypeStrategy> = {\n [NodeTypes.TRANSLATION]: { kind: 'helperRecord', helper: 't' },\n [NodeTypes.ENUMERATION]: { kind: 'helperRecord', helper: 'enu' },\n [NodeTypes.PLURAL]: { kind: 'helperRecord', helper: 'plural' },\n [NodeTypes.CONDITION]: { kind: 'helperRecord', helper: 'cond' },\n [NodeTypes.GENDER]: { kind: 'helperRecord', helper: 'gender' },\n [NodeTypes.SELECT]: {\n kind: 'helperRecord',\n helper: 'select',\n getExtraArguments: (node) =>\n typeof node.variable === 'string' && node.variable.length > 0\n ? [b.literal(node.variable)]\n : [],\n },\n [NodeTypes.INSERTION]: { kind: 'helperValue', helper: 'insert' },\n [NodeTypes.MARKDOWN]: { kind: 'helperValue', helper: 'md' },\n [NodeTypes.HTML]: { kind: 'helperValue', helper: 'html' },\n [NodeTypes.FILE]: { kind: 'helperValue', helper: 'file' },\n [NodeTypes.NESTED]: { kind: 'nesting', helper: 'nest' },\n [NodeTypes.TEXT]: { kind: 'unwrap' },\n [NodeTypes.NUMBER]: { kind: 'unwrap' },\n [NodeTypes.BOOLEAN]: { kind: 'unwrap' },\n [NodeTypes.NULL]: { kind: 'unwrap' },\n [NodeTypes.REACT_NODE]: { kind: 'preserve' },\n [NodeTypes.PREACT_NODE]: { kind: 'preserve' },\n [NodeTypes.SOLID_NODE]: { kind: 'preserve' },\n [NodeTypes.OBJECT]: { kind: 'structural' },\n [NodeTypes.ARRAY]: { kind: 'structural' },\n [NodeTypes.UNKNOWN]: { kind: 'structural' },\n};\n\n/** Every `intlayer` helper the transform is allowed to rewrite. */\nconst helperNames = new Set<string>(\n Object.values(nodeTypeStrategies).flatMap((strategy) =>\n 'helper' in strategy ? [strategy.helper] : []\n )\n);\n\n/** Helpers wrapping a single content, e.g. `md(t({ … }))`. */\nconst wrapperHelperNames = new Set<string>(\n Object.values(nodeTypeStrategies).flatMap((strategy) =>\n strategy.kind === 'helperValue' ? [strategy.helper] : []\n )\n);\n\n/**\n * Returned by {@link buildNodeForValue} when a value must not be written to the\n * source file — framework elements and functions have no data representation,\n * so the original expression (when there is one) is left untouched and no new\n * property is created otherwise.\n */\nconst SKIP_WRITE = Symbol('intlayer.skipWrite');\n\n/**\n * Unwraps TypeScript/Babel expression wrappers (satisfies, as, !, <Type>).\n * Uses string fallbacks to bypass outdated ast-types definitions.\n */\nconst unwrap = (node: any) => {\n while (\n node &&\n (n.TSSatisfiesExpression?.check(node) ||\n n.TSAsExpression?.check(node) ||\n n.TSTypeAssertion?.check(node) ||\n n.TSNonNullExpression?.check(node) ||\n [\n 'TSSatisfiesExpression',\n 'TSAsExpression',\n 'TSTypeAssertion',\n 'TSNonNullExpression',\n ].includes(node.type))\n ) {\n node = node.expression;\n }\n return node;\n};\n\n/**\n * Robustly finds a property in a recast ObjectExpression.\n * Handles quoted (\"key\") or unquoted (key) properties.\n */\nconst getMatchingProperty = (node: any, key: string) => {\n return node.properties.find((prop: any) => {\n if (n.Property.check(prop) || n.ObjectProperty.check(prop)) {\n if (n.Identifier.check(prop.key) && prop.key.name === key) return true;\n\n if (n.StringLiteral.check(prop.key) && prop.key.value === key)\n return true;\n\n if (n.Literal.check(prop.key) && prop.key.value === key) return true;\n }\n\n return false;\n });\n};\n\n/**\n * Synchronizes numeric suffixes across locales.\n * E.g. \"Hello 1\" -> \"Hello 3\" updates \"Bonjour 1\" to \"Bonjour 3\".\n */\nconst syncNumericSuffixAcrossLocales = (\n existingNode: any,\n fallbackLocaleCode: string,\n newFallbackValue: string\n) => {\n const trailingNumberMatch = newFallbackValue.match(/\\d+(?!.*\\d)/);\n if (!trailingNumberMatch) return;\n const newTrailingNumber = trailingNumberMatch[0];\n\n if (n.ObjectExpression.check(existingNode)) {\n for (const prop of existingNode.properties) {\n if (n.Property.check(prop) || n.ObjectProperty.check(prop)) {\n let propName = '';\n\n if (n.Identifier.check(prop.key)) propName = prop.key.name;\n else if (\n n.Literal.check(prop.key) &&\n typeof prop.key.value === 'string'\n )\n propName = prop.key.value;\n else if (n.StringLiteral.check(prop.key)) propName = prop.key.value;\n\n if (propName && propName !== fallbackLocaleCode) {\n if (\n n.Literal.check(prop.value) &&\n typeof prop.value.value === 'string'\n ) {\n const currentValue = prop.value.value;\n const currentTrailingNumberMatch =\n currentValue.match(/\\d+(?!.*\\d)/);\n\n if (currentTrailingNumberMatch) {\n prop.value = b.literal(\n currentValue.replace(/(\\d+)(?!.*\\d)/, newTrailingNumber)\n );\n }\n } else if (n.StringLiteral.check(prop.value)) {\n const currentValue = prop.value.value;\n const currentTrailingNumberMatch =\n currentValue.match(/\\d+(?!.*\\d)/);\n\n if (currentTrailingNumberMatch) {\n prop.value = b.stringLiteral(\n currentValue.replace(/(\\d+)(?!.*\\d)/, newTrailingNumber)\n );\n }\n }\n }\n }\n }\n }\n};\n\n/**\n * Checks if a value represents a multilingual Intlayer node.\n *\n * A node is multilingual if it is a Translation node, if it wraps one\n * (Markdown, HTML, Insertion…), or if any of its variants contains one\n * (Enumeration, Plural, Condition, Gender, Select…).\n */\nconst isMultilingualNode = (val: any): boolean => {\n if (typeof val !== 'object' || val === null || Array.isArray(val)) {\n return false;\n }\n\n const nodeType = getNodeType(val as ContentNode);\n\n if (nodeType === NodeTypes.TRANSLATION) {\n return true;\n }\n\n const strategy = nodeTypeStrategies[nodeType];\n const nodeData = (val as any)[nodeType];\n\n if (strategy.kind === 'helperValue' || strategy.kind === 'unwrap') {\n return isMultilingualNode(nodeData);\n }\n\n if (\n strategy.kind === 'helperRecord' &&\n nodeData &&\n typeof nodeData === 'object'\n ) {\n return Object.values(nodeData).some((variant) =>\n isMultilingualNode(variant)\n );\n }\n\n return false;\n};\n\n/**\n * Checks whether two AST nodes are literals holding the same value.\n */\nconst isEquivalentLiteral = (left: any, right: any): boolean => {\n const isLiteral = (node: any) =>\n n.Literal.check(node) ||\n n.StringLiteral.check(node) ||\n n.NumericLiteral.check(node) ||\n n.BooleanLiteral.check(node);\n\n return isLiteral(left) && isLiteral(right) && left.value === right.value;\n};\n\n/**\n * Aligns the arguments of an existing call expression with the desired ones.\n *\n * Mutates the call only when the arguments actually differ, so Recast keeps the\n * original formatting (and quote style) of calls that did not change.\n */\nconst syncCallArguments = (callNode: any, desiredArguments: any[]) => {\n const isUnchanged =\n callNode.arguments.length === desiredArguments.length &&\n desiredArguments.every((desired, index) => {\n const current = callNode.arguments[index];\n\n return current === desired || isEquivalentLiteral(current, desired);\n });\n\n if (!isUnchanged) {\n callNode.arguments = desiredArguments;\n }\n};\n\n/**\n * Recursively builds or updates an AST node for a given dictionary value.\n *\n * Returns {@link SKIP_WRITE} when the value cannot be represented in source and\n * no existing expression can be kept.\n */\nconst buildNodeForValue = (\n val: any,\n existingNode: any,\n fallbackLocale: string | undefined, // In per-locale mode, this is the locale of the file\n requiredImports: Set<string>\n): any => {\n // Values with no source representation must never overwrite existing code.\n if (val === undefined || typeof val === 'function') {\n return existingNode ?? SKIP_WRITE;\n }\n\n const unwrappedExisting = unwrap(existingNode);\n\n // --- CRITICAL GUARD: STRICT AST PRESERVATION ---\n // If the existing node is code (JSX, Variables, standard functions), leave it alone.\n // Only allow updates to literals, plain objects, arrays, and Intlayer helpers.\n if (unwrappedExisting) {\n const isUpdatableNode =\n n.Literal.check(unwrappedExisting) ||\n n.StringLiteral.check(unwrappedExisting) ||\n n.NumericLiteral.check(unwrappedExisting) ||\n n.BooleanLiteral.check(unwrappedExisting) ||\n n.TemplateLiteral.check(unwrappedExisting) ||\n n.ObjectExpression.check(unwrappedExisting) ||\n n.ArrayExpression.check(unwrappedExisting) ||\n (n.CallExpression.check(unwrappedExisting) &&\n n.Identifier.check(unwrappedExisting.callee) &&\n helperNames.has(unwrappedExisting.callee.name));\n\n if (!isUpdatableNode) {\n return existingNode;\n }\n }\n\n // If we are in per-locale mode (fallbackLocale is set)\n // and the value is not already a complex translation node,\n // we want to store it as a simple literal, NOT wrapped in t().\n if (fallbackLocale && !existingNode && !isMultilingualNode(val)) {\n if (val === null) return b.literal(null);\n if (\n typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean'\n ) {\n if (typeof val === 'string' && val.includes('\\n')) {\n return b.templateLiteral(\n [b.templateElement({ raw: val, cooked: val }, true)],\n []\n );\n }\n return b.literal(val);\n }\n }\n\n if (fallbackLocale && existingNode && !isMultilingualNode(val)) {\n if (\n n.CallExpression.check(existingNode) &&\n n.Identifier.check(existingNode.callee) &&\n existingNode.callee.name === 't'\n ) {\n const arg = unwrap(existingNode.arguments[0]);\n\n if (n.ObjectExpression.check(arg)) {\n if (typeof val === 'string') {\n syncNumericSuffixAcrossLocales(arg, fallbackLocale, val);\n }\n updateObjectLiteral(\n arg,\n { [fallbackLocale]: val },\n fallbackLocale,\n requiredImports\n );\n\n if (!fallbackLocale) {\n requiredImports.add('t');\n }\n\n return existingNode;\n }\n }\n\n // Wrapped translations — `md(t({ … }))`, `html(t({ … }))`, `insert(t({ … }))`:\n // update the inner translation in place instead of replacing the wrapper.\n if (\n (!val || typeof val !== 'object') &&\n n.CallExpression.check(existingNode) &&\n n.Identifier.check(existingNode.callee) &&\n wrapperHelperNames.has(existingNode.callee.name)\n ) {\n const wrapperName = existingNode.callee.name;\n const innerArg = existingNode.arguments[0];\n\n if (\n n.CallExpression.check(innerArg) &&\n n.Identifier.check(innerArg.callee) &&\n innerArg.callee.name === 't'\n ) {\n const tArg = unwrap(innerArg.arguments[0]);\n\n if (n.ObjectExpression.check(tArg)) {\n if (typeof val === 'string') {\n syncNumericSuffixAcrossLocales(tArg, fallbackLocale, val);\n }\n updateObjectLiteral(\n tArg,\n { [fallbackLocale]: val },\n fallbackLocale,\n requiredImports\n );\n requiredImports.add(wrapperName);\n requiredImports.add('t');\n\n return existingNode;\n }\n }\n }\n }\n\n // 1. Primitives\n if (val === null) return b.literal(null);\n if (\n typeof val === 'string' ||\n typeof val === 'number' ||\n typeof val === 'boolean'\n ) {\n if (unwrappedExisting) {\n // Preserve existing template literals (backticks)\n if (\n n.TemplateLiteral.check(unwrappedExisting) &&\n unwrappedExisting.quasis[0] &&\n unwrappedExisting.expressions.length === 0\n ) {\n unwrappedExisting.quasis[0].value.raw = String(val);\n unwrappedExisting.quasis[0].value.cooked = String(val);\n return existingNode;\n }\n // Preserve existing standard literals (keeps quote styling)\n if (\n n.Literal.check(unwrappedExisting) ||\n n.StringLiteral.check(unwrappedExisting)\n ) {\n unwrappedExisting.value = val;\n return existingNode;\n }\n }\n\n // Force multiline strings to use Template Literals\n if (typeof val === 'string' && val.includes('\\n')) {\n return b.templateLiteral(\n [b.templateElement({ raw: val, cooked: val }, true)],\n []\n );\n }\n return b.literal(val);\n }\n\n // 2. Arrays\n if (Array.isArray(val)) {\n if (unwrappedExisting && n.ArrayExpression.check(unwrappedExisting)) {\n const elements = [...unwrappedExisting.elements];\n val.forEach((item, i) => {\n const elementNode = buildNodeForValue(\n item,\n elements[i],\n fallbackLocale,\n requiredImports\n );\n\n elements[i] =\n elementNode === SKIP_WRITE\n ? (elements[i] ?? b.literal(null))\n : elementNode;\n });\n\n if (elements.length > val.length) elements.length = val.length;\n unwrappedExisting.elements = elements as any;\n\n return existingNode;\n } else {\n return b.arrayExpression(\n val.map((item) => {\n const elementNode = buildNodeForValue(\n item,\n null,\n fallbackLocale,\n requiredImports\n );\n\n return elementNode === SKIP_WRITE ? b.literal(null) : elementNode;\n })\n );\n }\n }\n\n // 3. Intlayer Specialized Nodes — dispatched through the exhaustive registry\n const nodeType =\n val && typeof val === 'object' && !Array.isArray(val)\n ? getNodeType(val as ContentNode)\n : null;\n\n if (nodeType) {\n const strategy = nodeTypeStrategies[nodeType];\n\n // Framework elements (React/Preact/Solid) cannot be serialized back to\n // source: keep whatever the file already declares.\n if (strategy.kind === 'preserve') {\n return existingNode ?? SKIP_WRITE;\n }\n\n const hasNodeData = Object.hasOwn(val as object, nodeType);\n const nodeData = (val as any)[nodeType];\n\n // A typed node missing its payload is malformed — fall back to the generic\n // object branch rather than printing a broken helper call.\n if (strategy.kind !== 'structural' && hasNodeData) {\n if (strategy.kind === 'unwrap') {\n return buildNodeForValue(\n nodeData,\n existingNode,\n fallbackLocale,\n requiredImports\n );\n }\n\n const { helper } = strategy;\n\n requiredImports.add(helper);\n\n const isMatchingCall =\n existingNode &&\n n.CallExpression.check(existingNode) &&\n n.Identifier.check(existingNode.callee) &&\n existingNode.callee.name === helper;\n\n if (strategy.kind === 'helperRecord') {\n const recordArgument =\n isMatchingCall &&\n existingNode.arguments.length > 0 &&\n n.ObjectExpression.check(existingNode.arguments[0])\n ? existingNode.arguments[0]\n : b.objectExpression([]);\n\n updateObjectLiteral(\n recordArgument,\n nodeData ?? {},\n fallbackLocale,\n requiredImports\n );\n\n const callArguments = [\n recordArgument,\n ...(strategy.getExtraArguments?.(val as Record<string, unknown>) ??\n []),\n ];\n\n if (isMatchingCall) {\n syncCallArguments(existingNode, callArguments);\n\n return existingNode;\n }\n\n return b.callExpression(b.identifier(helper), callArguments);\n }\n\n if (strategy.kind === 'helperValue') {\n const contentArgument = buildNodeForValue(\n nodeData,\n isMatchingCall && existingNode.arguments.length > 0\n ? existingNode.arguments[0]\n : null,\n fallbackLocale,\n requiredImports\n );\n\n if (contentArgument === SKIP_WRITE) {\n return existingNode ?? SKIP_WRITE;\n }\n\n if (isMatchingCall) {\n // Keep any extra argument the source declares (custom components\n // passed to `md()` / `html()`), which the node does not carry back.\n syncCallArguments(existingNode, [\n contentArgument,\n ...existingNode.arguments.slice(1),\n ]);\n\n return existingNode;\n }\n\n return b.callExpression(b.identifier(helper), [contentArgument]);\n }\n\n // strategy.kind === 'nesting'\n const callArguments = [b.literal(nodeData?.dictionaryKey ?? '')];\n\n if (nodeData?.path) callArguments.push(b.literal(nodeData.path));\n\n if (isMatchingCall) {\n syncCallArguments(existingNode, callArguments);\n\n return existingNode;\n }\n\n return b.callExpression(b.identifier(helper), callArguments);\n }\n }\n\n // 4. Plain Object\n const objNode =\n unwrappedExisting && n.ObjectExpression.check(unwrappedExisting)\n ? unwrappedExisting\n : b.objectExpression([]);\n\n updateObjectLiteral(objNode, val, fallbackLocale, requiredImports);\n\n return existingNode && unwrappedExisting === existingNode\n ? objNode\n : existingNode || objNode;\n};\n\n/**\n * Recursively updates the AST object literal properties.\n */\nconst updateObjectLiteral = (\n node: recast.types.namedTypes.ObjectExpression,\n data: Record<string, any>,\n fallbackLocale: string | undefined,\n requiredImports: Set<string>\n) => {\n for (const [key, val] of Object.entries(data)) {\n if (val === undefined) continue;\n\n const existingProp = getMatchingProperty(node, key);\n\n if (existingProp) {\n const valueNode = buildNodeForValue(\n val,\n existingProp.value,\n fallbackLocale,\n requiredImports\n );\n\n if (valueNode !== SKIP_WRITE) {\n existingProp.value = valueNode;\n }\n } else {\n const isValidId = /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key);\n const keyNode = isValidId ? b.identifier(key) : b.literal(key);\n const valueNode = buildNodeForValue(\n val,\n null,\n fallbackLocale,\n requiredImports\n );\n\n if (valueNode === SKIP_WRITE) continue;\n\n node.properties.push(b.property('init', keyNode, valueNode));\n }\n }\n};\n\n/**\n * Modifies the AST's top-level imports to inject dynamically needed helper utilities seamlessly.\n */\nconst addImports = (ast: any, requiredImports: Set<string>, isESM: boolean) => {\n if (requiredImports.size === 0) return;\n\n const existingCoreImports = new Set<string>();\n let coreImportPath: any = null;\n\n recast.visit(ast, {\n visitImportDeclaration(path) {\n const source = path.node.source.value;\n\n if (source === 'intlayer') {\n coreImportPath = path;\n path.node.specifiers?.forEach((spec) => {\n if (\n n.ImportSpecifier.check(spec) &&\n typeof spec.imported.name === 'string'\n ) {\n existingCoreImports.add(spec.imported.name);\n }\n });\n }\n\n return false;\n },\n visitVariableDeclaration(path) {\n path.node.declarations.forEach((decl) => {\n if (\n n.VariableDeclarator.check(decl) &&\n n.CallExpression.check(decl.init) &&\n n.Identifier.check(decl.init.callee) &&\n decl.init.callee.name === 'require'\n ) {\n const arg = decl.init.arguments[0];\n\n if (n.Literal.check(arg)) {\n if (arg.value === 'intlayer') {\n if (n.ObjectPattern.check(decl.id)) {\n decl.id.properties.forEach((prop) => {\n if (\n n.Property.check(prop) &&\n (n.Identifier.check(prop.key) ||\n n.Identifier.check(prop.value))\n ) {\n const name = n.Identifier.check(prop.key)\n ? prop.key.name\n : (prop.value as any).name;\n existingCoreImports.add(name);\n }\n });\n } else if (n.Identifier.check(decl.id)) {\n // Handle const intlayer = require('intlayer')\n existingCoreImports.add(decl.id.name);\n }\n }\n }\n }\n });\n\n return false;\n },\n });\n\n const missingCore = Array.from(requiredImports).filter(\n (imp) => !existingCoreImports.has(imp)\n );\n\n if (missingCore.length === 0) return;\n\n if (isESM) {\n if (coreImportPath) {\n missingCore.forEach((imp) => {\n coreImportPath.node.specifiers.push(\n b.importSpecifier(b.identifier(imp))\n );\n });\n coreImportPath.node.specifiers.sort((a: any, b: any) =>\n a.imported.name.localeCompare(b.imported.name)\n );\n } else {\n const specifiers = missingCore\n .sort()\n .map((imp) => b.importSpecifier(b.identifier(imp)));\n const newImport = b.importDeclaration(specifiers, b.literal('intlayer'));\n ast.program.body.unshift(newImport);\n }\n } else {\n let insertIndex = 0;\n\n if (\n ast.program.body.length > 0 &&\n n.ExpressionStatement.check(ast.program.body[0]) &&\n n.Literal.check(ast.program.body[0].expression)\n ) {\n insertIndex = 1; // Insert after 'use strict'\n }\n const cjsLines: any[] = [];\n\n const properties = missingCore.sort().map((imp) => {\n const prop = b.property('init', b.identifier(imp), b.identifier(imp));\n prop.shorthand = true;\n\n return prop;\n });\n cjsLines.push(\n b.variableDeclaration('const', [\n b.variableDeclarator(\n b.objectPattern(properties),\n b.callExpression(b.identifier('require'), [b.literal('intlayer')])\n ),\n ])\n );\n\n ast.program.body.splice(insertIndex, 0, ...cjsLines);\n }\n};\n\n/**\n * Updates a JS/TS file seamlessly to map new localization keys, arrays, complex nodes and nested dictionaries gracefully using AST updates via Recast parser.\n */\nexport const transformJSFile = async (\n fileContent: string,\n dictionary: Dictionary,\n fallbackLocale?: Locale,\n noMetadata?: boolean\n): Promise<string> => {\n if (!dictionary || typeof dictionary !== 'object') return fileContent;\n\n let ast: any;\n try {\n ast = recast.parse(fileContent, {\n parser: babelTsParser,\n });\n } catch (error) {\n console.error({ error });\n return fileContent;\n }\n\n let rootObject: any = null;\n let isESM = false;\n\n recast.visit(ast, {\n visitExportDefaultDeclaration() {\n isESM = true;\n\n return false;\n },\n visitImportDeclaration() {\n isESM = true;\n\n return false;\n },\n });\n\n recast.visit(ast, {\n visitExportDefaultDeclaration(path) {\n const decl = path.node.declaration;\n const unwrappedDecl = unwrap(decl);\n\n if (n.ObjectExpression.check(unwrappedDecl)) {\n rootObject = unwrappedDecl;\n } else if (n.Identifier.check(unwrappedDecl)) {\n const varName = unwrappedDecl.name;\n recast.visit(ast, {\n visitVariableDeclarator(vp) {\n const unwrappedInit = unwrap(vp.node.init);\n\n if (\n n.Identifier.check(vp.node.id) &&\n vp.node.id.name === varName &&\n n.ObjectExpression.check(unwrappedInit)\n ) {\n rootObject = unwrappedInit;\n }\n\n return false;\n },\n });\n }\n\n return false;\n },\n visitAssignmentExpression(path) {\n const left = path.node.left;\n\n if (n.MemberExpression.check(left)) {\n if (\n n.Identifier.check(left.object) &&\n left.object.name === 'module' &&\n n.Identifier.check(left.property) &&\n left.property.name === 'exports'\n ) {\n const unwrappedRight = unwrap(path.node.right);\n\n if (n.ObjectExpression.check(unwrappedRight)) {\n rootObject = unwrappedRight;\n }\n }\n\n if (\n n.Identifier.check(left.object) &&\n left.object.name === 'exports' &&\n n.Identifier.check(left.property) &&\n left.property.name === 'default'\n ) {\n const unwrappedRight = unwrap(path.node.right);\n\n if (n.ObjectExpression.check(unwrappedRight)) {\n rootObject = unwrappedRight;\n }\n }\n }\n this.traverse(path);\n },\n });\n\n if (!rootObject) {\n recast.visit(ast, {\n visitVariableDeclarator(path) {\n const unwrappedInit = unwrap(path.node.init);\n\n if (!rootObject && n.ObjectExpression.check(unwrappedInit)) {\n rootObject = unwrappedInit;\n }\n\n return false;\n },\n });\n }\n\n if (!rootObject) return fileContent;\n\n const requiredImports = new Set<string>();\n const effectiveFallbackLocale = (fallbackLocale as string) ?? 'en';\n\n const metadataProperties = [\n 'id',\n 'locale',\n 'filled',\n 'fill',\n 'title',\n 'description',\n 'tags',\n 'version',\n 'priority',\n 'contentAutoTransformation',\n ];\n\n if (noMetadata) {\n // Remove key, content and metadata properties if they exist\n rootObject.properties = rootObject.properties.filter((prop: any) => {\n if (n.Property.check(prop) || n.ObjectProperty.check(prop)) {\n let propName = '';\n if (n.Identifier.check(prop.key)) propName = prop.key.name;\n else if (n.StringLiteral.check(prop.key)) propName = prop.key.value;\n else if (n.Literal.check(prop.key)) propName = String(prop.key.value);\n\n return !['key', 'content', ...metadataProperties].includes(propName);\n }\n return true;\n });\n\n // Update satisfies type if exists\n recast.visit(ast, {\n visitNode(path) {\n const node = path.node;\n if (\n (n.TSSatisfiesExpression?.check(node) ||\n node.type === 'TSSatisfiesExpression') &&\n (node as any).typeAnnotation &&\n n.TSTypeReference.check((node as any).typeAnnotation) &&\n n.Identifier.check((node as any).typeAnnotation.typeName) &&\n (node as any).typeAnnotation.typeName.name === 'Dictionary'\n ) {\n (node as any).typeAnnotation = b.tsIndexedAccessType(\n b.tsTypeReference(b.identifier('Dictionary')),\n b.tsLiteralType(b.stringLiteral('content'))\n );\n }\n this.traverse(path);\n },\n });\n } else {\n for (const prop of metadataProperties) {\n if ((dictionary as any)[prop] !== undefined) {\n updateObjectLiteral(\n rootObject,\n { [prop]: (dictionary as any)[prop] },\n undefined,\n requiredImports\n );\n }\n }\n }\n\n if (dictionary.content !== undefined) {\n updateObjectLiteral(\n rootObject,\n noMetadata\n ? (dictionary.content as Record<string, any>)\n : { content: dictionary.content },\n effectiveFallbackLocale,\n requiredImports\n );\n }\n\n addImports(ast, requiredImports, isESM);\n\n return recast.print(ast).code;\n};\n"],"mappings":"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"}
@@ -2,10 +2,11 @@ import { readDictionariesFromDisk } from "../utils/readDictionariesFromDisk.mjs"
2
2
  import { writeDynamicDictionary, writeDynamicQualifiedDictionaries } from "./writeDynamicDictionary.mjs";
3
3
  import { writeFetchDictionary } from "./writeFetchDictionary.mjs";
4
4
  import { writeMergedDictionaries } from "./writeMergedDictionary.mjs";
5
+ import { writeNestedDictionaries } from "./writeNestedDictionary.mjs";
5
6
  import { writeUnmergedDictionaries } from "./writeUnmergedDictionary.mjs";
6
7
  import { colorizeKey, getAppLogger } from "@intlayer/config/logger";
7
8
  import { IMPORT_MODE, OUTPUT_FORMAT } from "@intlayer/config/defaultValues";
8
- import { isQualifiedDictionaryGroup } from "@intlayer/core/dictionaryManipulator";
9
+ import { getNestedDictionaryGraph, isQualifiedDictionaryGroup } from "@intlayer/core/dictionaryManipulator";
9
10
 
10
11
  //#region src/buildIntlayerDictionary/buildIntlayerDictionary.ts
11
12
  const defaultOptions = {
@@ -35,6 +36,8 @@ const buildDictionary = async (localDictionariesEntries, configuration, options)
35
36
  }
36
37
  const unmergedDictionaries = await writeUnmergedDictionaries(unmergedDictionariesToUpdate, configuration, env);
37
38
  const mergedDictionaries = await writeMergedDictionaries(unmergedDictionaries, configuration);
39
+ const nestedDictionaryGraph = getNestedDictionaryGraph(Object.values(readDictionariesFromDisk(configuration.system.dictionariesDir)));
40
+ await writeNestedDictionaries(nestedDictionaryGraph, configuration, formats);
38
41
  const dictionariesToBuildDynamic = {};
39
42
  const qualifiedDictionariesToBuildDynamic = {};
40
43
  const keysToBuildFetch = /* @__PURE__ */ new Set();
@@ -56,14 +59,23 @@ const buildDictionary = async (localDictionariesEntries, configuration, options)
56
59
  };
57
60
  if (mode === "fetch") keysToBuildFetch.add(key);
58
61
  }
62
+ for (const consumerKey of Object.keys(dictionariesToBuildDynamic)) for (const nestedKey of nestedDictionaryGraph.get(consumerKey) ?? []) {
63
+ if (dictionariesToBuildDynamic[nestedKey]) continue;
64
+ const nestedResult = mergedDictionaries[nestedKey];
65
+ if (!nestedResult || isQualifiedDictionaryGroup(nestedResult.dictionary)) continue;
66
+ dictionariesToBuildDynamic[nestedKey] = {
67
+ dictionaryPath: nestedResult.dictionaryPath,
68
+ dictionary: nestedResult.dictionary
69
+ };
70
+ }
59
71
  let dynamicDictionaries = null;
60
- if (Object.keys(dictionariesToBuildDynamic).length > 0) dynamicDictionaries = await writeDynamicDictionary(dictionariesToBuildDynamic, configuration, formats);
72
+ if (Object.keys(dictionariesToBuildDynamic).length > 0) dynamicDictionaries = await writeDynamicDictionary(dictionariesToBuildDynamic, configuration, formats, nestedDictionaryGraph);
61
73
  if (Object.keys(qualifiedDictionariesToBuildDynamic).length > 0) await writeDynamicQualifiedDictionaries(qualifiedDictionariesToBuildDynamic, configuration, formats);
62
74
  let fetchDictionaries = null;
63
75
  if (dynamicDictionaries && keysToBuildFetch.size > 0) {
64
76
  const dictionariesToBuildFetch = {};
65
77
  for (const key of keysToBuildFetch) if (dynamicDictionaries[key]) dictionariesToBuildFetch[key] = dynamicDictionaries[key];
66
- if (Object.keys(dictionariesToBuildFetch).length > 0) fetchDictionaries = await writeFetchDictionary(dictionariesToBuildFetch, configuration, formats);
78
+ if (Object.keys(dictionariesToBuildFetch).length > 0) fetchDictionaries = await writeFetchDictionary(dictionariesToBuildFetch, configuration, formats, nestedDictionaryGraph);
67
79
  }
68
80
  return {
69
81
  unmergedDictionaries,
@@ -1 +1 @@
1
- {"version":3,"file":"buildIntlayerDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/buildIntlayerDictionary.ts"],"sourcesContent":["import { IMPORT_MODE, OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport { isQualifiedDictionaryGroup } from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { readDictionariesFromDisk } from '../utils/readDictionariesFromDisk';\nimport {\n type LocalizedDictionaryOutput,\n type QualifiedMergedDictionaryOutput,\n writeDynamicDictionary,\n writeDynamicQualifiedDictionaries,\n} from './writeDynamicDictionary';\nimport { writeFetchDictionary } from './writeFetchDictionary';\nimport {\n type PlainMergedDictionaryOutput,\n writeMergedDictionaries,\n} from './writeMergedDictionary';\nimport { writeUnmergedDictionaries } from './writeUnmergedDictionary';\n\nexport type BuildDictionariesOptions = Partial<{\n formats: typeof OUTPUT_FORMAT;\n importOtherDictionaries: boolean;\n env: 'prod' | 'dev';\n}>;\n\nconst defaultOptions = {\n formats: OUTPUT_FORMAT,\n importOtherDictionaries: true,\n env: 'dev',\n} as const satisfies BuildDictionariesOptions;\n\n/**\n * This function transpile the bundled code to to make dictionaries as JSON files\n */\nexport const buildDictionary = async (\n localDictionariesEntries: Dictionary[],\n configuration: IntlayerConfig,\n options?: BuildDictionariesOptions\n) => {\n const importMode =\n configuration?.build?.importMode ??\n configuration?.dictionary?.importMode ??\n IMPORT_MODE;\n\n const { importOtherDictionaries, env, formats } = {\n ...defaultOptions,\n ...options,\n };\n\n const unmergedDictionariesToUpdate: Dictionary[] = [\n ...localDictionariesEntries,\n ];\n\n if (importOtherDictionaries) {\n const prevUnmergedDictionaries: Record<string, Dictionary[]> =\n readDictionariesFromDisk(configuration.system.unmergedDictionariesDir);\n\n // Reinsert other dictionaries with the same key to avoid merging errors\n for (const dictionaryToWrite of localDictionariesEntries) {\n const allPrebuiltUnmergedDictionaries =\n prevUnmergedDictionaries[dictionaryToWrite.key]!;\n\n if (allPrebuiltUnmergedDictionaries?.length > 0) {\n // Do not add the same dictionary again by filtering out the one with the same localId\n const otherUnmergedDictionaries =\n allPrebuiltUnmergedDictionaries?.filter(\n (unmergedDictionary) =>\n unmergedDictionary.localId !== dictionaryToWrite.localId\n );\n\n unmergedDictionariesToUpdate.push(...(otherUnmergedDictionaries ?? []));\n }\n }\n }\n\n const unmergedDictionaries = await writeUnmergedDictionaries(\n unmergedDictionariesToUpdate,\n configuration,\n env\n );\n\n const mergedDictionaries = await writeMergedDictionaries(\n unmergedDictionaries,\n configuration\n );\n\n const dictionariesToBuildDynamic: PlainMergedDictionaryOutput = {};\n const qualifiedDictionariesToBuildDynamic: QualifiedMergedDictionaryOutput =\n {};\n const keysToBuildFetch = new Set<string>();\n\n for (const [key, mergedResult] of Object.entries(mergedDictionaries)) {\n const dictionary = mergedResult.dictionary;\n\n if (isQualifiedDictionaryGroup(dictionary)) {\n // Collections / variants resolve their qualifier at\n // runtime from a selector. Static mode keeps every entry in one JSON;\n // dynamic mode splits them into one chunk per (locale, qualifierId).\n const entryMode = dictionary.importMode ?? importMode;\n\n if (entryMode === 'dynamic') {\n qualifiedDictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n } else if (entryMode === 'fetch') {\n const appLogger = getAppLogger(configuration);\n appLogger(\n `Dictionary ${colorizeKey(key)} uses 'fetch' import mode with (${dictionary.qualifierTypes.join(', ')}) entries — fetch mode is not qualifier-aware yet, falling back to static import.`,\n { level: 'warn' }\n );\n }\n\n continue;\n }\n\n const mode = dictionary.importMode ?? importMode;\n\n if (mode === 'dynamic' || mode === 'fetch') {\n dictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n }\n\n if (mode === 'fetch') {\n keysToBuildFetch.add(key);\n }\n }\n\n let dynamicDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (Object.keys(dictionariesToBuildDynamic).length > 0) {\n dynamicDictionaries = await writeDynamicDictionary(\n dictionariesToBuildDynamic,\n configuration,\n formats\n );\n }\n\n if (Object.keys(qualifiedDictionariesToBuildDynamic).length > 0) {\n await writeDynamicQualifiedDictionaries(\n qualifiedDictionariesToBuildDynamic,\n configuration,\n formats\n );\n }\n\n let fetchDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (dynamicDictionaries && keysToBuildFetch.size > 0) {\n const dictionariesToBuildFetch: LocalizedDictionaryOutput = {};\n\n for (const key of keysToBuildFetch) {\n if (dynamicDictionaries[key]) {\n dictionariesToBuildFetch[key] = dynamicDictionaries[key];\n }\n }\n\n if (Object.keys(dictionariesToBuildFetch).length > 0) {\n fetchDictionaries = await writeFetchDictionary(\n dictionariesToBuildFetch,\n configuration,\n formats\n );\n }\n }\n\n return {\n unmergedDictionaries,\n mergedDictionaries,\n dynamicDictionaries,\n fetchDictionaries,\n };\n};\n"],"mappings":";;;;;;;;;;AAyBA,MAAM,iBAAiB;CACrB,SAAS;CACT,yBAAyB;CACzB,KAAK;AACP;;;;AAKA,MAAa,kBAAkB,OAC7B,0BACA,eACA,YACG;CACH,MAAM,aACJ,eAAe,OAAO,cACtB,eAAe,YAAY,cAC3B;CAEF,MAAM,EAAE,yBAAyB,KAAK,YAAY;EAChD,GAAG;EACH,GAAG;CACL;CAEA,MAAM,+BAA6C,CACjD,GAAG,wBACL;CAEA,IAAI,yBAAyB;EAC3B,MAAM,2BACJ,yBAAyB,cAAc,OAAO,uBAAuB;EAGvE,KAAK,MAAM,qBAAqB,0BAA0B;GACxD,MAAM,kCACJ,yBAAyB,kBAAkB;GAE7C,IAAI,iCAAiC,SAAS,GAAG;IAE/C,MAAM,4BACJ,iCAAiC,QAC9B,uBACC,mBAAmB,YAAY,kBAAkB,OACrD;IAEF,6BAA6B,KAAK,GAAI,6BAA6B,CAAC,CAAE;GACxE;EACF;CACF;CAEA,MAAM,uBAAuB,MAAM,0BACjC,8BACA,eACA,GACF;CAEA,MAAM,qBAAqB,MAAM,wBAC/B,sBACA,aACF;CAEA,MAAM,6BAA0D,CAAC;CACjE,MAAM,sCACJ,CAAC;CACH,MAAM,mCAAmB,IAAI,IAAY;CAEzC,KAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,kBAAkB,GAAG;EACpE,MAAM,aAAa,aAAa;EAEhC,IAAI,2BAA2B,UAAU,GAAG;GAI1C,MAAM,YAAY,WAAW,cAAc;GAE3C,IAAI,cAAc,WAChB,oCAAoC,OAAO;IACzC,gBAAgB,aAAa;IAC7B;GACF;QACK,IAAI,cAAc,SAEvB,AADkB,aAAa,aACvB,CAAC,CACP,cAAc,YAAY,GAAG,EAAE,kCAAkC,WAAW,eAAe,KAAK,IAAI,EAAE,oFACtG,EAAE,OAAO,OAAO,CAClB;GAGF;EACF;EAEA,MAAM,OAAO,WAAW,cAAc;EAEtC,IAAI,SAAS,aAAa,SAAS,SACjC,2BAA2B,OAAO;GAChC,gBAAgB,aAAa;GAC7B;EACF;EAGF,IAAI,SAAS,SACX,iBAAiB,IAAI,GAAG;CAE5B;CAEA,IAAI,sBAAwD;CAE5D,IAAI,OAAO,KAAK,0BAA0B,CAAC,CAAC,SAAS,GACnD,sBAAsB,MAAM,uBAC1B,4BACA,eACA,OACF;CAGF,IAAI,OAAO,KAAK,mCAAmC,CAAC,CAAC,SAAS,GAC5D,MAAM,kCACJ,qCACA,eACA,OACF;CAGF,IAAI,oBAAsD;CAE1D,IAAI,uBAAuB,iBAAiB,OAAO,GAAG;EACpD,MAAM,2BAAsD,CAAC;EAE7D,KAAK,MAAM,OAAO,kBAChB,IAAI,oBAAoB,MACtB,yBAAyB,OAAO,oBAAoB;EAIxD,IAAI,OAAO,KAAK,wBAAwB,CAAC,CAAC,SAAS,GACjD,oBAAoB,MAAM,qBACxB,0BACA,eACA,OACF;CAEJ;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}
1
+ {"version":3,"file":"buildIntlayerDictionary.mjs","names":[],"sources":["../../../src/buildIntlayerDictionary/buildIntlayerDictionary.ts"],"sourcesContent":["import { IMPORT_MODE, OUTPUT_FORMAT } from '@intlayer/config/defaultValues';\nimport { colorizeKey, getAppLogger } from '@intlayer/config/logger';\nimport {\n getNestedDictionaryGraph,\n isQualifiedDictionaryGroup,\n} from '@intlayer/core/dictionaryManipulator';\nimport type { IntlayerConfig } from '@intlayer/types/config';\nimport type { Dictionary } from '@intlayer/types/dictionary';\nimport { readDictionariesFromDisk } from '../utils/readDictionariesFromDisk';\nimport {\n type LocalizedDictionaryOutput,\n type QualifiedMergedDictionaryOutput,\n writeDynamicDictionary,\n writeDynamicQualifiedDictionaries,\n} from './writeDynamicDictionary';\nimport { writeFetchDictionary } from './writeFetchDictionary';\nimport {\n type PlainMergedDictionaryOutput,\n writeMergedDictionaries,\n} from './writeMergedDictionary';\nimport { writeNestedDictionaries } from './writeNestedDictionary';\nimport { writeUnmergedDictionaries } from './writeUnmergedDictionary';\n\nexport type BuildDictionariesOptions = Partial<{\n formats: typeof OUTPUT_FORMAT;\n importOtherDictionaries: boolean;\n env: 'prod' | 'dev';\n}>;\n\nconst defaultOptions = {\n formats: OUTPUT_FORMAT,\n importOtherDictionaries: true,\n env: 'dev',\n} as const satisfies BuildDictionariesOptions;\n\n/**\n * This function transpile the bundled code to to make dictionaries as JSON files\n */\nexport const buildDictionary = async (\n localDictionariesEntries: Dictionary[],\n configuration: IntlayerConfig,\n options?: BuildDictionariesOptions\n) => {\n const importMode =\n configuration?.build?.importMode ??\n configuration?.dictionary?.importMode ??\n IMPORT_MODE;\n\n const { importOtherDictionaries, env, formats } = {\n ...defaultOptions,\n ...options,\n };\n\n const unmergedDictionariesToUpdate: Dictionary[] = [\n ...localDictionariesEntries,\n ];\n\n if (importOtherDictionaries) {\n const prevUnmergedDictionaries: Record<string, Dictionary[]> =\n readDictionariesFromDisk(configuration.system.unmergedDictionariesDir);\n\n // Reinsert other dictionaries with the same key to avoid merging errors\n for (const dictionaryToWrite of localDictionariesEntries) {\n const allPrebuiltUnmergedDictionaries =\n prevUnmergedDictionaries[dictionaryToWrite.key]!;\n\n if (allPrebuiltUnmergedDictionaries?.length > 0) {\n // Do not add the same dictionary again by filtering out the one with the same localId\n const otherUnmergedDictionaries =\n allPrebuiltUnmergedDictionaries?.filter(\n (unmergedDictionary) =>\n unmergedDictionary.localId !== dictionaryToWrite.localId\n );\n\n unmergedDictionariesToUpdate.push(...(otherUnmergedDictionaries ?? []));\n }\n }\n }\n\n const unmergedDictionaries = await writeUnmergedDictionaries(\n unmergedDictionariesToUpdate,\n configuration,\n env\n );\n\n const mergedDictionaries = await writeMergedDictionaries(\n unmergedDictionaries,\n configuration\n );\n\n // `nest()` dependency graph, read back from disk so it stays complete on\n // incremental rebuilds where only a subset of dictionaries was regenerated.\n // Every artifact kind attaches its dependencies, letting `getNesting` resolve\n // them locally instead of through the registry the optimizer strips.\n const nestedDictionaryGraph = getNestedDictionaryGraph(\n Object.values(\n readDictionariesFromDisk<Record<string, Dictionary>>(\n configuration.system.dictionariesDir\n )\n )\n );\n\n await writeNestedDictionaries(nestedDictionaryGraph, configuration, formats);\n\n const dictionariesToBuildDynamic: PlainMergedDictionaryOutput = {};\n const qualifiedDictionariesToBuildDynamic: QualifiedMergedDictionaryOutput =\n {};\n const keysToBuildFetch = new Set<string>();\n\n for (const [key, mergedResult] of Object.entries(mergedDictionaries)) {\n const dictionary = mergedResult.dictionary;\n\n if (isQualifiedDictionaryGroup(dictionary)) {\n // Collections / variants resolve their qualifier at\n // runtime from a selector. Static mode keeps every entry in one JSON;\n // dynamic mode splits them into one chunk per (locale, qualifierId).\n const entryMode = dictionary.importMode ?? importMode;\n\n if (entryMode === 'dynamic') {\n qualifiedDictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n } else if (entryMode === 'fetch') {\n const appLogger = getAppLogger(configuration);\n appLogger(\n `Dictionary ${colorizeKey(key)} uses 'fetch' import mode with (${dictionary.qualifierTypes.join(', ')}) entries — fetch mode is not qualifier-aware yet, falling back to static import.`,\n { level: 'warn' }\n );\n }\n\n continue;\n }\n\n const mode = dictionary.importMode ?? importMode;\n\n if (mode === 'dynamic' || mode === 'fetch') {\n dictionariesToBuildDynamic[key] = {\n dictionaryPath: mergedResult.dictionaryPath,\n dictionary,\n };\n }\n\n if (mode === 'fetch') {\n keysToBuildFetch.add(key);\n }\n }\n\n // A lazily loaded dictionary resolves its `nest()` references from chunks\n // loaded by the same loader, so its nest targets need dynamic artifacts of\n // their own — whatever import mode they declare for their own call sites.\n for (const consumerKey of Object.keys(dictionariesToBuildDynamic)) {\n for (const nestedKey of nestedDictionaryGraph.get(consumerKey) ?? []) {\n if (dictionariesToBuildDynamic[nestedKey]) continue;\n\n const nestedResult = mergedDictionaries[nestedKey];\n if (\n !nestedResult ||\n isQualifiedDictionaryGroup(nestedResult.dictionary)\n ) {\n continue;\n }\n\n dictionariesToBuildDynamic[nestedKey] = {\n dictionaryPath: nestedResult.dictionaryPath,\n dictionary: nestedResult.dictionary,\n };\n }\n }\n\n let dynamicDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (Object.keys(dictionariesToBuildDynamic).length > 0) {\n dynamicDictionaries = await writeDynamicDictionary(\n dictionariesToBuildDynamic,\n configuration,\n formats,\n nestedDictionaryGraph\n );\n }\n\n if (Object.keys(qualifiedDictionariesToBuildDynamic).length > 0) {\n await writeDynamicQualifiedDictionaries(\n qualifiedDictionariesToBuildDynamic,\n configuration,\n formats\n );\n }\n\n let fetchDictionaries: LocalizedDictionaryOutput | null = null;\n\n if (dynamicDictionaries && keysToBuildFetch.size > 0) {\n const dictionariesToBuildFetch: LocalizedDictionaryOutput = {};\n\n for (const key of keysToBuildFetch) {\n if (dynamicDictionaries[key]) {\n dictionariesToBuildFetch[key] = dynamicDictionaries[key];\n }\n }\n\n if (Object.keys(dictionariesToBuildFetch).length > 0) {\n fetchDictionaries = await writeFetchDictionary(\n dictionariesToBuildFetch,\n configuration,\n formats,\n nestedDictionaryGraph\n );\n }\n }\n\n return {\n unmergedDictionaries,\n mergedDictionaries,\n dynamicDictionaries,\n fetchDictionaries,\n };\n};\n"],"mappings":";;;;;;;;;;;AA6BA,MAAM,iBAAiB;CACrB,SAAS;CACT,yBAAyB;CACzB,KAAK;AACP;;;;AAKA,MAAa,kBAAkB,OAC7B,0BACA,eACA,YACG;CACH,MAAM,aACJ,eAAe,OAAO,cACtB,eAAe,YAAY,cAC3B;CAEF,MAAM,EAAE,yBAAyB,KAAK,YAAY;EAChD,GAAG;EACH,GAAG;CACL;CAEA,MAAM,+BAA6C,CACjD,GAAG,wBACL;CAEA,IAAI,yBAAyB;EAC3B,MAAM,2BACJ,yBAAyB,cAAc,OAAO,uBAAuB;EAGvE,KAAK,MAAM,qBAAqB,0BAA0B;GACxD,MAAM,kCACJ,yBAAyB,kBAAkB;GAE7C,IAAI,iCAAiC,SAAS,GAAG;IAE/C,MAAM,4BACJ,iCAAiC,QAC9B,uBACC,mBAAmB,YAAY,kBAAkB,OACrD;IAEF,6BAA6B,KAAK,GAAI,6BAA6B,CAAC,CAAE;GACxE;EACF;CACF;CAEA,MAAM,uBAAuB,MAAM,0BACjC,8BACA,eACA,GACF;CAEA,MAAM,qBAAqB,MAAM,wBAC/B,sBACA,aACF;CAMA,MAAM,wBAAwB,yBAC5B,OAAO,OACL,yBACE,cAAc,OAAO,eACvB,CACF,CACF;CAEA,MAAM,wBAAwB,uBAAuB,eAAe,OAAO;CAE3E,MAAM,6BAA0D,CAAC;CACjE,MAAM,sCACJ,CAAC;CACH,MAAM,mCAAmB,IAAI,IAAY;CAEzC,KAAK,MAAM,CAAC,KAAK,iBAAiB,OAAO,QAAQ,kBAAkB,GAAG;EACpE,MAAM,aAAa,aAAa;EAEhC,IAAI,2BAA2B,UAAU,GAAG;GAI1C,MAAM,YAAY,WAAW,cAAc;GAE3C,IAAI,cAAc,WAChB,oCAAoC,OAAO;IACzC,gBAAgB,aAAa;IAC7B;GACF;QACK,IAAI,cAAc,SAEvB,AADkB,aAAa,aACvB,CAAC,CACP,cAAc,YAAY,GAAG,EAAE,kCAAkC,WAAW,eAAe,KAAK,IAAI,EAAE,oFACtG,EAAE,OAAO,OAAO,CAClB;GAGF;EACF;EAEA,MAAM,OAAO,WAAW,cAAc;EAEtC,IAAI,SAAS,aAAa,SAAS,SACjC,2BAA2B,OAAO;GAChC,gBAAgB,aAAa;GAC7B;EACF;EAGF,IAAI,SAAS,SACX,iBAAiB,IAAI,GAAG;CAE5B;CAKA,KAAK,MAAM,eAAe,OAAO,KAAK,0BAA0B,GAC9D,KAAK,MAAM,aAAa,sBAAsB,IAAI,WAAW,KAAK,CAAC,GAAG;EACpE,IAAI,2BAA2B,YAAY;EAE3C,MAAM,eAAe,mBAAmB;EACxC,IACE,CAAC,gBACD,2BAA2B,aAAa,UAAU,GAElD;EAGF,2BAA2B,aAAa;GACtC,gBAAgB,aAAa;GAC7B,YAAY,aAAa;EAC3B;CACF;CAGF,IAAI,sBAAwD;CAE5D,IAAI,OAAO,KAAK,0BAA0B,CAAC,CAAC,SAAS,GACnD,sBAAsB,MAAM,uBAC1B,4BACA,eACA,SACA,qBACF;CAGF,IAAI,OAAO,KAAK,mCAAmC,CAAC,CAAC,SAAS,GAC5D,MAAM,kCACJ,qCACA,eACA,OACF;CAGF,IAAI,oBAAsD;CAE1D,IAAI,uBAAuB,iBAAiB,OAAO,GAAG;EACpD,MAAM,2BAAsD,CAAC;EAE7D,KAAK,MAAM,OAAO,kBAChB,IAAI,oBAAoB,MACtB,yBAAyB,OAAO,oBAAoB;EAIxD,IAAI,OAAO,KAAK,wBAAwB,CAAC,CAAC,SAAS,GACjD,oBAAoB,MAAM,qBACxB,0BACA,eACA,SACA,qBACF;CAEJ;CAEA,OAAO;EACL;EACA;EACA;EACA;CACF;AACF"}