@focus-reactive/payload-plugin-translator 0.7.1 → 0.7.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -11,13 +11,15 @@ export interface BlockLike {
|
|
|
11
11
|
}
|
|
12
12
|
/**
|
|
13
13
|
* A tab as this layer needs to read it: an optional `name` (present → it opens a data boundary;
|
|
14
|
-
* absent → it flattens into the parent scope)
|
|
15
|
-
*
|
|
14
|
+
* absent → it flattens into the parent scope), its child `fields`, and `localized` (a *named* tab
|
|
15
|
+
* may be `localized`, partitioning its subtree per locale — Payload's sanitizer propagates it the
|
|
16
|
+
* same as a group). Payload's `Tab` (`NamedTab | UnnamedTab`) is assignable to this.
|
|
16
17
|
*
|
|
17
18
|
* @public
|
|
18
19
|
*/
|
|
19
20
|
export interface TabLike {
|
|
20
21
|
name?: string;
|
|
22
|
+
localized?: boolean;
|
|
21
23
|
fields: FieldLike[];
|
|
22
24
|
}
|
|
23
25
|
/**
|
|
@@ -5,9 +5,9 @@ const asObject = (value)=>isObject(value) ? value : {};
|
|
|
5
5
|
/**
|
|
6
6
|
* Reconcile walker: produces the full document shape from source + target, with target
|
|
7
7
|
* priority (source fills empty target slots). Iteration is driven by `source`; a field with
|
|
8
|
-
* no source value is dropped, `
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* no source value is dropped, `blockType` is preserved, non-object array items / unknown blocks
|
|
9
|
+
* pass through unchanged, and array/block `id` is kept for shared rows but stripped for per-locale
|
|
10
|
+
* rows (see {@link Cursor.sharedRow} — the data-loss-critical bit).
|
|
11
11
|
*
|
|
12
12
|
* Array/block elements are paired with their target counterpart by `id`, not by position (see
|
|
13
13
|
* {@link matchElementById}); output order always follows `source`.
|
|
@@ -15,9 +15,12 @@ const asObject = (value)=>isObject(value) ? value : {};
|
|
|
15
15
|
enterObject (field, cursor) {
|
|
16
16
|
const sourceValue = cursor.source[field.name];
|
|
17
17
|
if (!isObject(sourceValue)) return "skip"; // undefined / non-object source → drop the field
|
|
18
|
+
// A localized group or named tab partitions its whole subtree per locale → descendants are
|
|
19
|
+
// per-locale rows (Payload's sanitizer propagates `tab.localized` the same as a group).
|
|
18
20
|
return {
|
|
19
21
|
source: sourceValue,
|
|
20
|
-
target: asObject(cursor.target[field.name])
|
|
22
|
+
target: asObject(cursor.target[field.name]),
|
|
23
|
+
sharedRow: cursor.sharedRow && !field.localized
|
|
21
24
|
};
|
|
22
25
|
},
|
|
23
26
|
enterList (field, cursor) {
|
|
@@ -26,6 +29,8 @@ const asObject = (value)=>isObject(value) ? value : {};
|
|
|
26
29
|
const targetValue = cursor.target[field.name];
|
|
27
30
|
const targetArr = Array.isArray(targetValue) ? targetValue : [];
|
|
28
31
|
const isBlocks = field.type === "blocks";
|
|
32
|
+
// Elements are shared rows only when this container AND every ancestor is non-localized.
|
|
33
|
+
const childShared = cursor.sharedRow && !field.localized;
|
|
29
34
|
const children = [];
|
|
30
35
|
sourceValue.forEach((item, index)=>{
|
|
31
36
|
if (!isObject(item)) return; // non-object element → passthrough (rebuilt in combine)
|
|
@@ -35,7 +40,8 @@ const asObject = (value)=>isObject(value) ? value : {};
|
|
|
35
40
|
children.push({
|
|
36
41
|
cursor: {
|
|
37
42
|
source: item,
|
|
38
|
-
target: matchElementById(targetArr, item, isBlocks)
|
|
43
|
+
target: matchElementById(targetArr, item, isBlocks),
|
|
44
|
+
sharedRow: childShared
|
|
39
45
|
},
|
|
40
46
|
fields,
|
|
41
47
|
key: index
|
|
@@ -58,13 +64,29 @@ const asObject = (value)=>isObject(value) ? value : {};
|
|
|
58
64
|
child.key,
|
|
59
65
|
child.out
|
|
60
66
|
]));
|
|
61
|
-
|
|
67
|
+
// Passthrough items (unknown blockType / unresolved fields) never reach the element branch's
|
|
68
|
+
// id guard, so apply the same rule here: strip a per-locale row's id to avoid an insert
|
|
69
|
+
// collision. Elements are shared only when this container and every ancestor is non-localized.
|
|
70
|
+
const childShared = cursor.sharedRow && !container.field.localized;
|
|
71
|
+
return sourceArr.map((item, index)=>{
|
|
72
|
+
if (byIndex.has(index)) return byIndex.get(index);
|
|
73
|
+
if (!childShared && isObject(item) && item.id != null) {
|
|
74
|
+
const { id: _dropped, ...rest } = item;
|
|
75
|
+
return rest;
|
|
76
|
+
}
|
|
77
|
+
return item;
|
|
78
|
+
});
|
|
62
79
|
}
|
|
63
80
|
const result = {};
|
|
64
81
|
for (const child of children)result[child.key] = child.out;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
result.blockType = cursor.source.blockType;
|
|
82
|
+
if (container.kind === "element") {
|
|
83
|
+
// Block elements keep their blockType.
|
|
84
|
+
if (container.field.type === "blocks") result.blockType = cursor.source.blockType;
|
|
85
|
+
// Keep `id` only for a shared (non-localized, no localized ancestor) row so Payload updates it
|
|
86
|
+
// in place; stripping it there makes Payload recreate the row and wipe other locales. Under a
|
|
87
|
+
// localized container/ancestor the rows are per-locale, so the id is dropped to avoid an
|
|
88
|
+
// insert collision with the source locale's row. Guard against writing `id: undefined`.
|
|
89
|
+
if (cursor.sharedRow && cursor.source.id != null) result.id = cursor.source.id;
|
|
68
90
|
}
|
|
69
91
|
return result;
|
|
70
92
|
}
|
|
@@ -88,7 +110,8 @@ const asObject = (value)=>isObject(value) ? value : {};
|
|
|
88
110
|
*/ reconcile(sourceData, targetData) {
|
|
89
111
|
const root = {
|
|
90
112
|
source: sourceData,
|
|
91
|
-
target: targetData ?? {}
|
|
113
|
+
target: targetData ?? {},
|
|
114
|
+
sharedRow: true
|
|
92
115
|
};
|
|
93
116
|
return walkFields(this.schema, root, reconcileWalker) ?? {};
|
|
94
117
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@focus-reactive/payload-plugin-translator",
|
|
3
|
-
"version": "0.7.
|
|
3
|
+
"version": "0.7.2",
|
|
4
4
|
"description": "Translation plugin for Payload CMS 3.x. Automatically translate your localized content using any translation provider.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|