@roxxel/payload-multilang 0.0.5 → 0.0.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +16 -3
- package/dist/components/LanguageListToolbar.js +4 -3
- package/dist/components/LanguageListToolbar.js.map +1 -1
- package/dist/components/LanguageMetabox.js +18 -17
- package/dist/components/LanguageMetabox.js.map +1 -1
- package/dist/components/TranslationActionsClient.js +16 -14
- package/dist/components/TranslationActionsClient.js.map +1 -1
- package/dist/components/TranslationColumnCell.js +4 -1
- package/dist/components/TranslationColumnCell.js.map +1 -1
- package/dist/components/TranslationColumnCellClient.js +16 -7
- package/dist/components/TranslationColumnCellClient.js.map +1 -1
- package/dist/components/TranslationsTab.js +9 -8
- package/dist/components/TranslationsTab.js.map +1 -1
- package/dist/constants.d.ts +1 -1
- package/dist/constants.js +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/endpoints/translations.js +4 -6
- package/dist/endpoints/translations.js.map +1 -1
- package/dist/hooks/translatedCollection.d.ts +2 -1
- package/dist/hooks/translatedCollection.js +321 -16
- package/dist/hooks/translatedCollection.js.map +1 -1
- package/dist/hooks/translatedGlobal.js +5 -1
- package/dist/hooks/translatedGlobal.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +22 -2
- package/dist/index.js.map +1 -1
- package/dist/lib/config.js +2 -10
- package/dist/lib/config.js.map +1 -1
- package/dist/lib/data.d.ts +1 -2
- package/dist/lib/data.js +32 -4
- package/dist/lib/data.js.map +1 -1
- package/dist/translations.d.ts +72 -0
- package/dist/translations.js +72 -0
- package/dist/translations.js.map +1 -0
- package/dist/types.d.ts +0 -19
- package/dist/types.js.map +1 -1
- package/docs/configuration.md +51 -9
- package/docs/usage.md +17 -35
- package/package.json +1 -1
|
@@ -1,13 +1,298 @@
|
|
|
1
1
|
import { randomUUID } from 'crypto';
|
|
2
2
|
import { MULTILANG_SKIP_HOOK } from '../constants.js';
|
|
3
3
|
import { asDocument, getID, getStringValue } from '../lib/data.js';
|
|
4
|
+
const LANGUAGE_LABEL = {
|
|
5
|
+
en: 'Language',
|
|
6
|
+
uk: 'Мова'
|
|
7
|
+
};
|
|
8
|
+
const TRANSLATIONS_LABEL = {
|
|
9
|
+
en: 'Translations',
|
|
10
|
+
uk: 'Переклади'
|
|
11
|
+
};
|
|
4
12
|
const hasSkipContext = (context)=>context?.[MULTILANG_SKIP_HOOK] === true;
|
|
13
|
+
const isObject = (value)=>typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
14
|
+
const toArray = (value)=>Array.isArray(value) ? value.filter(isObject) : [];
|
|
5
15
|
const valuesAreEqual = (left, right)=>{
|
|
6
16
|
if (left === right) {
|
|
7
17
|
return true;
|
|
8
18
|
}
|
|
9
19
|
return JSON.stringify(left) === JSON.stringify(right);
|
|
10
20
|
};
|
|
21
|
+
const fieldAffectsData = (field)=>'name' in field && typeof field.name === 'string' && field.name !== 'id' && field.type !== 'ui';
|
|
22
|
+
const fieldSynchronizes = (field)=>{
|
|
23
|
+
const custom = isObject(field.custom) ? field.custom : {};
|
|
24
|
+
const multilang = isObject(custom.multilang) ? custom.multilang : {};
|
|
25
|
+
return multilang.synchronize === true;
|
|
26
|
+
};
|
|
27
|
+
const fieldSynchronizesPosition = (field)=>{
|
|
28
|
+
const custom = isObject(field.custom) ? field.custom : {};
|
|
29
|
+
const multilang = isObject(custom.multilang) ? custom.multilang : {};
|
|
30
|
+
return multilang.synchronizePosition === true;
|
|
31
|
+
};
|
|
32
|
+
const hasName = (value)=>isObject(value) && typeof value.name === 'string';
|
|
33
|
+
const getSynchronizedBlocks = (field, inheritedSynchronize)=>{
|
|
34
|
+
if (field.type !== 'blocks') {
|
|
35
|
+
return [];
|
|
36
|
+
}
|
|
37
|
+
return field.blocks.flatMap((block)=>{
|
|
38
|
+
const fields = getSynchronizedFields(block.fields, inheritedSynchronize);
|
|
39
|
+
if (fields.length === 0) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
return [
|
|
43
|
+
{
|
|
44
|
+
slug: block.slug,
|
|
45
|
+
fields
|
|
46
|
+
}
|
|
47
|
+
];
|
|
48
|
+
});
|
|
49
|
+
};
|
|
50
|
+
const getSynchronizedTabFields = (field, inheritedSynchronize)=>field.tabs.flatMap((tab)=>{
|
|
51
|
+
const fields = getSynchronizedFields(tab.fields, inheritedSynchronize);
|
|
52
|
+
if (fields.length === 0) {
|
|
53
|
+
return [];
|
|
54
|
+
}
|
|
55
|
+
if (hasName(tab)) {
|
|
56
|
+
return [
|
|
57
|
+
{
|
|
58
|
+
name: tab.name,
|
|
59
|
+
fields,
|
|
60
|
+
kind: 'group'
|
|
61
|
+
}
|
|
62
|
+
];
|
|
63
|
+
}
|
|
64
|
+
return fields;
|
|
65
|
+
});
|
|
66
|
+
const getSynchronizedFields = (fields = [], inheritedSynchronize = false)=>fields.flatMap((field)=>{
|
|
67
|
+
if (field.type === 'row' || field.type === 'collapsible') {
|
|
68
|
+
return getSynchronizedFields(field.fields, inheritedSynchronize || fieldSynchronizes(field));
|
|
69
|
+
}
|
|
70
|
+
if (field.type === 'tabs') {
|
|
71
|
+
return getSynchronizedTabFields(field, inheritedSynchronize);
|
|
72
|
+
}
|
|
73
|
+
if (!fieldAffectsData(field)) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
const synchronize = inheritedSynchronize || fieldSynchronizes(field);
|
|
77
|
+
if (field.type === 'array') {
|
|
78
|
+
const fields = getSynchronizedFields(field.fields, synchronize);
|
|
79
|
+
const synchronizePosition = synchronize || fieldSynchronizesPosition(field);
|
|
80
|
+
if (!synchronizePosition && fields.length === 0) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
return [
|
|
84
|
+
{
|
|
85
|
+
name: field.name,
|
|
86
|
+
fields,
|
|
87
|
+
kind: 'array',
|
|
88
|
+
synchronizePosition
|
|
89
|
+
}
|
|
90
|
+
];
|
|
91
|
+
}
|
|
92
|
+
if (field.type === 'blocks') {
|
|
93
|
+
const blocks = getSynchronizedBlocks(field, synchronize);
|
|
94
|
+
const synchronizePosition = synchronize || fieldSynchronizesPosition(field);
|
|
95
|
+
if (!synchronizePosition && blocks.length === 0) {
|
|
96
|
+
return [];
|
|
97
|
+
}
|
|
98
|
+
return [
|
|
99
|
+
{
|
|
100
|
+
name: field.name,
|
|
101
|
+
blocks,
|
|
102
|
+
kind: 'blocks',
|
|
103
|
+
synchronizePosition
|
|
104
|
+
}
|
|
105
|
+
];
|
|
106
|
+
}
|
|
107
|
+
if (field.type === 'group') {
|
|
108
|
+
const fields = getSynchronizedFields(field.fields, synchronize);
|
|
109
|
+
if (fields.length === 0) {
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
return [
|
|
113
|
+
{
|
|
114
|
+
name: field.name,
|
|
115
|
+
fields,
|
|
116
|
+
kind: 'group'
|
|
117
|
+
}
|
|
118
|
+
];
|
|
119
|
+
}
|
|
120
|
+
if (!synchronize) {
|
|
121
|
+
return [];
|
|
122
|
+
}
|
|
123
|
+
return [
|
|
124
|
+
{
|
|
125
|
+
name: field.name,
|
|
126
|
+
kind: 'value'
|
|
127
|
+
}
|
|
128
|
+
];
|
|
129
|
+
});
|
|
130
|
+
const getRowKey = (row, index)=>{
|
|
131
|
+
const id = getID(row.id);
|
|
132
|
+
return id === undefined ? `index:${index}` : `id:${String(id)}`;
|
|
133
|
+
};
|
|
134
|
+
const getShellSignature = (value, field)=>JSON.stringify(toArray(value).map((row, index)=>({
|
|
135
|
+
blockName: field.kind === 'blocks' ? getStringValue(row.blockName) : undefined,
|
|
136
|
+
blockType: field.kind === 'blocks' ? getStringValue(row.blockType) : undefined,
|
|
137
|
+
key: getRowKey(row, index)
|
|
138
|
+
})));
|
|
139
|
+
const positionChanged = (field, source, previous)=>{
|
|
140
|
+
if (field.kind !== 'array' && field.kind !== 'blocks' || !field.synchronizePosition || !(field.name in source)) {
|
|
141
|
+
return false;
|
|
142
|
+
}
|
|
143
|
+
return getShellSignature(source[field.name], field) !== getShellSignature(previous[field.name], field);
|
|
144
|
+
};
|
|
145
|
+
const getBlockFieldsForRow = (field, sourceRow)=>{
|
|
146
|
+
if (field.kind !== 'blocks') {
|
|
147
|
+
return [];
|
|
148
|
+
}
|
|
149
|
+
const blockType = getStringValue(sourceRow.blockType);
|
|
150
|
+
return field.blocks?.find((block)=>block.slug === blockType)?.fields || [];
|
|
151
|
+
};
|
|
152
|
+
const createSynchronizedRow = (sourceRow, previousRow, targetRow, field)=>{
|
|
153
|
+
const row = targetRow ? {
|
|
154
|
+
...targetRow
|
|
155
|
+
} : {};
|
|
156
|
+
if (field.kind === 'blocks') {
|
|
157
|
+
row.id = randomUUID();
|
|
158
|
+
}
|
|
159
|
+
if (field.synchronizePosition && field.kind === 'blocks' && 'blockType' in sourceRow) {
|
|
160
|
+
row.blockType = sourceRow.blockType;
|
|
161
|
+
}
|
|
162
|
+
if (field.synchronizePosition && field.kind === 'blocks') {
|
|
163
|
+
if ('blockName' in sourceRow) {
|
|
164
|
+
row.blockName = sourceRow.blockName;
|
|
165
|
+
} else {
|
|
166
|
+
delete row.blockName;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
const fields = field.kind === 'array' ? field.fields : getBlockFieldsForRow(field, sourceRow);
|
|
170
|
+
return synchronizeData({
|
|
171
|
+
fields,
|
|
172
|
+
previous: previousRow || {},
|
|
173
|
+
source: sourceRow,
|
|
174
|
+
target: row
|
|
175
|
+
});
|
|
176
|
+
};
|
|
177
|
+
const synchronizeContainerValue = ({ field, previousSourceValue, sourceValue, targetValue })=>{
|
|
178
|
+
const targetRows = toArray(targetValue);
|
|
179
|
+
const previousSourceRows = toArray(previousSourceValue);
|
|
180
|
+
const sourceRows = toArray(sourceValue);
|
|
181
|
+
if (!field.synchronizePosition) {
|
|
182
|
+
const sourceRowsByPreviousKey = new Map(sourceRows.map((row, index)=>{
|
|
183
|
+
const previousRow = previousSourceRows[index];
|
|
184
|
+
const key = previousRow ? getRowKey(previousRow, index) : getRowKey(row, index);
|
|
185
|
+
return [
|
|
186
|
+
key,
|
|
187
|
+
row
|
|
188
|
+
];
|
|
189
|
+
}));
|
|
190
|
+
return targetRows.map((targetRow, index)=>{
|
|
191
|
+
const previousRow = previousSourceRows[index];
|
|
192
|
+
const sourceRow = previousRow && sourceRowsByPreviousKey.get(getRowKey(previousRow, index)) || sourceRows[index];
|
|
193
|
+
return sourceRow ? createSynchronizedRow(sourceRow, previousRow, targetRow, field) : {
|
|
194
|
+
...targetRow
|
|
195
|
+
};
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
const previousSourceIndexesByKey = new Map(previousSourceRows.map((row, index)=>[
|
|
199
|
+
getRowKey(row, index),
|
|
200
|
+
index
|
|
201
|
+
]));
|
|
202
|
+
return sourceRows.map((sourceRow, index)=>{
|
|
203
|
+
const previousIndex = previousSourceIndexesByKey.get(getRowKey(sourceRow, index));
|
|
204
|
+
return createSynchronizedRow(sourceRow, previousIndex === undefined ? undefined : previousSourceRows[previousIndex], previousIndex === undefined ? undefined : targetRows[previousIndex], field);
|
|
205
|
+
});
|
|
206
|
+
};
|
|
207
|
+
const descriptorChanged = ({ field, previous, source })=>{
|
|
208
|
+
if (field.kind === 'value') {
|
|
209
|
+
return !valuesAreEqual(source[field.name], previous[field.name]);
|
|
210
|
+
}
|
|
211
|
+
if (field.kind === 'group') {
|
|
212
|
+
return descriptorsChanged({
|
|
213
|
+
fields: field.fields,
|
|
214
|
+
previous: asDocument(previous[field.name]),
|
|
215
|
+
source: asDocument(source[field.name])
|
|
216
|
+
});
|
|
217
|
+
}
|
|
218
|
+
if (!(field.name in source)) {
|
|
219
|
+
return false;
|
|
220
|
+
}
|
|
221
|
+
if (positionChanged(field, source, previous)) {
|
|
222
|
+
return true;
|
|
223
|
+
}
|
|
224
|
+
const previousRows = toArray(previous[field.name]);
|
|
225
|
+
const previousRowsByKey = new Map(previousRows.map((row, index)=>[
|
|
226
|
+
getRowKey(row, index),
|
|
227
|
+
row
|
|
228
|
+
]));
|
|
229
|
+
return toArray(source[field.name]).some((sourceRow, index)=>{
|
|
230
|
+
const previousRow = previousRowsByKey.get(getRowKey(sourceRow, index)) || previousRows[index];
|
|
231
|
+
const fields = field.kind === 'array' ? field.fields : getBlockFieldsForRow(field, sourceRow);
|
|
232
|
+
return descriptorsChanged({
|
|
233
|
+
fields,
|
|
234
|
+
previous: previousRow || {},
|
|
235
|
+
source: sourceRow
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
const descriptorsChanged = ({ fields, previous, source })=>fields.some((field)=>descriptorChanged({
|
|
240
|
+
field,
|
|
241
|
+
previous,
|
|
242
|
+
source
|
|
243
|
+
}));
|
|
244
|
+
const synchronizeData = ({ fields, previous, source, target })=>fields.reduce((acc, field)=>{
|
|
245
|
+
if (field.kind === 'value') {
|
|
246
|
+
if (field.name in source) {
|
|
247
|
+
acc[field.name] = source[field.name];
|
|
248
|
+
} else {
|
|
249
|
+
delete acc[field.name];
|
|
250
|
+
}
|
|
251
|
+
return acc;
|
|
252
|
+
}
|
|
253
|
+
if (field.kind === 'group') {
|
|
254
|
+
if (field.name in source) {
|
|
255
|
+
const value = synchronizeData({
|
|
256
|
+
fields: field.fields,
|
|
257
|
+
previous: asDocument(previous[field.name]),
|
|
258
|
+
source: asDocument(source[field.name]),
|
|
259
|
+
target: asDocument(acc[field.name])
|
|
260
|
+
});
|
|
261
|
+
if (!valuesAreEqual(value, acc[field.name])) {
|
|
262
|
+
acc[field.name] = value;
|
|
263
|
+
}
|
|
264
|
+
} else {
|
|
265
|
+
delete acc[field.name];
|
|
266
|
+
}
|
|
267
|
+
return acc;
|
|
268
|
+
}
|
|
269
|
+
const value = synchronizeContainerValue({
|
|
270
|
+
field,
|
|
271
|
+
previousSourceValue: previous[field.name],
|
|
272
|
+
sourceValue: source[field.name],
|
|
273
|
+
targetValue: target[field.name]
|
|
274
|
+
});
|
|
275
|
+
if (!valuesAreEqual(value, target[field.name])) {
|
|
276
|
+
acc[field.name] = value;
|
|
277
|
+
}
|
|
278
|
+
return acc;
|
|
279
|
+
}, {
|
|
280
|
+
...target
|
|
281
|
+
});
|
|
282
|
+
const getSynchronizedDataForTranslation = ({ fields, nextDoc, previous, translation })=>{
|
|
283
|
+
const synchronized = synchronizeData({
|
|
284
|
+
fields,
|
|
285
|
+
previous,
|
|
286
|
+
source: nextDoc,
|
|
287
|
+
target: translation
|
|
288
|
+
});
|
|
289
|
+
return fields.reduce((acc, field)=>{
|
|
290
|
+
if (!valuesAreEqual(synchronized[field.name], translation[field.name])) {
|
|
291
|
+
acc[field.name] = synchronized[field.name];
|
|
292
|
+
}
|
|
293
|
+
return acc;
|
|
294
|
+
}, {});
|
|
295
|
+
};
|
|
11
296
|
const isConfiguredLanguage = (collection, language)=>Boolean(language && collection.languages.some((configuredLanguage)=>configuredLanguage.code === language));
|
|
12
297
|
const getDuplicateLanguageIDs = async ({ collection, excludeID, group, language, req })=>{
|
|
13
298
|
const and = [
|
|
@@ -85,8 +370,9 @@ export const createTranslatedCollectionBeforeChangeHook = ({ collection })=>asyn
|
|
|
85
370
|
}
|
|
86
371
|
return nextData;
|
|
87
372
|
};
|
|
88
|
-
export const createSynchronizedFieldsAfterChangeHook = ({ collection })=>async ({ context, doc, operation, previousDoc, req })=>{
|
|
89
|
-
|
|
373
|
+
export const createSynchronizedFieldsAfterChangeHook = ({ collection, fields })=>async ({ context, doc, operation, previousDoc, req })=>{
|
|
374
|
+
const synchronizedFields = getSynchronizedFields(fields);
|
|
375
|
+
if (hasSkipContext(context) || operation !== 'update' || synchronizedFields.length === 0) {
|
|
90
376
|
return doc;
|
|
91
377
|
}
|
|
92
378
|
const nextDoc = asDocument(doc);
|
|
@@ -96,13 +382,12 @@ export const createSynchronizedFieldsAfterChangeHook = ({ collection })=>async (
|
|
|
96
382
|
if (!group || !currentID) {
|
|
97
383
|
return doc;
|
|
98
384
|
}
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
if (Object.keys(synchronizedData).length === 0) {
|
|
385
|
+
const changedFields = synchronizedFields.filter((field)=>descriptorChanged({
|
|
386
|
+
field,
|
|
387
|
+
previous,
|
|
388
|
+
source: nextDoc
|
|
389
|
+
}));
|
|
390
|
+
if (changedFields.length === 0) {
|
|
106
391
|
return doc;
|
|
107
392
|
}
|
|
108
393
|
const translations = await req.payload.find({
|
|
@@ -126,13 +411,32 @@ export const createSynchronizedFieldsAfterChangeHook = ({ collection })=>async (
|
|
|
126
411
|
]
|
|
127
412
|
}
|
|
128
413
|
});
|
|
129
|
-
await Promise.all(translations.docs.map((translation)=>
|
|
414
|
+
await Promise.all(translations.docs.map((translation)=>{
|
|
415
|
+
const translationDoc = asDocument(translation);
|
|
416
|
+
const id = getID(translationDoc.id);
|
|
417
|
+
if (id === undefined) {
|
|
418
|
+
return undefined;
|
|
419
|
+
}
|
|
420
|
+
const synchronizedData = getSynchronizedDataForTranslation({
|
|
421
|
+
fields: changedFields,
|
|
422
|
+
nextDoc,
|
|
423
|
+
previous,
|
|
424
|
+
translation: translationDoc
|
|
425
|
+
});
|
|
426
|
+
if (Object.keys(synchronizedData).length === 0) {
|
|
427
|
+
return undefined;
|
|
428
|
+
}
|
|
429
|
+
return {
|
|
430
|
+
id,
|
|
431
|
+
data: synchronizedData
|
|
432
|
+
};
|
|
433
|
+
}).filter((update)=>update !== undefined).map(({ id, data })=>req.payload.update({
|
|
130
434
|
id,
|
|
131
435
|
collection: collection.slug,
|
|
132
436
|
context: {
|
|
133
437
|
[MULTILANG_SKIP_HOOK]: true
|
|
134
438
|
},
|
|
135
|
-
data
|
|
439
|
+
data,
|
|
136
440
|
overrideAccess: true,
|
|
137
441
|
req
|
|
138
442
|
})));
|
|
@@ -147,7 +451,7 @@ export const createHiddenFields = ({ collection })=>[
|
|
|
147
451
|
hidden: true
|
|
148
452
|
},
|
|
149
453
|
index: true,
|
|
150
|
-
label:
|
|
454
|
+
label: LANGUAGE_LABEL
|
|
151
455
|
},
|
|
152
456
|
{
|
|
153
457
|
name: collection.fieldNames.group,
|
|
@@ -157,7 +461,7 @@ export const createHiddenFields = ({ collection })=>[
|
|
|
157
461
|
hidden: true
|
|
158
462
|
},
|
|
159
463
|
index: true,
|
|
160
|
-
label:
|
|
464
|
+
label: TRANSLATIONS_LABEL
|
|
161
465
|
},
|
|
162
466
|
{
|
|
163
467
|
name: collection.fieldNames.meta,
|
|
@@ -192,7 +496,7 @@ export const createLanguageColumnFields = ({ collection })=>{
|
|
|
192
496
|
disableListColumn: false,
|
|
193
497
|
width: '132px'
|
|
194
498
|
},
|
|
195
|
-
label: label ||
|
|
499
|
+
label: label || TRANSLATIONS_LABEL
|
|
196
500
|
}
|
|
197
501
|
];
|
|
198
502
|
};
|
|
@@ -242,7 +546,7 @@ export const withTranslatedCollection = ({ collection, config })=>{
|
|
|
242
546
|
Component: '@roxxel/payload-multilang/rsc#TranslationsTab',
|
|
243
547
|
path: '/translations',
|
|
244
548
|
tab: {
|
|
245
|
-
label: '
|
|
549
|
+
label: ({ t })=>t('payloadMultilang:translations'),
|
|
246
550
|
order: 80
|
|
247
551
|
}
|
|
248
552
|
}
|
|
@@ -273,7 +577,8 @@ export const withTranslatedCollection = ({ collection, config })=>{
|
|
|
273
577
|
...config.hooks,
|
|
274
578
|
afterChange: [
|
|
275
579
|
createSynchronizedFieldsAfterChangeHook({
|
|
276
|
-
collection
|
|
580
|
+
collection,
|
|
581
|
+
fields: config.fields
|
|
277
582
|
}),
|
|
278
583
|
...config.hooks?.afterChange || []
|
|
279
584
|
],
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/translatedCollection.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeChangeHook,\n CollectionConfig,\n Field,\n Where,\n} from 'payload'\n\nimport { randomUUID } from 'crypto'\n\nimport type { ResolvedMultilangCollection } from '../types.js'\n\nimport { MULTILANG_SKIP_HOOK } from '../constants.js'\nimport { asDocument, getID, getStringValue } from '../lib/data.js'\n\nconst hasSkipContext = (context?: Record<string, unknown>): boolean =>\n context?.[MULTILANG_SKIP_HOOK] === true\n\nconst valuesAreEqual = (left: unknown, right: unknown): boolean => {\n if (left === right) {\n return true\n }\n\n return JSON.stringify(left) === JSON.stringify(right)\n}\n\nconst isConfiguredLanguage = (\n collection: ResolvedMultilangCollection,\n language: string | undefined,\n): boolean =>\n Boolean(\n language &&\n collection.languages.some((configuredLanguage) => configuredLanguage.code === language),\n )\n\ntype CollectionEditViews = NonNullable<\n NonNullable<NonNullable<CollectionConfig['admin']>['components']>['views']\n>['edit']\n\nconst getDuplicateLanguageIDs = async ({\n collection,\n excludeID,\n group,\n language,\n req,\n}: {\n collection: ResolvedMultilangCollection\n excludeID?: number | string\n group: string\n language: string\n req: Parameters<CollectionBeforeChangeHook>[0]['req']\n}): Promise<Array<number | string>> => {\n const and: Where[] = [\n {\n [collection.fieldNames.group]: {\n equals: group,\n },\n },\n {\n [collection.fieldNames.language]: {\n equals: language,\n },\n },\n ]\n\n if (excludeID) {\n and.push({\n id: {\n not_equals: excludeID,\n },\n })\n }\n\n const result = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 200,\n overrideAccess: true,\n req,\n where: {\n and,\n },\n })\n\n return result.docs\n .map((doc) => getID(asDocument(doc).id))\n .filter((id): id is number | string => id !== undefined)\n}\n\nexport const createTranslatedCollectionBeforeChangeHook =\n ({ collection }: { collection: ResolvedMultilangCollection }): CollectionBeforeChangeHook =>\n async ({ context, data, operation, originalDoc, req }) => {\n if (hasSkipContext(context)) {\n return data\n }\n\n const nextData = asDocument(data)\n const original = asDocument(originalDoc)\n const { group: groupField, language: languageField } = collection.fieldNames\n const originalLanguage = getStringValue(original[languageField])\n const originalLanguageIsConfigured = isConfiguredLanguage(collection, originalLanguage)\n const incomingLanguage = getStringValue(nextData[languageField])\n\n if (operation === 'update' && originalLanguage && !originalLanguageIsConfigured) {\n if (\n !incomingLanguage ||\n incomingLanguage === originalLanguage ||\n !isConfiguredLanguage(collection, incomingLanguage)\n ) {\n nextData[languageField] = ''\n }\n } else if (!incomingLanguage) {\n nextData[languageField] =\n operation === 'create'\n ? collection.defaultLanguage.code\n : originalLanguageIsConfigured\n ? originalLanguage\n : ''\n }\n\n const language = getStringValue(nextData[languageField])\n\n if (\n operation === 'update' &&\n originalLanguage &&\n originalLanguageIsConfigured &&\n language !== originalLanguage\n ) {\n throw new Error('Document language cannot be changed after creation.')\n }\n\n if (language && !isConfiguredLanguage(collection, language)) {\n throw new Error(`Language \"${language}\" is not configured for ${collection.slug}.`)\n }\n\n if (!getStringValue(nextData[groupField])) {\n const fallbackGroup = getStringValue(original[groupField])\n nextData[groupField] = fallbackGroup || randomUUID()\n }\n\n const group = getStringValue(nextData[groupField])\n\n if (language && group) {\n const currentID = operation === 'update' ? getID(original.id) : undefined\n const duplicateIDs = await getDuplicateLanguageIDs({\n collection,\n excludeID: currentID,\n group,\n language,\n req,\n })\n\n if (duplicateIDs.length > 0) {\n throw new Error(\n `A ${collection.slug} translation already exists for language \"${language}\" in this translation group.`,\n )\n }\n }\n\n return nextData\n }\n\nexport const createSynchronizedFieldsAfterChangeHook =\n ({ collection }: { collection: ResolvedMultilangCollection }): CollectionAfterChangeHook =>\n async ({ context, doc, operation, previousDoc, req }) => {\n if (\n hasSkipContext(context) ||\n operation !== 'update' ||\n collection.synchronizedFields.length === 0\n ) {\n return doc\n }\n\n const nextDoc = asDocument(doc)\n const previous = asDocument(previousDoc)\n const group = getStringValue(nextDoc[collection.fieldNames.group])\n const currentID = getID(nextDoc.id)\n\n if (!group || !currentID) {\n return doc\n }\n\n const synchronizedData = collection.synchronizedFields.reduce<Record<string, unknown>>(\n (acc, fieldName) => {\n if (fieldName in nextDoc && !valuesAreEqual(nextDoc[fieldName], previous[fieldName])) {\n acc[fieldName] = nextDoc[fieldName]\n }\n\n return acc\n },\n {},\n )\n\n if (Object.keys(synchronizedData).length === 0) {\n return doc\n }\n\n const translations = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 200,\n overrideAccess: true,\n req,\n where: {\n and: [\n {\n [collection.fieldNames.group]: {\n equals: group,\n },\n },\n {\n id: {\n not_equals: currentID,\n },\n },\n ],\n },\n })\n\n await Promise.all(\n translations.docs\n .map((translation) => getID(asDocument(translation).id))\n .filter((id): id is number | string => id !== undefined)\n .map((id) =>\n req.payload.update({\n id,\n collection: collection.slug,\n context: {\n [MULTILANG_SKIP_HOOK]: true,\n },\n data: synchronizedData,\n overrideAccess: true,\n req,\n }),\n ),\n )\n\n return doc\n }\n\nexport const createHiddenFields = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Field[] => [\n {\n name: collection.fieldNames.language,\n type: 'text',\n admin: {\n disableListColumn: true,\n hidden: true,\n },\n index: true,\n label: 'Language',\n },\n {\n name: collection.fieldNames.group,\n type: 'text',\n admin: {\n disableListColumn: true,\n hidden: true,\n },\n index: true,\n label: 'Translations',\n },\n {\n name: collection.fieldNames.meta,\n type: 'json',\n admin: {\n disableListColumn: true,\n hidden: true,\n },\n },\n {\n name: 'multilangLanguageMetabox',\n type: 'ui',\n admin: {\n components: {\n Field: '@roxxel/payload-multilang/client#LanguageMetabox',\n },\n position: 'sidebar',\n },\n },\n]\n\nexport const getLanguageColumnName = (): string => 'payloadMultilangTranslations'\n\nexport const createLanguageColumnFields = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Field[] => {\n const label = collection.languages\n .map((language) => language.flagLabel || language.code.toUpperCase())\n .join(' ')\n\n return [\n {\n name: getLanguageColumnName(),\n type: 'ui',\n admin: {\n components: {\n Cell: '@roxxel/payload-multilang/rsc#TranslationColumnCell',\n },\n disableListColumn: false,\n width: '132px',\n },\n label: label || 'Translations',\n },\n ]\n}\n\nexport const translatedCollectionMeta = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}) => ({\n defaultLanguage: collection.defaultLanguage,\n fieldNames: collection.fieldNames,\n languages: collection.languages,\n})\n\nconst getDefaultColumns = ({\n collection,\n existingDefaultColumns,\n languageColumnName,\n}: {\n collection: ResolvedMultilangCollection\n existingDefaultColumns: string[]\n languageColumnName: string\n}): string[] => {\n const hiddenMultilangColumns = new Set([\n collection.fieldNames.group,\n collection.fieldNames.language,\n collection.fieldNames.meta,\n languageColumnName,\n ])\n const visibleExistingColumns = existingDefaultColumns.filter(\n (column) => !hiddenMultilangColumns.has(column),\n )\n\n return [...visibleExistingColumns, languageColumnName]\n}\n\nexport const withTranslatedCollection = ({\n collection,\n config,\n}: {\n collection: ResolvedMultilangCollection\n config: CollectionConfig\n}): CollectionConfig => {\n const existingDefaultColumns = config.admin?.defaultColumns || []\n const languageColumnName = getLanguageColumnName()\n const existingEditViews =\n (config.admin?.components?.views?.edit as Record<string, unknown> | undefined) || {}\n const defaultColumns = getDefaultColumns({\n collection,\n existingDefaultColumns,\n languageColumnName,\n })\n\n return {\n ...config,\n admin: {\n ...config.admin,\n components: {\n ...config.admin?.components,\n beforeList: [\n ...(config.admin?.components?.beforeList || []),\n '@roxxel/payload-multilang/client#LanguageListToolbar',\n ],\n beforeListTable: config.admin?.components?.beforeListTable,\n views: {\n ...config.admin?.components?.views,\n edit: {\n ...existingEditViews,\n translations: {\n Component: '@roxxel/payload-multilang/rsc#TranslationsTab',\n path: '/translations',\n tab: {\n label: 'Translations',\n order: 80,\n },\n },\n } as CollectionEditViews,\n },\n },\n custom: {\n ...config.admin?.custom,\n payloadMultilang: translatedCollectionMeta({\n collection,\n }),\n },\n defaultColumns,\n },\n endpoints: [...(config.endpoints || [])],\n fields: [\n ...(config.fields || []),\n ...createHiddenFields({ collection }),\n ...createLanguageColumnFields({ collection }),\n ],\n hooks: {\n ...config.hooks,\n afterChange: [\n createSynchronizedFieldsAfterChangeHook({\n collection,\n }),\n ...(config.hooks?.afterChange || []),\n ],\n beforeChange: [\n createTranslatedCollectionBeforeChangeHook({\n collection,\n }),\n ...(config.hooks?.beforeChange || []),\n ],\n },\n }\n}\n"],"names":["randomUUID","MULTILANG_SKIP_HOOK","asDocument","getID","getStringValue","hasSkipContext","context","valuesAreEqual","left","right","JSON","stringify","isConfiguredLanguage","collection","language","Boolean","languages","some","configuredLanguage","code","getDuplicateLanguageIDs","excludeID","group","req","and","fieldNames","equals","push","id","not_equals","result","payload","find","slug","depth","limit","overrideAccess","where","docs","map","doc","filter","undefined","createTranslatedCollectionBeforeChangeHook","data","operation","originalDoc","nextData","original","groupField","languageField","originalLanguage","originalLanguageIsConfigured","incomingLanguage","defaultLanguage","Error","fallbackGroup","currentID","duplicateIDs","length","createSynchronizedFieldsAfterChangeHook","previousDoc","synchronizedFields","nextDoc","previous","synchronizedData","reduce","acc","fieldName","Object","keys","translations","Promise","all","translation","update","createHiddenFields","name","type","admin","disableListColumn","hidden","index","label","meta","components","Field","position","getLanguageColumnName","createLanguageColumnFields","flagLabel","toUpperCase","join","Cell","width","translatedCollectionMeta","getDefaultColumns","existingDefaultColumns","languageColumnName","hiddenMultilangColumns","Set","visibleExistingColumns","column","has","withTranslatedCollection","config","defaultColumns","existingEditViews","views","edit","beforeList","beforeListTable","Component","path","tab","order","custom","payloadMultilang","endpoints","fields","hooks","afterChange","beforeChange"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/translatedCollection.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeChangeHook,\n CollectionConfig,\n Field,\n Where,\n} from 'payload'\n\nimport { randomUUID } from 'crypto'\n\nimport type { ResolvedMultilangCollection } from '../types.js'\n\nimport { MULTILANG_SKIP_HOOK } from '../constants.js'\nimport { asDocument, getID, getStringValue } from '../lib/data.js'\n\nconst LANGUAGE_LABEL = {\n en: 'Language',\n uk: 'Мова',\n}\n\nconst TRANSLATIONS_LABEL = {\n en: 'Translations',\n uk: 'Переклади',\n}\n\ntype FieldAffectingData = { name: string } & Field\ntype SynchronizedBlock = {\n fields: SynchronizedField[]\n slug: string\n}\ntype SynchronizedField =\n | {\n blocks: SynchronizedBlock[]\n kind: 'blocks'\n name: string\n synchronizePosition: boolean\n }\n | {\n fields: SynchronizedField[]\n kind: 'array'\n name: string\n synchronizePosition: boolean\n }\n | {\n fields: SynchronizedField[]\n kind: 'group'\n name: string\n }\n | {\n kind: 'value'\n name: string\n }\ntype SynchronizedContainerField = Extract<SynchronizedField, { kind: 'array' | 'blocks' }>\n\nconst hasSkipContext = (context?: Record<string, unknown>): boolean =>\n context?.[MULTILANG_SKIP_HOOK] === true\n\nconst isObject = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value)\n\nconst toArray = (value: unknown): Record<string, unknown>[] =>\n Array.isArray(value) ? value.filter(isObject) : []\n\nconst valuesAreEqual = (left: unknown, right: unknown): boolean => {\n if (left === right) {\n return true\n }\n\n return JSON.stringify(left) === JSON.stringify(right)\n}\n\nconst fieldAffectsData = (field: Field): field is FieldAffectingData =>\n 'name' in field && typeof field.name === 'string' && field.name !== 'id' && field.type !== 'ui'\n\nconst fieldSynchronizes = (field: Field): boolean => {\n const custom = isObject(field.custom) ? field.custom : {}\n const multilang = isObject(custom.multilang) ? custom.multilang : {}\n\n return multilang.synchronize === true\n}\n\nconst fieldSynchronizesPosition = (field: Field): boolean => {\n const custom = isObject(field.custom) ? field.custom : {}\n const multilang = isObject(custom.multilang) ? custom.multilang : {}\n\n return multilang.synchronizePosition === true\n}\n\nconst hasName = (value: unknown): value is { name: string } =>\n isObject(value) && typeof value.name === 'string'\n\nconst getSynchronizedBlocks = (\n field: Field,\n inheritedSynchronize: boolean,\n): SynchronizedBlock[] => {\n if (field.type !== 'blocks') {\n return []\n }\n\n return field.blocks.flatMap((block) => {\n const fields = getSynchronizedFields(block.fields, inheritedSynchronize)\n\n if (fields.length === 0) {\n return []\n }\n\n return [\n {\n slug: block.slug,\n fields,\n },\n ]\n })\n}\n\nconst getSynchronizedTabFields = (\n field: Extract<Field, { type: 'tabs' }>,\n inheritedSynchronize: boolean,\n): SynchronizedField[] =>\n field.tabs.flatMap<SynchronizedField>((tab) => {\n const fields = getSynchronizedFields(tab.fields, inheritedSynchronize)\n\n if (fields.length === 0) {\n return []\n }\n\n if (hasName(tab)) {\n return [\n {\n name: tab.name,\n fields,\n kind: 'group',\n },\n ]\n }\n\n return fields\n })\n\nconst getSynchronizedFields = (\n fields: Field[] = [],\n inheritedSynchronize = false,\n): SynchronizedField[] =>\n fields.flatMap<SynchronizedField>((field) => {\n if (field.type === 'row' || field.type === 'collapsible') {\n return getSynchronizedFields(\n field.fields,\n inheritedSynchronize || fieldSynchronizes(field),\n )\n }\n\n if (field.type === 'tabs') {\n return getSynchronizedTabFields(field, inheritedSynchronize)\n }\n\n if (!fieldAffectsData(field)) {\n return []\n }\n\n const synchronize = inheritedSynchronize || fieldSynchronizes(field)\n\n if (field.type === 'array') {\n const fields = getSynchronizedFields(field.fields, synchronize)\n const synchronizePosition = synchronize || fieldSynchronizesPosition(field)\n\n if (!synchronizePosition && fields.length === 0) {\n return []\n }\n\n return [\n {\n name: field.name,\n fields,\n kind: 'array',\n synchronizePosition,\n },\n ]\n }\n\n if (field.type === 'blocks') {\n const blocks = getSynchronizedBlocks(field, synchronize)\n const synchronizePosition = synchronize || fieldSynchronizesPosition(field)\n\n if (!synchronizePosition && blocks.length === 0) {\n return []\n }\n\n return [\n {\n name: field.name,\n blocks,\n kind: 'blocks',\n synchronizePosition,\n },\n ]\n }\n\n if (field.type === 'group') {\n const fields = getSynchronizedFields(field.fields, synchronize)\n\n if (fields.length === 0) {\n return []\n }\n\n return [\n {\n name: field.name,\n fields,\n kind: 'group',\n },\n ]\n }\n\n if (!synchronize) {\n return []\n }\n\n return [\n {\n name: field.name,\n kind: 'value',\n },\n ]\n })\n\nconst getRowKey = (row: Record<string, unknown>, index: number): string => {\n const id = getID(row.id)\n\n return id === undefined ? `index:${index}` : `id:${String(id)}`\n}\n\nconst getShellSignature = (value: unknown, field: SynchronizedField): string =>\n JSON.stringify(\n toArray(value).map((row, index) => ({\n blockName: field.kind === 'blocks' ? getStringValue(row.blockName) : undefined,\n blockType: field.kind === 'blocks' ? getStringValue(row.blockType) : undefined,\n key: getRowKey(row, index),\n })),\n )\n\nconst positionChanged = (\n field: SynchronizedField,\n source: Record<string, unknown>,\n previous: Record<string, unknown>,\n): boolean => {\n if (\n (field.kind !== 'array' && field.kind !== 'blocks') ||\n !field.synchronizePosition ||\n !(field.name in source)\n ) {\n return false\n }\n\n return (\n getShellSignature(source[field.name], field) !==\n getShellSignature(previous[field.name], field)\n )\n}\n\nconst getBlockFieldsForRow = (\n field: SynchronizedField,\n sourceRow: Record<string, unknown>,\n): SynchronizedField[] => {\n if (field.kind !== 'blocks') {\n return []\n }\n\n const blockType = getStringValue(sourceRow.blockType)\n\n return field.blocks?.find((block) => block.slug === blockType)?.fields || []\n}\n\nconst createSynchronizedRow = (\n sourceRow: Record<string, unknown>,\n previousRow: Record<string, unknown> | undefined,\n targetRow: Record<string, unknown> | undefined,\n field: SynchronizedContainerField,\n): Record<string, unknown> => {\n const row = targetRow ? { ...targetRow } : {}\n\n if (field.kind === 'blocks') {\n row.id = randomUUID()\n }\n\n if (field.synchronizePosition && field.kind === 'blocks' && 'blockType' in sourceRow) {\n row.blockType = sourceRow.blockType\n }\n\n if (field.synchronizePosition && field.kind === 'blocks') {\n if ('blockName' in sourceRow) {\n row.blockName = sourceRow.blockName\n } else {\n delete row.blockName\n }\n }\n\n const fields =\n field.kind === 'array' ? field.fields : getBlockFieldsForRow(field, sourceRow)\n\n return synchronizeData({\n fields,\n previous: previousRow || {},\n source: sourceRow,\n target: row,\n })\n}\n\nconst synchronizeContainerValue = ({\n field,\n previousSourceValue,\n sourceValue,\n targetValue,\n}: {\n field: SynchronizedContainerField\n previousSourceValue: unknown\n sourceValue: unknown\n targetValue: unknown\n}): unknown[] => {\n const targetRows = toArray(targetValue)\n const previousSourceRows = toArray(previousSourceValue)\n const sourceRows = toArray(sourceValue)\n\n if (!field.synchronizePosition) {\n const sourceRowsByPreviousKey = new Map(\n sourceRows.map((row, index) => {\n const previousRow = previousSourceRows[index]\n const key = previousRow ? getRowKey(previousRow, index) : getRowKey(row, index)\n\n return [key, row] as const\n }),\n )\n\n return targetRows.map((targetRow, index) => {\n const previousRow = previousSourceRows[index]\n const sourceRow =\n (previousRow && sourceRowsByPreviousKey.get(getRowKey(previousRow, index))) ||\n sourceRows[index]\n\n return sourceRow\n ? createSynchronizedRow(sourceRow, previousRow, targetRow, field)\n : { ...targetRow }\n })\n }\n\n const previousSourceIndexesByKey = new Map(\n previousSourceRows.map((row, index) => [getRowKey(row, index), index] as const),\n )\n\n return sourceRows.map((sourceRow, index) => {\n const previousIndex = previousSourceIndexesByKey.get(getRowKey(sourceRow, index))\n\n return createSynchronizedRow(\n sourceRow,\n previousIndex === undefined ? undefined : previousSourceRows[previousIndex],\n previousIndex === undefined ? undefined : targetRows[previousIndex],\n field,\n )\n })\n}\n\nconst descriptorChanged = ({\n field,\n previous,\n source,\n}: {\n field: SynchronizedField\n previous: Record<string, unknown>\n source: Record<string, unknown>\n}): boolean => {\n if (field.kind === 'value') {\n return !valuesAreEqual(source[field.name], previous[field.name])\n }\n\n if (field.kind === 'group') {\n return descriptorsChanged({\n fields: field.fields,\n previous: asDocument(previous[field.name]),\n source: asDocument(source[field.name]),\n })\n }\n\n if (!(field.name in source)) {\n return false\n }\n\n if (positionChanged(field, source, previous)) {\n return true\n }\n\n const previousRows = toArray(previous[field.name])\n const previousRowsByKey = new Map(\n previousRows.map((row, index) => [getRowKey(row, index), row] as const),\n )\n\n return toArray(source[field.name]).some((sourceRow, index) => {\n const previousRow = previousRowsByKey.get(getRowKey(sourceRow, index)) || previousRows[index]\n const fields =\n field.kind === 'array' ? field.fields : getBlockFieldsForRow(field, sourceRow)\n\n return descriptorsChanged({\n fields,\n previous: previousRow || {},\n source: sourceRow,\n })\n })\n}\n\nconst descriptorsChanged = ({\n fields,\n previous,\n source,\n}: {\n fields: SynchronizedField[]\n previous: Record<string, unknown>\n source: Record<string, unknown>\n}): boolean =>\n fields.some((field) =>\n descriptorChanged({\n field,\n previous,\n source,\n }),\n )\n\nconst synchronizeData = ({\n fields,\n previous,\n source,\n target,\n}: {\n fields: SynchronizedField[]\n previous: Record<string, unknown>\n source: Record<string, unknown>\n target: Record<string, unknown>\n}): Record<string, unknown> =>\n fields.reduce<Record<string, unknown>>((acc, field) => {\n if (field.kind === 'value') {\n if (field.name in source) {\n acc[field.name] = source[field.name]\n } else {\n delete acc[field.name]\n }\n\n return acc\n }\n\n if (field.kind === 'group') {\n if (field.name in source) {\n const value = synchronizeData({\n fields: field.fields,\n previous: asDocument(previous[field.name]),\n source: asDocument(source[field.name]),\n target: asDocument(acc[field.name]),\n })\n\n if (!valuesAreEqual(value, acc[field.name])) {\n acc[field.name] = value\n }\n } else {\n delete acc[field.name]\n }\n\n return acc\n }\n\n const value = synchronizeContainerValue({\n field,\n previousSourceValue: previous[field.name],\n sourceValue: source[field.name],\n targetValue: target[field.name],\n })\n\n if (!valuesAreEqual(value, target[field.name])) {\n acc[field.name] = value\n }\n\n return acc\n }, { ...target })\n\nconst getSynchronizedDataForTranslation = ({\n fields,\n nextDoc,\n previous,\n translation,\n}: {\n fields: SynchronizedField[]\n nextDoc: Record<string, unknown>\n previous: Record<string, unknown>\n translation: Record<string, unknown>\n}): Record<string, unknown> => {\n const synchronized = synchronizeData({\n fields,\n previous,\n source: nextDoc,\n target: translation,\n })\n\n return fields.reduce<Record<string, unknown>>((acc, field) => {\n if (!valuesAreEqual(synchronized[field.name], translation[field.name])) {\n acc[field.name] = synchronized[field.name]\n }\n\n return acc\n }, {})\n}\n\nconst isConfiguredLanguage = (\n collection: ResolvedMultilangCollection,\n language: string | undefined,\n): boolean =>\n Boolean(\n language &&\n collection.languages.some((configuredLanguage) => configuredLanguage.code === language),\n )\n\ntype CollectionEditViews = NonNullable<\n NonNullable<NonNullable<CollectionConfig['admin']>['components']>['views']\n>['edit']\n\nconst getDuplicateLanguageIDs = async ({\n collection,\n excludeID,\n group,\n language,\n req,\n}: {\n collection: ResolvedMultilangCollection\n excludeID?: number | string\n group: string\n language: string\n req: Parameters<CollectionBeforeChangeHook>[0]['req']\n}): Promise<Array<number | string>> => {\n const and: Where[] = [\n {\n [collection.fieldNames.group]: {\n equals: group,\n },\n },\n {\n [collection.fieldNames.language]: {\n equals: language,\n },\n },\n ]\n\n if (excludeID) {\n and.push({\n id: {\n not_equals: excludeID,\n },\n })\n }\n\n const result = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 200,\n overrideAccess: true,\n req,\n where: {\n and,\n },\n })\n\n return result.docs\n .map((doc) => getID(asDocument(doc).id))\n .filter((id): id is number | string => id !== undefined)\n}\n\nexport const createTranslatedCollectionBeforeChangeHook =\n ({ collection }: { collection: ResolvedMultilangCollection }): CollectionBeforeChangeHook =>\n async ({ context, data, operation, originalDoc, req }) => {\n if (hasSkipContext(context)) {\n return data\n }\n\n const nextData = asDocument(data)\n const original = asDocument(originalDoc)\n const { group: groupField, language: languageField } = collection.fieldNames\n const originalLanguage = getStringValue(original[languageField])\n const originalLanguageIsConfigured = isConfiguredLanguage(collection, originalLanguage)\n const incomingLanguage = getStringValue(nextData[languageField])\n\n if (operation === 'update' && originalLanguage && !originalLanguageIsConfigured) {\n if (\n !incomingLanguage ||\n incomingLanguage === originalLanguage ||\n !isConfiguredLanguage(collection, incomingLanguage)\n ) {\n nextData[languageField] = ''\n }\n } else if (!incomingLanguage) {\n nextData[languageField] =\n operation === 'create'\n ? collection.defaultLanguage.code\n : originalLanguageIsConfigured\n ? originalLanguage\n : ''\n }\n\n const language = getStringValue(nextData[languageField])\n\n if (\n operation === 'update' &&\n originalLanguage &&\n originalLanguageIsConfigured &&\n language !== originalLanguage\n ) {\n throw new Error('Document language cannot be changed after creation.')\n }\n\n if (language && !isConfiguredLanguage(collection, language)) {\n throw new Error(`Language \"${language}\" is not configured for ${collection.slug}.`)\n }\n\n if (!getStringValue(nextData[groupField])) {\n const fallbackGroup = getStringValue(original[groupField])\n nextData[groupField] = fallbackGroup || randomUUID()\n }\n\n const group = getStringValue(nextData[groupField])\n\n if (language && group) {\n const currentID = operation === 'update' ? getID(original.id) : undefined\n const duplicateIDs = await getDuplicateLanguageIDs({\n collection,\n excludeID: currentID,\n group,\n language,\n req,\n })\n\n if (duplicateIDs.length > 0) {\n throw new Error(\n `A ${collection.slug} translation already exists for language \"${language}\" in this translation group.`,\n )\n }\n }\n\n return nextData\n }\n\nexport const createSynchronizedFieldsAfterChangeHook =\n ({\n collection,\n fields,\n }: {\n collection: ResolvedMultilangCollection\n fields?: Field[]\n }): CollectionAfterChangeHook =>\n async ({ context, doc, operation, previousDoc, req }) => {\n const synchronizedFields = getSynchronizedFields(fields)\n\n if (hasSkipContext(context) || operation !== 'update' || synchronizedFields.length === 0) {\n return doc\n }\n\n const nextDoc = asDocument(doc)\n const previous = asDocument(previousDoc)\n const group = getStringValue(nextDoc[collection.fieldNames.group])\n const currentID = getID(nextDoc.id)\n\n if (!group || !currentID) {\n return doc\n }\n\n const changedFields = synchronizedFields.filter((field) =>\n descriptorChanged({\n field,\n previous,\n source: nextDoc,\n }),\n )\n\n if (changedFields.length === 0) {\n return doc\n }\n\n const translations = await req.payload.find({\n collection: collection.slug,\n depth: 0,\n limit: 200,\n overrideAccess: true,\n req,\n where: {\n and: [\n {\n [collection.fieldNames.group]: {\n equals: group,\n },\n },\n {\n id: {\n not_equals: currentID,\n },\n },\n ],\n },\n })\n\n await Promise.all(\n translations.docs\n .map((translation) => {\n const translationDoc = asDocument(translation)\n const id = getID(translationDoc.id)\n\n if (id === undefined) {\n return undefined\n }\n\n const synchronizedData = getSynchronizedDataForTranslation({\n fields: changedFields,\n nextDoc,\n previous,\n translation: translationDoc,\n })\n\n if (Object.keys(synchronizedData).length === 0) {\n return undefined\n }\n\n return {\n id,\n data: synchronizedData,\n }\n })\n .filter(\n (update): update is { data: Record<string, unknown>; id: number | string } =>\n update !== undefined,\n )\n .map(({ id, data }) =>\n req.payload.update({\n id,\n collection: collection.slug,\n context: {\n [MULTILANG_SKIP_HOOK]: true,\n },\n data,\n overrideAccess: true,\n req,\n }),\n ),\n )\n\n return doc\n }\n\nexport const createHiddenFields = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Field[] => [\n {\n name: collection.fieldNames.language,\n type: 'text',\n admin: {\n disableListColumn: true,\n hidden: true,\n },\n index: true,\n label: LANGUAGE_LABEL,\n },\n {\n name: collection.fieldNames.group,\n type: 'text',\n admin: {\n disableListColumn: true,\n hidden: true,\n },\n index: true,\n label: TRANSLATIONS_LABEL,\n },\n {\n name: collection.fieldNames.meta,\n type: 'json',\n admin: {\n disableListColumn: true,\n hidden: true,\n },\n },\n {\n name: 'multilangLanguageMetabox',\n type: 'ui',\n admin: {\n components: {\n Field: '@roxxel/payload-multilang/client#LanguageMetabox',\n },\n position: 'sidebar',\n },\n },\n]\n\nexport const getLanguageColumnName = (): string => 'payloadMultilangTranslations'\n\nexport const createLanguageColumnFields = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Field[] => {\n const label = collection.languages\n .map((language) => language.flagLabel || language.code.toUpperCase())\n .join(' ')\n\n return [\n {\n name: getLanguageColumnName(),\n type: 'ui',\n admin: {\n components: {\n Cell: '@roxxel/payload-multilang/rsc#TranslationColumnCell',\n },\n disableListColumn: false,\n width: '132px',\n },\n label: label || TRANSLATIONS_LABEL,\n },\n ]\n}\n\nexport const translatedCollectionMeta = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}) => ({\n defaultLanguage: collection.defaultLanguage,\n fieldNames: collection.fieldNames,\n languages: collection.languages,\n})\n\nconst getDefaultColumns = ({\n collection,\n existingDefaultColumns,\n languageColumnName,\n}: {\n collection: ResolvedMultilangCollection\n existingDefaultColumns: string[]\n languageColumnName: string\n}): string[] => {\n const hiddenMultilangColumns = new Set([\n collection.fieldNames.group,\n collection.fieldNames.language,\n collection.fieldNames.meta,\n languageColumnName,\n ])\n const visibleExistingColumns = existingDefaultColumns.filter(\n (column) => !hiddenMultilangColumns.has(column),\n )\n\n return [...visibleExistingColumns, languageColumnName]\n}\n\nexport const withTranslatedCollection = ({\n collection,\n config,\n}: {\n collection: ResolvedMultilangCollection\n config: CollectionConfig\n}): CollectionConfig => {\n const existingDefaultColumns = config.admin?.defaultColumns || []\n const languageColumnName = getLanguageColumnName()\n const existingEditViews =\n (config.admin?.components?.views?.edit as Record<string, unknown> | undefined) || {}\n const defaultColumns = getDefaultColumns({\n collection,\n existingDefaultColumns,\n languageColumnName,\n })\n\n return {\n ...config,\n admin: {\n ...config.admin,\n components: {\n ...config.admin?.components,\n beforeList: [\n ...(config.admin?.components?.beforeList || []),\n '@roxxel/payload-multilang/client#LanguageListToolbar',\n ],\n beforeListTable: config.admin?.components?.beforeListTable,\n views: {\n ...config.admin?.components?.views,\n edit: {\n ...existingEditViews,\n translations: {\n Component: '@roxxel/payload-multilang/rsc#TranslationsTab',\n path: '/translations',\n tab: {\n label: ({ t }) => t('payloadMultilang:translations'),\n order: 80,\n },\n },\n } as CollectionEditViews,\n },\n },\n custom: {\n ...config.admin?.custom,\n payloadMultilang: translatedCollectionMeta({\n collection,\n }),\n },\n defaultColumns,\n },\n endpoints: [...(config.endpoints || [])],\n fields: [\n ...(config.fields || []),\n ...createHiddenFields({ collection }),\n ...createLanguageColumnFields({ collection }),\n ],\n hooks: {\n ...config.hooks,\n afterChange: [\n createSynchronizedFieldsAfterChangeHook({\n collection,\n fields: config.fields,\n }),\n ...(config.hooks?.afterChange || []),\n ],\n beforeChange: [\n createTranslatedCollectionBeforeChangeHook({\n collection,\n }),\n ...(config.hooks?.beforeChange || []),\n ],\n },\n }\n}\n"],"names":["randomUUID","MULTILANG_SKIP_HOOK","asDocument","getID","getStringValue","LANGUAGE_LABEL","en","uk","TRANSLATIONS_LABEL","hasSkipContext","context","isObject","value","Array","isArray","toArray","filter","valuesAreEqual","left","right","JSON","stringify","fieldAffectsData","field","name","type","fieldSynchronizes","custom","multilang","synchronize","fieldSynchronizesPosition","synchronizePosition","hasName","getSynchronizedBlocks","inheritedSynchronize","blocks","flatMap","block","fields","getSynchronizedFields","length","slug","getSynchronizedTabFields","tabs","tab","kind","getRowKey","row","index","id","undefined","String","getShellSignature","map","blockName","blockType","key","positionChanged","source","previous","getBlockFieldsForRow","sourceRow","find","createSynchronizedRow","previousRow","targetRow","synchronizeData","target","synchronizeContainerValue","previousSourceValue","sourceValue","targetValue","targetRows","previousSourceRows","sourceRows","sourceRowsByPreviousKey","Map","get","previousSourceIndexesByKey","previousIndex","descriptorChanged","descriptorsChanged","previousRows","previousRowsByKey","some","reduce","acc","getSynchronizedDataForTranslation","nextDoc","translation","synchronized","isConfiguredLanguage","collection","language","Boolean","languages","configuredLanguage","code","getDuplicateLanguageIDs","excludeID","group","req","and","fieldNames","equals","push","not_equals","result","payload","depth","limit","overrideAccess","where","docs","doc","createTranslatedCollectionBeforeChangeHook","data","operation","originalDoc","nextData","original","groupField","languageField","originalLanguage","originalLanguageIsConfigured","incomingLanguage","defaultLanguage","Error","fallbackGroup","currentID","duplicateIDs","createSynchronizedFieldsAfterChangeHook","previousDoc","synchronizedFields","changedFields","translations","Promise","all","translationDoc","synchronizedData","Object","keys","update","createHiddenFields","admin","disableListColumn","hidden","label","meta","components","Field","position","getLanguageColumnName","createLanguageColumnFields","flagLabel","toUpperCase","join","Cell","width","translatedCollectionMeta","getDefaultColumns","existingDefaultColumns","languageColumnName","hiddenMultilangColumns","Set","visibleExistingColumns","column","has","withTranslatedCollection","config","defaultColumns","existingEditViews","views","edit","beforeList","beforeListTable","Component","path","t","order","payloadMultilang","endpoints","hooks","afterChange","beforeChange"],"mappings":"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"}
|
|
@@ -1,3 +1,7 @@
|
|
|
1
|
+
const LOCALIZED_CONTENT_LABEL = {
|
|
2
|
+
en: 'Localized content',
|
|
3
|
+
uk: 'Локалізований вміст'
|
|
4
|
+
};
|
|
1
5
|
const withOptionalRequired = (field, required)=>{
|
|
2
6
|
if (required || !('required' in field)) {
|
|
3
7
|
return field;
|
|
@@ -42,7 +46,7 @@ export const translatedGlobalMeta = ({ global })=>({
|
|
|
42
46
|
});
|
|
43
47
|
export const createGlobalLanguageTabsField = ({ config, global })=>({
|
|
44
48
|
type: 'tabs',
|
|
45
|
-
label: global.label,
|
|
49
|
+
label: global.label === 'Localized content' ? LOCALIZED_CONTENT_LABEL : global.label,
|
|
46
50
|
tabs: global.languages.map((language)=>({
|
|
47
51
|
name: language.code,
|
|
48
52
|
fields: config.fields.map((field)=>cloneField(field, language.code === global.defaultLanguage.code)),
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/hooks/translatedGlobal.ts"],"sourcesContent":["import type { Field, GlobalConfig, Tab } from 'payload'\n\nimport type { ResolvedMultilangGlobal } from '../types.js'\n\nconst withOptionalRequired = (field: Field, required: boolean): Field => {\n if (required || !('required' in field)) {\n return field\n }\n\n return {\n ...field,\n required: false,\n } as Field\n}\n\nconst cloneField = (field: Field, required: boolean): Field => {\n if (field.type === 'tabs') {\n return withOptionalRequired(\n {\n ...field,\n tabs: field.tabs.map((tab) => ({\n ...tab,\n fields: tab.fields.map((tabField) => cloneField(tabField, required)),\n })),\n },\n required,\n )\n }\n\n if ('fields' in field && Array.isArray(field.fields)) {\n return withOptionalRequired(\n {\n ...field,\n fields: field.fields.map((childField) => cloneField(childField, required)),\n },\n required,\n )\n }\n\n if (field.type === 'blocks') {\n return withOptionalRequired(\n {\n ...field,\n blocks: field.blocks.map((block) => ({\n ...block,\n fields: block.fields.map((blockField) => cloneField(blockField, required)),\n })),\n },\n required,\n )\n }\n\n return withOptionalRequired(\n {\n ...field,\n },\n required,\n )\n}\n\nexport const translatedGlobalMeta = ({\n global,\n}: {\n global: ResolvedMultilangGlobal\n}) => ({\n defaultLanguage: global.defaultLanguage,\n languages: global.languages,\n})\n\nexport const createGlobalLanguageTabsField = ({\n config,\n global,\n}: {\n config: GlobalConfig\n global: ResolvedMultilangGlobal\n}): Field => ({\n type: 'tabs',\n label: global.label,\n tabs: global.languages.map(\n (language): Tab => ({\n name: language.code,\n fields: config.fields.map((field) =>\n cloneField(field, language.code === global.defaultLanguage.code),\n ),\n label: language.flagLabel ? `${language.flagLabel} ${language.name}` : language.name,\n }),\n ),\n})\n\nexport const withTranslatedGlobal = ({\n config,\n global,\n}: {\n config: GlobalConfig\n global: ResolvedMultilangGlobal\n}): GlobalConfig => ({\n ...config,\n admin: {\n ...config.admin,\n custom: {\n ...config.admin?.custom,\n payloadMultilang: translatedGlobalMeta({\n global,\n }),\n },\n },\n fields: [\n createGlobalLanguageTabsField({\n config,\n global,\n }),\n ],\n})\n"],"names":["withOptionalRequired","field","required","cloneField","type","tabs","map","tab","fields","tabField","Array","isArray","childField","blocks","block","blockField","translatedGlobalMeta","global","defaultLanguage","languages","createGlobalLanguageTabsField","config","label","language","name","code","flagLabel","withTranslatedGlobal","admin","custom","payloadMultilang"],"mappings":"AAIA,MAAMA,uBAAuB,CAACC,OAAcC;IAC1C,IAAIA,YAAY,CAAE,CAAA,cAAcD,KAAI,GAAI;QACtC,OAAOA;IACT;IAEA,OAAO;QACL,GAAGA,KAAK;QACRC,UAAU;IACZ;AACF;AAEA,MAAMC,aAAa,CAACF,OAAcC;IAChC,IAAID,MAAMG,IAAI,KAAK,QAAQ;QACzB,OAAOJ,qBACL;YACE,GAAGC,KAAK;YACRI,MAAMJ,MAAMI,IAAI,CAACC,GAAG,CAAC,CAACC,MAAS,CAAA;oBAC7B,GAAGA,GAAG;oBACNC,QAAQD,IAAIC,MAAM,CAACF,GAAG,CAAC,CAACG,WAAaN,WAAWM,UAAUP;gBAC5D,CAAA;QACF,GACAA;IAEJ;IAEA,IAAI,YAAYD,SAASS,MAAMC,OAAO,CAACV,MAAMO,MAAM,GAAG;QACpD,OAAOR,qBACL;YACE,GAAGC,KAAK;YACRO,QAAQP,MAAMO,MAAM,CAACF,GAAG,CAAC,CAACM,aAAeT,WAAWS,YAAYV;QAClE,GACAA;IAEJ;IAEA,IAAID,MAAMG,IAAI,KAAK,UAAU;QAC3B,OAAOJ,qBACL;YACE,GAAGC,KAAK;YACRY,QAAQZ,MAAMY,MAAM,CAACP,GAAG,CAAC,CAACQ,QAAW,CAAA;oBACnC,GAAGA,KAAK;oBACRN,QAAQM,MAAMN,MAAM,CAACF,GAAG,CAAC,CAACS,aAAeZ,WAAWY,YAAYb;gBAClE,CAAA;QACF,GACAA;IAEJ;IAEA,OAAOF,qBACL;QACE,GAAGC,KAAK;IACV,GACAC;AAEJ;AAEA,OAAO,MAAMc,uBAAuB,CAAC,EACnCC,MAAM,EAGP,GAAM,CAAA;QACLC,iBAAiBD,OAAOC,eAAe;QACvCC,WAAWF,OAAOE,SAAS;IAC7B,CAAA,EAAE;AAEF,OAAO,MAAMC,gCAAgC,CAAC,EAC5CC,MAAM,EACNJ,MAAM,EAIP,GAAa,CAAA;QACZb,MAAM;QACNkB,
|
|
1
|
+
{"version":3,"sources":["../../src/hooks/translatedGlobal.ts"],"sourcesContent":["import type { Field, GlobalConfig, Tab } from 'payload'\n\nimport type { ResolvedMultilangGlobal } from '../types.js'\n\nconst LOCALIZED_CONTENT_LABEL = {\n en: 'Localized content',\n uk: 'Локалізований вміст',\n}\n\nconst withOptionalRequired = (field: Field, required: boolean): Field => {\n if (required || !('required' in field)) {\n return field\n }\n\n return {\n ...field,\n required: false,\n } as Field\n}\n\nconst cloneField = (field: Field, required: boolean): Field => {\n if (field.type === 'tabs') {\n return withOptionalRequired(\n {\n ...field,\n tabs: field.tabs.map((tab) => ({\n ...tab,\n fields: tab.fields.map((tabField) => cloneField(tabField, required)),\n })),\n },\n required,\n )\n }\n\n if ('fields' in field && Array.isArray(field.fields)) {\n return withOptionalRequired(\n {\n ...field,\n fields: field.fields.map((childField) => cloneField(childField, required)),\n },\n required,\n )\n }\n\n if (field.type === 'blocks') {\n return withOptionalRequired(\n {\n ...field,\n blocks: field.blocks.map((block) => ({\n ...block,\n fields: block.fields.map((blockField) => cloneField(blockField, required)),\n })),\n },\n required,\n )\n }\n\n return withOptionalRequired(\n {\n ...field,\n },\n required,\n )\n}\n\nexport const translatedGlobalMeta = ({\n global,\n}: {\n global: ResolvedMultilangGlobal\n}) => ({\n defaultLanguage: global.defaultLanguage,\n languages: global.languages,\n})\n\nexport const createGlobalLanguageTabsField = ({\n config,\n global,\n}: {\n config: GlobalConfig\n global: ResolvedMultilangGlobal\n}): Field => ({\n type: 'tabs',\n label:\n global.label === 'Localized content'\n ? LOCALIZED_CONTENT_LABEL\n : global.label,\n tabs: global.languages.map(\n (language): Tab => ({\n name: language.code,\n fields: config.fields.map((field) =>\n cloneField(field, language.code === global.defaultLanguage.code),\n ),\n label: language.flagLabel ? `${language.flagLabel} ${language.name}` : language.name,\n }),\n ),\n})\n\nexport const withTranslatedGlobal = ({\n config,\n global,\n}: {\n config: GlobalConfig\n global: ResolvedMultilangGlobal\n}): GlobalConfig => ({\n ...config,\n admin: {\n ...config.admin,\n custom: {\n ...config.admin?.custom,\n payloadMultilang: translatedGlobalMeta({\n global,\n }),\n },\n },\n fields: [\n createGlobalLanguageTabsField({\n config,\n global,\n }),\n ],\n})\n"],"names":["LOCALIZED_CONTENT_LABEL","en","uk","withOptionalRequired","field","required","cloneField","type","tabs","map","tab","fields","tabField","Array","isArray","childField","blocks","block","blockField","translatedGlobalMeta","global","defaultLanguage","languages","createGlobalLanguageTabsField","config","label","language","name","code","flagLabel","withTranslatedGlobal","admin","custom","payloadMultilang"],"mappings":"AAIA,MAAMA,0BAA0B;IAC9BC,IAAI;IACJC,IAAI;AACN;AAEA,MAAMC,uBAAuB,CAACC,OAAcC;IAC1C,IAAIA,YAAY,CAAE,CAAA,cAAcD,KAAI,GAAI;QACtC,OAAOA;IACT;IAEA,OAAO;QACL,GAAGA,KAAK;QACRC,UAAU;IACZ;AACF;AAEA,MAAMC,aAAa,CAACF,OAAcC;IAChC,IAAID,MAAMG,IAAI,KAAK,QAAQ;QACzB,OAAOJ,qBACL;YACE,GAAGC,KAAK;YACRI,MAAMJ,MAAMI,IAAI,CAACC,GAAG,CAAC,CAACC,MAAS,CAAA;oBAC7B,GAAGA,GAAG;oBACNC,QAAQD,IAAIC,MAAM,CAACF,GAAG,CAAC,CAACG,WAAaN,WAAWM,UAAUP;gBAC5D,CAAA;QACF,GACAA;IAEJ;IAEA,IAAI,YAAYD,SAASS,MAAMC,OAAO,CAACV,MAAMO,MAAM,GAAG;QACpD,OAAOR,qBACL;YACE,GAAGC,KAAK;YACRO,QAAQP,MAAMO,MAAM,CAACF,GAAG,CAAC,CAACM,aAAeT,WAAWS,YAAYV;QAClE,GACAA;IAEJ;IAEA,IAAID,MAAMG,IAAI,KAAK,UAAU;QAC3B,OAAOJ,qBACL;YACE,GAAGC,KAAK;YACRY,QAAQZ,MAAMY,MAAM,CAACP,GAAG,CAAC,CAACQ,QAAW,CAAA;oBACnC,GAAGA,KAAK;oBACRN,QAAQM,MAAMN,MAAM,CAACF,GAAG,CAAC,CAACS,aAAeZ,WAAWY,YAAYb;gBAClE,CAAA;QACF,GACAA;IAEJ;IAEA,OAAOF,qBACL;QACE,GAAGC,KAAK;IACV,GACAC;AAEJ;AAEA,OAAO,MAAMc,uBAAuB,CAAC,EACnCC,MAAM,EAGP,GAAM,CAAA;QACLC,iBAAiBD,OAAOC,eAAe;QACvCC,WAAWF,OAAOE,SAAS;IAC7B,CAAA,EAAE;AAEF,OAAO,MAAMC,gCAAgC,CAAC,EAC5CC,MAAM,EACNJ,MAAM,EAIP,GAAa,CAAA;QACZb,MAAM;QACNkB,OACEL,OAAOK,KAAK,KAAK,sBACbzB,0BACAoB,OAAOK,KAAK;QAClBjB,MAAMY,OAAOE,SAAS,CAACb,GAAG,CACxB,CAACiB,WAAmB,CAAA;gBAClBC,MAAMD,SAASE,IAAI;gBACnBjB,QAAQa,OAAOb,MAAM,CAACF,GAAG,CAAC,CAACL,QACzBE,WAAWF,OAAOsB,SAASE,IAAI,KAAKR,OAAOC,eAAe,CAACO,IAAI;gBAEjEH,OAAOC,SAASG,SAAS,GAAG,GAAGH,SAASG,SAAS,CAAC,CAAC,EAAEH,SAASC,IAAI,EAAE,GAAGD,SAASC,IAAI;YACtF,CAAA;IAEJ,CAAA,EAAE;AAEF,OAAO,MAAMG,uBAAuB,CAAC,EACnCN,MAAM,EACNJ,MAAM,EAIP,GAAoB,CAAA;QACnB,GAAGI,MAAM;QACTO,OAAO;YACL,GAAGP,OAAOO,KAAK;YACfC,QAAQ;gBACN,GAAGR,OAAOO,KAAK,EAAEC,MAAM;gBACvBC,kBAAkBd,qBAAqB;oBACrCC;gBACF;YACF;QACF;QACAT,QAAQ;YACNY,8BAA8B;gBAC5BC;gBACAJ;YACF;SACD;IACH,CAAA,EAAE"}
|
package/dist/index.d.ts
CHANGED
|
@@ -3,5 +3,6 @@ import type { PayloadMultilangConfig } from './types.js';
|
|
|
3
3
|
export { DEFAULT_FIELD_NAMES, MULTILANG_GROUP_FIELD, MULTILANG_LANGUAGE_FIELD, MULTILANG_META_FIELD, } from './constants.js';
|
|
4
4
|
export { createMultilangHelpers, findGlobalByLanguageWithPayload, getDocumentTranslationsWithPayload, getDocumentTranslationWithPayload, getGroupTranslationsWithPayload, getMultilangDocumentLanguage, localizedSlugQuery, updateGlobalByLanguageWithPayload, withLanguage, } from './lib/data.js';
|
|
5
5
|
export type { FindGlobalByLanguageArgs, GetDocumentTranslationArgs, GetDocumentTranslationsArgs, LocalizedSlugQuery, LocalizedSlugQueryArgs, LocalizedSlugQueryStatus, MultilangDocumentLanguageArgs, MultilangHelpers, PayloadFactory, UpdateGlobalByLanguageArgs, } from './lib/data.js';
|
|
6
|
+
export { type PayloadMultilangTranslationKey, payloadMultilangTranslations, type PayloadMultilangTranslations, } from './translations.js';
|
|
6
7
|
export type { MultilangCollectionOptions, MultilangFieldNames, MultilangGlobalOptions, MultilangLanguage, PayloadMultilangConfig, ResolvedMultilangGlobal, TranslationMap, TranslationState, } from './types.js';
|
|
7
8
|
export declare const payloadMultilang: (pluginOptions?: PayloadMultilangConfig) => Plugin;
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,28 @@ import { createTranslationEndpoints } from './endpoints/translations.js';
|
|
|
2
2
|
import { withTranslatedCollection } from './hooks/translatedCollection.js';
|
|
3
3
|
import { withTranslatedGlobal } from './hooks/translatedGlobal.js';
|
|
4
4
|
import { getCollectionConfig, getGlobalConfig, sanitizePluginConfig } from './lib/config.js';
|
|
5
|
+
import { payloadMultilangTranslations } from './translations.js';
|
|
5
6
|
export { DEFAULT_FIELD_NAMES, MULTILANG_GROUP_FIELD, MULTILANG_LANGUAGE_FIELD, MULTILANG_META_FIELD } from './constants.js';
|
|
6
7
|
export { createMultilangHelpers, findGlobalByLanguageWithPayload, getDocumentTranslationsWithPayload, getDocumentTranslationWithPayload, getGroupTranslationsWithPayload, getMultilangDocumentLanguage, localizedSlugQuery, updateGlobalByLanguageWithPayload, withLanguage } from './lib/data.js';
|
|
8
|
+
export { payloadMultilangTranslations } from './translations.js';
|
|
9
|
+
const isRecord = (value)=>Boolean(value) && typeof value === 'object' && !Array.isArray(value);
|
|
10
|
+
const mergeTranslations = (base, override)=>{
|
|
11
|
+
const output = {
|
|
12
|
+
...base
|
|
13
|
+
};
|
|
14
|
+
Object.entries(override).forEach(([key, value])=>{
|
|
15
|
+
const existing = output[key];
|
|
16
|
+
output[key] = isRecord(existing) && isRecord(value) ? mergeTranslations(existing, value) : value;
|
|
17
|
+
});
|
|
18
|
+
return output;
|
|
19
|
+
};
|
|
20
|
+
const withPluginTranslations = (config)=>({
|
|
21
|
+
...config,
|
|
22
|
+
i18n: {
|
|
23
|
+
...config.i18n,
|
|
24
|
+
translations: mergeTranslations(payloadMultilangTranslations, config.i18n?.translations || {})
|
|
25
|
+
}
|
|
26
|
+
});
|
|
7
27
|
export const payloadMultilang = (pluginOptions = {
|
|
8
28
|
languages: []
|
|
9
29
|
})=>(config)=>{
|
|
@@ -46,7 +66,7 @@ export const payloadMultilang = (pluginOptions = {
|
|
|
46
66
|
global: translatedGlobal
|
|
47
67
|
});
|
|
48
68
|
});
|
|
49
|
-
return {
|
|
69
|
+
return withPluginTranslations({
|
|
50
70
|
...config,
|
|
51
71
|
admin: {
|
|
52
72
|
...config.admin,
|
|
@@ -61,7 +81,7 @@ export const payloadMultilang = (pluginOptions = {
|
|
|
61
81
|
},
|
|
62
82
|
collections,
|
|
63
83
|
globals
|
|
64
|
-
};
|
|
84
|
+
});
|
|
65
85
|
};
|
|
66
86
|
|
|
67
87
|
//# sourceMappingURL=index.js.map
|