@uniformdev/tms-sdk 19.135.1-alpha.11

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.
@@ -0,0 +1,1014 @@
1
+ // src/collectTranslationPayload.ts
2
+ import {
3
+ bindVariables,
4
+ walkNodeTree as walkNodeTree2
5
+ } from "@uniformdev/canvas";
6
+ import { isRichTextValue as isRichTextValue2, isRichTextValueConsideredEmpty as isRichTextValueConsideredEmpty2 } from "@uniformdev/richtext";
7
+
8
+ // src/constants.ts
9
+ var TRANSLATION_PAYLOAD_SOURCE_KEY = "source";
10
+ var TRANSLATION_PAYLOAD_TARGET_KEY = "target";
11
+ var TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY = "originalTarget";
12
+ var SUPPORTED_PARAM_TYPES = {
13
+ text: "text",
14
+ richText: "richText"
15
+ };
16
+
17
+ // src/richText/renderAsTranslatableXml.ts
18
+ import { getRichTextTagsFromTextFormat, isRichTextNodeType } from "@uniformdev/richtext";
19
+ var REF_ATTRIBUTE_NAME = "ref";
20
+ function renderAsTranslatableXml(root) {
21
+ if (!root) {
22
+ return null;
23
+ }
24
+ const result = {
25
+ attributes: [],
26
+ xmlParts: []
27
+ };
28
+ renderXmlNode(result, root);
29
+ const metadata = result.attributes.reduce(
30
+ (result2, current, index) => {
31
+ result2[String(index)] = {
32
+ attrs: current
33
+ };
34
+ return result2;
35
+ },
36
+ {}
37
+ );
38
+ return {
39
+ metadata,
40
+ xml: result.xmlParts.join("")
41
+ };
42
+ }
43
+ var IGNORE_ATTRS = ["type", "children", "text"];
44
+ function renderXmlNode(context, node) {
45
+ if (!node) {
46
+ return;
47
+ }
48
+ const base64Props = getPropsAsBase64(node, IGNORE_ATTRS);
49
+ let refKey = context.attributes.findIndex((x) => x === base64Props);
50
+ if (refKey == -1) {
51
+ context.attributes.push(base64Props);
52
+ refKey = context.attributes.length - 1;
53
+ }
54
+ context.xmlParts.push(`<${node.type} ${REF_ATTRIBUTE_NAME}="${refKey}"`);
55
+ const metaAttrsString = getNodeMetaAttributesString(node);
56
+ if (metaAttrsString) {
57
+ context.xmlParts.push(" " + metaAttrsString);
58
+ }
59
+ context.xmlParts.push(">");
60
+ if (isRichTextNodeType(node, "text")) {
61
+ context.xmlParts.push(node.text);
62
+ } else if (Array.isArray(node.children) && node.children.length) {
63
+ node.children.forEach((child) => {
64
+ renderXmlNode(context, child);
65
+ });
66
+ }
67
+ context.xmlParts.push(`</${node.type}>`);
68
+ }
69
+ var getPropsAsBase64 = (node, ignoreProps) => {
70
+ const props = {};
71
+ Object.keys(node).forEach((key) => {
72
+ if (!ignoreProps.includes(key)) {
73
+ props[key] = node[key];
74
+ }
75
+ });
76
+ return btoa(JSON.stringify(props));
77
+ };
78
+ var getNodeMetaAttributesString = (node) => {
79
+ const metadata = {};
80
+ if (isRichTextNodeType(node, "text")) {
81
+ const formatTags = getRichTextTagsFromTextFormat(node.format);
82
+ if (formatTags.length) {
83
+ metadata["format"] = formatTags.join(" ");
84
+ }
85
+ } else if (isRichTextNodeType(node, "heading")) {
86
+ if (node.tag) {
87
+ metadata["tag"] = node.tag;
88
+ }
89
+ } else if (isRichTextNodeType(node, "paragraph")) {
90
+ if (node.format) {
91
+ metadata["format"] = node.format;
92
+ }
93
+ } else if (isRichTextNodeType(node, "list")) {
94
+ if (node.tag) {
95
+ metadata["tag"] = node.tag;
96
+ }
97
+ } else if (isRichTextNodeType(node, "listitem")) {
98
+ metadata["value"] = String(node.value);
99
+ }
100
+ if (!Object.keys(metadata).length) {
101
+ return "";
102
+ }
103
+ const result = [];
104
+ Object.entries(metadata).forEach(([key, value]) => {
105
+ result.push(`${key}="${value}"`);
106
+ });
107
+ return result.join(" ");
108
+ };
109
+
110
+ // src/translationHelpers.ts
111
+ import {
112
+ walkNodeTree
113
+ } from "@uniformdev/canvas";
114
+ import { isRichTextValueConsideredEmpty } from "@uniformdev/richtext";
115
+ import { dequal } from "dequal/lite";
116
+
117
+ // src/richText/parseTranslatableXml.ts
118
+ import { isRichTextValue } from "@uniformdev/richtext";
119
+ import { XMLParser } from "fast-xml-parser";
120
+ var ATTR_NAME_PREFIX = "@_";
121
+ var ATTRIBUTES_SUBNODE_NAME = ":@";
122
+ var IGNORE_PROPS_PREFIX = [ATTR_NAME_PREFIX, ATTRIBUTES_SUBNODE_NAME, "#"];
123
+ var parseTranslatableXml = ({ xml, metadata }) => {
124
+ const parser = new XMLParser({
125
+ ignoreDeclaration: true,
126
+ ignorePiTags: true,
127
+ ignoreAttributes: false,
128
+ preserveOrder: true,
129
+ trimValues: false,
130
+ attributeNamePrefix: ATTR_NAME_PREFIX
131
+ });
132
+ const rawObj = parser.parse(prepareXml(xml));
133
+ const result = processParseObject(rawObj, {
134
+ metadata,
135
+ nodeTypes: []
136
+ });
137
+ return result;
138
+ };
139
+ var prepareXml = (xml) => {
140
+ const result = xml.replaceAll("&lt;/text>", "</text>");
141
+ return result;
142
+ };
143
+ var processParseObject = (rawObj, context) => {
144
+ const result = visitAndTransformNode(rawObj, context);
145
+ const root = Array.isArray(result) ? result.at(0) : result;
146
+ if (root && root.type === "root") {
147
+ const value = { root };
148
+ if (isRichTextValue(value)) {
149
+ return value;
150
+ }
151
+ }
152
+ return null;
153
+ };
154
+ var visitAndTransformNode = (node, context) => {
155
+ if (Array.isArray(node)) {
156
+ return node.map((x) => visitAndTransformNode(x, context)).filter((node2) => !!node2);
157
+ } else if (typeof node === "object" && node !== null) {
158
+ const type = Object.keys(node).find(
159
+ (key) => !IGNORE_PROPS_PREFIX.some((prefix) => key.startsWith(prefix))
160
+ );
161
+ if (!type) {
162
+ return null;
163
+ }
164
+ const transformed = {};
165
+ transformed["type"] = type;
166
+ const propsFromRef = restorePropsFromRef(node, context);
167
+ Object.entries(propsFromRef).forEach(([key, value]) => {
168
+ transformed[key] = value;
169
+ });
170
+ if (type === "text") {
171
+ const nestedNode = node[type];
172
+ const nestedNodeAsArray = Array.isArray(nestedNode) ? nestedNode : [nestedNode];
173
+ const firstChild = nestedNodeAsArray.at(0);
174
+ const text = firstChild == null ? void 0 : firstChild["#text"];
175
+ transformed["text"] = typeof text === "string" && text ? text : "";
176
+ } else {
177
+ const children = [];
178
+ const nestedNode = node[type];
179
+ if (typeof nestedNode === "object" && nestedNode) {
180
+ const nestedNodeAsArray = Array.isArray(nestedNode) ? nestedNode : [nestedNode];
181
+ nestedNodeAsArray.forEach((currNode) => {
182
+ const transformed2 = visitAndTransformNode(currNode, context);
183
+ if (transformed2) {
184
+ children.push(transformed2);
185
+ }
186
+ });
187
+ }
188
+ if (children.length) {
189
+ transformed["children"] = children;
190
+ } else if (type === "paragraph" && Array.isArray(nestedNode) && !nestedNode.length) {
191
+ transformed["children"] = [];
192
+ }
193
+ }
194
+ return transformed;
195
+ } else {
196
+ return node;
197
+ }
198
+ };
199
+ var restorePropsFromRef = (node, context) => {
200
+ const result = {};
201
+ let uniformRef = node[ATTR_NAME_PREFIX + REF_ATTRIBUTE_NAME];
202
+ if (!uniformRef) {
203
+ const attrsSubNode = node[ATTRIBUTES_SUBNODE_NAME];
204
+ uniformRef = attrsSubNode == null ? void 0 : attrsSubNode[ATTR_NAME_PREFIX + REF_ATTRIBUTE_NAME];
205
+ }
206
+ if (typeof uniformRef === "string" && uniformRef && context.metadata[uniformRef]) {
207
+ const metadata = context.metadata[uniformRef];
208
+ if (metadata.attrs) {
209
+ const decodedProps = JSON.parse(atob(metadata.attrs));
210
+ Object.keys(decodedProps).forEach((key) => {
211
+ result[key] = decodedProps[key];
212
+ });
213
+ }
214
+ }
215
+ return result;
216
+ };
217
+
218
+ // src/richText/types.ts
219
+ var isTranslatableRichTextValue = (value) => {
220
+ if (typeof value !== "object" || !value) {
221
+ return false;
222
+ }
223
+ if (!("xml" in value) || typeof value.xml !== "string") {
224
+ return false;
225
+ }
226
+ if (!("metadata" in value) || typeof value.metadata !== "object" || !value.metadata) {
227
+ return false;
228
+ }
229
+ return true;
230
+ };
231
+
232
+ // src/translationHelpers.ts
233
+ var MERGE_TRANSLATION_ERRORS = {
234
+ unknown: "Unknown error",
235
+ "invalid-args": "Invalid arguments",
236
+ "project-id-mismatch": "Project ID mismatch",
237
+ "entity-id-mismatch": "Enity ID mismatch",
238
+ "entity-locales-mismatch": "Entity does not include required locales"
239
+ };
240
+ var createErrorResult = (errorKind) => {
241
+ return { updated: false, errorKind, errorText: MERGE_TRANSLATION_ERRORS[errorKind] };
242
+ };
243
+ var processComponentTranslation = ({
244
+ uniformSourceLocale,
245
+ uniformTargetLocale,
246
+ originalNode,
247
+ translatedComponent
248
+ }) => {
249
+ var _a, _b;
250
+ let updated = false;
251
+ if (!originalNode.type || !originalNode._id) {
252
+ return { updated };
253
+ }
254
+ const componentParameters = "parameters" in originalNode ? originalNode.parameters : void 0;
255
+ const entryFields = "fields" in originalNode ? originalNode.fields : void 0;
256
+ const originalParametersOrFields = componentParameters != null ? componentParameters : entryFields;
257
+ Object.entries((_a = translatedComponent.parameters) != null ? _a : {}).forEach(([paramKey, parameter]) => {
258
+ const originalParameter = originalParametersOrFields == null ? void 0 : originalParametersOrFields[paramKey];
259
+ if (!originalParameter) {
260
+ return;
261
+ }
262
+ const result = processParameterTranslation({
263
+ uniformSourceLocale,
264
+ uniformTargetLocale,
265
+ originalParameter,
266
+ parameter
267
+ });
268
+ if (result.updated) {
269
+ updated = true;
270
+ }
271
+ });
272
+ Object.entries((_b = translatedComponent._overrides) != null ? _b : {}).forEach(([overrideKey, override]) => {
273
+ var _a2;
274
+ const originalOverride = (_a2 = originalNode._overrides) == null ? void 0 : _a2[overrideKey];
275
+ if (!originalOverride) {
276
+ return;
277
+ }
278
+ const result = processOverrideTranslation({
279
+ uniformSourceLocale,
280
+ uniformTargetLocale,
281
+ originalOverride,
282
+ override
283
+ });
284
+ if (result.updated) {
285
+ updated = true;
286
+ }
287
+ });
288
+ return { updated };
289
+ };
290
+ var processParameterTranslation = ({
291
+ uniformSourceLocale,
292
+ uniformTargetLocale,
293
+ originalParameter,
294
+ parameter
295
+ }) => {
296
+ var _a, _b, _c, _d;
297
+ if (originalParameter.type !== parameter.type) {
298
+ return { updated: false };
299
+ }
300
+ if (!originalParameter.locales && originalParameter.value === void 0) {
301
+ return { updated: false };
302
+ }
303
+ const sourceValue = (_a = parameter.locales) == null ? void 0 : _a[TRANSLATION_PAYLOAD_SOURCE_KEY];
304
+ const targetValue = (_b = parameter.locales) == null ? void 0 : _b[TRANSLATION_PAYLOAD_TARGET_KEY];
305
+ const originalTargetValue = (_c = parameter.locales) == null ? void 0 : _c[TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY];
306
+ const originalParameterSource = originalParameter.locales ? originalParameter.locales[uniformSourceLocale] : originalParameter.value;
307
+ const isSourceValueUntouched = isSameParameterValue({
308
+ parameterType: originalParameter.type,
309
+ left: originalParameterSource,
310
+ right: sourceValue
311
+ });
312
+ const isTargetValueUntouched = isSameParameterValue({
313
+ parameterType: originalParameter.type,
314
+ left: (_d = originalParameter.locales) == null ? void 0 : _d[uniformTargetLocale],
315
+ right: originalTargetValue
316
+ });
317
+ if (targetValue !== void 0 && isSourceValueUntouched && isTargetValueUntouched) {
318
+ if (parameter.type == SUPPORTED_PARAM_TYPES.richText && isTranslatableRichTextValue(targetValue)) {
319
+ try {
320
+ const richTextValue = parseTranslatableXml(targetValue);
321
+ updateOriginalParameterValue(richTextValue);
322
+ return { updated: true };
323
+ } catch (e) {
324
+ return { updated: false };
325
+ }
326
+ } else if (parameter.type == SUPPORTED_PARAM_TYPES.text) {
327
+ updateOriginalParameterValue(targetValue);
328
+ return { updated: true };
329
+ }
330
+ }
331
+ function updateOriginalParameterValue(value) {
332
+ if (originalParameter.locales) {
333
+ originalParameter.locales[uniformTargetLocale] = value;
334
+ } else if (originalParameter.value !== void 0) {
335
+ originalParameter.locales = {
336
+ [uniformSourceLocale]: originalParameter.value,
337
+ [uniformTargetLocale]: value
338
+ };
339
+ originalParameter.value = void 0;
340
+ }
341
+ }
342
+ return { updated: false };
343
+ };
344
+ var processOverrideTranslation = ({
345
+ uniformSourceLocale,
346
+ uniformTargetLocale,
347
+ originalOverride,
348
+ override
349
+ }) => {
350
+ var _a, _b;
351
+ let updated = false;
352
+ Object.entries((_a = override.parameters) != null ? _a : {}).forEach(([paramKey, parameter]) => {
353
+ var _a2;
354
+ const originalParameter = (_a2 = originalOverride.parameters) == null ? void 0 : _a2[paramKey];
355
+ if (!originalParameter) {
356
+ return;
357
+ }
358
+ const result = processParameterTranslation({
359
+ uniformSourceLocale,
360
+ uniformTargetLocale,
361
+ originalParameter,
362
+ parameter
363
+ });
364
+ if (result.updated) {
365
+ updated = true;
366
+ }
367
+ });
368
+ Object.entries((_b = override.slots) != null ? _b : {}).forEach(([slotKey, slotComponents]) => {
369
+ var _a2;
370
+ const originalSlotComponents = (_a2 = originalOverride.slots) == null ? void 0 : _a2[slotKey];
371
+ if (!(originalSlotComponents == null ? void 0 : originalSlotComponents.length)) {
372
+ return;
373
+ }
374
+ slotComponents.forEach((slotComponent) => {
375
+ if (!slotComponent.type || !slotComponent._id) {
376
+ return;
377
+ }
378
+ const originalSlotComponent = originalSlotComponents.find(
379
+ (x) => x._id === slotComponent._id && x.type === slotComponent.type
380
+ );
381
+ if (!originalSlotComponent) {
382
+ return;
383
+ }
384
+ walkNodeTree(slotComponent, ({ node: component, type, actions }) => {
385
+ if (type !== "component" || !component._id || !component.type) {
386
+ actions.stopProcessingDescendants();
387
+ return;
388
+ }
389
+ const originalComponent = findComponentInNodeTree(originalSlotComponent, component._id);
390
+ if (!originalComponent || originalComponent.type !== component.type) {
391
+ actions.stopProcessingDescendants();
392
+ return;
393
+ }
394
+ const { updated: isComponentUpdated } = processComponentTranslation({
395
+ uniformSourceLocale,
396
+ uniformTargetLocale,
397
+ originalNode: originalComponent,
398
+ translatedComponent: component
399
+ });
400
+ if (isComponentUpdated) {
401
+ updated = true;
402
+ }
403
+ });
404
+ });
405
+ });
406
+ return { updated };
407
+ };
408
+ var isSameParameterValue = ({
409
+ parameterType,
410
+ left,
411
+ right
412
+ }) => {
413
+ switch (parameterType) {
414
+ case SUPPORTED_PARAM_TYPES.text:
415
+ return left === right || !left && !right;
416
+ break;
417
+ case SUPPORTED_PARAM_TYPES.richText:
418
+ try {
419
+ if (isRichTextValueConsideredEmpty(left) && isRichTextValueConsideredEmpty(right)) {
420
+ return true;
421
+ }
422
+ } catch (e) {
423
+ return false;
424
+ }
425
+ return dequal(left, right);
426
+ break;
427
+ default:
428
+ return left === right;
429
+ }
430
+ };
431
+ var findComponentInNodeTree = (root, id) => {
432
+ let result;
433
+ walkNodeTree(root, ({ node, actions }) => {
434
+ if (node._id === id) {
435
+ result = node;
436
+ actions.stopProcessingDescendants();
437
+ }
438
+ });
439
+ return result;
440
+ };
441
+
442
+ // src/collectTranslationPayload.ts
443
+ var MERGE_TRANSLATION_ERRORS2 = {
444
+ unknown: "Unknown error",
445
+ "invalid-args": "Invalid arguments",
446
+ "entity-source-locale-missing": "Entity does not include specified Uniform source locale"
447
+ };
448
+ var createErrorResult2 = (errorKind) => {
449
+ return { errorKind, errorText: MERGE_TRANSLATION_ERRORS2[errorKind] };
450
+ };
451
+ var collectTranslationPayload = ({
452
+ uniformProjectId,
453
+ uniformSourceLocale,
454
+ uniformTargetLocale,
455
+ uniformReleaseId,
456
+ targetLang,
457
+ entity,
458
+ entityType
459
+ }) => {
460
+ if (!uniformSourceLocale || !uniformTargetLocale || !targetLang || !entity) {
461
+ return createErrorResult2("invalid-args");
462
+ }
463
+ if (!entity._locales || !entity._locales.includes(uniformSourceLocale)) {
464
+ return createErrorResult2("entity-source-locale-missing");
465
+ }
466
+ const payload = {
467
+ schemaVersion: 1,
468
+ metadata: {
469
+ uniformProjectId,
470
+ uniformSourceLocale,
471
+ uniformTargetLocale,
472
+ uniformReleaseId,
473
+ targetLang,
474
+ entityType,
475
+ entity: {
476
+ id: entity._id,
477
+ slug: entity._slug || ""
478
+ }
479
+ },
480
+ components: {}
481
+ };
482
+ walkNodeTree2(entity, ({ node, actions }) => {
483
+ if (!node.type || !node._id) {
484
+ actions.stopProcessingDescendants();
485
+ return;
486
+ }
487
+ const { _id, type, parameters, _overrides } = collectFromNode({
488
+ uniformSourceLocale,
489
+ uniformTargetLocale,
490
+ node,
491
+ deep: false
492
+ });
493
+ if (parameters || _overrides) {
494
+ payload.components[node._id] = {
495
+ _id,
496
+ type,
497
+ parameters,
498
+ _overrides
499
+ };
500
+ }
501
+ });
502
+ return { payload };
503
+ };
504
+ var collectFromNode = ({
505
+ uniformSourceLocale,
506
+ uniformTargetLocale,
507
+ node,
508
+ deep
509
+ }) => {
510
+ var _a, _b, _c;
511
+ const collectedParameters = {};
512
+ const collectedSlots = {};
513
+ const collectedOverrides = {};
514
+ const componentParameters = "parameters" in node ? node.parameters : void 0;
515
+ const entryFields = "fields" in node ? node.fields : void 0;
516
+ Object.entries((_a = componentParameters != null ? componentParameters : entryFields) != null ? _a : {}).forEach(([paramKey, param]) => {
517
+ var _a2, _b2;
518
+ const sourceLocaleValue = (_a2 = param.locales) == null ? void 0 : _a2[uniformSourceLocale];
519
+ const targetLocaleValue = (_b2 = param.locales) == null ? void 0 : _b2[uniformTargetLocale];
520
+ if (!canTranslateParameterValue(param, sourceLocaleValue)) {
521
+ return;
522
+ }
523
+ if (!isTargetLocaleUntouched(param.type, sourceLocaleValue, targetLocaleValue)) {
524
+ return;
525
+ }
526
+ collectedParameters[paramKey] = {
527
+ type: param.type,
528
+ locales: {
529
+ [TRANSLATION_PAYLOAD_SOURCE_KEY]: sourceLocaleValue,
530
+ [TRANSLATION_PAYLOAD_TARGET_KEY]: preprocessTargetValue(param, sourceLocaleValue),
531
+ [TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY]: targetLocaleValue
532
+ }
533
+ };
534
+ });
535
+ if (deep) {
536
+ Object.entries((_b = "slots" in node ? node.slots : null) != null ? _b : {}).forEach(([slotKey, slotComponents]) => {
537
+ slotComponents.map((slotComponent) => {
538
+ var _a2;
539
+ if (!slotComponent.type || !slotComponent._id) {
540
+ return;
541
+ }
542
+ const collectedNode = collectFromNode({
543
+ uniformSourceLocale,
544
+ uniformTargetLocale,
545
+ node: slotComponent,
546
+ deep: true
547
+ });
548
+ const hasContent = collectedNode.parameters || collectedNode._overrides || collectedNode.slots;
549
+ if (hasContent) {
550
+ (_a2 = collectedSlots[slotKey]) != null ? _a2 : collectedSlots[slotKey] = [];
551
+ collectedSlots[slotKey].push(collectedNode);
552
+ }
553
+ });
554
+ });
555
+ }
556
+ Object.entries((_c = node._overrides) != null ? _c : {}).forEach(([overrideKey, override]) => {
557
+ var _a2, _b2;
558
+ Object.entries((_a2 = override.parameters) != null ? _a2 : {}).forEach(([paramKey, param]) => {
559
+ var _a3, _b3, _c2, _d, _e;
560
+ const sourceLocaleValue = (_a3 = param.locales) == null ? void 0 : _a3[uniformSourceLocale];
561
+ const targetLocaleValue = (_b3 = param.locales) == null ? void 0 : _b3[uniformTargetLocale];
562
+ if (!canTranslateParameterValue(param, sourceLocaleValue)) {
563
+ return;
564
+ }
565
+ if (!isTargetLocaleUntouched(param.type, sourceLocaleValue, targetLocaleValue)) {
566
+ return;
567
+ }
568
+ (_c2 = collectedOverrides[overrideKey]) != null ? _c2 : collectedOverrides[overrideKey] = {};
569
+ (_e = (_d = collectedOverrides[overrideKey]).parameters) != null ? _e : _d.parameters = {};
570
+ collectedOverrides[overrideKey].parameters[paramKey] = {
571
+ type: param.type,
572
+ locales: {
573
+ [TRANSLATION_PAYLOAD_SOURCE_KEY]: sourceLocaleValue,
574
+ [TRANSLATION_PAYLOAD_TARGET_KEY]: preprocessTargetValue(param, sourceLocaleValue),
575
+ [TRANSLATION_PAYLOAD_ORIGINAL_TARGET_KEY]: targetLocaleValue
576
+ }
577
+ };
578
+ });
579
+ Object.entries((_b2 = override.slots) != null ? _b2 : {}).forEach(([slotKey, slotComponents]) => {
580
+ slotComponents.map((slotComponent) => {
581
+ var _a3, _b3, _c2, _d, _e;
582
+ if (!slotComponent.type || !slotComponent._id) {
583
+ return;
584
+ }
585
+ const collectedNode = collectFromNode({
586
+ uniformSourceLocale,
587
+ uniformTargetLocale,
588
+ node: slotComponent,
589
+ // keep tree structure for `Slot Sections`
590
+ // to store whole `override` content in scope of current component
591
+ deep: true
592
+ });
593
+ const hasContent = collectedNode.parameters || collectedNode._overrides || collectedNode.slots;
594
+ if (hasContent) {
595
+ (_a3 = collectedOverrides[overrideKey]) != null ? _a3 : collectedOverrides[overrideKey] = {};
596
+ (_c2 = (_b3 = collectedOverrides[overrideKey]).slots) != null ? _c2 : _b3.slots = {};
597
+ (_e = (_d = collectedOverrides[overrideKey].slots)[slotKey]) != null ? _e : _d[slotKey] = [];
598
+ collectedOverrides[overrideKey].slots[slotKey].push(collectedNode);
599
+ }
600
+ });
601
+ });
602
+ });
603
+ const hasParameters = Object.keys(collectedParameters).length > 0;
604
+ const hasSlots = Object.keys(collectedSlots).length > 0;
605
+ const hasOverrides = Object.keys(collectedOverrides).length > 0;
606
+ return {
607
+ _id: node._id,
608
+ type: node.type,
609
+ parameters: hasParameters ? collectedParameters : void 0,
610
+ slots: hasSlots ? collectedSlots : void 0,
611
+ _overrides: hasOverrides ? collectedOverrides : void 0
612
+ };
613
+ };
614
+ var canTranslateParameterValue = (parameter, value) => {
615
+ if (parameter.type === SUPPORTED_PARAM_TYPES.text) {
616
+ if (typeof value !== "string" || !value) {
617
+ return false;
618
+ }
619
+ if (value.trim().length === 0) {
620
+ return false;
621
+ }
622
+ const bindResult = bindVariables({
623
+ variables: {},
624
+ value,
625
+ handleBinding: () => ""
626
+ });
627
+ const valueWithoutVariables = bindResult.result;
628
+ if (!valueWithoutVariables || valueWithoutVariables.trim().length === 0) {
629
+ return false;
630
+ }
631
+ return true;
632
+ } else if (parameter.type === SUPPORTED_PARAM_TYPES.richText) {
633
+ return isRichTextValue2(value) && !isRichTextValueConsideredEmpty2(value);
634
+ }
635
+ return false;
636
+ };
637
+ var isTargetLocaleUntouched = (parameterType, sourceLocaleValue, targetLocaleValue) => {
638
+ if (targetLocaleValue === void 0 || targetLocaleValue === null) {
639
+ return true;
640
+ }
641
+ if (parameterType === SUPPORTED_PARAM_TYPES.text && !targetLocaleValue) {
642
+ return true;
643
+ }
644
+ if (parameterType === SUPPORTED_PARAM_TYPES.richText && isRichTextValueConsideredEmpty2(targetLocaleValue)) {
645
+ return true;
646
+ }
647
+ return isSameParameterValue({
648
+ parameterType,
649
+ left: sourceLocaleValue,
650
+ right: targetLocaleValue
651
+ });
652
+ };
653
+ var preprocessTargetValue = (parameter, value) => {
654
+ if (parameter.type === SUPPORTED_PARAM_TYPES.richText) {
655
+ try {
656
+ return isRichTextValue2(value) ? renderAsTranslatableXml(value.root) : value;
657
+ } catch (e) {
658
+ return value;
659
+ }
660
+ }
661
+ return value;
662
+ };
663
+
664
+ // src/getCompositionForTranslation.ts
665
+ import { CANVAS_DRAFT_STATE } from "@uniformdev/canvas";
666
+ var getCompositionForTranslation = async ({
667
+ canvasClient,
668
+ compositionId,
669
+ releaseId,
670
+ state = CANVAS_DRAFT_STATE
671
+ }) => {
672
+ if (!compositionId) {
673
+ return void 0;
674
+ }
675
+ const composition = await canvasClient.getCompositionById({
676
+ compositionId,
677
+ releaseId: releaseId ? releaseId : void 0,
678
+ withComponentIDs: true,
679
+ skipDataResolution: true,
680
+ skipOverridesResolution: true,
681
+ skipPatternResolution: true,
682
+ state
683
+ });
684
+ return composition ? composition : void 0;
685
+ };
686
+
687
+ // src/getEntryForTranslation.ts
688
+ import { CANVAS_DRAFT_STATE as CANVAS_DRAFT_STATE2 } from "@uniformdev/canvas";
689
+ var getEntryForTranslation = async ({
690
+ contentClient,
691
+ entryId,
692
+ releaseId,
693
+ pattern,
694
+ state = CANVAS_DRAFT_STATE2
695
+ }) => {
696
+ if (!entryId) {
697
+ return void 0;
698
+ }
699
+ const entriesResponse = await contentClient.getEntries({
700
+ entryIDs: [entryId],
701
+ releaseId: releaseId ? releaseId : void 0,
702
+ limit: 1,
703
+ withComponentIDs: true,
704
+ skipDataResolution: true,
705
+ skipOverridesResolution: true,
706
+ skipPatternResolution: true,
707
+ pattern,
708
+ state
709
+ });
710
+ const entry = entriesResponse.entries.at(0);
711
+ return entry ? entry : void 0;
712
+ };
713
+
714
+ // src/mergeCompositionTranslationToUniform.ts
715
+ import { CANVAS_DRAFT_STATE as CANVAS_DRAFT_STATE4 } from "@uniformdev/canvas";
716
+
717
+ // src/translateComposition.ts
718
+ import { CANVAS_DRAFT_STATE as CANVAS_DRAFT_STATE3, walkNodeTree as walkNodeTree3 } from "@uniformdev/canvas";
719
+ import { produce } from "immer";
720
+ var translateComposition = ({
721
+ composition,
722
+ translationPayload
723
+ }) => {
724
+ var _a;
725
+ if (!composition || !composition.composition || !translationPayload) {
726
+ return createErrorResult("invalid-args");
727
+ }
728
+ if (composition.projectId !== translationPayload.metadata.uniformProjectId) {
729
+ return createErrorResult("project-id-mismatch");
730
+ }
731
+ if (composition.composition._id !== translationPayload.metadata.entity.id) {
732
+ return createErrorResult("entity-id-mismatch");
733
+ }
734
+ const uniformSourceLocale = translationPayload.metadata.uniformSourceLocale;
735
+ const uniformTargetLocale = translationPayload.metadata.uniformTargetLocale;
736
+ const compositionLocales = (_a = composition.composition._locales) != null ? _a : [];
737
+ if (compositionLocales.length > 0 && !compositionLocales.includes(uniformSourceLocale)) {
738
+ return createErrorResult("entity-locales-mismatch");
739
+ }
740
+ let updated = false;
741
+ const translatedComposition = produce(composition, (draft) => {
742
+ var _a2, _b, _c;
743
+ draft.state = CANVAS_DRAFT_STATE3;
744
+ if (!((_a2 = draft.composition._locales) == null ? void 0 : _a2.length)) {
745
+ (_c = (_b = draft.composition)._locales) != null ? _c : _b._locales = [];
746
+ draft.composition._locales.push(uniformSourceLocale);
747
+ }
748
+ if (!draft.composition._locales.includes(uniformTargetLocale)) {
749
+ draft.composition._locales.push(uniformTargetLocale);
750
+ }
751
+ walkNodeTree3(draft.composition, ({ node: component, type, actions }) => {
752
+ if (type !== "component") {
753
+ actions.stopProcessingDescendants();
754
+ return;
755
+ }
756
+ if (!component.type || !component._id) {
757
+ actions.stopProcessingDescendants();
758
+ return;
759
+ }
760
+ const translatedComponent = translationPayload.components[component._id];
761
+ if (!translatedComponent || component.type !== translatedComponent.type) {
762
+ return;
763
+ }
764
+ const { updated: isComponentUpdated } = processComponentTranslation({
765
+ uniformSourceLocale,
766
+ uniformTargetLocale,
767
+ originalNode: component,
768
+ translatedComponent
769
+ });
770
+ if (isComponentUpdated) {
771
+ updated = true;
772
+ }
773
+ });
774
+ });
775
+ return { result: translatedComposition, updated };
776
+ };
777
+
778
+ // src/mergeCompositionTranslationToUniform.ts
779
+ var mergeCompositionTranslationToUniform = async ({
780
+ canvasClient,
781
+ translationPayload,
782
+ updateComposition = defaultUpdateComposition,
783
+ onNotFound,
784
+ onNotTranslatedResult
785
+ }) => {
786
+ if (!translationPayload) {
787
+ return { translationMerged: false };
788
+ }
789
+ const entityType = translationPayload.metadata.entityType;
790
+ const entityId = translationPayload.metadata.entity.id;
791
+ if (entityType !== "composition" && entityType !== "componentPattern") {
792
+ return { translationMerged: false, entityId };
793
+ }
794
+ const composition = await getCurrentCompositionFromPayload({
795
+ canvasClient,
796
+ translationPayload
797
+ });
798
+ if (!composition) {
799
+ await (onNotFound == null ? void 0 : onNotFound({
800
+ translationPayload
801
+ }));
802
+ return { translationMerged: false, entityId };
803
+ }
804
+ const translationResult = translateComposition({
805
+ composition,
806
+ translationPayload
807
+ });
808
+ const { updated, errorKind, errorText, result: translatedComposition } = translationResult;
809
+ if (translatedComposition && updated && !errorKind) {
810
+ const translationMerged = await updateComposition({
811
+ canvasClient,
812
+ translationPayload,
813
+ composition: translatedComposition
814
+ });
815
+ return { translationMerged, entityId };
816
+ } else {
817
+ await (onNotTranslatedResult == null ? void 0 : onNotTranslatedResult({ updated, errorKind, errorText }));
818
+ return { translationMerged: false, entityId };
819
+ }
820
+ };
821
+ var getCurrentCompositionFromPayload = async ({
822
+ canvasClient,
823
+ translationPayload
824
+ }) => {
825
+ const compositionId = translationPayload.metadata.entity.id;
826
+ const releaseId = translationPayload.metadata.uniformReleaseId;
827
+ const currentComposition = await getCompositionForTranslation({
828
+ canvasClient,
829
+ compositionId,
830
+ releaseId,
831
+ state: CANVAS_DRAFT_STATE4
832
+ });
833
+ return currentComposition;
834
+ };
835
+ var defaultUpdateComposition = async ({
836
+ canvasClient,
837
+ composition
838
+ }) => {
839
+ await canvasClient.updateComposition(composition);
840
+ return true;
841
+ };
842
+
843
+ // src/mergeEntryTranslationToUniform.ts
844
+ import { CANVAS_DRAFT_STATE as CANVAS_DRAFT_STATE6 } from "@uniformdev/canvas";
845
+
846
+ // src/translateEntry.ts
847
+ import { CANVAS_DRAFT_STATE as CANVAS_DRAFT_STATE5, walkNodeTree as walkNodeTree4 } from "@uniformdev/canvas";
848
+ import { produce as produce2 } from "immer";
849
+ var translateEntry = ({
850
+ entry,
851
+ translationPayload
852
+ }) => {
853
+ var _a;
854
+ if (!entry || !translationPayload) {
855
+ return createErrorResult("invalid-args");
856
+ }
857
+ if (entry.projectId !== translationPayload.metadata.uniformProjectId) {
858
+ return createErrorResult("project-id-mismatch");
859
+ }
860
+ if ((entry == null ? void 0 : entry.entry._id) !== translationPayload.metadata.entity.id) {
861
+ return createErrorResult("entity-id-mismatch");
862
+ }
863
+ const entryLocales = (_a = entry.entry._locales) != null ? _a : [];
864
+ const uniformSourceLocale = translationPayload.metadata.uniformSourceLocale;
865
+ const uniformTargetLocale = translationPayload.metadata.uniformTargetLocale;
866
+ if (!entryLocales.includes(uniformSourceLocale)) {
867
+ return createErrorResult("entity-locales-mismatch");
868
+ }
869
+ let updated = false;
870
+ const translatedEntry = produce2(entry, (draft) => {
871
+ var _a2, _b;
872
+ draft.state = CANVAS_DRAFT_STATE5;
873
+ if (!entryLocales.includes(uniformTargetLocale)) {
874
+ (_b = (_a2 = draft.entry)._locales) != null ? _b : _a2._locales = [];
875
+ draft.entry._locales.push(uniformTargetLocale);
876
+ }
877
+ walkNodeTree4(draft.entry, ({ node: component, type, actions }) => {
878
+ if (type !== "entry") {
879
+ actions.stopProcessingDescendants();
880
+ return;
881
+ }
882
+ if (!component.type || !component._id) {
883
+ actions.stopProcessingDescendants();
884
+ return;
885
+ }
886
+ const translatedComponent = translationPayload.components[component._id];
887
+ if (!translatedComponent || component.type !== translatedComponent.type) {
888
+ return;
889
+ }
890
+ const { updated: isComponentUpdated } = processComponentTranslation({
891
+ uniformSourceLocale,
892
+ uniformTargetLocale,
893
+ originalNode: component,
894
+ translatedComponent
895
+ });
896
+ if (isComponentUpdated) {
897
+ updated = true;
898
+ }
899
+ });
900
+ });
901
+ return { result: translatedEntry, updated };
902
+ };
903
+
904
+ // src/mergeEntryTranslationToUniform.ts
905
+ var mergeEntryTranslationToUniform = async ({
906
+ contentClient,
907
+ translationPayload,
908
+ updateEntry = defaultUpdateEntry,
909
+ onNotFound,
910
+ onNotTranslatedResult
911
+ }) => {
912
+ if (!translationPayload) {
913
+ return { translationMerged: false };
914
+ }
915
+ const entityType = translationPayload.metadata.entityType;
916
+ const entityId = translationPayload.metadata.entity.id;
917
+ if (entityType !== "entry" && entityType !== "entryPattern") {
918
+ return { translationMerged: false, entityId };
919
+ }
920
+ const entry = await getCurrentEntryFromPayload({
921
+ contentClient,
922
+ translationPayload
923
+ });
924
+ if (!entry) {
925
+ await (onNotFound == null ? void 0 : onNotFound({
926
+ translationPayload
927
+ }));
928
+ return { translationMerged: false, entityId };
929
+ }
930
+ const translationResult = translateEntry({
931
+ entry,
932
+ translationPayload
933
+ });
934
+ const { updated, errorKind, errorText, result: translatedEntry } = translationResult;
935
+ if (translatedEntry && updated && !errorKind) {
936
+ const translationMerged = await updateEntry({
937
+ contentClient,
938
+ translationPayload,
939
+ entry: translatedEntry
940
+ });
941
+ return { translationMerged, entityId };
942
+ } else {
943
+ await (onNotTranslatedResult == null ? void 0 : onNotTranslatedResult({ updated, errorKind, errorText }));
944
+ return { translationMerged: false, entityId };
945
+ }
946
+ };
947
+ var getCurrentEntryFromPayload = async ({
948
+ contentClient,
949
+ translationPayload
950
+ }) => {
951
+ const entityType = translationPayload.metadata.entityType;
952
+ const entryId = translationPayload.metadata.entity.id;
953
+ const releaseId = translationPayload.metadata.uniformReleaseId;
954
+ const currentEntry = await getEntryForTranslation({
955
+ contentClient,
956
+ entryId,
957
+ releaseId,
958
+ pattern: entityType === "entryPattern",
959
+ state: CANVAS_DRAFT_STATE6
960
+ });
961
+ return currentEntry;
962
+ };
963
+ var defaultUpdateEntry = async ({
964
+ contentClient,
965
+ entry
966
+ }) => {
967
+ await contentClient.upsertEntry(entry);
968
+ return true;
969
+ };
970
+
971
+ // src/mergeTranslationToUniform.ts
972
+ var mergeTranslationToUniform = async ({
973
+ canvasClient,
974
+ contentClient,
975
+ translationPayload,
976
+ updateComposition,
977
+ updateEntry,
978
+ onNotFound,
979
+ onNotTranslatedResult
980
+ }) => {
981
+ if (!translationPayload) {
982
+ return { translationMerged: false };
983
+ }
984
+ const entityType = translationPayload.metadata.entityType;
985
+ const entityId = translationPayload.metadata.entity.id;
986
+ if (entityType === "composition" || entityType === "componentPattern") {
987
+ return await mergeCompositionTranslationToUniform({
988
+ canvasClient,
989
+ translationPayload,
990
+ updateComposition,
991
+ onNotFound,
992
+ onNotTranslatedResult
993
+ });
994
+ } else if (entityType === "entry" || entityType === "entryPattern") {
995
+ return await mergeEntryTranslationToUniform({
996
+ contentClient,
997
+ translationPayload,
998
+ updateEntry,
999
+ onNotFound,
1000
+ onNotTranslatedResult
1001
+ });
1002
+ }
1003
+ return { translationMerged: false, entityId };
1004
+ };
1005
+ export {
1006
+ collectTranslationPayload,
1007
+ getCompositionForTranslation,
1008
+ getEntryForTranslation,
1009
+ mergeCompositionTranslationToUniform,
1010
+ mergeEntryTranslationToUniform,
1011
+ mergeTranslationToUniform,
1012
+ translateComposition,
1013
+ translateEntry
1014
+ };