Skip to content

Commit 601759d

Browse files
feat: adds ability to copy data from across locales (#8203)
### What? Adds ability to copy data from one locale to another at a document level. ### How? For any localized collection, you will find a new option in the document controls called `Copy to Locale`. This option will open a drawer, from here you can select your origin and destination locales. If data already exists in the destination locale, you can choose to: 1. Overwrite this data (this will copy any empty fields in your origin locale) 2. Not overwrite existing data (this will only copy data into empty fields in the destination locale) --------- Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
1 parent 61d6614 commit 601759d

File tree

50 files changed

+1401
-5
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+1401
-5
lines changed

packages/next/src/utilities/handleServerFunctions.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import type { ServerFunction, ServerFunctionHandler } from 'payload'
22

3+
import { copyDataFromLocaleHandler } from '@payloadcms/ui/rsc'
34
import { buildFormStateHandler } from '@payloadcms/ui/utilities/buildFormState'
45
import { buildTableStateHandler } from '@payloadcms/ui/utilities/buildTableState'
56

@@ -20,6 +21,7 @@ export const handleServerFunctions: ServerFunctionHandler = async (args) => {
2021
}
2122

2223
const serverFunctions = {
24+
'copy-data-from-locale': copyDataFromLocaleHandler as any as ServerFunction,
2325
'form-state': buildFormStateHandler as any as ServerFunction,
2426
'render-document': renderDocumentHandler as any as ServerFunction,
2527
'render-document-slots': renderDocumentSlotsHandler as any as ServerFunction,

packages/translations/src/clientKeys.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,14 @@ export const clientTranslationKeys = createClientTranslationKeys([
141141
'general:columns',
142142
'general:columnToSort',
143143
'general:confirm',
144+
'general:confirmCopy',
144145
'general:confirmDeletion',
145146
'general:confirmDuplication',
146147
'general:copied',
147148
'general:clearAll',
148149
'general:copy',
150+
'general:copyWarning',
151+
'general:copying',
149152
'general:create',
150153
'general:created',
151154
'general:createdAt',
@@ -212,6 +215,7 @@ export const clientTranslationKeys = createClientTranslationKeys([
212215
'general:only',
213216
'general:or',
214217
'general:order',
218+
'general:overwriteExistingData',
215219
'general:pageNotFound',
216220
'general:password',
217221
'general:payloadSettings',
@@ -247,6 +251,7 @@ export const clientTranslationKeys = createClientTranslationKeys([
247251
'general:user',
248252
'general:username',
249253
'general:unauthorized',
254+
'general:unsavedChanges',
250255
'general:unsavedChangesDuplicate',
251256
'general:untitled',
252257
'general:updatedAt',
@@ -258,6 +263,13 @@ export const clientTranslationKeys = createClientTranslationKeys([
258263
'general:uploadingBulk',
259264
'general:welcome',
260265

266+
'localization:copyToLocale',
267+
'localization:copyFromTo',
268+
'localization:selectLocaleToCopy',
269+
'localization:cannotCopySameLocale',
270+
'localization:copyFrom',
271+
'localization:copyTo',
272+
261273
'operators:equals',
262274
'operators:exists',
263275
'operators:isNotIn',

packages/translations/src/languages/ar.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,10 +192,13 @@ export const arTranslations: DefaultTranslationsObject = {
192192
columns: 'الأعمدة',
193193
columnToSort: 'التّرتيب حسب العامود',
194194
confirm: 'تأكيد',
195+
confirmCopy: 'تأكيد النسخ',
195196
confirmDeletion: 'تأكيد الحذف',
196197
confirmDuplication: 'تأكيد التّكرار',
197198
copied: 'تمّ النّسخ',
198199
copy: 'نسخ',
200+
copying: 'نسخ',
201+
copyWarning: 'أنت على وشك الكتابة فوق {{to}} بـ {{from}} لـ {{label}} {{title}}. هل أنت متأكد؟',
199202
create: 'إنشاء',
200203
created: 'تمّ الإنشاء',
201204
createdAt: 'تمّ الإنشاء في',
@@ -269,6 +272,7 @@ export const arTranslations: DefaultTranslationsObject = {
269272
open: 'فتح',
270273
or: 'أو',
271274
order: 'التّرتيب',
275+
overwriteExistingData: 'استبدل بيانات الحقل الموجودة',
272276
pageNotFound: 'الصّفحة غير موجودة',
273277
password: 'كلمة المرور',
274278
payloadSettings: 'الإعدادات',
@@ -301,6 +305,7 @@ export const arTranslations: DefaultTranslationsObject = {
301305
titleDeleted: 'تم حذف {{label}} "{{title}}" بنجاح.',
302306
true: 'صحيح',
303307
unauthorized: 'غير مصرح به',
308+
unsavedChanges: 'لديك تغييرات غير محفوظة. قم بالحفظ أو التجاهل قبل المتابعة.',
304309
unsavedChangesDuplicate: 'لديك تغييرات لم يتم حفظها. هل تريد الاستمرار في الاستنساخ؟',
305310
untitled: 'بدون عنوان',
306311
updatedAt: 'تم التحديث في',
@@ -316,6 +321,14 @@ export const arTranslations: DefaultTranslationsObject = {
316321
viewReadOnly: 'عرض للقراءة فقط',
317322
welcome: 'مرحبًا',
318323
},
324+
localization: {
325+
cannotCopySameLocale: 'لا يمكن النسخ إلى نفس الموقع',
326+
copyFrom: 'نسخ من',
327+
copyFromTo: 'النسخ من {{from}} إلى {{to}}',
328+
copyTo: 'انسخ إلى',
329+
copyToLocale: 'نسخ إلى الموقع المحلي',
330+
selectLocaleToCopy: 'حدد الموقع المحلي للنسخ',
331+
},
319332
operators: {
320333
contains: 'يحتوي',
321334
equals: 'يساوي',

packages/translations/src/languages/az.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -194,10 +194,14 @@ export const azTranslations: DefaultTranslationsObject = {
194194
columns: 'Sütunlar',
195195
columnToSort: 'Sıralamağa sütun',
196196
confirm: 'Təsdiqlə',
197+
confirmCopy: 'Kopyanı təsdiqləyin',
197198
confirmDeletion: 'Silməni təsdiqlə',
198199
confirmDuplication: 'Dublikasiyanı təsdiqlə',
199200
copied: 'Kopyalandı',
200201
copy: 'Kopyala',
202+
copying: 'Kopyalama',
203+
copyWarning:
204+
'Siz {{label}} {{title}} üçün {{from}} ilə {{to}} -nu üzərindən yazmaq ətrafındasınız. Eminsiniz?',
201205
create: 'Yarat',
202206
created: 'Yaradıldı',
203207
createdAt: 'Yaradıldığı tarix',
@@ -271,6 +275,7 @@ export const azTranslations: DefaultTranslationsObject = {
271275
open: 'Aç',
272276
or: 'Və ya',
273277
order: 'Sıra',
278+
overwriteExistingData: 'Mövcud sahə məlumatlarını yenidən yazın',
274279
pageNotFound: 'Səhifə tapılmadı',
275280
password: 'Şifrə',
276281
payloadSettings: 'Payload Parametrləri',
@@ -303,6 +308,8 @@ export const azTranslations: DefaultTranslationsObject = {
303308
titleDeleted: '{{label}} "{{title}}" uğurla silindi.',
304309
true: 'Doğru',
305310
unauthorized: 'İcazəsiz',
311+
unsavedChanges:
312+
'Sizin saxlanılmamış dəyişiklikləriniz var. Davam etmədən əvvəl saxlayın və ya atın.',
306313
unsavedChangesDuplicate:
307314
'Saxlanılmamış dəyişiklikləriniz var. Dublikatla davam etmək istəyirsiniz?',
308315
untitled: 'Başlıqsız',
@@ -319,6 +326,14 @@ export const azTranslations: DefaultTranslationsObject = {
319326
viewReadOnly: 'Yalnız oxu rejimində bax',
320327
welcome: 'Xoş gəldiniz',
321328
},
329+
localization: {
330+
cannotCopySameLocale: 'Eyni dildə köçürmək mümkün deyil',
331+
copyFrom: 'Kopyalayın',
332+
copyFromTo: '{{from}}-dan {{to}}-ya kopyalama',
333+
copyTo: 'Köçür',
334+
copyToLocale: 'Yerliyə köçürün',
335+
selectLocaleToCopy: 'Köçürmək üçün yerli seçin',
336+
},
322337
operators: {
323338
contains: 'daxilində',
324339
equals: 'bərabərdir',

packages/translations/src/languages/bg.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,14 @@ export const bgTranslations: DefaultTranslationsObject = {
193193
columns: 'Колони',
194194
columnToSort: 'Колона за сортиране',
195195
confirm: 'Потвърди',
196+
confirmCopy: 'Потвърди копирането',
196197
confirmDeletion: 'Потвърди изтриване',
197198
confirmDuplication: 'Потвърди дупликация',
198199
copied: 'Копирано',
199200
copy: 'Копирай',
201+
copying: 'Копиране',
202+
copyWarning:
203+
'Предстои да презапишете {{to}} с {{from}} за {{label}} {{title}}. Сигурни ли сте?',
200204
create: 'Създай',
201205
created: 'Създаден',
202206
createdAt: 'Създаден на',
@@ -270,6 +274,7 @@ export const bgTranslations: DefaultTranslationsObject = {
270274
open: 'Отвори',
271275
or: 'Или',
272276
order: 'Ред',
277+
overwriteExistingData: 'Презапишете съществуващите данни в полето',
273278
pageNotFound: 'Страницата не беше открита',
274279
password: 'Парола',
275280
payloadSettings: 'Настройки на Payload',
@@ -302,6 +307,7 @@ export const bgTranslations: DefaultTranslationsObject = {
302307
titleDeleted: '{{label}} "{{title}}" успешно изтрит.',
303308
true: 'Вярно',
304309
unauthorized: 'Неоторизиран',
310+
unsavedChanges: 'Имате незапазени промени. Запазете или отхвърлете преди да продължите.',
305311
unsavedChangesDuplicate: 'Имаш незапазени промени. Искаш ли да продължиш да дупликираш?',
306312
untitled: 'Неозаглавен',
307313
updatedAt: 'Обновен на',
@@ -317,6 +323,14 @@ export const bgTranslations: DefaultTranslationsObject = {
317323
viewReadOnly: 'Преглед само за четене',
318324
welcome: 'Добре дошъл',
319325
},
326+
localization: {
327+
cannotCopySameLocale: 'Не може да се копира в същата локация',
328+
copyFrom: 'Копирай от',
329+
copyFromTo: 'Копиране от {{from}} към {{to}}',
330+
copyTo: 'Копирай в',
331+
copyToLocale: 'Копирайте в местното',
332+
selectLocaleToCopy: 'Изберете място за копиране',
333+
},
320334
operators: {
321335
contains: 'съдържа',
322336
equals: 'е равно на',

packages/translations/src/languages/cs.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,13 @@ export const csTranslations: DefaultTranslationsObject = {
193193
columns: 'Sloupce',
194194
columnToSort: 'Sloupec k seřazení',
195195
confirm: 'Potvrdit',
196+
confirmCopy: 'Potvrzení kopie',
196197
confirmDeletion: 'Potvrdit odstranění',
197198
confirmDuplication: 'Potvrdit duplikaci',
198199
copied: 'Zkopírováno',
199200
copy: 'Kopírovat',
201+
copying: 'Kopírování',
202+
copyWarning: 'Chystáte se přepsat {{to}} s {{from}} pro {{label}} {{title}}. Jste si jistý?',
200203
create: 'Vytvořit',
201204
created: 'Vytvořeno',
202205
createdAt: 'Vytvořeno v',
@@ -270,6 +273,7 @@ export const csTranslations: DefaultTranslationsObject = {
270273
open: 'Otevřít',
271274
or: 'Nebo',
272275
order: 'Pořadí',
276+
overwriteExistingData: 'Přepsat existující data pole',
273277
pageNotFound: 'Stránka nenalezena',
274278
password: 'Heslo',
275279
payloadSettings: 'Payload nastavení',
@@ -302,6 +306,7 @@ export const csTranslations: DefaultTranslationsObject = {
302306
titleDeleted: '{{label}} "{{title}}" úspěšně smazáno.',
303307
true: 'Pravda',
304308
unauthorized: 'Neoprávněný',
309+
unsavedChanges: 'Máte neuložené změny. Uložte nebo zahoďte před pokračováním.',
305310
unsavedChangesDuplicate: 'Máte neuložené změny. Chtěli byste pokračovat v duplikování?',
306311
untitled: 'Bez názvu',
307312
updatedAt: 'Aktualizováno v',
@@ -317,6 +322,14 @@ export const csTranslations: DefaultTranslationsObject = {
317322
viewReadOnly: 'Zobrazit pouze pro čtení',
318323
welcome: 'Vítejte',
319324
},
325+
localization: {
326+
cannotCopySameLocale: 'Nelze kopírovat do stejného umístění',
327+
copyFrom: 'Kopírovat z',
328+
copyFromTo: 'Kopírování z {{from}} do {{to}}',
329+
copyTo: 'Kopírovat do',
330+
copyToLocale: 'Kopírovat do lokalizace',
331+
selectLocaleToCopy: 'Vyberte lokalitu ke kopírování',
332+
},
320333
operators: {
321334
contains: 'obsahuje',
322335
equals: 'rovná se',

packages/translations/src/languages/da.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,10 +193,14 @@ export const daTranslations: DefaultTranslationsObject = {
193193
columns: 'Kolonner',
194194
columnToSort: 'Kolonne at sortere',
195195
confirm: 'Bekræft',
196+
confirmCopy: 'Bekræft kopi',
196197
confirmDeletion: 'Bekræft sletning',
197198
confirmDuplication: 'Bekræft duplikering',
198199
copied: 'Kopieret',
199200
copy: 'Kopier',
201+
copying: 'Kopiering',
202+
copyWarning:
203+
'Du er lige ved at overskrive {{to}} med {{from}} for {{label}} {{title}}. Er du sikker?',
200204
create: 'Opret',
201205
created: 'Oprettet',
202206
createdAt: 'Oprettet til',
@@ -269,6 +273,7 @@ export const daTranslations: DefaultTranslationsObject = {
269273
open: 'Åben',
270274
or: 'Eller',
271275
order: 'Rækkefølge',
276+
overwriteExistingData: 'Overskriv eksisterende feltdata',
272277
pageNotFound: 'Siden blev ikke fundet',
273278
password: 'Adgangskode',
274279
payloadSettings: 'Payload-indstillinger',
@@ -301,6 +306,7 @@ export const daTranslations: DefaultTranslationsObject = {
301306
titleDeleted: '{{label}} "{{title}}" slettet.',
302307
true: 'Sandt',
303308
unauthorized: 'Uautoriseret',
309+
unsavedChanges: 'Du har ikke gemte ændringer. Gem eller kassér før fortsættelse.',
304310
unsavedChangesDuplicate: 'Du har ikke-gemte ændringer. Vil du fortsætte med at duplikere?',
305311
untitled: 'Uden titel',
306312
updatedAt: 'Opdateret ved',
@@ -316,6 +322,14 @@ export const daTranslations: DefaultTranslationsObject = {
316322
viewReadOnly: 'Vis kun-læsning',
317323
welcome: 'Velkommen',
318324
},
325+
localization: {
326+
cannotCopySameLocale: 'Kan ikke kopiere til den samme lokalitet',
327+
copyFrom: 'Kopier fra',
328+
copyFromTo: 'Kopierer fra {{from}} til {{to}}',
329+
copyTo: 'Kopier til',
330+
copyToLocale: 'Kopier til lokal',
331+
selectLocaleToCopy: 'Vælg lokalitet til kopiering',
332+
},
319333
operators: {
320334
contains: 'Indeholder',
321335
equals: 'Lig med',

packages/translations/src/languages/de.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,14 @@ export const deTranslations: DefaultTranslationsObject = {
198198
columns: 'Spalten',
199199
columnToSort: 'Spalten zum Sortieren',
200200
confirm: 'Bestätigen',
201+
confirmCopy: 'Kopie bestätigen',
201202
confirmDeletion: 'Löschen bestätigen',
202203
confirmDuplication: 'Duplizieren bestätigen',
203204
copied: 'Kopiert',
204205
copy: 'Kopieren',
206+
copying: 'Kopieren',
207+
copyWarning:
208+
'Sie sind dabei, {{to}} mit {{from}} für {{label}} {{title}} zu überschreiben. Sind Sie sicher?',
205209
create: 'Erstellen',
206210
created: 'Erstellt',
207211
createdAt: 'Erstellt am',
@@ -275,6 +279,7 @@ export const deTranslations: DefaultTranslationsObject = {
275279
open: 'Öffnen',
276280
or: 'oder',
277281
order: 'Reihenfolge',
282+
overwriteExistingData: 'Überschreiben Sie vorhandene Felddaten',
278283
pageNotFound: 'Seite nicht gefunden',
279284
password: 'Passwort',
280285
payloadSettings: 'Payload Einstellungen',
@@ -307,6 +312,8 @@ export const deTranslations: DefaultTranslationsObject = {
307312
titleDeleted: '{{label}} {{title}} wurde erfolgreich gelöscht.',
308313
true: 'Wahr',
309314
unauthorized: 'Nicht autorisiert',
315+
unsavedChanges:
316+
'Sie haben ungespeicherte Änderungen. Speichern oder verwerfen Sie diese, bevor Sie fortfahren.',
310317
unsavedChangesDuplicate:
311318
'Du hast ungespeicherte Änderungen, möchtest du mit dem Duplizieren fortfahren?',
312319
untitled: 'ohne Titel',
@@ -323,6 +330,14 @@ export const deTranslations: DefaultTranslationsObject = {
323330
viewReadOnly: 'Nur-Lese-Ansicht',
324331
welcome: 'Willkommen',
325332
},
333+
localization: {
334+
cannotCopySameLocale: 'Kann nicht in dieselbe Gebietsschema kopieren',
335+
copyFrom: 'Kopieren von',
336+
copyFromTo: 'Kopieren von {{from}} zu {{to}}',
337+
copyTo: 'Kopieren nach',
338+
copyToLocale: 'Kopieren in das Gebietsschema',
339+
selectLocaleToCopy: 'Wählen Sie den Ort zum Kopieren aus',
340+
},
326341
operators: {
327342
contains: 'enthält',
328343
equals: 'gleich',

packages/translations/src/languages/en.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,10 +195,14 @@ export const enTranslations = {
195195
columns: 'Columns',
196196
columnToSort: 'Column to Sort',
197197
confirm: 'Confirm',
198+
confirmCopy: 'Confirm copy',
198199
confirmDeletion: 'Confirm deletion',
199200
confirmDuplication: 'Confirm duplication',
200201
copied: 'Copied',
201202
copy: 'Copy',
203+
copying: 'Copying',
204+
copyWarning:
205+
'You are about to overwrite {{to}} with {{from}} for {{label}} {{title}}. Are you sure?',
202206
create: 'Create',
203207
created: 'Created',
204208
createdAt: 'Created At',
@@ -272,6 +276,7 @@ export const enTranslations = {
272276
open: 'Open',
273277
or: 'Or',
274278
order: 'Order',
279+
overwriteExistingData: 'Overwrite existing field data',
275280
pageNotFound: 'Page not found',
276281
password: 'Password',
277282
payloadSettings: 'Payload Settings',
@@ -304,6 +309,7 @@ export const enTranslations = {
304309
titleDeleted: '{{label}} "{{title}}" successfully deleted.',
305310
true: 'True',
306311
unauthorized: 'Unauthorized',
312+
unsavedChanges: 'You have unsaved changes. Save or discard before continuing.',
307313
unsavedChangesDuplicate: 'You have unsaved changes. Would you like to continue to duplicate?',
308314
untitled: 'Untitled',
309315
updatedAt: 'Updated At',
@@ -319,6 +325,14 @@ export const enTranslations = {
319325
viewReadOnly: 'View read-only',
320326
welcome: 'Welcome',
321327
},
328+
localization: {
329+
cannotCopySameLocale: 'Cannot copy to the same locale',
330+
copyFrom: 'Copy from',
331+
copyFromTo: 'Copying from {{from}} to {{to}}',
332+
copyTo: 'Copy to',
333+
copyToLocale: 'Copy to locale',
334+
selectLocaleToCopy: 'Select locale to copy',
335+
},
322336
operators: {
323337
contains: 'contains',
324338
equals: 'equals',

0 commit comments

Comments
 (0)