@roxxel/payload-multilang 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +165 -0
  2. package/dist/components/LanguageListToolbar.d.ts +6 -0
  3. package/dist/components/LanguageListToolbar.js +69 -0
  4. package/dist/components/LanguageListToolbar.js.map +1 -0
  5. package/dist/components/LanguageMetabox.d.ts +2 -0
  6. package/dist/components/LanguageMetabox.js +275 -0
  7. package/dist/components/LanguageMetabox.js.map +1 -0
  8. package/dist/components/TranslationActionsClient.d.ts +10 -0
  9. package/dist/components/TranslationActionsClient.js +166 -0
  10. package/dist/components/TranslationActionsClient.js.map +1 -0
  11. package/dist/components/TranslationColumnCell.d.ts +2 -0
  12. package/dist/components/TranslationColumnCell.js +69 -0
  13. package/dist/components/TranslationColumnCell.js.map +1 -0
  14. package/dist/components/TranslationColumnCellClient.d.ts +12 -0
  15. package/dist/components/TranslationColumnCellClient.js +107 -0
  16. package/dist/components/TranslationColumnCellClient.js.map +1 -0
  17. package/dist/components/TranslationsTab.d.ts +2 -0
  18. package/dist/components/TranslationsTab.js +118 -0
  19. package/dist/components/TranslationsTab.js.map +1 -0
  20. package/dist/components/config.d.ts +40 -0
  21. package/dist/components/config.js +31 -0
  22. package/dist/components/config.js.map +1 -0
  23. package/dist/constants.d.ts +5 -0
  24. package/dist/constants.js +24 -0
  25. package/dist/constants.js.map +1 -0
  26. package/dist/endpoints/translations.d.ts +19 -0
  27. package/dist/endpoints/translations.js +301 -0
  28. package/dist/endpoints/translations.js.map +1 -0
  29. package/dist/exports/client.d.ts +4 -0
  30. package/dist/exports/client.js +6 -0
  31. package/dist/exports/client.js.map +1 -0
  32. package/dist/exports/rsc.d.ts +2 -0
  33. package/dist/exports/rsc.js +4 -0
  34. package/dist/exports/rsc.js.map +1 -0
  35. package/dist/hooks/translatedCollection.d.ts +26 -0
  36. package/dist/hooks/translatedCollection.js +290 -0
  37. package/dist/hooks/translatedCollection.js.map +1 -0
  38. package/dist/hooks/translatedGlobal.d.ts +16 -0
  39. package/dist/hooks/translatedGlobal.js +71 -0
  40. package/dist/hooks/translatedGlobal.js.map +1 -0
  41. package/dist/index.d.ts +5 -0
  42. package/dist/index.js +63 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/lib/config.d.ts +14 -0
  45. package/dist/lib/config.js +96 -0
  46. package/dist/lib/config.js.map +1 -0
  47. package/dist/lib/data.d.ts +107 -0
  48. package/dist/lib/data.js +307 -0
  49. package/dist/lib/data.js.map +1 -0
  50. package/dist/payload-config.d.js +2 -0
  51. package/dist/payload-config.d.js.map +1 -0
  52. package/dist/styles/admin.css +316 -0
  53. package/dist/types.d.ts +96 -0
  54. package/dist/types.js +3 -0
  55. package/dist/types.js.map +1 -0
  56. package/docs/assets/admin-ui/collection-list-language-shortcuts.png +0 -0
  57. package/docs/assets/admin-ui/english-post-translations.png +0 -0
  58. package/docs/assets/admin-ui/ukrainian-post-translations.png +0 -0
  59. package/docs/configuration.md +192 -0
  60. package/docs/helpers.md +231 -0
  61. package/docs/usage.md +269 -0
  62. package/package.json +95 -0
@@ -0,0 +1,24 @@
1
+ export const DEFAULT_FIELD_NAMES = {
2
+ group: '_multilangGroup',
3
+ language: '_multilangLanguage',
4
+ meta: '_multilangMeta'
5
+ };
6
+ export const DEFAULT_GLOBAL_TABS_LABEL = 'Localized content';
7
+ export const DEFAULT_DUPLICATE_EXCLUDE_FIELDS = [
8
+ 'id',
9
+ 'createdAt',
10
+ 'updatedAt',
11
+ 'deletedAt',
12
+ '_status',
13
+ 'sizes',
14
+ 'filename',
15
+ 'filesize',
16
+ 'height',
17
+ 'mimeType',
18
+ 'thumbnailURL',
19
+ 'url',
20
+ 'width'
21
+ ];
22
+ export const MULTILANG_SKIP_HOOK = 'payloadMultilangSkip';
23
+
24
+ //# sourceMappingURL=constants.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/constants.ts"],"sourcesContent":["import type { MultilangFieldNames } from './types.js'\n\nexport const DEFAULT_FIELD_NAMES: MultilangFieldNames = {\n group: '_multilangGroup',\n language: '_multilangLanguage',\n meta: '_multilangMeta',\n}\n\nexport const DEFAULT_GLOBAL_TABS_LABEL = 'Localized content'\n\nexport const DEFAULT_DUPLICATE_EXCLUDE_FIELDS = [\n 'id',\n 'createdAt',\n 'updatedAt',\n 'deletedAt',\n '_status',\n 'sizes',\n 'filename',\n 'filesize',\n 'height',\n 'mimeType',\n 'thumbnailURL',\n 'url',\n 'width',\n]\n\nexport const MULTILANG_SKIP_HOOK = 'payloadMultilangSkip'\n"],"names":["DEFAULT_FIELD_NAMES","group","language","meta","DEFAULT_GLOBAL_TABS_LABEL","DEFAULT_DUPLICATE_EXCLUDE_FIELDS","MULTILANG_SKIP_HOOK"],"mappings":"AAEA,OAAO,MAAMA,sBAA2C;IACtDC,OAAO;IACPC,UAAU;IACVC,MAAM;AACR,EAAC;AAED,OAAO,MAAMC,4BAA4B,oBAAmB;AAE5D,OAAO,MAAMC,mCAAmC;IAC9C;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;IACA;CACD,CAAA;AAED,OAAO,MAAMC,sBAAsB,uBAAsB"}
@@ -0,0 +1,19 @@
1
+ import type { CollectionConfig, Endpoint } from 'payload';
2
+ import type { ResolvedMultilangCollection } from '../types.js';
3
+ export declare const createTranslationStateEndpoint: ({ collection, }: {
4
+ collection: ResolvedMultilangCollection;
5
+ }) => Endpoint;
6
+ export declare const createCreateTranslationEndpoint: ({ collection, collectionConfig, }: {
7
+ collection: ResolvedMultilangCollection;
8
+ collectionConfig: CollectionConfig;
9
+ }) => Endpoint;
10
+ export declare const createConnectTranslationEndpoint: ({ collection, }: {
11
+ collection: ResolvedMultilangCollection;
12
+ }) => Endpoint;
13
+ export declare const createDisconnectTranslationEndpoint: ({ collection, }: {
14
+ collection: ResolvedMultilangCollection;
15
+ }) => Endpoint;
16
+ export declare const createTranslationEndpoints: ({ collection, collectionConfig, }: {
17
+ collection: ResolvedMultilangCollection;
18
+ collectionConfig: CollectionConfig;
19
+ }) => Endpoint[];
@@ -0,0 +1,301 @@
1
+ import { randomUUID } from 'crypto';
2
+ import { MULTILANG_SKIP_HOOK } from '../constants.js';
3
+ import { asDocument, duplicateDocumentData, getDocumentTranslationsWithPayload, getGroupTranslationsWithPayload, getID, getStringValue } from '../lib/data.js';
4
+ const json = (body, init)=>Response.json(body, init);
5
+ const parseBody = async (req)=>{
6
+ if (typeof req.json !== 'function') {
7
+ return {};
8
+ }
9
+ return asDocument(await req.json());
10
+ };
11
+ const getLanguageCode = (value)=>{
12
+ const language = getStringValue(value)?.trim().toLowerCase();
13
+ return language || undefined;
14
+ };
15
+ const validateLanguage = ({ collection, language })=>{
16
+ if (collection.languages.some((candidate)=>candidate.code === language)) {
17
+ return undefined;
18
+ }
19
+ return json({
20
+ message: `Language "${language}" is not configured for ${collection.slug}.`
21
+ }, {
22
+ status: 400
23
+ });
24
+ };
25
+ const ensureGroup = async ({ collection, doc, req })=>{
26
+ const existingGroup = getStringValue(doc[collection.fieldNames.group]);
27
+ if (existingGroup) {
28
+ return existingGroup;
29
+ }
30
+ const id = getID(doc.id);
31
+ if (!id) {
32
+ return randomUUID();
33
+ }
34
+ const group = randomUUID();
35
+ await req.payload.update({
36
+ id,
37
+ collection: collection.slug,
38
+ context: {
39
+ [MULTILANG_SKIP_HOOK]: true
40
+ },
41
+ data: {
42
+ [collection.fieldNames.group]: group
43
+ },
44
+ overrideAccess: false,
45
+ req
46
+ });
47
+ return group;
48
+ };
49
+ const checkDuplicateLanguage = async ({ collection, excludeID, group, language, req })=>{
50
+ const and = [
51
+ {
52
+ [collection.fieldNames.group]: {
53
+ equals: group
54
+ }
55
+ },
56
+ {
57
+ [collection.fieldNames.language]: {
58
+ equals: language
59
+ }
60
+ }
61
+ ];
62
+ if (excludeID) {
63
+ and.push({
64
+ id: {
65
+ not_equals: excludeID
66
+ }
67
+ });
68
+ }
69
+ const { totalDocs } = await req.payload.count({
70
+ collection: collection.slug,
71
+ overrideAccess: false,
72
+ req,
73
+ where: {
74
+ and
75
+ }
76
+ });
77
+ if (totalDocs > 0) {
78
+ return json({
79
+ message: `A translation already exists for language "${language}".`
80
+ }, {
81
+ status: 409
82
+ });
83
+ }
84
+ };
85
+ export const createTranslationStateEndpoint = ({ collection })=>({
86
+ handler: async (req)=>{
87
+ const id = getID(req.query?.id);
88
+ const group = getStringValue(req.query?.group);
89
+ if (!id && !group) {
90
+ return json({
91
+ message: 'Missing document id or translation group.'
92
+ }, {
93
+ status: 400
94
+ });
95
+ }
96
+ const state = id ? await getDocumentTranslationsWithPayload({
97
+ id,
98
+ collection: collection.slug,
99
+ fieldNames: collection.fieldNames,
100
+ payload: req.payload,
101
+ overrideAccess: false,
102
+ req
103
+ }) : await getGroupTranslationsWithPayload({
104
+ collection: collection.slug,
105
+ fieldNames: collection.fieldNames,
106
+ group: group,
107
+ payload: req.payload,
108
+ overrideAccess: false,
109
+ req
110
+ });
111
+ return json(state);
112
+ },
113
+ method: 'get',
114
+ path: '/multilang/state'
115
+ });
116
+ export const createCreateTranslationEndpoint = ({ collection, collectionConfig })=>({
117
+ handler: async (req)=>{
118
+ const body = await parseBody(req);
119
+ const sourceID = getID(body.sourceId);
120
+ const targetLanguage = getLanguageCode(body.targetLanguage);
121
+ if (!sourceID || !targetLanguage) {
122
+ return json({
123
+ message: 'sourceId and targetLanguage are required.'
124
+ }, {
125
+ status: 400
126
+ });
127
+ }
128
+ const languageError = validateLanguage({
129
+ collection,
130
+ language: targetLanguage
131
+ });
132
+ if (languageError) {
133
+ return languageError;
134
+ }
135
+ const source = asDocument(await req.payload.findByID({
136
+ id: sourceID,
137
+ collection: collection.slug,
138
+ depth: 0,
139
+ overrideAccess: false,
140
+ req
141
+ }));
142
+ const group = await ensureGroup({
143
+ collection,
144
+ doc: source,
145
+ req
146
+ });
147
+ const duplicateError = await checkDuplicateLanguage({
148
+ collection,
149
+ group,
150
+ language: targetLanguage,
151
+ req
152
+ });
153
+ if (duplicateError) {
154
+ return duplicateError;
155
+ }
156
+ const shouldDuplicate = body.duplicate !== false && collection.duplicate;
157
+ const data = shouldDuplicate ? duplicateDocumentData({
158
+ collection: collectionConfig,
159
+ doc: source,
160
+ duplicateExcludeFields: collection.duplicateExcludeFields,
161
+ fieldNames: collection.fieldNames,
162
+ targetLanguage
163
+ }) : {};
164
+ const doc = await req.payload.create({
165
+ collection: collection.slug,
166
+ data: {
167
+ ...data,
168
+ [collection.fieldNames.group]: group,
169
+ [collection.fieldNames.language]: targetLanguage,
170
+ [collection.fieldNames.meta]: {
171
+ createdFrom: sourceID
172
+ }
173
+ },
174
+ overrideAccess: false,
175
+ req
176
+ });
177
+ return json({
178
+ doc
179
+ });
180
+ },
181
+ method: 'post',
182
+ path: '/multilang/create'
183
+ });
184
+ export const createConnectTranslationEndpoint = ({ collection })=>({
185
+ handler: async (req)=>{
186
+ const body = await parseBody(req);
187
+ const sourceID = getID(body.sourceId);
188
+ const targetID = getID(body.targetId);
189
+ const targetLanguage = getLanguageCode(body.targetLanguage);
190
+ if (!sourceID || !targetID || sourceID === targetID) {
191
+ return json({
192
+ message: 'sourceId and a different targetId are required.'
193
+ }, {
194
+ status: 400
195
+ });
196
+ }
197
+ const source = asDocument(await req.payload.findByID({
198
+ id: sourceID,
199
+ collection: collection.slug,
200
+ depth: 0,
201
+ overrideAccess: false,
202
+ req
203
+ }));
204
+ const target = asDocument(await req.payload.findByID({
205
+ id: targetID,
206
+ collection: collection.slug,
207
+ depth: 0,
208
+ overrideAccess: false,
209
+ req
210
+ }));
211
+ const group = await ensureGroup({
212
+ collection,
213
+ doc: source,
214
+ req
215
+ });
216
+ const language = targetLanguage || getLanguageCode(target[collection.fieldNames.language]) || getLanguageCode(source[collection.fieldNames.language]);
217
+ if (!language) {
218
+ return json({
219
+ message: 'Target language is required.'
220
+ }, {
221
+ status: 400
222
+ });
223
+ }
224
+ const languageError = validateLanguage({
225
+ collection,
226
+ language
227
+ });
228
+ if (languageError) {
229
+ return languageError;
230
+ }
231
+ const duplicateError = await checkDuplicateLanguage({
232
+ collection,
233
+ excludeID: targetID,
234
+ group,
235
+ language,
236
+ req
237
+ });
238
+ if (duplicateError) {
239
+ return duplicateError;
240
+ }
241
+ const doc = await req.payload.update({
242
+ id: targetID,
243
+ collection: collection.slug,
244
+ data: {
245
+ [collection.fieldNames.group]: group,
246
+ [collection.fieldNames.language]: language
247
+ },
248
+ overrideAccess: false,
249
+ req
250
+ });
251
+ return json({
252
+ doc
253
+ });
254
+ },
255
+ method: 'post',
256
+ path: '/multilang/connect'
257
+ });
258
+ export const createDisconnectTranslationEndpoint = ({ collection })=>({
259
+ handler: async (req)=>{
260
+ const body = await parseBody(req);
261
+ const id = getID(body.id);
262
+ if (!id) {
263
+ return json({
264
+ message: 'Missing document id.'
265
+ }, {
266
+ status: 400
267
+ });
268
+ }
269
+ const doc = await req.payload.update({
270
+ id,
271
+ collection: collection.slug,
272
+ data: {
273
+ [collection.fieldNames.group]: randomUUID()
274
+ },
275
+ overrideAccess: false,
276
+ req
277
+ });
278
+ return json({
279
+ doc
280
+ });
281
+ },
282
+ method: 'post',
283
+ path: '/multilang/disconnect'
284
+ });
285
+ export const createTranslationEndpoints = ({ collection, collectionConfig })=>[
286
+ createTranslationStateEndpoint({
287
+ collection
288
+ }),
289
+ createCreateTranslationEndpoint({
290
+ collection,
291
+ collectionConfig
292
+ }),
293
+ createConnectTranslationEndpoint({
294
+ collection
295
+ }),
296
+ createDisconnectTranslationEndpoint({
297
+ collection
298
+ })
299
+ ];
300
+
301
+ //# sourceMappingURL=translations.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/endpoints/translations.ts"],"sourcesContent":["import type { CollectionConfig, Endpoint, PayloadRequest, Where } from 'payload'\n\nimport { randomUUID } from 'crypto'\n\nimport type { ResolvedMultilangCollection } from '../types.js'\n\nimport { MULTILANG_SKIP_HOOK } from '../constants.js'\nimport {\n asDocument,\n duplicateDocumentData,\n getDocumentTranslationsWithPayload,\n getGroupTranslationsWithPayload,\n getID,\n getStringValue,\n} from '../lib/data.js'\n\nconst json = (body: unknown, init?: ResponseInit): Response =>\n Response.json(body, init)\n\nconst parseBody = async (req: PayloadRequest): Promise<Record<string, unknown>> => {\n if (typeof req.json !== 'function') {\n return {}\n }\n\n return asDocument(await req.json())\n}\n\nconst getLanguageCode = (value: unknown): string | undefined => {\n const language = getStringValue(value)?.trim().toLowerCase()\n\n return language || undefined\n}\n\nconst validateLanguage = ({\n collection,\n language,\n}: {\n collection: ResolvedMultilangCollection\n language: string\n}): Response | undefined => {\n if (collection.languages.some((candidate) => candidate.code === language)) {\n return undefined\n }\n\n return json(\n {\n message: `Language \"${language}\" is not configured for ${collection.slug}.`,\n },\n { status: 400 },\n )\n}\n\nconst ensureGroup = async ({\n collection,\n doc,\n req,\n}: {\n collection: ResolvedMultilangCollection\n doc: Record<string, unknown>\n req: PayloadRequest\n}): Promise<string> => {\n const existingGroup = getStringValue(doc[collection.fieldNames.group])\n\n if (existingGroup) {\n return existingGroup\n }\n\n const id = getID(doc.id)\n\n if (!id) {\n return randomUUID()\n }\n\n const group = randomUUID()\n\n await req.payload.update({\n id,\n collection: collection.slug,\n context: {\n [MULTILANG_SKIP_HOOK]: true,\n },\n data: {\n [collection.fieldNames.group]: group,\n },\n overrideAccess: false,\n req,\n })\n\n return group\n}\n\nconst checkDuplicateLanguage = 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: PayloadRequest\n}): Promise<Response | undefined> => {\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 { totalDocs } = await req.payload.count({\n collection: collection.slug,\n overrideAccess: false,\n req,\n where: {\n and,\n },\n })\n\n if (totalDocs > 0) {\n return json(\n {\n message: `A translation already exists for language \"${language}\".`,\n },\n { status: 409 },\n )\n }\n}\n\nexport const createTranslationStateEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const id = getID(req.query?.id)\n const group = getStringValue(req.query?.group)\n\n if (!id && !group) {\n return json({ message: 'Missing document id or translation group.' }, { status: 400 })\n }\n\n const state = id\n ? await getDocumentTranslationsWithPayload({\n id,\n collection: collection.slug,\n fieldNames: collection.fieldNames,\n payload: req.payload,\n overrideAccess: false,\n req,\n })\n : await getGroupTranslationsWithPayload({\n collection: collection.slug,\n fieldNames: collection.fieldNames,\n group: group!,\n payload: req.payload,\n overrideAccess: false,\n req,\n })\n\n return json(state)\n },\n method: 'get',\n path: '/multilang/state',\n})\n\nexport const createCreateTranslationEndpoint = ({\n collection,\n collectionConfig,\n}: {\n collection: ResolvedMultilangCollection\n collectionConfig: CollectionConfig\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const sourceID = getID(body.sourceId)\n const targetLanguage = getLanguageCode(body.targetLanguage)\n\n if (!sourceID || !targetLanguage) {\n return json(\n { message: 'sourceId and targetLanguage are required.' },\n { status: 400 },\n )\n }\n\n const languageError = validateLanguage({\n collection,\n language: targetLanguage,\n })\n\n if (languageError) {\n return languageError\n }\n\n const source = asDocument(\n await req.payload.findByID({\n id: sourceID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const group = await ensureGroup({ collection, doc: source, req })\n const duplicateError = await checkDuplicateLanguage({\n collection,\n group,\n language: targetLanguage,\n req,\n })\n\n if (duplicateError) {\n return duplicateError\n }\n\n const shouldDuplicate = body.duplicate !== false && collection.duplicate\n const data = shouldDuplicate\n ? duplicateDocumentData({\n collection: collectionConfig,\n doc: source,\n duplicateExcludeFields: collection.duplicateExcludeFields,\n fieldNames: collection.fieldNames,\n targetLanguage,\n })\n : {}\n\n const doc = await req.payload.create({\n collection: collection.slug,\n data: {\n ...data,\n [collection.fieldNames.group]: group,\n [collection.fieldNames.language]: targetLanguage,\n [collection.fieldNames.meta]: {\n createdFrom: sourceID,\n },\n },\n overrideAccess: false,\n req,\n })\n\n return json({\n doc,\n })\n },\n method: 'post',\n path: '/multilang/create',\n})\n\nexport const createConnectTranslationEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const sourceID = getID(body.sourceId)\n const targetID = getID(body.targetId)\n const targetLanguage = getLanguageCode(body.targetLanguage)\n\n if (!sourceID || !targetID || sourceID === targetID) {\n return json({ message: 'sourceId and a different targetId are required.' }, { status: 400 })\n }\n\n const source = asDocument(\n await req.payload.findByID({\n id: sourceID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const target = asDocument(\n await req.payload.findByID({\n id: targetID,\n collection: collection.slug,\n depth: 0,\n overrideAccess: false,\n req,\n }),\n )\n const group = await ensureGroup({ collection, doc: source, req })\n const language =\n targetLanguage ||\n getLanguageCode(target[collection.fieldNames.language]) ||\n getLanguageCode(source[collection.fieldNames.language])\n\n if (!language) {\n return json({ message: 'Target language is required.' }, { status: 400 })\n }\n\n const languageError = validateLanguage({\n collection,\n language,\n })\n\n if (languageError) {\n return languageError\n }\n\n const duplicateError = await checkDuplicateLanguage({\n collection,\n excludeID: targetID,\n group,\n language,\n req,\n })\n\n if (duplicateError) {\n return duplicateError\n }\n\n const doc = await req.payload.update({\n id: targetID,\n collection: collection.slug,\n data: {\n [collection.fieldNames.group]: group,\n [collection.fieldNames.language]: language,\n },\n overrideAccess: false,\n req,\n })\n\n return json({ doc })\n },\n method: 'post',\n path: '/multilang/connect',\n})\n\nexport const createDisconnectTranslationEndpoint = ({\n collection,\n}: {\n collection: ResolvedMultilangCollection\n}): Endpoint => ({\n handler: async (req) => {\n const body = await parseBody(req)\n const id = getID(body.id)\n\n if (!id) {\n return json({ message: 'Missing document id.' }, { status: 400 })\n }\n\n const doc = await req.payload.update({\n id,\n collection: collection.slug,\n data: {\n [collection.fieldNames.group]: randomUUID(),\n },\n overrideAccess: false,\n req,\n })\n\n return json({ doc })\n },\n method: 'post',\n path: '/multilang/disconnect',\n})\n\nexport const createTranslationEndpoints = ({\n collection,\n collectionConfig,\n}: {\n collection: ResolvedMultilangCollection\n collectionConfig: CollectionConfig\n}): Endpoint[] => [\n createTranslationStateEndpoint({ collection }),\n createCreateTranslationEndpoint({ collection, collectionConfig }),\n createConnectTranslationEndpoint({ collection }),\n createDisconnectTranslationEndpoint({ collection }),\n]\n"],"names":["randomUUID","MULTILANG_SKIP_HOOK","asDocument","duplicateDocumentData","getDocumentTranslationsWithPayload","getGroupTranslationsWithPayload","getID","getStringValue","json","body","init","Response","parseBody","req","getLanguageCode","value","language","trim","toLowerCase","undefined","validateLanguage","collection","languages","some","candidate","code","message","slug","status","ensureGroup","doc","existingGroup","fieldNames","group","id","payload","update","context","data","overrideAccess","checkDuplicateLanguage","excludeID","and","equals","push","not_equals","totalDocs","count","where","createTranslationStateEndpoint","handler","query","state","method","path","createCreateTranslationEndpoint","collectionConfig","sourceID","sourceId","targetLanguage","languageError","source","findByID","depth","duplicateError","shouldDuplicate","duplicate","duplicateExcludeFields","create","meta","createdFrom","createConnectTranslationEndpoint","targetID","targetId","target","createDisconnectTranslationEndpoint","createTranslationEndpoints"],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export { LanguageListToolbar } from '../components/LanguageListToolbar.js';
2
+ export { LanguageMetabox } from '../components/LanguageMetabox.js';
3
+ export { TranslationActionsClient } from '../components/TranslationActionsClient.js';
4
+ export { TranslationColumnCellClient } from '../components/TranslationColumnCellClient.js';
@@ -0,0 +1,6 @@
1
+ export { LanguageListToolbar } from '../components/LanguageListToolbar.js';
2
+ export { LanguageMetabox } from '../components/LanguageMetabox.js';
3
+ export { TranslationActionsClient } from '../components/TranslationActionsClient.js';
4
+ export { TranslationColumnCellClient } from '../components/TranslationColumnCellClient.js';
5
+
6
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["export { LanguageListToolbar } from '../components/LanguageListToolbar.js'\nexport { LanguageMetabox } from '../components/LanguageMetabox.js'\nexport { TranslationActionsClient } from '../components/TranslationActionsClient.js'\nexport { TranslationColumnCellClient } from '../components/TranslationColumnCellClient.js'\n"],"names":["LanguageListToolbar","LanguageMetabox","TranslationActionsClient","TranslationColumnCellClient"],"mappings":"AAAA,SAASA,mBAAmB,QAAQ,uCAAsC;AAC1E,SAASC,eAAe,QAAQ,mCAAkC;AAClE,SAASC,wBAAwB,QAAQ,4CAA2C;AACpF,SAASC,2BAA2B,QAAQ,+CAA8C"}
@@ -0,0 +1,2 @@
1
+ export { TranslationColumnCell } from '../components/TranslationColumnCell.js';
2
+ export { TranslationsTab } from '../components/TranslationsTab.js';
@@ -0,0 +1,4 @@
1
+ export { TranslationColumnCell } from '../components/TranslationColumnCell.js';
2
+ export { TranslationsTab } from '../components/TranslationsTab.js';
3
+
4
+ //# sourceMappingURL=rsc.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/exports/rsc.ts"],"sourcesContent":["export { TranslationColumnCell } from '../components/TranslationColumnCell.js'\nexport { TranslationsTab } from '../components/TranslationsTab.js'\n"],"names":["TranslationColumnCell","TranslationsTab"],"mappings":"AAAA,SAASA,qBAAqB,QAAQ,yCAAwC;AAC9E,SAASC,eAAe,QAAQ,mCAAkC"}
@@ -0,0 +1,26 @@
1
+ import type { CollectionAfterChangeHook, CollectionBeforeChangeHook, CollectionConfig, Field } from 'payload';
2
+ import type { ResolvedMultilangCollection } from '../types.js';
3
+ export declare const createTranslatedCollectionBeforeChangeHook: ({ collection }: {
4
+ collection: ResolvedMultilangCollection;
5
+ }) => CollectionBeforeChangeHook;
6
+ export declare const createSynchronizedFieldsAfterChangeHook: ({ collection }: {
7
+ collection: ResolvedMultilangCollection;
8
+ }) => CollectionAfterChangeHook;
9
+ export declare const createHiddenFields: ({ collection, }: {
10
+ collection: ResolvedMultilangCollection;
11
+ }) => Field[];
12
+ export declare const getLanguageColumnName: () => string;
13
+ export declare const createLanguageColumnFields: ({ collection, }: {
14
+ collection: ResolvedMultilangCollection;
15
+ }) => Field[];
16
+ export declare const translatedCollectionMeta: ({ collection, }: {
17
+ collection: ResolvedMultilangCollection;
18
+ }) => {
19
+ defaultLanguage: import("../types.js").MultilangLanguage;
20
+ fieldNames: import("../types.js").MultilangFieldNames;
21
+ languages: import("../types.js").MultilangLanguage[];
22
+ };
23
+ export declare const withTranslatedCollection: ({ collection, config, }: {
24
+ collection: ResolvedMultilangCollection;
25
+ config: CollectionConfig;
26
+ }) => CollectionConfig;