feat: adds ability to copy data from across locales (#8203)

### What?

Adds ability to copy data from one locale to another at a document
level.

### How?

For any localized collection, you will find a new option in the document
controls called `Copy to Locale`.

This option will open a drawer, from here you can select your origin and
destination locales.

If data already exists in the destination locale, you can choose to: 
1. Overwrite this data (this will copy any empty fields in your origin
locale)
2. Not overwrite existing data (this will only copy data into empty
fields in the destination locale)

---------

Co-authored-by: Jarrod Flesch <jarrodmflesch@gmail.com>
This commit is contained in:
Jessica Chowdhury
2024-11-26 17:06:30 -05:00
committed by GitHub
parent 61d6614746
commit 601759d967
50 changed files with 1401 additions and 5 deletions

View File

@@ -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,

View File

@@ -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',

View File

@@ -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: 'يساوي',

View File

@@ -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',

View File

@@ -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: 'е равно на',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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: 'برابر با',

View File

@@ -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 à',

View File

@@ -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: 'שווה ל',

View File

@@ -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',

View File

@@ -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ő',

View File

@@ -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',

View File

@@ -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: '等しい',

View File

@@ -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: '같음',

View File

@@ -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: 'ညီမျှ',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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: 'једнако',

View File

@@ -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',

View File

@@ -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: 'равно',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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',

View File

@@ -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: 'เท่ากับ',

View File

@@ -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',

View File

@@ -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: 'дорівнює',

View File

@@ -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',

View File

@@ -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: '等于',

View File

@@ -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: '等於',

View File

@@ -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);
}
}
}

View File

@@ -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 | string>(null)
const [fromLocale, setFromLocale] = React.useState<null | string>(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 (
<React.Fragment>
<PopupList.Button
id={`${baseClass}__button`}
onClick={() => {
if (modified) {
toast.info(t('general:unsavedChanges'))
} else {
toggleModal(drawerSlug)
}
}}
>
{t('localization:copyToLocale')}
</PopupList.Button>
<Drawer
className={baseClass}
gutter={false}
Header={
<DrawerHeader
onClose={() => {
toggleModal(drawerSlug)
}}
title={t('localization:copyToLocale')}
/>
}
slug={drawerSlug}
>
<div className={`${baseClass}__sub-header`}>
<span>
{fromLocale && toLocale ? (
<div>
{t('localization:copyFromTo', {
from: getLocaleLabel(fromLocale),
to: getLocaleLabel(toLocale),
})}
</div>
) : (
t('localization:selectLocaleToCopy')
)}
</span>
<Button
buttonStyle="primary"
disabled={!fromLocale || !toLocale}
iconPosition="left"
onClick={async () => {
if (fromLocale === toLocale) {
toast.error(t('localization:cannotCopySameLocale'))
return
}
if (!copying) {
await copyLocaleData({
from: fromLocale,
to: toLocale,
})
}
}}
size="medium"
>
{copying ? t('general:copying') + '...' : t('general:copy')}
</Button>
</div>
<div className={`${baseClass}__content`}>
<SelectInput
label={t('localization:copyFrom')}
name={'fromLocale'}
onChange={(selectedOption: { value: string }) => {
if (selectedOption?.value) {
setFromLocale(selectedOption.value)
}
}}
options={localeOptions}
path="fromLocale"
readOnly
value={fromLocale}
/>
<SelectInput
label={t('localization:copyTo')}
name="toLocale"
onChange={(selectedOption: { value: string }) => {
if (selectedOption?.value) {
setToLocale(selectedOption.value)
}
}}
options={localeOptionsWithoutCurrent}
path="toLocale"
value={toLocale}
/>
<CheckboxField
checked={overwriteExisting}
field={{
name: 'overwriteExisting',
label: t('general:overwriteExistingData'),
}}
onChange={() => setOverwriteExisting(!overwriteExisting)}
path={'overwriteExisting'}
/>
</div>
</Drawer>
</React.Fragment>
)
}

View File

@@ -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"
>
<PopupList.ButtonGroup>
{localization && <CopyLocaleData />}
{hasCreatePermission && (
<React.Fragment>
{!disableCreate && (

View File

@@ -60,6 +60,11 @@ export const PopupTrigger: React.FC<PopupTriggerProps> = (props) => {
className={classes}
disabled={disabled}
onClick={handleClick}
onKeyDown={(e) => {
if (e.key === 'Enter') {
handleClick()
}
}}
tabIndex={0}
type="button"
>

View File

@@ -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'

View File

@@ -1 +1,2 @@
export { copyDataFromLocaleHandler } from '../../utilities/copyDataFromLocale.js'
export { renderFilters, renderTable } from '../../utilities/renderTable.js'

View File

@@ -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<CopyDataFromLocaleArgs, 'req'>,
) => Promise<{ data: Data }>
type GetDocumentSlots = (args: {
collectionSlug: string
signal?: AbortSignal
}) => Promise<DocumentSlots>
type ServerFunctionsContextType = {
copyDataFromLocale: CopyDataFromLocaleClient
getDocumentSlots: GetDocumentSlots
getFormState: GetFormStateClient
getTableState: GetTableStateClient
@@ -142,9 +150,30 @@ export const ServerFunctionsProvider: React.FC<{
[serverFunction],
)
const copyDataFromLocale = useCallback<CopyDataFromLocaleClient>(
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 (
<ServerFunctionsContext.Provider
value={{
copyDataFromLocale,
getDocumentSlots,
getFormState,
getTableState,

View File

@@ -0,0 +1,251 @@
import {
type CollectionSlug,
type Data,
type Field,
formatErrors,
type PayloadRequest,
} from 'payload'
import { fieldAffectsData, tabHasName } from 'payload/shared'
export type CopyDataFromLocaleArgs = {
collectionSlug?: CollectionSlug
docID?: number | string
fromLocale: string
globalSlug?: string
overrideData?: boolean
req: PayloadRequest
toLocale: string
}
function iterateFields(fields: Field[], fromLocaleData: Data, toLocaleData: Data): void {
fields.map((field) => {
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
}

View File

@@ -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',
},
],
},
],
}

View File

@@ -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,
},
],
}

View File

@@ -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()],
}),
},
],
}

View File

@@ -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,

View File

@@ -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<Config>
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<Config>({ 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 = '<p>This is rich text in English</p>'
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<LocalizedPost>) {
@@ -263,3 +409,31 @@ async function fillValues(data: Partial<LocalizedPost>) {
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()
}

View File

@@ -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<false> | RichTextSelect<true>;
'blocks-fields': BlocksFieldsSelect<false> | BlocksFieldsSelect<true>;
'nested-arrays': NestedArraysSelect<false> | NestedArraysSelect<true>;
'nested-field-tables': NestedFieldTablesSelect<false> | NestedFieldTablesSelect<true>;
users: UsersSelect<false> | UsersSelect<true>;
'localized-posts': LocalizedPostsSelect<false> | LocalizedPostsSelect<true>;
'no-localized-fields': NoLocalizedFieldsSelect<false> | NoLocalizedFieldsSelect<true>;
'array-fields': ArrayFieldsSelect<false> | ArrayFieldsSelect<true>;
'localized-required': LocalizedRequiredSelect<false> | LocalizedRequiredSelect<true>;
'with-localized-relationship': WithLocalizedRelationshipSelect<false> | WithLocalizedRelationshipSelect<true>;
@@ -58,17 +62,19 @@ export interface Config {
};
globals: {
'global-array': GlobalArray;
'global-text': GlobalText;
};
globalsSelect: {
'global-array': GlobalArraySelect<false> | GlobalArraySelect<true>;
'global-text': GlobalTextSelect<false> | GlobalTextSelect<true>;
};
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<T extends boolean = true> {
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<T extends boolean = true> {
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<T extends boolean = true> {
updatedAt?: T;
createdAt?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "no-localized-fields_select".
*/
export interface NoLocalizedFieldsSelect<T extends boolean = true> {
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<T extends boolean = true> {
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<T extends boolean = true> {
createdAt?: T;
globalType?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "global-text_select".
*/
export interface GlobalTextSelect<T extends boolean = true> {
text?: T;
updatedAt?: T;
createdAt?: T;
globalType?: T;
}
/**
* This interface was referenced by `Config`'s JSON-Schema
* via the `definition` "auth".