diff --git a/packages/next/src/utilities/handleServerFunctions.ts b/packages/next/src/utilities/handleServerFunctions.ts index 96bbe6458..57fdb8abc 100644 --- a/packages/next/src/utilities/handleServerFunctions.ts +++ b/packages/next/src/utilities/handleServerFunctions.ts @@ -1,5 +1,6 @@ import type { ServerFunction, ServerFunctionHandler } from 'payload' +import { copyDataFromLocaleHandler } from '@payloadcms/ui/rsc' import { buildFormStateHandler } from '@payloadcms/ui/utilities/buildFormState' import { buildTableStateHandler } from '@payloadcms/ui/utilities/buildTableState' @@ -20,6 +21,7 @@ export const handleServerFunctions: ServerFunctionHandler = async (args) => { } const serverFunctions = { + 'copy-data-from-locale': copyDataFromLocaleHandler as any as ServerFunction, 'form-state': buildFormStateHandler as any as ServerFunction, 'render-document': renderDocumentHandler as any as ServerFunction, 'render-document-slots': renderDocumentSlotsHandler as any as ServerFunction, diff --git a/packages/translations/src/clientKeys.ts b/packages/translations/src/clientKeys.ts index 49d0bdaa9..82e6de9eb 100644 --- a/packages/translations/src/clientKeys.ts +++ b/packages/translations/src/clientKeys.ts @@ -141,11 +141,14 @@ export const clientTranslationKeys = createClientTranslationKeys([ 'general:columns', 'general:columnToSort', 'general:confirm', + 'general:confirmCopy', 'general:confirmDeletion', 'general:confirmDuplication', 'general:copied', 'general:clearAll', 'general:copy', + 'general:copyWarning', + 'general:copying', 'general:create', 'general:created', 'general:createdAt', @@ -212,6 +215,7 @@ export const clientTranslationKeys = createClientTranslationKeys([ 'general:only', 'general:or', 'general:order', + 'general:overwriteExistingData', 'general:pageNotFound', 'general:password', 'general:payloadSettings', @@ -247,6 +251,7 @@ export const clientTranslationKeys = createClientTranslationKeys([ 'general:user', 'general:username', 'general:unauthorized', + 'general:unsavedChanges', 'general:unsavedChangesDuplicate', 'general:untitled', 'general:updatedAt', @@ -258,6 +263,13 @@ export const clientTranslationKeys = createClientTranslationKeys([ 'general:uploadingBulk', 'general:welcome', + 'localization:copyToLocale', + 'localization:copyFromTo', + 'localization:selectLocaleToCopy', + 'localization:cannotCopySameLocale', + 'localization:copyFrom', + 'localization:copyTo', + 'operators:equals', 'operators:exists', 'operators:isNotIn', diff --git a/packages/translations/src/languages/ar.ts b/packages/translations/src/languages/ar.ts index 2757cc726..ec144b087 100644 --- a/packages/translations/src/languages/ar.ts +++ b/packages/translations/src/languages/ar.ts @@ -192,10 +192,13 @@ export const arTranslations: DefaultTranslationsObject = { columns: 'الأعمدة', columnToSort: 'التّرتيب حسب العامود', confirm: 'تأكيد', + confirmCopy: 'تأكيد النسخ', confirmDeletion: 'تأكيد الحذف', confirmDuplication: 'تأكيد التّكرار', copied: 'تمّ النّسخ', copy: 'نسخ', + copying: 'نسخ', + copyWarning: 'أنت على وشك الكتابة فوق {{to}} بـ {{from}} لـ {{label}} {{title}}. هل أنت متأكد؟', create: 'إنشاء', created: 'تمّ الإنشاء', createdAt: 'تمّ الإنشاء في', @@ -269,6 +272,7 @@ export const arTranslations: DefaultTranslationsObject = { open: 'فتح', or: 'أو', order: 'التّرتيب', + overwriteExistingData: 'استبدل بيانات الحقل الموجودة', pageNotFound: 'الصّفحة غير موجودة', password: 'كلمة المرور', payloadSettings: 'الإعدادات', @@ -301,6 +305,7 @@ export const arTranslations: DefaultTranslationsObject = { titleDeleted: 'تم حذف {{label}} "{{title}}" بنجاح.', true: 'صحيح', unauthorized: 'غير مصرح به', + unsavedChanges: 'لديك تغييرات غير محفوظة. قم بالحفظ أو التجاهل قبل المتابعة.', unsavedChangesDuplicate: 'لديك تغييرات لم يتم حفظها. هل تريد الاستمرار في الاستنساخ؟', untitled: 'بدون عنوان', updatedAt: 'تم التحديث في', @@ -316,6 +321,14 @@ export const arTranslations: DefaultTranslationsObject = { viewReadOnly: 'عرض للقراءة فقط', welcome: 'مرحبًا', }, + localization: { + cannotCopySameLocale: 'لا يمكن النسخ إلى نفس الموقع', + copyFrom: 'نسخ من', + copyFromTo: 'النسخ من {{from}} إلى {{to}}', + copyTo: 'انسخ إلى', + copyToLocale: 'نسخ إلى الموقع المحلي', + selectLocaleToCopy: 'حدد الموقع المحلي للنسخ', + }, operators: { contains: 'يحتوي', equals: 'يساوي', diff --git a/packages/translations/src/languages/az.ts b/packages/translations/src/languages/az.ts index ab7a4cdf5..d154b7ab4 100644 --- a/packages/translations/src/languages/az.ts +++ b/packages/translations/src/languages/az.ts @@ -194,10 +194,14 @@ export const azTranslations: DefaultTranslationsObject = { columns: 'Sütunlar', columnToSort: 'Sıralamağa sütun', confirm: 'Təsdiqlə', + confirmCopy: 'Kopyanı təsdiqləyin', confirmDeletion: 'Silməni təsdiqlə', confirmDuplication: 'Dublikasiyanı təsdiqlə', copied: 'Kopyalandı', copy: 'Kopyala', + copying: 'Kopyalama', + copyWarning: + 'Siz {{label}} {{title}} üçün {{from}} ilə {{to}} -nu üzərindən yazmaq ətrafındasınız. Eminsiniz?', create: 'Yarat', created: 'Yaradıldı', createdAt: 'Yaradıldığı tarix', @@ -271,6 +275,7 @@ export const azTranslations: DefaultTranslationsObject = { open: 'Aç', or: 'Və ya', order: 'Sıra', + overwriteExistingData: 'Mövcud sahə məlumatlarını yenidən yazın', pageNotFound: 'Səhifə tapılmadı', password: 'Şifrə', payloadSettings: 'Payload Parametrləri', @@ -303,6 +308,8 @@ export const azTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" uğurla silindi.', true: 'Doğru', unauthorized: 'İcazəsiz', + unsavedChanges: + 'Sizin saxlanılmamış dəyişiklikləriniz var. Davam etmədən əvvəl saxlayın və ya atın.', unsavedChangesDuplicate: 'Saxlanılmamış dəyişiklikləriniz var. Dublikatla davam etmək istəyirsiniz?', untitled: 'Başlıqsız', @@ -319,6 +326,14 @@ export const azTranslations: DefaultTranslationsObject = { viewReadOnly: 'Yalnız oxu rejimində bax', welcome: 'Xoş gəldiniz', }, + localization: { + cannotCopySameLocale: 'Eyni dildə köçürmək mümkün deyil', + copyFrom: 'Kopyalayın', + copyFromTo: '{{from}}-dan {{to}}-ya kopyalama', + copyTo: 'Köçür', + copyToLocale: 'Yerliyə köçürün', + selectLocaleToCopy: 'Köçürmək üçün yerli seçin', + }, operators: { contains: 'daxilində', equals: 'bərabərdir', diff --git a/packages/translations/src/languages/bg.ts b/packages/translations/src/languages/bg.ts index 9249bbbe3..791b2e606 100644 --- a/packages/translations/src/languages/bg.ts +++ b/packages/translations/src/languages/bg.ts @@ -193,10 +193,14 @@ export const bgTranslations: DefaultTranslationsObject = { columns: 'Колони', columnToSort: 'Колона за сортиране', confirm: 'Потвърди', + confirmCopy: 'Потвърди копирането', confirmDeletion: 'Потвърди изтриване', confirmDuplication: 'Потвърди дупликация', copied: 'Копирано', copy: 'Копирай', + copying: 'Копиране', + copyWarning: + 'Предстои да презапишете {{to}} с {{from}} за {{label}} {{title}}. Сигурни ли сте?', create: 'Създай', created: 'Създаден', createdAt: 'Създаден на', @@ -270,6 +274,7 @@ export const bgTranslations: DefaultTranslationsObject = { open: 'Отвори', or: 'Или', order: 'Ред', + overwriteExistingData: 'Презапишете съществуващите данни в полето', pageNotFound: 'Страницата не беше открита', password: 'Парола', payloadSettings: 'Настройки на Payload', @@ -302,6 +307,7 @@ export const bgTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" успешно изтрит.', true: 'Вярно', unauthorized: 'Неоторизиран', + unsavedChanges: 'Имате незапазени промени. Запазете или отхвърлете преди да продължите.', unsavedChangesDuplicate: 'Имаш незапазени промени. Искаш ли да продължиш да дупликираш?', untitled: 'Неозаглавен', updatedAt: 'Обновен на', @@ -317,6 +323,14 @@ export const bgTranslations: DefaultTranslationsObject = { viewReadOnly: 'Преглед само за четене', welcome: 'Добре дошъл', }, + localization: { + cannotCopySameLocale: 'Не може да се копира в същата локация', + copyFrom: 'Копирай от', + copyFromTo: 'Копиране от {{from}} към {{to}}', + copyTo: 'Копирай в', + copyToLocale: 'Копирайте в местното', + selectLocaleToCopy: 'Изберете място за копиране', + }, operators: { contains: 'съдържа', equals: 'е равно на', diff --git a/packages/translations/src/languages/cs.ts b/packages/translations/src/languages/cs.ts index 54be96d69..75234f075 100644 --- a/packages/translations/src/languages/cs.ts +++ b/packages/translations/src/languages/cs.ts @@ -193,10 +193,13 @@ export const csTranslations: DefaultTranslationsObject = { columns: 'Sloupce', columnToSort: 'Sloupec k seřazení', confirm: 'Potvrdit', + confirmCopy: 'Potvrzení kopie', confirmDeletion: 'Potvrdit odstranění', confirmDuplication: 'Potvrdit duplikaci', copied: 'Zkopírováno', copy: 'Kopírovat', + copying: 'Kopírování', + copyWarning: 'Chystáte se přepsat {{to}} s {{from}} pro {{label}} {{title}}. Jste si jistý?', create: 'Vytvořit', created: 'Vytvořeno', createdAt: 'Vytvořeno v', @@ -270,6 +273,7 @@ export const csTranslations: DefaultTranslationsObject = { open: 'Otevřít', or: 'Nebo', order: 'Pořadí', + overwriteExistingData: 'Přepsat existující data pole', pageNotFound: 'Stránka nenalezena', password: 'Heslo', payloadSettings: 'Payload nastavení', @@ -302,6 +306,7 @@ export const csTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" úspěšně smazáno.', true: 'Pravda', unauthorized: 'Neoprávněný', + unsavedChanges: 'Máte neuložené změny. Uložte nebo zahoďte před pokračováním.', unsavedChangesDuplicate: 'Máte neuložené změny. Chtěli byste pokračovat v duplikování?', untitled: 'Bez názvu', updatedAt: 'Aktualizováno v', @@ -317,6 +322,14 @@ export const csTranslations: DefaultTranslationsObject = { viewReadOnly: 'Zobrazit pouze pro čtení', welcome: 'Vítejte', }, + localization: { + cannotCopySameLocale: 'Nelze kopírovat do stejného umístění', + copyFrom: 'Kopírovat z', + copyFromTo: 'Kopírování z {{from}} do {{to}}', + copyTo: 'Kopírovat do', + copyToLocale: 'Kopírovat do lokalizace', + selectLocaleToCopy: 'Vyberte lokalitu ke kopírování', + }, operators: { contains: 'obsahuje', equals: 'rovná se', diff --git a/packages/translations/src/languages/da.ts b/packages/translations/src/languages/da.ts index f7a0f5502..22b38bb95 100644 --- a/packages/translations/src/languages/da.ts +++ b/packages/translations/src/languages/da.ts @@ -193,10 +193,14 @@ export const daTranslations: DefaultTranslationsObject = { columns: 'Kolonner', columnToSort: 'Kolonne at sortere', confirm: 'Bekræft', + confirmCopy: 'Bekræft kopi', confirmDeletion: 'Bekræft sletning', confirmDuplication: 'Bekræft duplikering', copied: 'Kopieret', copy: 'Kopier', + copying: 'Kopiering', + copyWarning: + 'Du er lige ved at overskrive {{to}} med {{from}} for {{label}} {{title}}. Er du sikker?', create: 'Opret', created: 'Oprettet', createdAt: 'Oprettet til', @@ -269,6 +273,7 @@ export const daTranslations: DefaultTranslationsObject = { open: 'Åben', or: 'Eller', order: 'Rækkefølge', + overwriteExistingData: 'Overskriv eksisterende feltdata', pageNotFound: 'Siden blev ikke fundet', password: 'Adgangskode', payloadSettings: 'Payload-indstillinger', @@ -301,6 +306,7 @@ export const daTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" slettet.', true: 'Sandt', unauthorized: 'Uautoriseret', + unsavedChanges: 'Du har ikke gemte ændringer. Gem eller kassér før fortsættelse.', unsavedChangesDuplicate: 'Du har ikke-gemte ændringer. Vil du fortsætte med at duplikere?', untitled: 'Uden titel', updatedAt: 'Opdateret ved', @@ -316,6 +322,14 @@ export const daTranslations: DefaultTranslationsObject = { viewReadOnly: 'Vis kun-læsning', welcome: 'Velkommen', }, + localization: { + cannotCopySameLocale: 'Kan ikke kopiere til den samme lokalitet', + copyFrom: 'Kopier fra', + copyFromTo: 'Kopierer fra {{from}} til {{to}}', + copyTo: 'Kopier til', + copyToLocale: 'Kopier til lokal', + selectLocaleToCopy: 'Vælg lokalitet til kopiering', + }, operators: { contains: 'Indeholder', equals: 'Lig med', diff --git a/packages/translations/src/languages/de.ts b/packages/translations/src/languages/de.ts index b44fa7b24..c6af96859 100644 --- a/packages/translations/src/languages/de.ts +++ b/packages/translations/src/languages/de.ts @@ -198,10 +198,14 @@ export const deTranslations: DefaultTranslationsObject = { columns: 'Spalten', columnToSort: 'Spalten zum Sortieren', confirm: 'Bestätigen', + confirmCopy: 'Kopie bestätigen', confirmDeletion: 'Löschen bestätigen', confirmDuplication: 'Duplizieren bestätigen', copied: 'Kopiert', copy: 'Kopieren', + copying: 'Kopieren', + copyWarning: + 'Sie sind dabei, {{to}} mit {{from}} für {{label}} {{title}} zu überschreiben. Sind Sie sicher?', create: 'Erstellen', created: 'Erstellt', createdAt: 'Erstellt am', @@ -275,6 +279,7 @@ export const deTranslations: DefaultTranslationsObject = { open: 'Öffnen', or: 'oder', order: 'Reihenfolge', + overwriteExistingData: 'Überschreiben Sie vorhandene Felddaten', pageNotFound: 'Seite nicht gefunden', password: 'Passwort', payloadSettings: 'Payload Einstellungen', @@ -307,6 +312,8 @@ export const deTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} {{title}} wurde erfolgreich gelöscht.', true: 'Wahr', unauthorized: 'Nicht autorisiert', + unsavedChanges: + 'Sie haben ungespeicherte Änderungen. Speichern oder verwerfen Sie diese, bevor Sie fortfahren.', unsavedChangesDuplicate: 'Du hast ungespeicherte Änderungen, möchtest du mit dem Duplizieren fortfahren?', untitled: 'ohne Titel', @@ -323,6 +330,14 @@ export const deTranslations: DefaultTranslationsObject = { viewReadOnly: 'Nur-Lese-Ansicht', welcome: 'Willkommen', }, + localization: { + cannotCopySameLocale: 'Kann nicht in dieselbe Gebietsschema kopieren', + copyFrom: 'Kopieren von', + copyFromTo: 'Kopieren von {{from}} zu {{to}}', + copyTo: 'Kopieren nach', + copyToLocale: 'Kopieren in das Gebietsschema', + selectLocaleToCopy: 'Wählen Sie den Ort zum Kopieren aus', + }, operators: { contains: 'enthält', equals: 'gleich', diff --git a/packages/translations/src/languages/en.ts b/packages/translations/src/languages/en.ts index 5d0d1fbca..05262ee2f 100644 --- a/packages/translations/src/languages/en.ts +++ b/packages/translations/src/languages/en.ts @@ -195,10 +195,14 @@ export const enTranslations = { columns: 'Columns', columnToSort: 'Column to Sort', confirm: 'Confirm', + confirmCopy: 'Confirm copy', confirmDeletion: 'Confirm deletion', confirmDuplication: 'Confirm duplication', copied: 'Copied', copy: 'Copy', + copying: 'Copying', + copyWarning: + 'You are about to overwrite {{to}} with {{from}} for {{label}} {{title}}. Are you sure?', create: 'Create', created: 'Created', createdAt: 'Created At', @@ -272,6 +276,7 @@ export const enTranslations = { open: 'Open', or: 'Or', order: 'Order', + overwriteExistingData: 'Overwrite existing field data', pageNotFound: 'Page not found', password: 'Password', payloadSettings: 'Payload Settings', @@ -304,6 +309,7 @@ export const enTranslations = { titleDeleted: '{{label}} "{{title}}" successfully deleted.', true: 'True', unauthorized: 'Unauthorized', + unsavedChanges: 'You have unsaved changes. Save or discard before continuing.', unsavedChangesDuplicate: 'You have unsaved changes. Would you like to continue to duplicate?', untitled: 'Untitled', updatedAt: 'Updated At', @@ -319,6 +325,14 @@ export const enTranslations = { viewReadOnly: 'View read-only', welcome: 'Welcome', }, + localization: { + cannotCopySameLocale: 'Cannot copy to the same locale', + copyFrom: 'Copy from', + copyFromTo: 'Copying from {{from}} to {{to}}', + copyTo: 'Copy to', + copyToLocale: 'Copy to locale', + selectLocaleToCopy: 'Select locale to copy', + }, operators: { contains: 'contains', equals: 'equals', diff --git a/packages/translations/src/languages/es.ts b/packages/translations/src/languages/es.ts index 62026fd86..dd6af3906 100644 --- a/packages/translations/src/languages/es.ts +++ b/packages/translations/src/languages/es.ts @@ -198,10 +198,14 @@ export const esTranslations: DefaultTranslationsObject = { columns: 'Columnas', columnToSort: 'Columna de ordenado', confirm: 'Confirmar', + confirmCopy: 'Confirmar copia', confirmDeletion: 'Confirmar eliminación', confirmDuplication: 'Confirmar duplicado', copied: 'Copiado', copy: 'Copiar', + copying: 'Copiando', + copyWarning: + 'Estás a punto de sobrescribir {{to}} con {{from}} para {{label}} {{title}}. ¿Estás seguro?', create: 'Crear', created: 'Creado', createdAt: 'Fecha de creación', @@ -275,6 +279,7 @@ export const esTranslations: DefaultTranslationsObject = { open: 'Abrir', or: 'O', order: 'Orden', + overwriteExistingData: 'Sobrescribir los datos del campo existente', pageNotFound: 'Página no encontrada', password: 'Contraseña', payloadSettings: 'Configuración de la carga', @@ -307,6 +312,7 @@ export const esTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} {{title}} eliminado correctamente.', true: 'Verdadero', unauthorized: 'No autorizado', + unsavedChanges: 'Tiene cambios no guardados. Guarde o descarte antes de continuar.', unsavedChangesDuplicate: 'Tienes cambios sin guardar. ¿Deseas continuar para duplicar?', untitled: 'Sin título', updatedAt: 'Fecha de modificado', @@ -322,6 +328,14 @@ export const esTranslations: DefaultTranslationsObject = { viewReadOnly: 'Ver solo lectura', welcome: 'Bienvenido', }, + localization: { + cannotCopySameLocale: 'No se puede copiar al mismo lugar', + copyFrom: 'Copiar de', + copyFromTo: 'Copiando de {{from}} a {{to}}', + copyTo: 'Copia a', + copyToLocale: 'Copiar a localización', + selectLocaleToCopy: 'Seleccione la ubicación para copiar', + }, operators: { contains: 'contiene', equals: 'igual', diff --git a/packages/translations/src/languages/fa.ts b/packages/translations/src/languages/fa.ts index f24e41098..df4f5bca9 100644 --- a/packages/translations/src/languages/fa.ts +++ b/packages/translations/src/languages/fa.ts @@ -193,10 +193,14 @@ export const faTranslations: DefaultTranslationsObject = { columns: 'ستون‌ها', columnToSort: 'ستون برای مرتب‌سازی', confirm: 'تأیید', + confirmCopy: 'تأیید کپی', confirmDeletion: 'تأئید عملیات حذف', confirmDuplication: 'تأئید رونوشت', copied: 'رونوشت شده', copy: 'رونوشت', + copying: 'کپی کردن', + copyWarning: + 'شما در حال استفاده از {{from}} به جای {{to}} برای {{label}} {{title}} هستید. آیا مطمئن هستید؟', create: 'ساختن', created: 'ساخته شده', createdAt: 'ساخته شده در', @@ -270,6 +274,7 @@ export const faTranslations: DefaultTranslationsObject = { open: 'باز کردن', or: 'یا', order: 'چیدمان', + overwriteExistingData: 'بازنویسی داده‌های فیلد موجود', pageNotFound: 'برگه یافت نشد', password: 'گذرواژه', payloadSettings: 'تنظیمات پی‌لود', @@ -302,6 +307,7 @@ export const faTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" با موفقیت پاک شد.', true: 'درست', unauthorized: 'غیرمجاز', + unsavedChanges: 'تغییرات ذخیره نشده ای دارید. قبل از ادامه ذخیره کنید یا رد کنید.', unsavedChangesDuplicate: 'شما تغییرات ذخیره نشده دارید. مطمئنید میخواهید به رونوشت ادامه دهید؟', untitled: 'بدون عنوان', updatedAt: 'بروز شده در', @@ -317,6 +323,14 @@ export const faTranslations: DefaultTranslationsObject = { viewReadOnly: 'فقط برای خواندن مشاهده کنید', welcome: 'خوش‌آمدید', }, + localization: { + cannotCopySameLocale: 'نمی توان به همان محل نسخه برداری کرد', + copyFrom: 'کپی از', + copyFromTo: 'کپی از {{from}} به {{to}}', + copyTo: 'کپی کنید به', + copyToLocale: 'کپی به محلی', + selectLocaleToCopy: 'انتخاب مکان برای کپی کردن', + }, operators: { contains: 'شامل', equals: 'برابر با', diff --git a/packages/translations/src/languages/fr.ts b/packages/translations/src/languages/fr.ts index 085970eba..5dd8899d4 100644 --- a/packages/translations/src/languages/fr.ts +++ b/packages/translations/src/languages/fr.ts @@ -201,10 +201,14 @@ export const frTranslations: DefaultTranslationsObject = { columns: 'Colonnes', columnToSort: 'Colonne à trier', confirm: 'Confirmer', + confirmCopy: 'Confirmer la copie', confirmDeletion: 'Confirmer la suppression', confirmDuplication: 'Confirmer la duplication', copied: 'Copié', copy: 'Copie', + copying: 'Copie', + copyWarning: + "Vous êtes sur le point d'écraser {{to}} avec {{from}} pour {{label}} {{title}}. Êtes-vous sûr ?", create: 'Créer', created: 'Créé(e)', createdAt: 'Créé(e) à', @@ -278,6 +282,7 @@ export const frTranslations: DefaultTranslationsObject = { open: 'Ouvrir', or: 'ou', order: 'Ordre', + overwriteExistingData: 'Écraser les données existantes du champ', pageNotFound: 'Page non trouvée', password: 'Mot de passe', payloadSettings: 'Paramètres de Payload', @@ -310,6 +315,8 @@ export const frTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" supprimé(e) avec succès.', true: 'Vrai', unauthorized: 'Non autorisé', + unsavedChanges: + 'Vous avez des modifications non enregistrées. Enregistrez ou supprimez avant de continuer.', unsavedChangesDuplicate: 'Vous avez des changements non enregistrés. Souhaitez-vous continuer la duplication ?', untitled: 'Sans titre', @@ -326,6 +333,14 @@ export const frTranslations: DefaultTranslationsObject = { viewReadOnly: 'Afficher en lecture seule', welcome: 'Bienvenue', }, + localization: { + cannotCopySameLocale: 'Impossible de copier dans le même endroit', + copyFrom: 'Copier de', + copyFromTo: 'Copier de {{from}} à {{to}}', + copyTo: 'Copier à', + copyToLocale: 'Copier vers le lieu', + selectLocaleToCopy: 'Sélectionnez la locale à copier', + }, operators: { contains: 'contient', equals: 'est égal à', diff --git a/packages/translations/src/languages/he.ts b/packages/translations/src/languages/he.ts index 02fef5b95..82d4c8c16 100644 --- a/packages/translations/src/languages/he.ts +++ b/packages/translations/src/languages/he.ts @@ -189,10 +189,14 @@ export const heTranslations: DefaultTranslationsObject = { columns: 'עמודות', columnToSort: 'עמודה למיון', confirm: 'אישור', + confirmCopy: 'אשר עותק', confirmDeletion: 'אישור מחיקה', confirmDuplication: 'אישור שכפול', copied: 'הועתק', copy: 'העתק', + copying: 'העתקה', + copyWarning: + 'אתה עומד לדרוס את {{to}} באמצעות {{from}} עבור {{label}} {{title}}. האם אתה בטוח?', create: 'יצירה', created: 'נוצר', createdAt: 'נוצר בתאריך', @@ -265,6 +269,7 @@ export const heTranslations: DefaultTranslationsObject = { open: 'פתח', or: 'או', order: 'סדר', + overwriteExistingData: 'דרוס את נתוני השדה הקיימים', pageNotFound: 'הדף לא נמצא', password: 'סיסמה', payloadSettings: 'הגדרות מערכת Payload', @@ -297,6 +302,7 @@ export const heTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" נמחק בהצלחה.', true: 'True', unauthorized: 'אין הרשאה', + unsavedChanges: 'יש לך שינויים שלא נשמרו. שמור או מחק לפני שתמשיך.', unsavedChangesDuplicate: 'יש לך שינויים שלא נשמרו. האם ברצונך להמשיך לשכפל?', untitled: 'ללא כותרת', updatedAt: 'עודכן בתאריך', @@ -312,6 +318,14 @@ export const heTranslations: DefaultTranslationsObject = { viewReadOnly: 'הצג קריאה בלבד', welcome: 'ברוך הבא', }, + localization: { + cannotCopySameLocale: 'לא ניתן להעתיק לאותו מקום', + copyFrom: 'העתק מ', + copyFromTo: 'העתקה מ-{{from}} ל-{{to}}', + copyTo: 'העתק אל', + copyToLocale: 'העתק למקום', + selectLocaleToCopy: 'בחר מיקום להעתקה', + }, operators: { contains: 'מכיל', equals: 'שווה ל', diff --git a/packages/translations/src/languages/hr.ts b/packages/translations/src/languages/hr.ts index 543a28750..08e03b543 100644 --- a/packages/translations/src/languages/hr.ts +++ b/packages/translations/src/languages/hr.ts @@ -194,10 +194,14 @@ export const hrTranslations: DefaultTranslationsObject = { columns: 'Stupci', columnToSort: 'Stupac za sortiranje', confirm: 'Potvrdi', + confirmCopy: 'Potvrdi kopiju', confirmDeletion: 'Potvrdi brisanje', confirmDuplication: 'Potvrdi duplikaciju', copied: 'Kopirano', copy: 'Kopiraj', + copying: 'Kopiranje', + copyWarning: + 'Na rubu ste prepisivanja {{to}} s {{from}} za {{label}} {{title}}. Jeste li sigurni?', create: 'Izradi', created: 'Kreirano', createdAt: 'Izrađeno u', @@ -271,6 +275,7 @@ export const hrTranslations: DefaultTranslationsObject = { open: 'Otvori', or: 'ili', order: 'Poredak', + overwriteExistingData: 'Prepišite postojeće podatke u polju', pageNotFound: 'Stranica nije pronađena', password: 'Lozinka', payloadSettings: 'Payload postavke', @@ -303,6 +308,7 @@ export const hrTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" uspješno izbrisano.', true: 'Istinito', unauthorized: 'Neovlašteno', + unsavedChanges: 'Imate nespremljene promjene. Spremite ili odbacite prije nastavka.', unsavedChangesDuplicate: 'Imate nespremljene promjene. Želite li nastaviti s dupliciranjem?', untitled: 'Bez naslova', updatedAt: 'Ažurirano u', @@ -318,6 +324,14 @@ export const hrTranslations: DefaultTranslationsObject = { viewReadOnly: 'Pogledaj samo za čitanje', welcome: 'Dobrodošli', }, + localization: { + cannotCopySameLocale: 'Ne može se kopirati na istu lokaciju', + copyFrom: 'Kopiraj iz', + copyFromTo: 'Kopiranje iz {{from}} u {{to}}', + copyTo: 'Kopiraj na', + copyToLocale: 'Kopiraj na lokaciju', + selectLocaleToCopy: 'Odaberite mjesto za kopiranje', + }, operators: { contains: 'sadrži', equals: 'jednako', diff --git a/packages/translations/src/languages/hu.ts b/packages/translations/src/languages/hu.ts index 4c8a2a228..6772ff045 100644 --- a/packages/translations/src/languages/hu.ts +++ b/packages/translations/src/languages/hu.ts @@ -196,10 +196,14 @@ export const huTranslations: DefaultTranslationsObject = { columns: 'Oszlopok', columnToSort: 'Rendezendő oszlop', confirm: 'Megerősítés', + confirmCopy: 'Jóváhagyott másolat', confirmDeletion: 'Törlés megerősítése', confirmDuplication: 'Duplikáció megerősítése', copied: 'Másolva', copy: 'Másolás', + copying: 'Másolás', + copyWarning: + 'Ön azzal készül felülírni {{to}} -t {{from}} -mal a {{label}} {{title}} számára. Biztos benne?', create: 'Létrehozás', created: 'Létrehozva', createdAt: 'Létrehozva:', @@ -273,6 +277,7 @@ export const huTranslations: DefaultTranslationsObject = { open: 'Megnyitás', or: 'Vagy', order: 'Sorrend', + overwriteExistingData: 'Írja felül a meglévő mezőadatokat', pageNotFound: 'Az oldal nem található', password: 'Jelszó', payloadSettings: 'Payload beállítások', @@ -305,6 +310,7 @@ export const huTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" sikeresen törölve.', true: 'Igaz', unauthorized: 'Jogosulatlan', + unsavedChanges: 'Vannak mentetlen változtatásai. Mentsen vagy dobja el mielőtt folytatja.', unsavedChangesDuplicate: 'Nem mentett módosításai vannak. Szeretné folytatni a duplikációt?', untitled: 'Névtelen', updatedAt: 'Frissítve:', @@ -320,6 +326,14 @@ export const huTranslations: DefaultTranslationsObject = { viewReadOnly: 'Csak olvasható nézet', welcome: 'Üdvözöljük', }, + localization: { + cannotCopySameLocale: 'Nem lehet ugyanarra a helyre másolni', + copyFrom: 'Másolás innen', + copyFromTo: 'Másolás {{from}}-ról {{to}}-ra', + copyTo: 'Másolja ide', + copyToLocale: 'Másolás a helyi verzióba', + selectLocaleToCopy: 'Válassza ki a másolni kívánt területet.', + }, operators: { contains: 'tartalmaz', equals: 'egyenlő', diff --git a/packages/translations/src/languages/it.ts b/packages/translations/src/languages/it.ts index 8a0554abc..88394f282 100644 --- a/packages/translations/src/languages/it.ts +++ b/packages/translations/src/languages/it.ts @@ -197,10 +197,13 @@ export const itTranslations: DefaultTranslationsObject = { columns: 'Colonne', columnToSort: 'Colonna da Ordinare', confirm: 'Conferma', + confirmCopy: 'Conferma copia', confirmDeletion: "Conferma l'eliminazione", confirmDuplication: 'Conferma la duplicazione', copied: 'Copiato', copy: 'Copia', + copying: 'Copia', + copyWarning: 'Stai per sovrascrivere {{to}} con {{from}} per {{label}} {{title}}. Sei sicuro?', create: 'Crea', created: 'Data di creazione', createdAt: 'Creato il', @@ -274,6 +277,7 @@ export const itTranslations: DefaultTranslationsObject = { open: 'Apri', or: 'Oppure', order: 'Ordine', + overwriteExistingData: 'Sovrascrivi i dati del campo esistente', pageNotFound: 'Pagina non trovata', password: 'Password', payloadSettings: 'Impostazioni di Payload', @@ -306,6 +310,7 @@ export const itTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} {{title}} eliminato con successo.', true: 'Vero', unauthorized: 'Non autorizzato', + unsavedChanges: 'Hai delle modifiche non salvate. Salva o scarta prima di continuare.', unsavedChangesDuplicate: 'Sono presenti modifiche non salvate. Vuoi continuare a duplicare?', untitled: 'Senza titolo', updatedAt: 'Aggiornato il', @@ -321,6 +326,14 @@ export const itTranslations: DefaultTranslationsObject = { viewReadOnly: 'Visualizza solo lettura', welcome: 'Benvenuto', }, + localization: { + cannotCopySameLocale: 'Non è possibile copiare nella stessa posizione', + copyFrom: 'Copia da', + copyFromTo: 'Copiando da {{from}} a {{to}}', + copyTo: 'Copia per', + copyToLocale: 'Copia in locale', + selectLocaleToCopy: 'Seleziona la località da copiare', + }, operators: { contains: 'contiene', equals: 'uguale', diff --git a/packages/translations/src/languages/ja.ts b/packages/translations/src/languages/ja.ts index d06e68649..f5ea60f53 100644 --- a/packages/translations/src/languages/ja.ts +++ b/packages/translations/src/languages/ja.ts @@ -194,10 +194,14 @@ export const jaTranslations: DefaultTranslationsObject = { columns: '行の表示', columnToSort: '並び替え対象の行', confirm: '実行', + confirmCopy: 'コピーを確認します', confirmDeletion: '削除の確認', confirmDuplication: '複製の確認', copied: 'コピーしました', copy: 'コピー', + copying: 'コピーする', + copyWarning: + 'あなたは{{label}} {{title}}の{{to}}を{{from}}で上書きしようとしています。よろしいですか?', create: '作成', created: '作成', createdAt: '作成日', @@ -271,6 +275,7 @@ export const jaTranslations: DefaultTranslationsObject = { open: '開く', or: 'または', order: '表示順', + overwriteExistingData: '既存のフィールドデータを上書きする', pageNotFound: 'ページが見つかりません', password: 'パスワード', payloadSettings: 'Payload 設定', @@ -303,6 +308,7 @@ export const jaTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" が削除されました。', true: '真実', unauthorized: '未認証', + unsavedChanges: '保存されていない変更があります。続行する前に保存または破棄してください。', unsavedChangesDuplicate: '未保存の変更があります。複製を続けますか?', untitled: 'Untitled', updatedAt: '更新日', @@ -318,6 +324,14 @@ export const jaTranslations: DefaultTranslationsObject = { viewReadOnly: '読み取り専用で表示', welcome: 'ようこそ', }, + localization: { + cannotCopySameLocale: '同じロケールにはコピーできません', + copyFrom: 'からコピーする', + copyFromTo: '{{from}}から{{to}}へのコピー', + copyTo: 'コピー先', + copyToLocale: 'ロケールにコピー', + selectLocaleToCopy: 'コピーするロケールを選択してください', + }, operators: { contains: '含む', equals: '等しい', diff --git a/packages/translations/src/languages/ko.ts b/packages/translations/src/languages/ko.ts index 8fe4877d4..c4d9f7e80 100644 --- a/packages/translations/src/languages/ko.ts +++ b/packages/translations/src/languages/ko.ts @@ -193,10 +193,13 @@ export const koTranslations: DefaultTranslationsObject = { columns: '열', columnToSort: '정렬할 열', confirm: '확인', + confirmCopy: '복사 확인', confirmDeletion: '삭제하시겠습니까?', confirmDuplication: '복제하시겠습니까?', copied: '복사됨', copy: '복사', + copying: '복사하기', + copyWarning: '{{label}} {{title}}에 대해 {{from}}으로 {{to}}를 덮어쓰려고 합니다. 확실합니까?', create: '생성', created: '생성됨', createdAt: '생성 일시', @@ -270,6 +273,7 @@ export const koTranslations: DefaultTranslationsObject = { open: '열기', or: '또는', order: '순서', + overwriteExistingData: '기존 필드 데이터 덮어쓰기', pageNotFound: '페이지를 찾을 수 없음', password: '비밀번호', payloadSettings: 'Payload 설정', @@ -302,6 +306,7 @@ export const koTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}"을(를) 삭제했습니다.', true: '참', unauthorized: '권한 없음', + unsavedChanges: '저장되지 않은 변경 사항이 있습니다. 계속하기 전에 저장하거나 무시하십시오.', unsavedChangesDuplicate: '저장되지 않은 변경 사항이 있습니다. 복제를 계속하시겠습니까?', untitled: '제목 없음', updatedAt: '업데이트 일시', @@ -317,6 +322,14 @@ export const koTranslations: DefaultTranslationsObject = { viewReadOnly: '읽기 전용으로 보기', welcome: '환영합니다', }, + localization: { + cannotCopySameLocale: '동일한 로캘에 복사할 수 없습니다.', + copyFrom: '에서 복사하십시오.', + copyFromTo: '{{from}}에서 {{to}}로 복사하기', + copyTo: '복사하기', + copyToLocale: '로케일로 복사', + selectLocaleToCopy: '복사할 지역을 선택하십시오.', + }, operators: { contains: '포함', equals: '같음', diff --git a/packages/translations/src/languages/my.ts b/packages/translations/src/languages/my.ts index f0048fe41..7fe50c43d 100644 --- a/packages/translations/src/languages/my.ts +++ b/packages/translations/src/languages/my.ts @@ -196,10 +196,14 @@ export const myTranslations: DefaultTranslationsObject = { columns: 'ကော်လံများ', columnToSort: 'ကော်လံ စီရန်', confirm: 'သေချာပါပြီ။', + confirmCopy: 'အောင်မြင်စေသည့်ကူးထားပြီးအတည်ပြုပါ', confirmDeletion: 'ဖျက်တော့မယ်နော်။', confirmDuplication: 'ပုံတူပွားခြင်းကို အတည်ပြုပါ။', copied: 'ကူးယူပြီးပြီ။', copy: 'ကူးယူမည်။', + copying: 'ကူးယူခြင်း', + copyWarning: + 'Anda akan menulis ganti {{to}} dengan {{from}} untuk {{label}} {{title}}. Adakah anda pasti?', create: 'ဖန်တီးမည်။', created: 'ဖန်တီးခဲ့သည်။', createdAt: 'ဖန်တီးခဲ့သည့်အချိန်', @@ -273,6 +277,7 @@ export const myTranslations: DefaultTranslationsObject = { open: 'ဖွင့်မည်။', or: 'သို့မဟုတ်', order: 'အစဉ်လိုက်', + overwriteExistingData: 'Menulis semula data bidang yang sedia ada', pageNotFound: 'ရောက်ရှိနေသော စာမျက်နှာသည် မရှိပါ။', password: 'စကားဝှက်', payloadSettings: 'ရွေးချယ်စရာများ', @@ -305,6 +310,8 @@ export const myTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} {{title}} အောင်မြင်စွာ ဖျက်သိမ်းခဲ့သည်။', true: 'အမှန်', unauthorized: 'အခွင့်မရှိပါ။', + unsavedChanges: + 'Anda mempunyai perubahan yang belum disimpan. Simpan atau buang sebelum meneruskan.', unsavedChangesDuplicate: 'သင့်တွင် မသိမ်းဆည်းရသေးသော ပြောင်းလဲမှုများ ရှိနေပါသည်။ ပုံတူပွားမှာ သေချာပြီလား။', untitled: 'ခေါင်းစဥ်မဲ့', @@ -321,6 +328,14 @@ export const myTranslations: DefaultTranslationsObject = { viewReadOnly: 'ဖတ်ရှုရန်သာကြည့်ပါ', welcome: 'ကြိုဆိုပါတယ်။', }, + localization: { + cannotCopySameLocale: 'Tidak boleh menyalin ke lokasi yang sama', + copyFrom: 'Salin dari', + copyFromTo: 'Menyalin dari {{from}} ke {{to}}', + copyTo: 'Salin ke', + copyToLocale: 'Salin ke tempat setempat', + selectLocaleToCopy: 'Pilih tempatan untuk menyalin', + }, operators: { contains: 'ပါဝင်သည်', equals: 'ညီမျှ', diff --git a/packages/translations/src/languages/nb.ts b/packages/translations/src/languages/nb.ts index d825f139e..05e317e49 100644 --- a/packages/translations/src/languages/nb.ts +++ b/packages/translations/src/languages/nb.ts @@ -194,10 +194,14 @@ export const nbTranslations: DefaultTranslationsObject = { columns: 'Kolonner', columnToSort: 'Kolonne å sortere', confirm: 'Bekreft', + confirmCopy: 'Bekreft kopi', confirmDeletion: 'Bekreft sletting', confirmDuplication: 'Bekreft duplisering', copied: 'Kopiert', copy: 'Kopiér', + copying: 'Kopiering', + copyWarning: + 'Du er i ferd med å overskrive {{to}} med {{from}} for {{label}} {{title}}. Er du sikker?', create: 'Opprett', created: 'Opprettet', createdAt: 'Opprettet', @@ -271,6 +275,7 @@ export const nbTranslations: DefaultTranslationsObject = { open: 'Åpne', or: 'Eller', order: 'Rekkefølge', + overwriteExistingData: 'Overskriv eksisterende feltdata', pageNotFound: 'Siden ble ikke funnet', password: 'Passord', payloadSettings: 'Payload-innstillinger', @@ -303,6 +308,7 @@ export const nbTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" ble slettet.', true: 'Sann', unauthorized: 'Ikke autorisert', + unsavedChanges: 'Du har ulagrede endringer. Lagre eller forkast før du fortsetter.', unsavedChangesDuplicate: 'Du har ulagrede endringer. Vil du fortsette å duplisere?', untitled: 'Uten tittel', updatedAt: 'Oppdatert', @@ -318,6 +324,14 @@ export const nbTranslations: DefaultTranslationsObject = { viewReadOnly: 'Vis skrivebeskyttet', welcome: 'Velkommen', }, + localization: { + cannotCopySameLocale: 'Kan ikke kopiere til samme sted', + copyFrom: 'Kopier fra', + copyFromTo: 'Kopiering fra {{fra}} til {{til}}', + copyTo: 'Kopier til', + copyToLocale: 'Kopiere til lokalt', + selectLocaleToCopy: 'Velg lokalitet for å kopiere', + }, operators: { contains: 'contains', equals: 'lik', diff --git a/packages/translations/src/languages/nl.ts b/packages/translations/src/languages/nl.ts index 60985a0cb..4954ec95b 100644 --- a/packages/translations/src/languages/nl.ts +++ b/packages/translations/src/languages/nl.ts @@ -196,10 +196,14 @@ export const nlTranslations: DefaultTranslationsObject = { columns: 'Kolommen', columnToSort: 'Kolom om te sorteren', confirm: 'Bevestigen', + confirmCopy: 'Bevestig kopie', confirmDeletion: 'Bevestig verwijdering', confirmDuplication: 'Bevestig duplicatie', copied: 'Gekopieerd', copy: 'Kopiëren', + copying: 'Kopiëren', + copyWarning: + 'U staat op het punt om {{to}} te overschrijven met {{from}} voor {{label}} {{title}}. Bent u zeker?', create: 'Aanmaken', created: 'Aangemaakt', createdAt: 'Aangemaakt op', @@ -273,6 +277,7 @@ export const nlTranslations: DefaultTranslationsObject = { open: 'Open', or: 'Of', order: 'Volgorde', + overwriteExistingData: 'Overschrijf bestaande veldgegevens', pageNotFound: 'Pagina niet gevonden', password: 'Wachtwoord', payloadSettings: 'Payload Instellingen', @@ -305,6 +310,7 @@ export const nlTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" succesvol verwijderd.', true: 'Waar', unauthorized: 'Onbevoegd', + unsavedChanges: 'U heeft niet-opgeslagen wijzigingen. Sla op of verwijder voordat u doorgaat.', unsavedChangesDuplicate: 'U heeft onbewaarde wijzigingen. Wilt u doorgaan met dupliceren?', untitled: 'Zonder titel', updatedAt: 'Aangepast op', @@ -320,6 +326,14 @@ export const nlTranslations: DefaultTranslationsObject = { viewReadOnly: 'Alleen-lezen weergave', welcome: 'Welkom', }, + localization: { + cannotCopySameLocale: 'Kan niet naar dezelfde locatie kopiëren', + copyFrom: 'Kopiëren van', + copyFromTo: 'Kopiëren van {{from}} naar {{to}}', + copyTo: 'Kopiëren naar', + copyToLocale: 'Kopieer naar locatie', + selectLocaleToCopy: 'Selecteer locatie om te kopiëren', + }, operators: { contains: 'bevat', equals: 'is gelijk aan', diff --git a/packages/translations/src/languages/pl.ts b/packages/translations/src/languages/pl.ts index b3ddc39d1..6bfc7677b 100644 --- a/packages/translations/src/languages/pl.ts +++ b/packages/translations/src/languages/pl.ts @@ -194,10 +194,14 @@ export const plTranslations: DefaultTranslationsObject = { columns: 'Kolumny', columnToSort: 'Kolumna sortowania', confirm: 'Potwierdź', + confirmCopy: 'Potwierdź kopię', confirmDeletion: 'Potwierdź usunięcie', confirmDuplication: 'Potwierdź duplikację', copied: 'Skopiowano', copy: 'Skopiuj', + copying: 'Kopiowanie', + copyWarning: + 'Zamierzasz nadpisać {{to}} na {{from}} dla {{label}} {{title}}. Czy jesteś pewny?', create: 'Stwórz', created: 'Utworzono', createdAt: 'Data utworzenia', @@ -271,6 +275,7 @@ export const plTranslations: DefaultTranslationsObject = { open: 'Otwórz', or: 'lub', order: 'Kolejność', + overwriteExistingData: 'Nadpisz istniejące dane pola', pageNotFound: 'Strona nie znaleziona', password: 'Hasło', payloadSettings: 'Ustawienia Payload', @@ -303,6 +308,7 @@ export const plTranslations: DefaultTranslationsObject = { titleDeleted: 'Pomyślnie usunięto {{label}} {{title}}', true: 'Prawda', unauthorized: 'Brak autoryzacji', + unsavedChanges: 'Masz niezapisane zmiany. Zapisz lub odrzuć, zanim kontynuujesz.', unsavedChangesDuplicate: 'Masz niezapisane zmiany. Czy chcesz kontynuować duplikowanie?', untitled: 'Bez nazwy', updatedAt: 'Data edycji', @@ -318,6 +324,14 @@ export const plTranslations: DefaultTranslationsObject = { viewReadOnly: 'Widok tylko do odczytu', welcome: 'Witaj', }, + localization: { + cannotCopySameLocale: 'Nie można skopiować do tego samego miejsca.', + copyFrom: 'Kopiuj z', + copyFromTo: 'Kopiowanie z {{from}} do {{to}}', + copyTo: 'Kopiuj do', + copyToLocale: 'Kopiuj do lokalizacji', + selectLocaleToCopy: 'Wybierz lokalizację do skopiowania', + }, operators: { contains: 'zawiera', equals: 'równe', diff --git a/packages/translations/src/languages/pt.ts b/packages/translations/src/languages/pt.ts index 3ee20b095..28208a95f 100644 --- a/packages/translations/src/languages/pt.ts +++ b/packages/translations/src/languages/pt.ts @@ -195,10 +195,14 @@ export const ptTranslations: DefaultTranslationsObject = { columns: 'Colunas', columnToSort: 'Coluna para Ordenar', confirm: 'Confirmar', + confirmCopy: 'Confirme cópia', confirmDeletion: 'Confirmar exclusão', confirmDuplication: 'Confirmar duplicação', copied: 'Copiado', copy: 'Copiar', + copying: 'Copiando', + copyWarning: + 'Você está prestes a sobrescrever {{to}} com {{from}} para {{label}} {{title}}. Tem certeza?', create: 'Criar', created: 'Criado', createdAt: 'Criado Em', @@ -272,6 +276,7 @@ export const ptTranslations: DefaultTranslationsObject = { open: 'Abrir', or: 'Ou', order: 'Ordem', + overwriteExistingData: 'Sobrescrever dados de campo existentes', pageNotFound: 'Página não encontrada', password: 'Senha', payloadSettings: 'Configurações do Payload', @@ -304,6 +309,7 @@ export const ptTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} {{title}} excluído com sucesso.', true: 'Verdadeiro', unauthorized: 'Não autorizado', + unsavedChanges: 'Você tem alterações não salvas. Salve ou descarte antes de continuar.', unsavedChangesDuplicate: 'Você tem mudanças não salvas. Você gostaria de continuar a duplicar?', untitled: 'Sem título', updatedAt: 'Atualizado Em', @@ -319,6 +325,14 @@ export const ptTranslations: DefaultTranslationsObject = { viewReadOnly: 'Visualizar somente leitura', welcome: 'Boas vindas', }, + localization: { + cannotCopySameLocale: 'Não é possível copiar para o mesmo local', + copyFrom: 'Copiar de', + copyFromTo: 'Copiando de {{from}} para {{to}}', + copyTo: 'Copiar para', + copyToLocale: 'Copiar para localidade', + selectLocaleToCopy: 'Selecione o local para copiar', + }, operators: { contains: 'contém', equals: 'igual', diff --git a/packages/translations/src/languages/ro.ts b/packages/translations/src/languages/ro.ts index 651389e7f..95637644f 100644 --- a/packages/translations/src/languages/ro.ts +++ b/packages/translations/src/languages/ro.ts @@ -198,10 +198,14 @@ export const roTranslations: DefaultTranslationsObject = { columns: 'Coloane', columnToSort: 'Coloana de sortat', confirm: 'Confirmați', + confirmCopy: 'Confirmă copierea', confirmDeletion: 'Confirmați ștergerea', confirmDuplication: 'Confirmați duplicarea', copied: 'Copiat', copy: 'Copiați', + copying: 'Copiere', + copyWarning: + 'Sunteți pe cale să suprascrieți {{to}} cu {{from}} pentru {{label}} {{title}}. Sunteți sigur?', create: 'Creează', created: 'Creat', createdAt: 'Creat la', @@ -275,6 +279,7 @@ export const roTranslations: DefaultTranslationsObject = { open: 'Deschide', or: 'Sau', order: 'ORdine', + overwriteExistingData: 'Suprascrieți datele existente din câmp', pageNotFound: 'Pagina nu a fost găsită', password: 'Parola', payloadSettings: 'Setări de Payload', @@ -307,6 +312,7 @@ export const roTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" șters cu succes.', true: 'Adevărat', unauthorized: 'neautorizat(ă)', + unsavedChanges: 'Aveți modificări nesalvate. Salvați sau renunțați înainte de a continua.', unsavedChangesDuplicate: 'Aveți modificări nesalvate. Doriți să continuați să duplicați?', untitled: 'Fără titlu', updatedAt: 'Actualizat la', @@ -322,6 +328,14 @@ export const roTranslations: DefaultTranslationsObject = { viewReadOnly: 'Vizualizare doar pentru citire', welcome: 'Bine ați venit', }, + localization: { + cannotCopySameLocale: 'Nu se poate copia în aceeași localizare', + copyFrom: 'Copiază de la', + copyFromTo: 'Copierea de la {{from}} la {{to}}', + copyTo: 'Copiați în', + copyToLocale: 'Copiați în localizare', + selectLocaleToCopy: 'Selectați localizarea pentru copiere', + }, operators: { contains: 'conține', equals: 'egal cu', diff --git a/packages/translations/src/languages/rs.ts b/packages/translations/src/languages/rs.ts index a60088d36..d807f4702 100644 --- a/packages/translations/src/languages/rs.ts +++ b/packages/translations/src/languages/rs.ts @@ -193,10 +193,14 @@ export const rsTranslations: DefaultTranslationsObject = { columns: 'Колоне', columnToSort: 'Колона за сортирање', confirm: 'Потврди', + confirmCopy: 'Potvrda kopiranja', confirmDeletion: 'Потврди брисање', confirmDuplication: 'Потврди дупликацију', copied: 'Копирано', copy: 'Копирај', + copying: 'Kopiranje', + copyWarning: + 'На путу сте да препишете {{to}} са {{from}} за {{label}} {{title}}. Да ли сте сигурни?', create: 'Креирај', created: 'Креирано', createdAt: 'Креирано у', @@ -270,6 +274,7 @@ export const rsTranslations: DefaultTranslationsObject = { open: 'Отвори', or: 'Или', order: 'Редослед', + overwriteExistingData: 'Prepišite postojeće podatke u polju', pageNotFound: 'Страница није пронађена', password: 'Лозинка', payloadSettings: 'Payload поставке', @@ -302,6 +307,7 @@ export const rsTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" успешно обрисано.', true: 'Istinito', unauthorized: 'Нисте ауторизовани', + unsavedChanges: 'Imate nesačuvane izmene. Sačuvajte ili odbacite pre nego što nastavite.', unsavedChangesDuplicate: 'Имате несачуване промене. Да ли желите наставити са дуплицирањем?', untitled: 'Без наслова', updatedAt: 'Ажурирано у', @@ -317,6 +323,14 @@ export const rsTranslations: DefaultTranslationsObject = { viewReadOnly: 'Прегледај само за читање', welcome: 'Добродошли', }, + localization: { + cannotCopySameLocale: 'Не може се копирати на исту локацију.', + copyFrom: 'Kopiraj iz', + copyFromTo: 'Kopiranje iz {{from}} u {{to}}', + copyTo: 'Kopiraj na', + copyToLocale: 'Kopiraj na lokaciju', + selectLocaleToCopy: 'Izaberite lokalitet za kopiranje', + }, operators: { contains: 'садржи', equals: 'једнако', diff --git a/packages/translations/src/languages/rsLatin.ts b/packages/translations/src/languages/rsLatin.ts index da1c2df41..545ebfaab 100644 --- a/packages/translations/src/languages/rsLatin.ts +++ b/packages/translations/src/languages/rsLatin.ts @@ -193,10 +193,14 @@ export const rsLatinTranslations: DefaultTranslationsObject = { columns: 'Kolone', columnToSort: 'Kolona za sortiranje', confirm: 'Potvrdi', + confirmCopy: 'Potvrdi kopiju', confirmDeletion: 'Potvrdi brisanje', confirmDuplication: 'Potvrdi duplikaciju', copied: 'Kopirano', copy: 'Kopiraj', + copying: 'Kopiranje', + copyWarning: + 'Na korak ste da prepišete {{to}} sa {{from}} za {{label}} {{title}}. Da li ste sigurni?', create: 'Kreiraj', created: 'Kreirano', createdAt: 'Kreirano u', @@ -270,6 +274,7 @@ export const rsLatinTranslations: DefaultTranslationsObject = { open: 'Otvori', or: 'Ili', order: 'Redosled', + overwriteExistingData: 'Prepiši postojeće podatke iz polja', pageNotFound: 'Stranica nije pronađena', password: 'Lozinka', payloadSettings: 'Payload postavke', @@ -302,6 +307,7 @@ export const rsLatinTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" uspešno obrisano.', true: 'Istinito', unauthorized: 'Niste autorizovani', + unsavedChanges: 'Imate nesačuvane promene. Sačuvajte ili odbacite pre nego što nastavite.', unsavedChangesDuplicate: 'Imate nesačuvane promene. Da li želite nastaviti sa dupliciranjem?', untitled: 'Bez naslova', updatedAt: 'Ažurirano u', @@ -317,6 +323,14 @@ export const rsLatinTranslations: DefaultTranslationsObject = { viewReadOnly: 'Pregledaj samo za čitanje', welcome: 'Dobrodošli', }, + localization: { + cannotCopySameLocale: 'Ne može se kopirati na istu lokaciju', + copyFrom: 'Kopiraj iz', + copyFromTo: 'Kopiranje iz {{from}} u {{to}}', + copyTo: 'Kopiraj u', + copyToLocale: 'Kopiraj na lokaciju', + selectLocaleToCopy: 'Izaberite lokalitet za kopiranje', + }, operators: { contains: 'sadrži', equals: 'jednako', diff --git a/packages/translations/src/languages/ru.ts b/packages/translations/src/languages/ru.ts index 4c0b9864f..dcf812304 100644 --- a/packages/translations/src/languages/ru.ts +++ b/packages/translations/src/languages/ru.ts @@ -196,10 +196,14 @@ export const ruTranslations: DefaultTranslationsObject = { columns: 'Колонки', columnToSort: 'Колонка для сортировки', confirm: 'Подтвердить', + confirmCopy: 'Подтвердить копирование', confirmDeletion: 'Подтвердить удаление', confirmDuplication: 'Подтвердить копирование', copied: 'Скопировано', copy: 'Скопировать', + copying: 'Копирование', + copyWarning: + 'Вы собираетесь перезаписать {{to}} на {{from}} для {{label}} {{title}}. Вы уверены?', create: 'Создать', created: 'Создано', createdAt: 'Дата создания', @@ -273,6 +277,7 @@ export const ruTranslations: DefaultTranslationsObject = { open: 'Открыть', or: 'Или же', order: 'Порядок', + overwriteExistingData: 'Перезаписать существующие данные поля', pageNotFound: 'Страница не найдена', password: 'Пароль', payloadSettings: 'Настройки Payload', @@ -305,6 +310,8 @@ export const ruTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} {{title}} успешно удалено.', true: 'Правда', unauthorized: 'Нет доступа', + unsavedChanges: + 'У вас есть несохраненные изменения. Сохраните или отмените их перед продолжением.', unsavedChangesDuplicate: 'У вас есть несохраненные изменения. Вы хотите продолжить дублирование?', untitled: 'Без названия', @@ -321,6 +328,14 @@ export const ruTranslations: DefaultTranslationsObject = { viewReadOnly: 'Просмотр только для чтения', welcome: 'Добро пожаловать', }, + localization: { + cannotCopySameLocale: 'Невозможно скопировать в ту же локаль', + copyFrom: 'Скопировать из', + copyFromTo: 'Копирование из {{from}} в {{to}}', + copyTo: 'Копировать в', + copyToLocale: 'Копировать в локаль', + selectLocaleToCopy: 'Выберите локаль для копирования', + }, operators: { contains: 'содержит', equals: 'равно', diff --git a/packages/translations/src/languages/sk.ts b/packages/translations/src/languages/sk.ts index 8559eb505..2501da497 100644 --- a/packages/translations/src/languages/sk.ts +++ b/packages/translations/src/languages/sk.ts @@ -195,10 +195,13 @@ export const skTranslations: DefaultTranslationsObject = { columns: 'Stĺpce', columnToSort: 'Stĺpec na zoradenie', confirm: 'Potvrdiť', + confirmCopy: 'Potvrdiť kópiu', confirmDeletion: 'Potvrdiť odstránenie', confirmDuplication: 'Potvrdiť duplikáciu', copied: 'Skopírované', copy: 'Kopírovať', + copying: 'Kopírovanie', + copyWarning: 'Chystáte sa prepísať {{to}} na {{from}} pre {{label}} {{title}}. Ste si istý?', create: 'Vytvoriť', created: 'Vytvořeno', createdAt: 'Vytvorené v', @@ -272,6 +275,7 @@ export const skTranslations: DefaultTranslationsObject = { open: 'Otvoriť', or: 'Alebo', order: 'Poradie', + overwriteExistingData: 'Prepísať existujúce pole dát', pageNotFound: 'Stránka nenájdená', password: 'Heslo', payloadSettings: 'Nastavenia dátového záznamu', @@ -304,6 +308,7 @@ export const skTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" úspešne zmazané.', true: 'Pravda', unauthorized: 'Neoprávnený prístup', + unsavedChanges: 'Máte neuložené zmeny. Uložte alebo zahoďte pred pokračovaním.', unsavedChangesDuplicate: 'Máte neuložené zmeny. Chceli by ste pokračovať v duplikovaní?', untitled: 'Bez názvu', updatedAt: 'Aktualizované v', @@ -319,6 +324,14 @@ export const skTranslations: DefaultTranslationsObject = { viewReadOnly: 'Zobraziť iba na čítanie', welcome: 'Vitajte', }, + localization: { + cannotCopySameLocale: 'Nemožno kopírovať do rovnakej lokalizácie.', + copyFrom: 'Kopírovať z', + copyFromTo: 'Kopírovanie z {{from}} do {{to}}', + copyTo: 'Kopírovať do', + copyToLocale: 'Kopírovať do lokalizácie', + selectLocaleToCopy: 'Vyberte miestny systém na kopírovanie', + }, operators: { contains: 'obsahuje', equals: 'rovná sa', diff --git a/packages/translations/src/languages/sl.ts b/packages/translations/src/languages/sl.ts index 93450217b..2e9dfbccc 100644 --- a/packages/translations/src/languages/sl.ts +++ b/packages/translations/src/languages/sl.ts @@ -194,10 +194,13 @@ export const slTranslations: DefaultTranslationsObject = { columns: 'Stolpci', columnToSort: 'Stolpec za razvrščanje', confirm: 'Potrdi', + confirmCopy: 'Potrdi kopiranje', confirmDeletion: 'Potrdi brisanje', confirmDuplication: 'Potrdi podvajanje', copied: 'Kopirano', copy: 'Kopiraj', + copying: 'Kopiranje', + copyWarning: 'Prepisali boste {{to}} z {{from}} za {{label}} {{title}}. Ste prepričani?', create: 'Ustvari', created: 'Ustvarjeno', createdAt: 'Ustvarjeno', @@ -271,6 +274,7 @@ export const slTranslations: DefaultTranslationsObject = { open: 'Odpri', or: 'Ali', order: 'Vrstni red', + overwriteExistingData: 'Prepišite obstoječe podatke polja', pageNotFound: 'Stran ni najdena', password: 'Geslo', payloadSettings: 'Nastavitve Payloada', @@ -303,6 +307,7 @@ export const slTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" uspešno izbrisan.', true: 'Da', unauthorized: 'Nepooblaščeno', + unsavedChanges: 'Neshranjene spremembe', unsavedChangesDuplicate: 'Imate neshranjene spremembe. Želite nadaljevati s podvajanjem?', untitled: 'Brez naslova', updatedAt: 'Posodobljeno', @@ -318,6 +323,14 @@ export const slTranslations: DefaultTranslationsObject = { viewReadOnly: 'Ogled samo za branje', welcome: 'Dobrodošli', }, + localization: { + cannotCopySameLocale: 'Ni mogoče kopirati v isti jezik', + copyFrom: 'Kopiraj iz', + copyFromTo: 'Kopiranje iz {{from}} v {{to}}', + copyTo: 'Kopiraj v', + copyToLocale: 'Kopiraj v jezik', + selectLocaleToCopy: 'Izberite jezik za kopiranje', + }, operators: { contains: 'vsebuje', equals: 'je enako', diff --git a/packages/translations/src/languages/sv.ts b/packages/translations/src/languages/sv.ts index a20910dcf..097f92505 100644 --- a/packages/translations/src/languages/sv.ts +++ b/packages/translations/src/languages/sv.ts @@ -194,10 +194,14 @@ export const svTranslations: DefaultTranslationsObject = { columns: 'Kolumner', columnToSort: 'Kolumn att Sortera', confirm: 'Bekräfta', + confirmCopy: 'Bekräfta kopia', confirmDeletion: 'Bekräfta radering', confirmDuplication: 'Bekräfta dubblering', copied: 'Kopierad', copy: 'Kopiera', + copying: 'Kopiering', + copyWarning: + 'Du håller på att skriva över {{to}} med {{from}} för {{label}} {{title}}. Är du säker?', create: 'Skapa', created: 'Skapad', createdAt: 'Skapad Vid', @@ -271,6 +275,7 @@ export const svTranslations: DefaultTranslationsObject = { open: 'Öppna', or: 'Eller', order: 'Ordning', + overwriteExistingData: 'Skriv över befintlig fältdatabas', pageNotFound: 'Sidan hittas inte', password: 'Lösenord', payloadSettings: 'Payload Inställningar', @@ -303,6 +308,7 @@ export const svTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" togs bort framgångsrikt.', true: 'Sann', unauthorized: 'Obehörig', + unsavedChanges: 'Du har osparade ändringar. Spara eller kassera innan du fortsätter.', unsavedChangesDuplicate: 'Du har osparade ändringar. Vill du fortsätta att duplicera?', untitled: 'Namnlös', updatedAt: 'Uppdaterades Vid', @@ -318,6 +324,14 @@ export const svTranslations: DefaultTranslationsObject = { viewReadOnly: 'Visa endast läsning', welcome: 'Välkommen', }, + localization: { + cannotCopySameLocale: 'Kan inte kopiera till samma plats', + copyFrom: 'Kopiera från', + copyFromTo: 'Kopierar från {{from}} till {{to}}', + copyTo: 'Kopiera till', + copyToLocale: 'Kopiera till plats', + selectLocaleToCopy: 'Välj plats att kopiera', + }, operators: { contains: 'innehåller', equals: 'likar med', diff --git a/packages/translations/src/languages/th.ts b/packages/translations/src/languages/th.ts index 5fdd9df7a..efecbb2ee 100644 --- a/packages/translations/src/languages/th.ts +++ b/packages/translations/src/languages/th.ts @@ -190,10 +190,14 @@ export const thTranslations: DefaultTranslationsObject = { columns: 'คอลัมน์', columnToSort: 'คอลัมน์ที่ต้องการเรียง', confirm: 'ยืนยัน', + confirmCopy: 'ยืนยันสำเนา', confirmDeletion: 'ยืนยันการลบ', confirmDuplication: 'ยืนยันการสำเนา', copied: 'คัดลอกแล้ว', copy: 'คัดลอก', + copying: 'การคัดลอก', + copyWarning: + 'คุณกำลังจะเขียนทับ {{to}} ด้วย {{from}} สำหรับ {{label}} {{title}}. คุณแน่ใจหรือไม่?', create: 'สร้าง', created: 'ถูกสร้างเมื่อ', createdAt: 'สร้างเมื่อ', @@ -267,6 +271,7 @@ export const thTranslations: DefaultTranslationsObject = { open: 'เปิด', or: 'หรือ', order: 'เรียงตาม', + overwriteExistingData: 'เขียนทับข้อมูลในฟิลด์ที่มีอยู่แล้ว', pageNotFound: 'ไม่พบหน้าที่ต้องการ', password: 'รหัสผ่าน', payloadSettings: 'การตั้งค่า Payload', @@ -299,6 +304,7 @@ export const thTranslations: DefaultTranslationsObject = { titleDeleted: 'ลบ {{label}} "{{title}}" สำเร็จ', true: 'จริง', unauthorized: 'ไม่ได้รับอนุญาต', + unsavedChanges: 'คุณมีการเปลี่ยนแปลงที่ยังไม่ได้บันทึก บันทึกหรือทิ้งก่อนที่จะดำเนินการต่อ', unsavedChangesDuplicate: 'คุณมีการแก้ไขที่ยังไม่ถูกบันทึก คุณต้องการทำสำเนาต่อหรือไม่?', untitled: 'ไม่มีชื่อ', updatedAt: 'แก้ไขเมื่อ', @@ -314,6 +320,14 @@ export const thTranslations: DefaultTranslationsObject = { viewReadOnly: 'ดูในโหมดอ่านอย่างเดียว', welcome: 'ยินดีต้อนรับ', }, + localization: { + cannotCopySameLocale: 'ไม่สามารถคัดลอกไปยังตำแหน่งที่ตั้งเดียวกัน', + copyFrom: 'คัดลอกจาก', + copyFromTo: 'คัดลอกจาก {{from}} ไปยัง {{to}}', + copyTo: 'คัดลอกไปที่', + copyToLocale: 'คัดลอกไปยังสถานที่', + selectLocaleToCopy: 'เลือกสถานที่ท้องถิ่นเพื่อคัดลอก', + }, operators: { contains: 'มี', equals: 'เท่ากับ', diff --git a/packages/translations/src/languages/tr.ts b/packages/translations/src/languages/tr.ts index ac7b42f1b..5b9312a86 100644 --- a/packages/translations/src/languages/tr.ts +++ b/packages/translations/src/languages/tr.ts @@ -197,10 +197,14 @@ export const trTranslations: DefaultTranslationsObject = { columns: 'Sütunlar', columnToSort: 'Sıralanacak Sütunlar', confirm: 'Onayla', + confirmCopy: 'Kopyayı onayla', confirmDeletion: 'Silmeyi onayla', confirmDuplication: 'Çoğaltmayı onayla', copied: 'Kopyalandı', copy: 'Kopyala', + copying: 'Kopyalama', + copyWarning: + "{{to}}'yu {{from}} ile {{label}} {{title}} için üstüne yazmak üzeresiniz. Emin misiniz?", create: 'Oluştur', created: 'Oluşturma tarihi', createdAt: 'Oluşturma tarihi', @@ -274,6 +278,7 @@ export const trTranslations: DefaultTranslationsObject = { open: 'Aç', or: 'Or', order: 'Order', + overwriteExistingData: 'Mevcut alan verilerinin üzerine yazın', pageNotFound: 'Sayfa bulunamadı', password: 'Parola', payloadSettings: 'Ayarlar', @@ -306,6 +311,7 @@ export const trTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} {{title}} başarıyla silindi.', true: 'Doğru', unauthorized: 'Yetkisiz', + unsavedChanges: 'Kaydedilmemiş değişiklikleriniz var. Devam etmeden önce kaydedin veya atın.', unsavedChangesDuplicate: 'Kaydedilmemiş değişiklikler var. Çoğaltma işlemine devam etmek istiyor musunuz?', untitled: 'Başlıksız', @@ -322,6 +328,14 @@ export const trTranslations: DefaultTranslationsObject = { viewReadOnly: 'Salt okunur olarak görüntüle', welcome: 'Hoşgeldiniz', }, + localization: { + cannotCopySameLocale: 'Aynı yerel ayara kopyalanamaz.', + copyFrom: 'Kopyala', + copyFromTo: "{{from}} 'dan {{to}} 'ya kopyalama", + copyTo: 'Kopyala', + copyToLocale: 'Yerel hafızaya kopyala', + selectLocaleToCopy: 'Kopyalamak için yerel seçimi yapın', + }, operators: { contains: 'içerir', equals: 'eşittir', diff --git a/packages/translations/src/languages/uk.ts b/packages/translations/src/languages/uk.ts index f59426f78..7aa1b25c0 100644 --- a/packages/translations/src/languages/uk.ts +++ b/packages/translations/src/languages/uk.ts @@ -194,10 +194,13 @@ export const ukTranslations: DefaultTranslationsObject = { columns: 'Колонки', columnToSort: 'Колонка для сортування', confirm: 'Підтвердити', + confirmCopy: 'Підтвердіть копію', confirmDeletion: 'Підтвердити видалення', confirmDuplication: 'Підтвердити копіювання', copied: 'Скопійовано', copy: 'Скопіювати', + copying: 'Копіювання', + copyWarning: 'Ви збираєтесь замінити {{to}} на {{from}} для {{label}} {{title}}. Ви впевнені?', create: 'Створити', created: 'Створено', createdAt: 'Дата створення', @@ -271,6 +274,7 @@ export const ukTranslations: DefaultTranslationsObject = { open: 'Відкрити', or: 'або', order: 'Порядок', + overwriteExistingData: 'Перезаписати існуючі дані поля', pageNotFound: 'Сторінка не знайдена', password: 'Пароль', payloadSettings: 'Налаштування Payload', @@ -303,6 +307,7 @@ export const ukTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}" успішно видалено.', true: 'Правда', unauthorized: 'Немає доступу', + unsavedChanges: 'У вас є незбережені зміни. Збережіть або скасуйте перед продовженням.', unsavedChangesDuplicate: 'Ви маєте незбережені зміни. Чи бажаєте ви продовжити дублювання?', untitled: 'Без назви', updatedAt: 'Змінено', @@ -318,6 +323,14 @@ export const ukTranslations: DefaultTranslationsObject = { viewReadOnly: 'Перегляд тільки для читання', welcome: 'Вітаю', }, + localization: { + cannotCopySameLocale: 'Не можна копіювати в ту ж саму локалізацію', + copyFrom: 'Копіювати з', + copyFromTo: 'Копіювання з {{from}} до {{to}}', + copyTo: 'Копіювати в', + copyToLocale: 'Копіювати до локалі', + selectLocaleToCopy: 'Виберіть локалізацію для копіювання', + }, operators: { contains: 'містить', equals: 'дорівнює', diff --git a/packages/translations/src/languages/vi.ts b/packages/translations/src/languages/vi.ts index b32de0607..1d389bb48 100644 --- a/packages/translations/src/languages/vi.ts +++ b/packages/translations/src/languages/vi.ts @@ -192,10 +192,14 @@ export const viTranslations: DefaultTranslationsObject = { columns: 'Hiển thị cột', columnToSort: 'Sắp xếp cột', confirm: 'Xác nhận', + confirmCopy: 'Xác nhận bản sao', confirmDeletion: 'Xác nhận xóa', confirmDuplication: 'Xác nhận tạo bản sao', copied: 'Đâ sao chép', copy: 'Sao chép', + copying: 'Sao chép', + copyWarning: + 'Bạn đang chuẩn bị ghi đè {{to}} bằng {{from}} cho {{label}} {{title}}. Bạn có chắc chắn không?', create: 'Tạo', created: 'Đã tạo', createdAt: 'Ngày tạo', @@ -269,6 +273,7 @@ export const viTranslations: DefaultTranslationsObject = { open: 'Mở', or: 'hoặc', order: 'Thứ tự', + overwriteExistingData: 'Ghi đè dữ liệu trường hiện tại', pageNotFound: 'Không tìm thấy trang', password: 'Mật khẩu', payloadSettings: 'Cài đặt', @@ -301,6 +306,7 @@ export const viTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} {{title}} đã được xóa thành công.', true: 'Thật', unauthorized: 'Không có quyền truy cập.', + unsavedChanges: 'Bạn có những thay đổi chưa được lưu. Lưu hoặc hủy trước khi tiếp tục.', unsavedChangesDuplicate: 'Bạn chưa lưu các thay đổi. Bạn có muốn tiếp tục tạo bản sao?', untitled: 'Chưa có tiêu đề', updatedAt: 'Ngày cập nhật', @@ -316,6 +322,14 @@ export const viTranslations: DefaultTranslationsObject = { viewReadOnly: 'Xem chỉ đọc', welcome: 'Xin chào', }, + localization: { + cannotCopySameLocale: 'Không thể sao chép vào cùng một vị trí', + copyFrom: 'Sao chép từ', + copyFromTo: 'Sao chép từ {{from}} đến {{to}}', + copyTo: 'Sao chép đến', + copyToLocale: 'Sao chép vào địa phương', + selectLocaleToCopy: 'Chọn địa phương để sao chép', + }, operators: { contains: 'có chứa', equals: 'bằng', diff --git a/packages/translations/src/languages/zh.ts b/packages/translations/src/languages/zh.ts index 1288ec369..42c209549 100644 --- a/packages/translations/src/languages/zh.ts +++ b/packages/translations/src/languages/zh.ts @@ -187,10 +187,13 @@ export const zhTranslations: DefaultTranslationsObject = { columns: '列', columnToSort: '要排序的列', confirm: '确认', + confirmCopy: '确认复制', confirmDeletion: '确认删除', confirmDuplication: '确认重复', copied: '已复制', copy: '复制', + copying: '复制', + copyWarning: '您即将用{{from}}覆盖{{to}},用于{{label}} {{title}}。您确定吗?', create: '创建', created: '已创建', createdAt: '创建于', @@ -263,6 +266,7 @@ export const zhTranslations: DefaultTranslationsObject = { open: '打开', or: '或', order: '排序', + overwriteExistingData: '覆盖现有字段数据', pageNotFound: '未找到页面', password: '密码', payloadSettings: 'Payload设置', @@ -295,6 +299,7 @@ export const zhTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}"已被成功删除。', true: '真实', unauthorized: '未经授权', + unsavedChanges: '您有未保存的更改。请在继续之前保存或放弃。', unsavedChangesDuplicate: '您有未保存的修改。您确定要继续重复吗?', untitled: '无标题', updatedAt: '更新于', @@ -310,6 +315,14 @@ export const zhTranslations: DefaultTranslationsObject = { viewReadOnly: '只读查看', welcome: '欢迎', }, + localization: { + cannotCopySameLocale: '无法复制到相同的位置', + copyFrom: '从复制', + copyFromTo: '从{{from}}复制到{{to}}', + copyTo: '复制到', + copyToLocale: '复制到本地化', + selectLocaleToCopy: '选择要复制的地区设置', + }, operators: { contains: '包含', equals: '等于', diff --git a/packages/translations/src/languages/zhTw.ts b/packages/translations/src/languages/zhTw.ts index a394411ae..023af4970 100644 --- a/packages/translations/src/languages/zhTw.ts +++ b/packages/translations/src/languages/zhTw.ts @@ -187,10 +187,13 @@ export const zhTwTranslations: DefaultTranslationsObject = { columns: '欄位', columnToSort: '要排序的欄位', confirm: '確認', + confirmCopy: '確認副本', confirmDeletion: '確認刪除', confirmDuplication: '確認複製', copied: '已複製', copy: '複製', + copying: '複製', + copyWarning: '您即將以{{from}}覆蓋{{to}},這將影響{{label}} {{title}}。您確定要這麼做嗎?', create: '建立', created: '已建立', createdAt: '建立於', @@ -263,6 +266,7 @@ export const zhTwTranslations: DefaultTranslationsObject = { open: '打開', or: '或', order: '排序', + overwriteExistingData: '覆蓋現有欄位資料', pageNotFound: '未找到頁面', password: '密碼', payloadSettings: 'Payload設定', @@ -295,6 +299,7 @@ export const zhTwTranslations: DefaultTranslationsObject = { titleDeleted: '{{label}} "{{title}}"已被成功刪除。', true: '真實', unauthorized: '未經授權', + unsavedChanges: '您有未保存的更改。繼續前請保存或放棄。', unsavedChangesDuplicate: '您有還沒儲存的修改,確定要繼續複製嗎?', untitled: '無標題', updatedAt: '更新於', @@ -310,6 +315,14 @@ export const zhTwTranslations: DefaultTranslationsObject = { viewReadOnly: '僅檢視', welcome: '歡迎', }, + localization: { + cannotCopySameLocale: '無法複製到相同的地區', + copyFrom: '從...複製', + copyFromTo: '從{{from}}複製到{{to}}', + copyTo: '複製到', + copyToLocale: '複製到區域設定', + selectLocaleToCopy: '選擇要複製的地區設定', + }, operators: { contains: '包含', equals: '等於', diff --git a/packages/ui/src/elements/CopyLocaleData/index.scss b/packages/ui/src/elements/CopyLocaleData/index.scss new file mode 100644 index 000000000..ace845e10 --- /dev/null +++ b/packages/ui/src/elements/CopyLocaleData/index.scss @@ -0,0 +1,24 @@ +@import '../../scss/styles.scss'; + +.copy-locale-data { + &__sub-header { + padding: 0 var(--gutter-h); + display: flex; + justify-content: space-between; + align-items: center; + border-bottom: 1px solid var(--theme-border-color); + } + + &__content { + padding: calc(var(--base) * 1.5) var(--gutter-h); + display: flex; + flex-direction: column; + gap: var(--base); + + > * { + display: flex; + flex-direction: column; + gap: calc(var(--base) * 0.25); + } + } +} diff --git a/packages/ui/src/elements/CopyLocaleData/index.tsx b/packages/ui/src/elements/CopyLocaleData/index.tsx new file mode 100644 index 000000000..f697f18fa --- /dev/null +++ b/packages/ui/src/elements/CopyLocaleData/index.tsx @@ -0,0 +1,206 @@ +'use client' + +import { useModal } from '@faceless-ui/modal' +import { useRouter } from 'next/navigation.js' +import React, { useCallback } from 'react' +import { toast } from 'sonner' + +import { CheckboxField } from '../../fields/Checkbox/index.js' +import { SelectInput } from '../../fields/Select/index.js' +import { useFormModified } from '../../forms/Form/context.js' +import { useConfig } from '../../providers/Config/index.js' +import { useDocumentInfo } from '../../providers/DocumentInfo/index.js' +import { useLocale } from '../../providers/Locale/index.js' +import { useServerFunctions } from '../../providers/ServerFunctions/index.js' +import { useTranslation } from '../../providers/Translation/index.js' +import { DrawerHeader } from '../BulkUpload/Header/index.js' +import { Button } from '../Button/index.js' +import { Drawer } from '../Drawer/index.js' +import { PopupList } from '../Popup/index.js' +import './index.scss' + +const baseClass = 'copy-locale-data' + +const drawerSlug = 'copy-locale' +export const CopyLocaleData: React.FC = () => { + const { + config: { + localization, + routes: { admin }, + serverURL, + }, + } = useConfig() + const { code } = useLocale() + const { id, collectionSlug, globalSlug } = useDocumentInfo() + const { t } = useTranslation() + const modified = useFormModified() + const { toggleModal } = useModal() + const { copyDataFromLocale } = useServerFunctions() + const router = useRouter() + + const localeOptions = + (localization && + localization.locales.map((locale) => ({ label: locale.label, value: locale.code }))) || + [] + + const localeOptionsWithoutCurrent = localeOptions.filter((locale) => locale.value !== code) + + const getLocaleLabel = (code: string) => { + const locale = localization && localization.locales.find((l) => l.code === code) + return locale && locale.label ? locale.label : code + } + + const [copying, setCopying] = React.useState(false) + const [toLocale, setToLocale] = React.useState(null) + const [fromLocale, setFromLocale] = React.useState(code) + const [overwriteExisting, setOverwriteExisting] = React.useState(false) + + React.useEffect(() => { + if (fromLocale !== code) { + // eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect + setFromLocale(code) + } + }, [code, fromLocale]) + + const copyLocaleData = useCallback( + async ({ from, to }) => { + setCopying(true) + + try { + await copyDataFromLocale({ + collectionSlug, + docID: id, + fromLocale: from, + globalSlug, + overrideData: overwriteExisting, + toLocale: to, + }) + + setCopying(false) + toggleModal(drawerSlug) + router.push( + `${serverURL}${admin}/${collectionSlug ? `collections/${collectionSlug}/${id}` : `globals/${globalSlug}`}?locale=${to}`, + ) + } catch (error) { + toast.error(error.message) + } + }, + [ + copyDataFromLocale, + collectionSlug, + id, + globalSlug, + overwriteExisting, + toggleModal, + router, + serverURL, + admin, + ], + ) + + if (!id && !globalSlug) { + return null + } + + return ( + + { + if (modified) { + toast.info(t('general:unsavedChanges')) + } else { + toggleModal(drawerSlug) + } + }} + > + {t('localization:copyToLocale')} + + { + toggleModal(drawerSlug) + }} + title={t('localization:copyToLocale')} + /> + } + slug={drawerSlug} + > +
+ + {fromLocale && toLocale ? ( +
+ {t('localization:copyFromTo', { + from: getLocaleLabel(fromLocale), + to: getLocaleLabel(toLocale), + })} +
+ ) : ( + t('localization:selectLocaleToCopy') + )} +
+ +
+ +
+ { + if (selectedOption?.value) { + setFromLocale(selectedOption.value) + } + }} + options={localeOptions} + path="fromLocale" + readOnly + value={fromLocale} + /> + { + if (selectedOption?.value) { + setToLocale(selectedOption.value) + } + }} + options={localeOptionsWithoutCurrent} + path="toLocale" + value={toLocale} + /> + setOverwriteExisting(!overwriteExisting)} + path={'overwriteExisting'} + /> +
+
+
+ ) +} diff --git a/packages/ui/src/elements/DocumentControls/index.tsx b/packages/ui/src/elements/DocumentControls/index.tsx index 7f4339f18..fd6e2d814 100644 --- a/packages/ui/src/elements/DocumentControls/index.tsx +++ b/packages/ui/src/elements/DocumentControls/index.tsx @@ -20,6 +20,7 @@ import { formatAdminURL } from '../../utilities/formatAdminURL.js' import { formatDate } from '../../utilities/formatDate.js' import { Autosave } from '../Autosave/index.js' import { Button } from '../Button/index.js' +import { CopyLocaleData } from '../CopyLocaleData/index.js' import { DeleteDocument } from '../DeleteDocument/index.js' import { DuplicateDocument } from '../DuplicateDocument/index.js' import { Gutter } from '../Gutter/index.js' @@ -102,6 +103,7 @@ export const DocumentControls: React.FC<{ const { admin: { dateFormat }, + localization, routes: { admin: adminRoute }, } = config @@ -258,6 +260,7 @@ export const DocumentControls: React.FC<{ verticalAlign="bottom" > + {localization && } {hasCreatePermission && ( {!disableCreate && ( diff --git a/packages/ui/src/elements/Popup/PopupTrigger/index.tsx b/packages/ui/src/elements/Popup/PopupTrigger/index.tsx index 974dcb964..62c834900 100644 --- a/packages/ui/src/elements/Popup/PopupTrigger/index.tsx +++ b/packages/ui/src/elements/Popup/PopupTrigger/index.tsx @@ -60,6 +60,11 @@ export const PopupTrigger: React.FC = (props) => { className={classes} disabled={disabled} onClick={handleClick} + onKeyDown={(e) => { + if (e.key === 'Enter') { + handleClick() + } + }} tabIndex={0} type="button" > diff --git a/packages/ui/src/exports/client/index.ts b/packages/ui/src/exports/client/index.ts index 3a28fe350..999bf065f 100644 --- a/packages/ui/src/exports/client/index.ts +++ b/packages/ui/src/exports/client/index.ts @@ -46,6 +46,7 @@ export { Banner } from '../../elements/Banner/index.js' export { Button } from '../../elements/Button/index.js' export { Card } from '../../elements/Card/index.js' export { Collapsible, useCollapsible } from '../../elements/Collapsible/index.js' +export { CopyLocaleData } from '../../elements/CopyLocaleData/index.js' export { CopyToClipboard } from '../../elements/CopyToClipboard/index.js' export { DeleteMany } from '../../elements/DeleteMany/index.js' export { DocumentControls } from '../../elements/DocumentControls/index.js' diff --git a/packages/ui/src/exports/rsc/index.ts b/packages/ui/src/exports/rsc/index.ts index 08e327359..5e91d750e 100644 --- a/packages/ui/src/exports/rsc/index.ts +++ b/packages/ui/src/exports/rsc/index.ts @@ -1 +1,2 @@ +export { copyDataFromLocaleHandler } from '../../utilities/copyDataFromLocale.js' export { renderFilters, renderTable } from '../../utilities/renderTable.js' diff --git a/packages/ui/src/providers/ServerFunctions/index.tsx b/packages/ui/src/providers/ServerFunctions/index.tsx index 7309fd1cb..1768cd11d 100644 --- a/packages/ui/src/providers/ServerFunctions/index.tsx +++ b/packages/ui/src/providers/ServerFunctions/index.tsx @@ -10,6 +10,7 @@ import React, { createContext, useCallback } from 'react' import type { buildFormStateHandler } from '../../utilities/buildFormState.js' import type { buildTableStateHandler } from '../../utilities/buildTableState.js' +import type { CopyDataFromLocaleArgs } from '../../utilities/copyDataFromLocale.js' type GetFormStateClient = ( args: { @@ -34,12 +35,19 @@ type RenderDocument = (args: { signal?: AbortSignal }) => Promise<{ data: Data; Document: React.ReactNode }> +type CopyDataFromLocaleClient = ( + args: { + signal?: AbortSignal + } & Omit, +) => Promise<{ data: Data }> + type GetDocumentSlots = (args: { collectionSlug: string signal?: AbortSignal }) => Promise type ServerFunctionsContextType = { + copyDataFromLocale: CopyDataFromLocaleClient getDocumentSlots: GetDocumentSlots getFormState: GetFormStateClient getTableState: GetTableStateClient @@ -142,9 +150,30 @@ export const ServerFunctionsProvider: React.FC<{ [serverFunction], ) + const copyDataFromLocale = useCallback( + async (args) => { + const { signal: remoteSignal, ...rest } = args || {} + + try { + const result = (await serverFunction({ + name: 'copy-data-from-locale', + args: rest, + })) as { data: Data } + + if (!remoteSignal?.aborted) { + return result + } + } catch (_err) { + console.error(_err) // eslint-disable-line no-console + } + }, + [serverFunction], + ) + return ( { + if (fieldAffectsData(field)) { + switch (field.type) { + case 'array': + // if the field has no value, take the source value + if ( + field.name in toLocaleData && + // only replace if the target value is null or undefined + [null, undefined].includes(toLocaleData[field.name]) && + field.name in fromLocaleData + ) { + toLocaleData[field.name] = fromLocaleData[field.name] + break + } + + // if the field has a value but is not localized, loop over the data from target + if (!field.localized && field.name in toLocaleData) { + toLocaleData[field.name].map((item: Data, index: number) => { + if (fromLocaleData[field.name]?.[index]) { + iterateFields(field.fields, fromLocaleData[field.name][index], item) + } + }) + } + break + + case 'blocks': + // if the field has no value, take the source value + if ( + field.name in toLocaleData && + // only replace if the target value is null or undefined + [null, undefined].includes(toLocaleData[field.name]) && + field.name in fromLocaleData + ) { + toLocaleData[field.name] = fromLocaleData[field.name] + break + } + + // if the field has a value but is not localized, loop over the data from target + if (!field.localized && field.name in toLocaleData) { + toLocaleData[field.name].map((blockData: Data, index: number) => { + const blockFields = field.blocks.find( + ({ slug }) => slug === blockData.blockType, + )?.fields + + if (blockFields?.length) { + iterateFields(blockFields, fromLocaleData[field.name][index], blockData) + } + }) + } + break + + case 'checkbox': + case 'code': + case 'date': + case 'email': + case 'json': + case 'number': + case 'point': + case 'radio': + case 'relationship': + case 'richText': + case 'select': + case 'text': + case 'textarea': + case 'upload': + if ( + field.name in toLocaleData && + // only replace if the target value is null or undefined + [null, undefined].includes(toLocaleData[field.name]) && + field.name in fromLocaleData + ) { + toLocaleData[field.name] = fromLocaleData[field.name] + } + break + + case 'group': { + if (field.name in toLocaleData && fromLocaleData?.[field.name] !== undefined) { + iterateFields(field.fields, fromLocaleData[field.name], toLocaleData[field.name]) + } + break + } + } + } else { + switch (field.type) { + case 'collapsible': + case 'row': + iterateFields(field.fields, fromLocaleData, toLocaleData) + break + + case 'tabs': + field.tabs.map((tab) => { + if (tabHasName(tab)) { + if (tab.name in toLocaleData && fromLocaleData?.[tab.name] !== undefined) { + iterateFields(tab.fields, fromLocaleData[tab.name], toLocaleData[tab.name]) + } + } else { + iterateFields(tab.fields, fromLocaleData, toLocaleData) + } + }) + break + } + } + }) +} + +function mergeData(fromLocaleData: Data, toLocaleData: Data, fields: Field[]): Data { + iterateFields(fields, fromLocaleData, toLocaleData) + + return toLocaleData +} + +export const copyDataFromLocaleHandler = async (args: CopyDataFromLocaleArgs) => { + const { req } = args + + try { + const res = await copyDataFromLocale(args) + return res + } catch (err) { + req.payload.logger.error({ + err, + msg: `There was an error copying data from "${args.fromLocale}" to "${args.toLocale}"`, + }) + + if (err.message === 'Unauthorized') { + return null + } + + return formatErrors(err) + } +} + +export const copyDataFromLocale = async (args: CopyDataFromLocaleArgs) => { + const { + collectionSlug, + docID, + fromLocale, + globalSlug, + overrideData = false, + req: { + payload, + payload: { collections, globals }, + user, + }, + toLocale, + } = args + + const incomingUserSlug = user?.collection + + const adminUserSlug = payload.config.admin.user + + // If we have a user slug, test it against the functions + if (incomingUserSlug) { + const adminAccessFunction = payload.collections[incomingUserSlug].config.access?.admin + + // Run the admin access function from the config if it exists + if (adminAccessFunction) { + const canAccessAdmin = await adminAccessFunction({ req: args.req }) + + if (!canAccessAdmin) { + throw new Error('Unauthorized') + } + // Match the user collection to the global admin config + } else if (adminUserSlug !== incomingUserSlug) { + throw new Error('Unauthorized') + } + } + + const [fromLocaleData, toLocaleData] = await Promise.allSettled([ + globalSlug + ? payload.findGlobal({ + slug: globalSlug, + locale: fromLocale, + user, + // `select` would allow us to select only the fields we need in the future + }) + : payload.findByID({ + id: docID, + collection: collectionSlug, + locale: fromLocale, + user, + // `select` would allow us to select only the fields we need in the future + }), + globalSlug + ? payload.findGlobal({ + slug: globalSlug, + locale: toLocale, + user, + // `select` would allow us to select only the fields we need in the future + }) + : payload.findByID({ + id: docID, + collection: collectionSlug, + locale: toLocale, + user, + // `select` would allow us to select only the fields we need in the future + }), + ]) + + if (fromLocaleData.status === 'rejected') { + throw new Error(`Error fetching data from locale "${fromLocale}"`) + } + + if (toLocaleData.status === 'rejected') { + throw new Error(`Error fetching data from locale "${toLocale}"`) + } + + const newToLocaleData = globalSlug + ? await payload.updateGlobal({ + slug: globalSlug, + data: overrideData + ? fromLocaleData.value + : mergeData(fromLocaleData.value, toLocaleData.value, globals[globalSlug].config.fields), + locale: toLocale, + user, + }) + : await payload.update({ + id: docID, + collection: collectionSlug, + data: overrideData + ? fromLocaleData.value + : mergeData( + fromLocaleData.value, + toLocaleData.value, + collections[collectionSlug].config.fields, + ), + locale: toLocale, + user, + }) + + return newToLocaleData +} diff --git a/test/localization/collections/NestedToArrayAndBlock/index.ts b/test/localization/collections/NestedToArrayAndBlock/index.ts index 505d10aac..06171c6be 100644 --- a/test/localization/collections/NestedToArrayAndBlock/index.ts +++ b/test/localization/collections/NestedToArrayAndBlock/index.ts @@ -31,5 +31,21 @@ export const NestedToArrayAndBlock: CollectionConfig = { }, ], }, + { + name: 'topLevelArray', + type: 'array', + localized: false, + fields: [ + { + name: 'localizedText', + type: 'text', + localized: true, + }, + { + name: 'notLocalizedText', + type: 'text', + }, + ], + }, ], } diff --git a/test/localization/collections/NoLocalizedFields/index.ts b/test/localization/collections/NoLocalizedFields/index.ts new file mode 100644 index 000000000..e04739bea --- /dev/null +++ b/test/localization/collections/NoLocalizedFields/index.ts @@ -0,0 +1,14 @@ +import type { CollectionConfig } from 'payload' + +export const noLocalizedFieldsCollectionSlug = 'no-localized-fields' + +export const NoLocalizedFieldsCollection: CollectionConfig = { + slug: noLocalizedFieldsCollectionSlug, + fields: [ + { + name: 'text', + type: 'text', + localized: false, + }, + ], +} diff --git a/test/localization/collections/RichText/index.ts b/test/localization/collections/RichText/index.ts new file mode 100644 index 000000000..416666f6d --- /dev/null +++ b/test/localization/collections/RichText/index.ts @@ -0,0 +1,31 @@ +import type { CollectionConfig } from 'payload/types' + +import { lexicalEditor, TreeViewFeature } from '@payloadcms/richtext-lexical' +import { slateEditor } from '@payloadcms/richtext-slate' + +export const richTextSlug = 'richText' + +export const RichTextCollection: CollectionConfig = { + slug: richTextSlug, + fields: [ + { + type: 'richText', + name: 'richText', + label: 'Rich Text', + localized: true, + editor: slateEditor({ + admin: { + elements: ['h1', 'h2', 'h3', 'h4', 'h5', 'h6'], + }, + }), + }, + { + name: 'lexical', + type: 'richText', + localized: true, + editor: lexicalEditor({ + features: ({ defaultFeatures }) => [...defaultFeatures, TreeViewFeature()], + }), + }, + ], +} diff --git a/test/localization/config.ts b/test/localization/config.ts index 815394f31..e68edba1e 100644 --- a/test/localization/config.ts +++ b/test/localization/config.ts @@ -13,6 +13,8 @@ import { LocalizedWithinLocalized } from './collections/LocalizedWithinLocalized import { NestedArray } from './collections/NestedArray/index.js' import { NestedFields } from './collections/NestedFields/index.js' import { NestedToArrayAndBlock } from './collections/NestedToArrayAndBlock/index.js' +import { NoLocalizedFieldsCollection } from './collections/NoLocalizedFields/index.js' +import { RichTextCollection } from './collections/RichText/index.js' import { Tab } from './collections/Tab/index.js' import { blocksWithLocalizedSameName, @@ -54,6 +56,7 @@ export default buildConfigWithDefaults({ }, }, collections: [ + RichTextCollection, BlocksCollection, NestedArray, NestedFields, @@ -119,6 +122,7 @@ export default buildConfigWithDefaults({ }, ], }, + NoLocalizedFieldsCollection, ArrayCollection, { fields: [ @@ -392,6 +396,16 @@ export default buildConfigWithDefaults({ ], slug: 'global-array', }, + { + fields: [ + { + name: 'text', + localized: true, + type: 'text', + }, + ], + slug: 'global-text', + }, ], localization: { defaultLocale, diff --git a/test/localization/e2e.spec.ts b/test/localization/e2e.spec.ts index 475ebea81..fe2deba84 100644 --- a/test/localization/e2e.spec.ts +++ b/test/localization/e2e.spec.ts @@ -3,7 +3,6 @@ import type { Page } from '@playwright/test' import { expect, test } from '@playwright/test' import { openDocControls } from 'helpers/e2e/openDocControls.js' import path from 'path' -import { wait } from 'payload/shared' import { fileURLToPath } from 'url' import type { PayloadTestSDK } from '../helpers/sdk/index.js' @@ -18,7 +17,10 @@ import { import { AdminUrlUtil } from '../helpers/adminUrlUtil.js' import { initPayloadE2ENoConfig } from '../helpers/initPayloadE2ENoConfig.js' import { POLL_TOPASS_TIMEOUT, TEST_TIMEOUT_LONG } from '../playwright.config.js' +import { nestedToArrayAndBlockCollectionSlug } from './collections/NestedToArrayAndBlock/index.js' +import { richTextSlug } from './collections/RichText/index.js' import { + defaultLocale, englishTitle, localizedPostsSlug, spanishLocale, @@ -40,7 +42,6 @@ const { beforeAll, describe } = test let url: AdminUrlUtil let urlWithRequiredLocalizedFields: AdminUrlUtil -const defaultLocale = 'en' const title = 'english title' const spanishTitle = 'spanish title' const arabicTitle = 'arabic title' @@ -49,13 +50,15 @@ const description = 'description' let page: Page let payload: PayloadTestSDK let serverURL: string +let richTextURL: AdminUrlUtil describe('Localization', () => { beforeAll(async ({ browser }, testInfo) => { testInfo.setTimeout(TEST_TIMEOUT_LONG) - ;({ payload, serverURL } = await initPayloadE2ENoConfig({ dirname })) + ;({ payload, serverURL } = await initPayloadE2ENoConfig({ dirname })) url = new AdminUrlUtil(serverURL, localizedPostsSlug) + richTextURL = new AdminUrlUtil(serverURL, richTextSlug) urlWithRequiredLocalizedFields = new AdminUrlUtil(serverURL, withRequiredLocalizedFields) const context = await browser.newContext() @@ -251,6 +254,149 @@ describe('Localization', () => { await expect(page.locator('#field-children .rs__menu')).toContainText('spanish-relation2') }) }) + + describe('copy localized data', () => { + test('should show Copy To Locale button and drawer', async () => { + await changeLocale(page, defaultLocale) + await createAndSaveDoc(page, url, { description, title }) + await openCopyToLocaleDrawer(page) + await expect(page.locator('.copy-locale-data__content')).toBeVisible() + }) + + test('should copy data to correct locale', async () => { + await createAndSaveDoc(page, url, { title }) + + await openCopyToLocaleDrawer(page) + await setToLocale(page, 'Spanish') + await runCopy(page) + + await expect(page.locator('#field-title')).toHaveValue(title) + }) + + test('should copy rich text data to correct locale', async () => { + await changeLocale(page, defaultLocale) + await page.goto(richTextURL.create) + const richTextField = page.locator('#field-richText') + const richTextContent = '

This is rich text in English

' + await richTextField.fill(richTextContent) + await saveDocAndAssert(page) + + await openCopyToLocaleDrawer(page) + await setToLocale(page, 'Spanish') + await runCopy(page) + + await expect(richTextField).toContainText(richTextContent) + }) + + test('should copy nested array to locale', async () => { + const sampleText = 'Copy this text' + const nestedArrayURL = new AdminUrlUtil(serverURL, nestedToArrayAndBlockCollectionSlug) + await page.goto(nestedArrayURL.create) + await changeLocale(page, 'ar') + const addArrayRow = page.locator('.array-field__add-row') + await addArrayRow.click() + + const arrayField = page.locator('#field-topLevelArray__0__localizedText') + await expect(arrayField).toBeVisible() + await arrayField.fill(sampleText) + await saveDocAndAssert(page) + + await openCopyToLocaleDrawer(page) + await setToLocale(page, 'English') + await runCopy(page) + + await expect(arrayField).toHaveValue(sampleText) + }) + + test('should default source locale to current locale', async () => { + await changeLocale(page, spanishLocale) + await createAndSaveDoc(page, url, { title }) + await openCopyToLocaleDrawer(page) + + const fromLocaleField = page.locator('#field-fromLocale') + await expect(fromLocaleField).toContainText('Spanish') + await page.locator('.drawer-close-button').click() + }) + + test('should not overwrite existing data when overwrite is unchecked', async () => { + await changeLocale(page, defaultLocale) + await createAndSaveDoc(page, url, { title: englishTitle, description }) + + await changeLocale(page, spanishLocale) + await fillValues({ title: spanishTitle, description: 'Spanish description' }) + await saveDocAndAssert(page) + + await changeLocale(page, defaultLocale) + await openCopyToLocaleDrawer(page) + await setToLocale(page, 'Spanish') + const overwriteCheckbox = page.locator('#field-overwriteExisting') + await expect(overwriteCheckbox).not.toBeChecked() + await runCopy(page) + + await expect(page.locator('#field-title')).toHaveValue(spanishTitle) + await expect(page.locator('#field-description')).toHaveValue('Spanish description') + }) + + test('should overwrite existing data when overwrite is checked', async () => { + await changeLocale(page, defaultLocale) + await createAndSaveDoc(page, url, { title: englishTitle, description }) + await changeLocale(page, spanishLocale) + await fillValues({ title: spanishTitle }) + await saveDocAndAssert(page) + await changeLocale(page, defaultLocale) + + await openCopyToLocaleDrawer(page) + await setToLocale(page, 'Spanish') + const overwriteCheckbox = page.locator('#field-overwriteExisting') + await overwriteCheckbox.click() + await runCopy(page) + + await expect(page.locator('#field-title')).toHaveValue(englishTitle) + }) + + test('should not include current locale in toLocale options', async () => { + await changeLocale(page, defaultLocale) + await createAndSaveDoc(page, url, { title }) + await openCopyToLocaleDrawer(page) + const toLocaleDropdown = page.locator('#field-toLocale') + await toLocaleDropdown.click() + + const options = await page + .locator('.rs__option') + .evaluateAll((els) => els.map((el) => el.textContent)) + + await expect.poll(() => options).not.toContain('English') + await page.locator('.drawer-close-button').click() + }) + + test('should handle back to back copies', async () => { + await changeLocale(page, defaultLocale) + await createAndSaveDoc(page, url, { title }) + + await openCopyToLocaleDrawer(page) + await setToLocale(page, 'Spanish') + await runCopy(page) + await expect(page.locator('#field-title')).toHaveValue(title) + + await openCopyToLocaleDrawer(page) + await setToLocale(page, 'Hungarian') + await runCopy(page) + await expect(page.locator('#field-title')).toHaveValue(title) + }) + + test('should throw error if unsaved data', async () => { + await createAndSaveDoc(page, url, { title }) + await fillValues({ title: 'updated' }) + const docControls = page.locator('.doc-controls__popup') + await docControls.click() + + const copyButton = page.locator('#copy-locale-data__button') + await expect(copyButton).toBeVisible() + await copyButton.click() + + await expect(page.locator('.payload-toast-container')).toContainText('unsaved') + }) + }) }) async function fillValues(data: Partial) { @@ -263,3 +409,31 @@ async function fillValues(data: Partial) { await page.locator('#field-description').fill(descVal) } } + +async function runCopy(page) { + const copyDrawerClose = page.locator('.copy-locale-data__sub-header button') + await expect(copyDrawerClose).toBeVisible() + await copyDrawerClose.click() +} + +async function createAndSaveDoc(page, url, values) { + await page.goto(url.create) + await fillValues(values) + await saveDocAndAssert(page) +} + +async function openCopyToLocaleDrawer(page) { + const docControls = page.locator('.doc-controls__popup') + await docControls.click() + const copyButton = page.locator('#copy-locale-data__button') + await expect(copyButton).toBeVisible() + await copyButton.click() + await expect(page.locator('.copy-locale-data__content')).toBeVisible() +} + +async function setToLocale(page, locale) { + const toField = page.locator('#field-toLocale') + await toField.click({ delay: 100 }) + const options = page.locator('.rs__option') + await options.locator(`text=${locale}`).click() +} diff --git a/test/localization/payload-types.ts b/test/localization/payload-types.ts index ef15ac217..ddd5e7e5e 100644 --- a/test/localization/payload-types.ts +++ b/test/localization/payload-types.ts @@ -11,11 +11,13 @@ export interface Config { users: UserAuthOperations; }; collections: { + richText: RichText; 'blocks-fields': BlocksField; 'nested-arrays': NestedArray; 'nested-field-tables': NestedFieldTable; users: User; 'localized-posts': LocalizedPost; + 'no-localized-fields': NoLocalizedField; 'array-fields': ArrayField; 'localized-required': LocalizedRequired; 'with-localized-relationship': WithLocalizedRelationship; @@ -33,11 +35,13 @@ export interface Config { }; collectionsJoins: {}; collectionsSelect: { + richText: RichTextSelect | RichTextSelect; 'blocks-fields': BlocksFieldsSelect | BlocksFieldsSelect; 'nested-arrays': NestedArraysSelect | NestedArraysSelect; 'nested-field-tables': NestedFieldTablesSelect | NestedFieldTablesSelect; users: UsersSelect | UsersSelect; 'localized-posts': LocalizedPostsSelect | LocalizedPostsSelect; + 'no-localized-fields': NoLocalizedFieldsSelect | NoLocalizedFieldsSelect; 'array-fields': ArrayFieldsSelect | ArrayFieldsSelect; 'localized-required': LocalizedRequiredSelect | LocalizedRequiredSelect; 'with-localized-relationship': WithLocalizedRelationshipSelect | WithLocalizedRelationshipSelect; @@ -58,17 +62,19 @@ export interface Config { }; globals: { 'global-array': GlobalArray; + 'global-text': GlobalText; }; globalsSelect: { 'global-array': GlobalArraySelect | GlobalArraySelect; + 'global-text': GlobalTextSelect | GlobalTextSelect; }; locale: 'en' | 'es' | 'pt' | 'ar' | 'hu'; user: User & { collection: 'users'; }; - jobs?: { + jobs: { tasks: unknown; - workflows?: unknown; + workflows: unknown; }; } export interface UserAuthOperations { @@ -89,6 +95,35 @@ export interface UserAuthOperations { password: string; }; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "richText". + */ +export interface RichText { + id: string; + richText?: + | { + [k: string]: unknown; + }[] + | null; + lexical?: { + root: { + type: string; + children: { + type: string; + version: number; + [k: string]: unknown; + }[]; + direction: ('ltr' | 'rtl') | null; + format: 'left' | 'start' | 'center' | 'right' | 'end' | 'justify' | ''; + indent: number; + version: number; + }; + [k: string]: unknown; + } | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "blocks-fields". @@ -118,6 +153,21 @@ export interface BlocksField { blockType: 'blockInsideBlock'; }[] | null; + nonLocalizedBlocksField?: + | { + array?: + | { + link?: { + label?: string | null; + }; + id?: string | null; + }[] + | null; + id?: string | null; + blockName?: string | null; + blockType: 'blockInsideBlock'; + }[] + | null; updatedAt: string; createdAt: string; } @@ -244,6 +294,16 @@ export interface User { lockUntil?: string | null; password?: string | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "no-localized-fields". + */ +export interface NoLocalizedField { + id: string; + text?: string | null; + updatedAt: string; + createdAt: string; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "array-fields". @@ -419,6 +479,13 @@ export interface Nested { blockType: 'block'; }[] | null; + topLevelArray?: + | { + localizedText?: string | null; + notLocalizedText?: string | null; + id?: string | null; + }[] + | null; updatedAt: string; createdAt: string; } @@ -559,6 +626,10 @@ export interface LocalizedWithinLocalized { export interface PayloadLockedDocument { id: string; document?: + | ({ + relationTo: 'richText'; + value: string | RichText; + } | null) | ({ relationTo: 'blocks-fields'; value: string | BlocksField; @@ -579,6 +650,10 @@ export interface PayloadLockedDocument { relationTo: 'localized-posts'; value: string | LocalizedPost; } | null) + | ({ + relationTo: 'no-localized-fields'; + value: string | NoLocalizedField; + } | null) | ({ relationTo: 'array-fields'; value: string | ArrayField; @@ -665,6 +740,16 @@ export interface PayloadMigration { updatedAt: string; createdAt: string; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "richText_select". + */ +export interface RichTextSelect { + richText?: T; + lexical?: T; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "blocks-fields_select". @@ -701,6 +786,26 @@ export interface BlocksFieldsSelect { blockName?: T; }; }; + nonLocalizedBlocksField?: + | T + | { + blockInsideBlock?: + | T + | { + array?: + | T + | { + link?: + | T + | { + label?: T; + }; + id?: T; + }; + id?: T; + blockName?: T; + }; + }; updatedAt?: T; createdAt?: T; } @@ -821,6 +926,15 @@ export interface LocalizedPostsSelect { updatedAt?: T; createdAt?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "no-localized-fields_select". + */ +export interface NoLocalizedFieldsSelect { + text?: T; + updatedAt?: T; + createdAt?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "array-fields_select". @@ -965,6 +1079,13 @@ export interface NestedSelect { blockName?: T; }; }; + topLevelArray?: + | T + | { + localizedText?: T; + notLocalizedText?: T; + id?: T; + }; updatedAt?: T; createdAt?: T; } @@ -1169,6 +1290,16 @@ export interface GlobalArray { updatedAt?: string | null; createdAt?: string | null; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "global-text". + */ +export interface GlobalText { + id: string; + text?: string | null; + updatedAt?: string | null; + createdAt?: string | null; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "global-array_select". @@ -1184,6 +1315,16 @@ export interface GlobalArraySelect { createdAt?: T; globalType?: T; } +/** + * This interface was referenced by `Config`'s JSON-Schema + * via the `definition` "global-text_select". + */ +export interface GlobalTextSelect { + text?: T; + updatedAt?: T; + createdAt?: T; + globalType?: T; +} /** * This interface was referenced by `Config`'s JSON-Schema * via the `definition` "auth".