Implement Cloudflare custom domain management flow

- Added support for connecting, refreshing, and removing custom domains through Cloudflare.
- Updated API routes and validation schemas to handle new domain actions.
- Refactored domain management logic in the dashboard to accommodate Cloudflare integration.
- Enhanced user experience with clear status messages and DNS instructions for domain setup.
- Updated translations and UI components to reflect new domain management features.
This commit is contained in:
Rotimi Best
2026-03-27 09:12:53 +01:00
parent 3919ff6c2f
commit f3d212f984
23 changed files with 1376 additions and 244 deletions
@@ -1,27 +1,25 @@
import type { DomainRequestData } from '$features/org/utils/types';
import { orgApi } from '$features/org/api/org.svelte';
export const sanitizeDomain = (domain: string) => {
return domain
.trim()
.toLowerCase()
.replace(/^(?:https?:\/\/)?(?:www\.)?/i, '')
.split('/')[0];
.replace(/^https?:\/\//i, '')
.split('/')[0]
.replace(/\.$/, '');
};
export async function sendDomainRequest(
key: 'verify_domain' | 'add_domain' | 'remove_domain',
action: 'connect' | 'refresh' | 'remove',
domain: string
): Promise<{ success: boolean; data?: unknown; verified?: boolean; message?: string }> {
const response = await orgApi.sendDomainRequest(key, domain);
if (orgApi.success && response) {
const data = 'data' in response ? response.data : null;
const verified = 'verified' in response ? response.verified : undefined;
): Promise<{ success: boolean; data?: DomainRequestData; message?: string }> {
const response = await orgApi.sendDomainRequest(action, domain);
if (orgApi.success && response?.data) {
return {
success: true,
data,
verified
data: response.data
};
}
@@ -311,6 +311,7 @@
"creating_new": "Oprettelse af nye oversættelser mislykkedes"
},
"exercise": {
"points_required_auto_grade": "Angiv en positiv pointværdi for hvert spørgsmål, før du gemmer.",
"success": "Gemt",
"submission_updated": "Indsendelse opdateret til",
"error_fetching": "Hentning af øvelser mislykkedes. Genindlæs venligst siden"
@@ -750,6 +751,8 @@
"certificates": {
"title": "Certifikater",
"certificate_settings": "Certifikatindstillinger",
"tab_design": "Design",
"tab_settings": "Indstillinger",
"theme": "Vælg et tema",
"logo": "Brand Logo",
"to_update": "Gå til for at opdatere dit brandimage",
@@ -1071,6 +1074,9 @@
"finish": "Afslut",
"next": "Næste",
"check": "Tjek",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "Indsendelser",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "Links"
},
"select_type": "Vælg type",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Opgrader for at bruge denne spørgsmålstype"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "Certifikater",
"nav_landing_page": "Landingsside",
"nav_settings": "Indstillinger"
},
"completion": {
"modal": {
"title": "Kursuskravene er fuldført!",
"subtitle": "Tillykke – du kan se og downloade dit certifikat når som helst.",
"view_certificate": "Se certifikat",
"later": "Luk"
}
},
"certification": {
"rules_heading": "Certificeringsregler",
"deadline_label": "Certificeringsfrist",
"deadline_helper": "Studerende skal opfylde fuldførelsesprocenten inden denne dato (lokal tid). Lad være tomt uden deadline.",
"threshold_label": "Minimum fuldførelse (%)",
"threshold_helper": "Kombineret fremskridt i lektion og træning kræves for at opnå certifikatet (0-100). Standard er 100 %.",
"email_message_label": "E-mail med certificering",
"email_message_helper": "Valgfri besked vist i e-mailen, når en elev opfylder kravene. Et link til certifikatsiden er altid inkluderet.",
"email_message_placeholder": "f.eks. Vi er stolte af dine fremskridt - fortsæt med at lære!"
},
"certificates": {
"progress_hint": "{current} % gennemført ({required} % kræves for at downloade)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "Opdater",
"remove": "Fjern",
"custom_favicon": "Brugerdefineret favicon",
"custom_code": "Brugerdefineret kode"
"custom_code": "Brugerdefineret kode",
"reconnect": "Gentilslut domæne",
"reconnect_hint": "Gentilslut dette domæne for at generere nye Cloudflare-opsætningsposter.",
"status_verified": "Verificeret",
"status_pending_dns": "Afventende DNS",
"status_pending_verification": "Afventer bekræftelse",
"status_reconnect_required": "Genopret forbindelse påkrævet",
"status_error": "Har brug for opmærksomhed",
"status_removed": "Fjernet",
"verified_description": "Dette tilpassede domæne er aktivt og bekræftet.",
"pending_dns_description": "Tilføj DNS-posterne nedenfor, og opdater derefter bekræftelsen.",
"pending_verification_description": "DNS-poster blev fundet. SSL-udstedelse eller -validering er stadig i gang.",
"reconnect_description": "Dette domæne skal forbindes igen gennem det nye Cloudflare-opsætningsflow.",
"error_description": "Dette tilpassede domæne eksisterer, men bekræftelsen er ikke fuldført endnu."
}
},
"quiz": {
@@ -311,6 +311,7 @@
"creating_new": "Das Erstellen neuer Übersetzungen ist fehlgeschlagen"
},
"exercise": {
"points_required_auto_grade": "Legen Sie für jede Frage einen positiven Punktwert fest, bevor Sie speichern.",
"success": "Erfolgreich gespeichert",
"submission_updated": "Einreichung aktualisiert auf",
"error_fetching": "Das Abrufen der Übungen ist fehlgeschlagen. Bitte laden Sie die Seite neu"
@@ -750,6 +751,8 @@
"certificates": {
"title": "Zertifikate",
"certificate_settings": "Zertifikatseinstellungen",
"tab_design": "Design",
"tab_settings": "Einstellungen",
"theme": "Wählen Sie ein Thema",
"logo": "Markenlogo",
"to_update": "Um Ihr Markenimage zu aktualisieren, gehen Sie zu",
@@ -1071,6 +1074,9 @@
"finish": "Fertig",
"next": "Als nächstes",
"check": "Überprüfen",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "Einsendungen",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "Links"
},
"select_type": "Typ auswählen",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Führen Sie ein Upgrade durch, um diesen Fragetyp zu verwenden"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "Zertifikate",
"nav_landing_page": "Landingpage",
"nav_settings": "Einstellungen"
},
"completion": {
"modal": {
"title": "Kursvoraussetzungen erfüllt!",
"subtitle": "Herzlichen Glückwunsch – Sie können Ihr Zertifikat jederzeit einsehen und herunterladen.",
"view_certificate": "Zertifikat ansehen",
"later": "Schließen"
}
},
"certification": {
"rules_heading": "Zertifizierungsregeln",
"deadline_label": "Zertifizierungsfrist",
"deadline_helper": "Die Schüler müssen den Abschlussprozentsatz vor diesem Datum/Uhrzeit (Ortszeit) erreichen. Für keine Frist leer lassen.",
"threshold_label": "Mindestabschluss (%)",
"threshold_helper": "Kombinierter Unterrichts- und Übungsfortschritt, der zum Erwerb des Zertifikats erforderlich ist (0–100). Der Standardwert ist 100 %.",
"email_message_label": "E-Mail-Nachricht zur Zertifizierung",
"email_message_helper": "Optionale Nachricht, die in der E-Mail angezeigt wird, wenn ein Student die Anforderungen erfüllt. Ein Link zur Zertifikatsseite ist immer enthalten.",
"email_message_placeholder": "z.B. Wir sind stolz auf Ihre Fortschritte – lernen Sie weiter!"
},
"certificates": {
"progress_hint": "{current} % abgeschlossen ({required} % zum Herunterladen erforderlich)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "Aktualisieren",
"remove": "Entfernen",
"custom_favicon": "Benutzerdefiniertes Favicon",
"custom_code": "Benutzerdefinierter Code"
"custom_code": "Benutzerdefinierter Code",
"reconnect": "Domäne erneut verbinden",
"reconnect_hint": "Verbinden Sie diese Domäne erneut, um neue Cloudflare-Setup-Datensätze zu generieren.",
"status_verified": "Verifiziert",
"status_pending_dns": "Ausstehendes DNS",
"status_pending_verification": "Ausstehende Überprüfung",
"status_reconnect_required": "Erneute Verbindung erforderlich",
"status_error": "Braucht Aufmerksamkeit",
"status_removed": "Entfernt",
"verified_description": "Diese benutzerdefinierte Domäne ist aktiv und überprüft.",
"pending_dns_description": "Fügen Sie die DNS-Einträge unten hinzu und aktualisieren Sie dann die Überprüfung.",
"pending_verification_description": "DNS-Einträge wurden gefunden. Die SSL-Ausstellung oder -Validierung ist noch im Gange.",
"reconnect_description": "Diese Domäne muss über den neuen Cloudflare-Setup-Ablauf erneut verbunden werden.",
"error_description": "Diese benutzerdefinierte Domäne existiert, aber die Überprüfung ist noch nicht abgeschlossen."
}
},
"quiz": {
@@ -777,7 +777,20 @@
"dns_value": "Value",
"dns_name": "Name",
"refresh": "Refresh",
"reconnect": "Reconnect domain",
"reconnect_hint": "Reconnect this domain to generate new Cloudflare setup records.",
"remove": "Remove",
"status_verified": "Verified",
"status_pending_dns": "Pending DNS",
"status_pending_verification": "Pending verification",
"status_reconnect_required": "Reconnect required",
"status_error": "Needs attention",
"status_removed": "Removed",
"verified_description": "This custom domain is active and verified.",
"pending_dns_description": "Add the DNS records below, then refresh verification.",
"pending_verification_description": "DNS records were found. SSL issuance or validation is still in progress.",
"reconnect_description": "This domain needs to be connected again through the new Cloudflare setup flow.",
"error_description": "This custom domain exists, but verification is not complete yet.",
"custom_favicon": "Custom favicon",
"custom_code": "Custom code"
},
@@ -961,6 +974,27 @@
"placeholder": "Search lessons or exercises",
"empty": "No results found"
},
"certificates": {
"progress_hint": "{current}% complete ({required}% required to download)"
},
"certification": {
"rules_heading": "Certification rules",
"deadline_label": "Certification deadline",
"deadline_helper": "Students must meet the completion percentage before this datetime (local time). Leave empty for no deadline.",
"threshold_label": "Minimum completion (%)",
"threshold_helper": "Combined lesson and exercise progress required to earn the certificate (0–100). Default is 100%.",
"email_message_label": "Certification email message",
"email_message_helper": "Optional message shown in the email when a student meets the requirements. A link to the certificate page is always included.",
"email_message_placeholder": "e.g. We are proud of your progress — keep learning!"
},
"completion": {
"modal": {
"title": "Course requirements complete!",
"subtitle": "Congratulations — you can view and download your certificate anytime.",
"view_certificate": "View certificate",
"later": "Close"
}
},
"header": {
"preview": "Preview course",
"preview_missing_slug": "Generate and save a course slug before previewing."
@@ -1261,6 +1295,9 @@
"finish": "Finish",
"next": "Next",
"check": "Check",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"description": {
"title": "Title",
"heading": "Description",
@@ -1279,6 +1316,8 @@
"no": "No, cancel",
"yes": "Yes, delete",
"select_type": "Select type",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Upgrade to use this question type",
"deleting": "Deleting...",
"error": "You have some errors",
@@ -1776,6 +1815,8 @@
"certificates": {
"title": "Certificates",
"certificate_settings": "Certificate Settings",
"tab_design": "Design",
"tab_settings": "Settings",
"theme": "Choose a theme",
"logo": "Brand Logo",
"to_update": "To update your brand image, go to",
@@ -2303,6 +2344,7 @@
}
},
"exercise": {
"points_required_auto_grade": "Set a positive point value for every question before saving.",
"success": "Saved Successfully",
"submission_updated": "Submission updated to",
"error_fetching": "Fetching exercises failed, please reload the page"
@@ -311,6 +311,7 @@
"creating_new": "Error al crear nuevas traducciones"
},
"exercise": {
"points_required_auto_grade": "Asigne un valor de puntos positivo a cada pregunta antes de guardar.",
"success": "Guardado exitosamente",
"submission_updated": "Envío actualizado a",
"error_fetching": "No se han podido recuperar los ejercicios. Vuelva a cargar la página."
@@ -750,6 +751,8 @@
"certificates": {
"title": "Certificados",
"certificate_settings": "Configuración del certificado",
"tab_design": "Diseño",
"tab_settings": "Configuración",
"theme": "Elige un tema",
"logo": "Logotipo de la marca",
"to_update": "Para actualizar su imagen de marca, vaya a",
@@ -1071,6 +1074,9 @@
"finish": "terminar",
"next": "Siguiente",
"check": "comprobar",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "Envíos",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "Enlaces"
},
"select_type": "Seleccionar tipo",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Actualice para usar este tipo de pregunta"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "Certificados",
"nav_landing_page": "Página de destino",
"nav_settings": "Configuración"
},
"completion": {
"modal": {
"title": "¡Requisitos del curso completos!",
"subtitle": "Felicitaciones, puede ver y descargar su certificado en cualquier momento.",
"view_certificate": "Ver certificado",
"later": "Cerrar"
}
},
"certification": {
"rules_heading": "Reglas de certificación",
"deadline_label": "Fecha límite de certificación",
"deadline_helper": "Los estudiantes deben alcanzar el porcentaje de finalización antes de esta fecha (hora local). Déjelo vacío sin fecha límite.",
"threshold_label": "Finalización mínima (%)",
"threshold_helper": "Progreso combinado de lección y ejercicio requerido para obtener el certificado (0–100). El valor predeterminado es 100%.",
"email_message_label": "Mensaje de correo electrónico de certificación",
"email_message_helper": "Mensaje opcional que se muestra en el correo electrónico cuando un estudiante cumple con los requisitos. Siempre se incluye un enlace a la página del certificado.",
"email_message_placeholder": "p.ej. Estamos orgullosos de tu progreso: ¡sigue aprendiendo!"
},
"certificates": {
"progress_hint": "{current}% completado ({required}% requerido para descargar)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "Actualizar",
"remove": "Quitar",
"custom_favicon": "favicon personalizado",
"custom_code": "código personalizado"
"custom_code": "código personalizado",
"reconnect": "Reconectar dominio",
"reconnect_hint": "Vuelva a conectar este dominio para generar nuevos registros de configuración de Cloudflare.",
"status_verified": "Verificado",
"status_pending_dns": "DNS pendiente",
"status_pending_verification": "Pendiente de verificación",
"status_reconnect_required": "Se requiere reconectar",
"status_error": "necesita atencion",
"status_removed": "Eliminado",
"verified_description": "Este dominio personalizado está activo y verificado.",
"pending_dns_description": "Agregue los registros DNS a continuación y luego actualice la verificación.",
"pending_verification_description": "Se encontraron registros DNS. La emisión o validación de SSL aún está en curso.",
"reconnect_description": "Este dominio debe conectarse nuevamente a través del nuevo flujo de configuración de Cloudflare.",
"error_description": "Este dominio personalizado existe, pero la verificación aún no se ha completado."
}
},
"quiz": {
@@ -311,6 +311,7 @@
"creating_new": "La création de nouvelles traductions a échoué"
},
"exercise": {
"points_required_auto_grade": "Définissez un nombre de points positif pour chaque question avant d'enregistrer.",
"success": "Enregistré avec succès",
"submission_updated": "Soumission mise à jour pour",
"error_fetching": "La récupération des exercices a échoué, veuillez recharger la page"
@@ -750,6 +751,8 @@
"certificates": {
"title": "Certificats",
"certificate_settings": "Paramètres du certificat",
"tab_design": "Conception",
"tab_settings": "Paramètres",
"theme": "Choisissez un thème",
"logo": "Logo de la marque",
"to_update": "Pour mettre à jour votre image de marque, rendez-vous sur",
@@ -1071,6 +1074,9 @@
"finish": "Terminer",
"next": "Suivant",
"check": "Vérifier",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "Soumissions",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "Liens"
},
"select_type": "Sélectionnez le type",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Mettre à niveau pour utiliser ce type de question"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "Certificats",
"nav_landing_page": "Page de destination",
"nav_settings": "Paramètres"
},
"completion": {
"modal": {
"title": "Exigences du cours terminées !",
"subtitle": "Félicitations : vous pouvez consulter et télécharger votre certificat à tout moment.",
"view_certificate": "Afficher le certificat",
"later": "Fermer"
}
},
"certification": {
"rules_heading": "Règles de certification",
"deadline_label": "Date limite de certification",
"deadline_helper": "Les étudiants doivent atteindre le pourcentage d'achèvement avant cette date/heure (heure locale). Laisser vide sans date limite.",
"threshold_label": "Achèvement minimum (%)",
"threshold_helper": "Progrès combiné des leçons et des exercices requis pour obtenir le certificat (0-100). La valeur par défaut est 100 %.",
"email_message_label": "Courriel de certification",
"email_message_helper": "Message facultatif affiché dans l'e-mail lorsqu'un étudiant répond aux exigences. Un lien vers la page du certificat est toujours inclus.",
"email_message_placeholder": "par ex. Nous sommes fiers de vos progrès – continuez à apprendre !"
},
"certificates": {
"progress_hint": "{current} % terminé ({required} % requis pour le téléchargement)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "Actualiser",
"remove": "Supprimer",
"custom_favicon": "Icône de favori personnalisée",
"custom_code": "Code personnalisé"
"custom_code": "Code personnalisé",
"reconnect": "Reconnecter le domaine",
"reconnect_hint": "Reconnectez ce domaine pour générer de nouveaux enregistrements de configuration Cloudflare.",
"status_verified": "Vérifié",
"status_pending_dns": "DNS en attente",
"status_pending_verification": "En attente de vérification",
"status_reconnect_required": "Reconnexion requise",
"status_error": "A besoin d'attention",
"status_removed": "Supprimé",
"verified_description": "Ce domaine personnalisé est actif et vérifié.",
"pending_dns_description": "Ajoutez les enregistrements DNS ci-dessous, puis actualisez la vérification.",
"pending_verification_description": "Des enregistrements DNS ont été trouvés. L'émission ou la validation SSL est toujours en cours.",
"reconnect_description": "Ce domaine doit être à nouveau connecté via le nouveau flux de configuration Cloudflare.",
"error_description": "Ce domaine personnalisé existe, mais la vérification n'est pas encore terminée."
}
},
"quiz": {
@@ -311,6 +311,7 @@
"creating_new": "नए अनुवाद बनाना विफल रहा"
},
"exercise": {
"points_required_auto_grade": "सहेजने से पहले प्रत्येक प्रश्न के लिए धनात्मक अंक निर्धारित करें।",
"success": "सफलतापूर्वक सहेजा गया",
"submission_updated": "सबमिशन को अद्यतन किया गया",
"error_fetching": "फ़ेचिंग अभ्यास विफल रहा, कृपया पृष्ठ पुनः लोड करें"
@@ -750,6 +751,8 @@
"certificates": {
"title": "प्रमाणपत्र",
"certificate_settings": "प्रमाणपत्र सेटिंग्स",
"tab_design": "डिज़ाइन",
"tab_settings": "सेटिंग्स",
"theme": "एक थीम चुनें",
"logo": "ब्रांड लोगो",
"to_update": "अपनी ब्रांड छवि को अद्यतन करने के लिए, पर जाएँ",
@@ -1071,6 +1074,9 @@
"finish": "ख़त्म करो",
"next": "अगला",
"check": "जांचें",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "प्रस्तुतियाँ",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "कड़ियाँ"
},
"select_type": "प्रकार चुनें",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "इस प्रश्न प्रकार का उपयोग करने के लिए अपग्रेड करें"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "प्रमाणपत्र",
"nav_landing_page": "लैंडिंग पृष्ठ",
"nav_settings": "सेटिंग्स"
},
"completion": {
"modal": {
"title": "पाठ्यक्रम की आवश्यकताएँ पूर्ण!",
"subtitle": "बधाई हो - आप अपना प्रमाणपत्र कभी भी देख और डाउनलोड कर सकते हैं।",
"view_certificate": "प्रमाणपत्र देखें",
"later": "बंद करें"
}
},
"certification": {
"rules_heading": "प्रमाणन नियम",
"deadline_label": "प्रमाणीकरण की समय सीमा",
"deadline_helper": "छात्रों को इस दिनांक समय (स्थानीय समय) से पहले पूर्णता प्रतिशत पूरा करना होगा। बिना किसी समय सीमा के खाली छोड़ दें.",
"threshold_label": "न्यूनतम पूर्णता (%)",
"threshold_helper": "प्रमाणपत्र (0-100) अर्जित करने के लिए संयुक्त पाठ और अभ्यास प्रगति की आवश्यकता है। डिफ़ॉल्ट 100% है.",
"email_message_label": "प्रमाणीकरण ईमेल संदेश",
"email_message_helper": "जब कोई छात्र आवश्यकताओं को पूरा करता है तो ईमेल में वैकल्पिक संदेश दिखाया जाता है। प्रमाणपत्र पृष्ठ का एक लिंक हमेशा शामिल किया जाता है।",
"email_message_placeholder": "जैसे हमें आपकी प्रगति पर गर्व है - सीखते रहें!"
},
"certificates": {
"progress_hint": "{वर्तमान}% पूर्ण (डाउनलोड करने के लिए {आवश्यक}% आवश्यक)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "ताज़ा करें",
"remove": "हटाओ",
"custom_favicon": "कस्टम फ़ेविकॉन",
"custom_code": "कस्टम कोड"
"custom_code": "कस्टम कोड",
"reconnect": "डोमेन पुनः कनेक्ट करें",
"reconnect_hint": "नए क्लाउडफ़ेयर सेटअप रिकॉर्ड बनाने के लिए इस डोमेन को पुनः कनेक्ट करें।",
"status_verified": "सत्यापित",
"status_pending_dns": "लंबित डीएनएस",
"status_pending_verification": "सत्यापन लंबित है",
"status_reconnect_required": "पुनः कनेक्ट करना आवश्यक है",
"status_error": "ध्यान देने की जरूरत है",
"status_removed": "हटा दिया गया",
"verified_description": "यह कस्टम डोमेन सक्रिय और सत्यापित है.",
"pending_dns_description": "नीचे DNS रिकॉर्ड जोड़ें, फिर सत्यापन ताज़ा करें।",
"pending_verification_description": "डीएनएस रिकॉर्ड पाए गए. एसएसएल जारी करना या सत्यापन अभी भी जारी है।",
"reconnect_description": "इस डोमेन को नए क्लाउडफ़ेयर सेटअप फ़्लो के माध्यम से फिर से कनेक्ट करने की आवश्यकता है।",
"error_description": "यह कस्टम डोमेन मौजूद है, लेकिन सत्यापन अभी तक पूरा नहीं हुआ है।"
}
},
"quiz": {
@@ -311,6 +311,7 @@
"creating_new": "Tworzenie nowych tłumaczeń nie powiodło się"
},
"exercise": {
"points_required_auto_grade": "Ustaw dodatnią liczbę punktów dla każdego pytania przed zapisaniem.",
"success": "Zapisano pomyślnie",
"submission_updated": "Zgłoszenie zaktualizowane do",
"error_fetching": "Pobieranie ćwiczeń nie powiodło się. Załaduj stronę ponownie"
@@ -750,6 +751,8 @@
"certificates": {
"title": "Certyfikaty",
"certificate_settings": "Ustawienia certyfikatu",
"tab_design": "Projekt",
"tab_settings": "Ustawienia",
"theme": "Wybierz motyw",
"logo": "Logo marki",
"to_update": "Aby zaktualizować wizerunek swojej marki, przejdź do",
@@ -1071,6 +1074,9 @@
"finish": "Zakończ",
"next": "Następny",
"check": "Sprawdź",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "Zgłoszenia",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "Linki"
},
"select_type": "Wybierz typ",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Uaktualnij, aby używać tego typu pytań"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "Certyfikaty",
"nav_landing_page": "Strona docelowa",
"nav_settings": "Ustawienia"
},
"completion": {
"modal": {
"title": "Wymagania dotyczące kursu zostały spełnione!",
"subtitle": "Gratulacje — możesz wyświetlić i pobrać swój certyfikat w dowolnym momencie.",
"view_certificate": "Zobacz certyfikat",
"later": "Zamknij"
}
},
"certification": {
"rules_heading": "Zasady certyfikacji",
"deadline_label": "Termin certyfikacji",
"deadline_helper": "Studenci muszą osiągnąć procent ukończenia przed tą datą (czasu lokalnego). Pozostaw puste bez terminu.",
"threshold_label": "Minimalne ukończenie (%)",
"threshold_helper": "Do uzyskania certyfikatu wymagany jest łączny postęp w lekcjach i ćwiczeniach (0–100). Wartość domyślna to 100%.",
"email_message_label": "Wiadomość e-mail z certyfikatem",
"email_message_helper": "Opcjonalna wiadomość wyświetlana w wiadomości e-mail, gdy uczeń spełni wymagania. Zawsze dołączany jest link do strony z certyfikatem.",
"email_message_placeholder": "np. Jesteśmy dumni z Twoich postępów — ucz się dalej!"
},
"certificates": {
"progress_hint": "{bieżący}% ukończenia ({required}% wymagane do pobrania)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "Odśwież",
"remove": "Usuń",
"custom_favicon": "Niestandardowa favikona",
"custom_code": "Kod niestandardowy"
"custom_code": "Kod niestandardowy",
"reconnect": "Połącz ponownie domenę",
"reconnect_hint": "Połącz ponownie tę domenę, aby wygenerować nowe rekordy konfiguracji Cloudflare.",
"status_verified": "Zweryfikowano",
"status_pending_dns": "Oczekujące DNS-y",
"status_pending_verification": "Oczekuje na weryfikację",
"status_reconnect_required": "Wymagane ponowne połączenie",
"status_error": "Potrzebuje uwagi",
"status_removed": "Usunięto",
"verified_description": "Ta domena niestandardowa jest aktywna i zweryfikowana.",
"pending_dns_description": "Dodaj poniższe rekordy DNS, a następnie odśwież weryfikację.",
"pending_verification_description": "Znaleziono rekordy DNS. Wydanie lub weryfikacja protokołu SSL jest nadal w toku.",
"reconnect_description": "Ta domena musi zostać ponownie połączona poprzez nowy proces konfiguracji Cloudflare.",
"error_description": "Ta domena niestandardowa istnieje, ale weryfikacja nie została jeszcze ukończona."
}
},
"quiz": {
@@ -311,6 +311,7 @@
"creating_new": "Falha ao criar novas traduções"
},
"exercise": {
"points_required_auto_grade": "Defina um valor de pontos positivo para cada pergunta antes de salvar.",
"success": "Salvo com sucesso",
"submission_updated": "Envio atualizado para",
"error_fetching": "Falha ao buscar exercícios. Atualize a página"
@@ -750,6 +751,8 @@
"certificates": {
"title": "Certificados",
"certificate_settings": "Configurações de certificado",
"tab_design": "Design",
"tab_settings": "Configurações",
"theme": "Escolha um tema",
"logo": "Logotipo da marca",
"to_update": "Para atualizar a imagem da sua marca, acesse",
@@ -1071,6 +1074,9 @@
"finish": "Concluir",
"next": "Próximo",
"check": "Verifique",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "Envios",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "Ligações"
},
"select_type": "Selecione o tipo",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Atualize para usar este tipo de pergunta"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "Certificados",
"nav_landing_page": "Página inicial",
"nav_settings": "Configurações"
},
"completion": {
"modal": {
"title": "Requisitos do curso concluídos!",
"subtitle": "Parabéns – você pode visualizar e baixar seu certificado a qualquer momento.",
"view_certificate": "Ver certificado",
"later": "Fechar"
}
},
"certification": {
"rules_heading": "Regras de certificação",
"deadline_label": "Prazo de certificação",
"deadline_helper": "Os alunos devem atingir o percentual de conclusão antes desta data e hora (horário local). Deixe em branco para não ter prazo.",
"threshold_label": "Conclusão mínima (%)",
"threshold_helper": "Progresso combinado de aulas e exercícios necessário para obter o certificado (0–100). O padrão é 100%.",
"email_message_label": "Mensagem de e-mail de certificação",
"email_message_helper": "Mensagem opcional mostrada no e-mail quando um aluno atende aos requisitos. Um link para a página do certificado está sempre incluído.",
"email_message_placeholder": "por exemplo Estamos orgulhosos do seu progresso – continue aprendendo!"
},
"certificates": {
"progress_hint": "{current}% concluído ({required}% necessário para download)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "Atualizar",
"remove": "Remover",
"custom_favicon": "Favicon personalizado",
"custom_code": "Código personalizado"
"custom_code": "Código personalizado",
"reconnect": "Reconectar domínio",
"reconnect_hint": "Reconecte este domínio para gerar novos registros de configuração da Cloudflare.",
"status_verified": "Verificado",
"status_pending_dns": "DNS pendente",
"status_pending_verification": "Verificação pendente",
"status_reconnect_required": "É necessário reconectar",
"status_error": "Precisa de atenção",
"status_removed": "Removido",
"verified_description": "Este domínio personalizado está ativo e verificado.",
"pending_dns_description": "Adicione os registros DNS abaixo e atualize a verificação.",
"pending_verification_description": "Registros DNS foram encontrados. A emissão ou validação de SSL ainda está em andamento.",
"reconnect_description": "Este domínio precisa ser conectado novamente por meio do novo fluxo de configuração da Cloudflare.",
"error_description": "Este domínio personalizado existe, mas a verificação ainda não foi concluída."
}
},
"quiz": {
@@ -311,6 +311,7 @@
"creating_new": "Не удалось создать новые переводы."
},
"exercise": {
"points_required_auto_grade": "Установите положительное количество баллов для каждого вопроса перед сохранением.",
"success": "Сохранено успешно",
"submission_updated": "Представление обновлено до",
"error_fetching": "Не удалось загрузить упражнения. Обновите страницу."
@@ -750,6 +751,8 @@
"certificates": {
"title": "Сертификаты",
"certificate_settings": "Настройки сертификата",
"tab_design": "Дизайн",
"tab_settings": "Настройки",
"theme": "Выберите тему",
"logo": "Логотип бренда",
"to_update": "Чтобы обновить имидж вашего бренда, перейдите по ссылке",
@@ -1071,6 +1074,9 @@
"finish": "Готово",
"next": "Далее",
"check": "Проверить",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "Материалы",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "Ссылки"
},
"select_type": "Выберите тип",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Обновите, чтобы использовать этот тип вопроса"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "Сертификаты",
"nav_landing_page": "Целевая страница",
"nav_settings": "Настройки"
},
"completion": {
"modal": {
"title": "Требования курса выполнены!",
"subtitle": "Поздравляем — вы можете просмотреть и скачать свой сертификат в любое время.",
"view_certificate": "Посмотреть сертификат",
"later": "Закрыть"
}
},
"certification": {
"rules_heading": "Правила сертификации",
"deadline_label": "Срок сертификации",
"deadline_helper": "Учащиеся должны достичь процента завершения до этой даты и времени (по местному времени). Оставьте пустым, если срок не установлен.",
"threshold_label": "Минимальное завершение (%)",
"threshold_helper": "Для получения сертификата необходим совмещенный прогресс урока и упражнений (0–100). По умолчанию — 100%.",
"email_message_label": "Сертификационное письмо по электронной почте",
"email_message_helper": "Дополнительное сообщение, отображаемое в электронном письме, когда учащийся соответствует требованиям. Ссылка на страницу сертификата всегда включена.",
"email_message_placeholder": "например Мы гордимся вашим прогрессом — продолжайте учиться!"
},
"certificates": {
"progress_hint": "Выполнено {current}% (для загрузки требуется {required}%)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "Обновить",
"remove": "Удалить",
"custom_favicon": "Пользовательский значок",
"custom_code": "Пользовательский код"
"custom_code": "Пользовательский код",
"reconnect": "Переподключить домен",
"reconnect_hint": "Повторно подключите этот домен, чтобы создать новые записи настройки Cloudflare.",
"status_verified": "Проверено",
"status_pending_dns": "Ожидание DNS",
"status_pending_verification": "Ожидает проверки",
"status_reconnect_required": "Требуется переподключение",
"status_error": "Требует внимания",
"status_removed": "Удален",
"verified_description": "Этот личный домен активен и проверен.",
"pending_dns_description": "Добавьте записи DNS ниже, затем обновите проверку.",
"pending_verification_description": "DNS-записи были найдены. Выдача или проверка SSL все еще продолжается.",
"reconnect_description": "Этот домен необходимо снова подключить с помощью нового процесса настройки Cloudflare.",
"error_description": "Этот личный домен существует, но проверка еще не завершена."
}
},
"quiz": {
@@ -311,6 +311,7 @@
"creating_new": "Tạo bản dịch mới không thành công"
},
"exercise": {
"points_required_auto_grade": "Đặt điểm dương cho mỗi câu hỏi trước khi lưu.",
"success": "Đã lưu thành công",
"submission_updated": "Đã cập nhật bài nộp vào",
"error_fetching": "Tìm nạp bài tập không thành công, vui lòng tải lại trang"
@@ -750,6 +751,8 @@
"certificates": {
"title": "Chứng chỉ",
"certificate_settings": "Cài đặt chứng chỉ",
"tab_design": "Thiết kế",
"tab_settings": "Cài đặt",
"theme": "Chọn một chủ đề",
"logo": "Logo thương hiệu",
"to_update": "Để cập nhật hình ảnh thương hiệu của bạn, hãy truy cập",
@@ -1071,6 +1074,9 @@
"finish": "Kết thúc",
"next": "Tiếp theo",
"check": "Kiểm tra",
"auto_graded_badge": "Auto-graded",
"manual_grading_required_badge": "Manual grading required",
"points_required_auto_grade": "Points must be greater than 0 for auto-graded exercises.",
"analytics": {
"submissions": "bài nộp",
"individual": {
@@ -1139,6 +1145,8 @@
"link": "Liên kết"
},
"select_type": "Chọn loại",
"question_type_auto_gradable": "Auto",
"question_type_manual_grading": "Manual",
"premium_question_type": "Nâng cấp để sử dụng loại câu hỏi này"
},
"delete_confirmation": {
@@ -1608,6 +1616,27 @@
"nav_certificates": "Chứng chỉ",
"nav_landing_page": "Trang đích",
"nav_settings": "Cài đặt"
},
"completion": {
"modal": {
"title": "Yêu cầu khóa học đã hoàn tất!",
"subtitle": "Xin chúc mừng — bạn có thể xem và tải xuống chứng chỉ của mình bất kỳ lúc nào.",
"view_certificate": "Xem chứng chỉ",
"later": "Đóng"
}
},
"certification": {
"rules_heading": "Quy tắc chứng nhận",
"deadline_label": "Thời hạn chứng nhận",
"deadline_helper": "Học sinh phải đáp ứng tỷ lệ hoàn thành trước ngày này (giờ địa phương). Để trống không có thời hạn.",
"threshold_label": "Hoàn thành tối thiểu (%)",
"threshold_helper": "Cần có tiến độ kết hợp của bài học và bài tập để đạt được chứng chỉ (0–100). Mặc định là 100%.",
"email_message_label": "Thông báo email chứng nhận",
"email_message_helper": "Thông báo tùy chọn hiển thị trong email khi học sinh đáp ứng yêu cầu. Một liên kết đến trang chứng chỉ luôn được bao gồm.",
"email_message_placeholder": "ví dụ. Chúng tôi tự hào về sự tiến bộ của bạn - hãy tiếp tục học hỏi!"
},
"certificates": {
"progress_hint": "Đã hoàn thành {current}% (cần có {required}% để tải xuống)"
}
},
"courses": {
@@ -1785,7 +1814,20 @@
"refresh": "Làm mới",
"remove": "Xóa",
"custom_favicon": "Biểu tượng yêu thích tùy chỉnh",
"custom_code": "Mã tùy chỉnh"
"custom_code": "Mã tùy chỉnh",
"reconnect": "Kết nối lại miền",
"reconnect_hint": "Kết nối lại miền này để tạo bản ghi thiết lập Cloudflare mới.",
"status_verified": "Đã xác minh",
"status_pending_dns": "DNS đang chờ xử lý",
"status_pending_verification": "Đang chờ xác minh",
"status_reconnect_required": "Yêu cầu kết nối lại",
"status_error": "Cần chú ý",
"status_removed": "Đã xóa",
"verified_description": "Miền tùy chỉnh này đang hoạt động và đã được xác minh.",
"pending_dns_description": "Thêm bản ghi DNS bên dưới, sau đó làm mới xác minh.",
"pending_verification_description": "Bản ghi DNS đã được tìm thấy. Việc cấp hoặc xác thực SSL vẫn đang được tiến hành.",
"reconnect_description": "Miền này cần được kết nối lại thông qua quy trình thiết lập Cloudflare mới.",
"error_description": "Miền tùy chỉnh này tồn tại nhưng quá trình xác minh chưa hoàn tất."
}
},
"quiz": {