feat: implement automation feature
This commit is contained in:
@@ -0,0 +1,71 @@
|
||||
// SaaS default CSP domains, baked in at build time.
|
||||
// Self-hosted (adapter-node) starts with empty lists; runtime domains
|
||||
// are added via env vars in hooks.server.ts so pre-built Docker images stay configurable.
|
||||
|
||||
const saasDefaults = {
|
||||
scriptSrc: [
|
||||
'https://assets.cdn.clsrio.com',
|
||||
'https://cdnjs.cloudflare.com',
|
||||
'https://*.posthog.com',
|
||||
'https://*.senja.io',
|
||||
'https://umami.hz.oncws.com',
|
||||
'https://www.youtube.com',
|
||||
'https://youtube.com',
|
||||
'https://google.com'
|
||||
],
|
||||
styleSrc: [
|
||||
'https://cdn.plyr.io',
|
||||
'https://unpkg.com/katex@0.12.0/dist/katex.min.css',
|
||||
'https://assets.cdn.clsrio.com/eqneditor_1.css',
|
||||
'https://fonts.googleapis.com'
|
||||
],
|
||||
connectSrc: [
|
||||
'https://*.classroomio.com',
|
||||
'https://classroomio.com',
|
||||
'https://app.classroomio.com',
|
||||
'https://api.classroomio.com',
|
||||
'https://pgrest.classroomio.com',
|
||||
'https://play.classroomio.com',
|
||||
'wss://*.classroomio.com',
|
||||
'https://assets.cdn.clsrio.com',
|
||||
'https://cdn.plyr.io',
|
||||
'https://*.posthog.com',
|
||||
'https://umami.hz.oncws.com',
|
||||
'https://*.r2.cloudflarestorage.com',
|
||||
'https://*.senja.io',
|
||||
'https://*.ytimg.com',
|
||||
'https://noembed.com'
|
||||
],
|
||||
frameSrc: [
|
||||
'https://www.youtube.com',
|
||||
'https://youtube.com',
|
||||
'https://www.youtube-nocookie.com',
|
||||
'https://www.google.com',
|
||||
'https://google.com'
|
||||
],
|
||||
fontSrc: ['https://fonts.gstatic.com', 'https://cdn.plyr.io'],
|
||||
mediaSrc: ['https:']
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {boolean} isSelfHosted
|
||||
* @param {string | undefined} serverUrl - PUBLIC_SERVER_URL, added to connect-src for SaaS builds
|
||||
*/
|
||||
export function getCspDomains(isSelfHosted, serverUrl) {
|
||||
if (isSelfHosted) {
|
||||
return {
|
||||
scriptSrc: [],
|
||||
styleSrc: [],
|
||||
connectSrc: [],
|
||||
frameSrc: [],
|
||||
fontSrc: [],
|
||||
mediaSrc: [],
|
||||
apiOrigin: null
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
...saasDefaults,
|
||||
apiOrigin: serverUrl ?? null
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
function parseCspDomains(value: string | undefined): string[] {
|
||||
if (!value) return [];
|
||||
return value
|
||||
.split(',')
|
||||
.map((d) => d.trim())
|
||||
.filter(Boolean)
|
||||
.map((d) => (d.startsWith('http://') || d.startsWith('https://') ? d : `https://${d}`));
|
||||
}
|
||||
|
||||
function buildCspExtensions(): Record<string, string[]> {
|
||||
const allDomains = parseCspDomains(process.env.ALLOWED_EXTERNAL_DOMAINS);
|
||||
|
||||
const or = (envVar: string) => (allDomains.length ? allDomains : parseCspDomains(process.env[envVar]));
|
||||
|
||||
const scriptSrc = or('CSP_SCRIPT_SRC_DOMAINS');
|
||||
const styleSrc = or('CSP_STYLE_SRC_DOMAINS');
|
||||
const connectSrcBase = or('CSP_CONNECT_SRC_DOMAINS');
|
||||
const frameSrc = or('CSP_FRAME_SRC_DOMAINS');
|
||||
const fontSrc = or('CSP_FONT_SRC_DOMAINS');
|
||||
const mediaSrc = or('CSP_MEDIA_SRC_DOMAINS');
|
||||
|
||||
const serverUrl = process.env.PUBLIC_SERVER_URL;
|
||||
const connectSrc = serverUrl ? [...connectSrcBase, serverUrl] : connectSrcBase;
|
||||
|
||||
const extensions: Record<string, string[]> = {};
|
||||
if (scriptSrc.length) extensions['script-src'] = scriptSrc;
|
||||
if (styleSrc.length) {
|
||||
extensions['style-src'] = styleSrc;
|
||||
extensions['style-src-elem'] = styleSrc;
|
||||
}
|
||||
if (connectSrc.length) extensions['connect-src'] = connectSrc;
|
||||
if (frameSrc.length) extensions['frame-src'] = frameSrc;
|
||||
if (fontSrc.length) extensions['font-src'] = fontSrc;
|
||||
if (mediaSrc.length) {
|
||||
extensions['img-src'] = mediaSrc;
|
||||
extensions['media-src'] = mediaSrc;
|
||||
}
|
||||
|
||||
return extensions;
|
||||
}
|
||||
|
||||
let cachedExtensions: Record<string, string[]> | null = null;
|
||||
|
||||
function getExtensions(): Record<string, string[]> {
|
||||
if (!cachedExtensions) cachedExtensions = buildCspExtensions();
|
||||
return cachedExtensions;
|
||||
}
|
||||
|
||||
function extendHeader(header: string, extensions: Record<string, string[]>): string {
|
||||
return header
|
||||
.split(';')
|
||||
.map((d) => d.trim())
|
||||
.filter(Boolean)
|
||||
.map((directive) => {
|
||||
const spaceIdx = directive.indexOf(' ');
|
||||
const name = spaceIdx === -1 ? directive : directive.substring(0, spaceIdx);
|
||||
const extra = extensions[name];
|
||||
return extra?.length ? `${directive} ${extra.join(' ')}` : directive;
|
||||
})
|
||||
.join('; ');
|
||||
}
|
||||
|
||||
export function applyCspExtensions(response: Response): Response {
|
||||
const extensions = getExtensions();
|
||||
if (Object.keys(extensions).length === 0) return response;
|
||||
|
||||
for (const name of ['content-security-policy', 'content-security-policy-report-only']) {
|
||||
const header = response.headers.get(name);
|
||||
if (header) {
|
||||
response.headers.set(name, extendHeader(header, extensions));
|
||||
}
|
||||
}
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -3,6 +3,8 @@ import { browser } from '$app/environment';
|
||||
export const isHtmlValueEmpty = (html: string) => {
|
||||
if (!html || typeof html !== 'string') return true;
|
||||
|
||||
if (/<svg\b/i.test(html)) return false;
|
||||
|
||||
if (!document || !browser) return false;
|
||||
|
||||
return getTextFromHTML(html) === '';
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "Opdater",
|
||||
"unsaved_changes": {
|
||||
"message": "Du har ikke-gemte ændringer. Er du sikker på, at du vil tage afsted?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "Søg efter lektioner eller øvelser",
|
||||
"empty": "Ingen resultater fundet"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "Tilbage til kurset",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Dato oprettet",
|
||||
"published": "Udgivet",
|
||||
"lessons": "Lektioner"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "Ryd alle",
|
||||
"popover_title": "Filtre",
|
||||
"sort": "Sorter",
|
||||
"order": "Rækkefølge",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Tags",
|
||||
"empty_tags": "Ingen tags tilgængelige"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "{provider} er aktiveret for dit domæne",
|
||||
"sso_redirect_error": "SSO-logon er forkert konfigureret. Indstil PUBLIC_SERVER_URL til din API-server.",
|
||||
"sso_required": "Log venligst ind med SSO. Adgangskodelogin er deaktiveret.",
|
||||
"sign_in_with_sso": "Log ind med {provider}",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "Aktualisieren",
|
||||
"unsaved_changes": {
|
||||
"message": "Sie haben nicht gespeicherte Änderungen. Sind Sie sicher, dass Sie gehen möchten?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "Suchen Sie nach Lektionen oder Übungen",
|
||||
"empty": "Keine Ergebnisse gefunden"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "Zurück zum Kurs",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Erstellungsdatum",
|
||||
"published": "Veröffentlicht",
|
||||
"lessons": "Lektionen"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "Alles löschen",
|
||||
"popover_title": "Filter",
|
||||
"sort": "Sortieren",
|
||||
"order": "Reihenfolge",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Schlagworte",
|
||||
"empty_tags": "Keine Tags verfügbar"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "{provider} ist für Ihre Domain aktiviert",
|
||||
"sso_redirect_error": "Die SSO-Anmeldung ist falsch konfiguriert. Bitte legen Sie PUBLIC_SERVER_URL auf Ihren API-Server fest.",
|
||||
"sso_required": "Bitte melden Sie sich mit SSO an. Die Passwortanmeldung ist deaktiviert.",
|
||||
"sign_in_with_sso": "Melden Sie sich mit {provider} an",
|
||||
|
||||
@@ -93,6 +93,9 @@
|
||||
"placeholder": "Search"
|
||||
}
|
||||
},
|
||||
"common": {
|
||||
"refresh": "Refresh"
|
||||
},
|
||||
"login": {
|
||||
"welcome": "Welcome back",
|
||||
"email": "Your email",
|
||||
@@ -240,7 +243,7 @@
|
||||
},
|
||||
"login": {
|
||||
"or_continue_with": "Or continue with email and password",
|
||||
"sso_enabled": "{provider} is enabled for your domain",
|
||||
"sso_enabled": "{provider} is enabled for this organization",
|
||||
"sso_redirect_error": "SSO sign-in is misconfigured. Please set PUBLIC_SERVER_URL to your API server.",
|
||||
"sso_required": "Please sign in with SSO. Password login is disabled.",
|
||||
"sign_in_with_sso": "Sign in with {provider}",
|
||||
@@ -566,6 +569,7 @@
|
||||
"actions": {
|
||||
"create_tag": "Create Tag",
|
||||
"create_group": "Create Tag Group",
|
||||
"actions_menu": "Tag actions",
|
||||
"edit_group": "Edit Group",
|
||||
"edit_tag": "Edit Tag",
|
||||
"save": "Save",
|
||||
@@ -865,10 +869,19 @@
|
||||
"clear_all": "Clear all",
|
||||
"popover_title": "Filters",
|
||||
"sort": "Sort",
|
||||
"order": "Order",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Tags",
|
||||
"empty_tags": "No tags available"
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Date Created",
|
||||
"published": "Published",
|
||||
"lessons": "Lessons"
|
||||
@@ -947,6 +960,10 @@
|
||||
"placeholder": "Search lessons or exercises",
|
||||
"empty": "No results found"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"navItem": {
|
||||
"news_feed": {
|
||||
"heading": "News Feed",
|
||||
@@ -2083,6 +2100,10 @@
|
||||
"created_at_label": "Created:",
|
||||
"last_used_label": "Last used:",
|
||||
"never_used": "Never",
|
||||
"table_key": "Key",
|
||||
"table_status": "Status",
|
||||
"table_created": "Created",
|
||||
"table_last_used": "Last used",
|
||||
"scopes_label": "Scopes:",
|
||||
"revoke_confirm": "Revoke this automation key?",
|
||||
"rotate_confirm": "Rotate this automation key?"
|
||||
@@ -2097,9 +2118,7 @@
|
||||
"keys_description": "Use one MCP key per integration so access can be rotated or revoked cleanly.",
|
||||
"rate_limits_title": "Rate limits",
|
||||
"rate_limits_description": "Read / write / publish requests allowed per minute.",
|
||||
"used_label": "Used:",
|
||||
"per_key_label": "Per key:",
|
||||
"per_org_label": "Per org:"
|
||||
"used_label": "Used:"
|
||||
},
|
||||
"keys": {
|
||||
"title": "MCP keys",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "Actualizar",
|
||||
"unsaved_changes": {
|
||||
"message": "Tienes cambios sin guardar. ¿Estás seguro de que quieres irte?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "Buscar lecciones o ejercicios",
|
||||
"empty": "No se encontraron resultados"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "volver al curso",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Fecha de creación",
|
||||
"published": "Publicado",
|
||||
"lessons": "Lecciones"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "Borrar todo",
|
||||
"popover_title": "Filtros",
|
||||
"sort": "ordenar",
|
||||
"order": "Orden",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Etiquetas",
|
||||
"empty_tags": "No hay etiquetas disponibles"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "{provider} está habilitado para tu dominio",
|
||||
"sso_redirect_error": "El inicio de sesión SSO está mal configurado. Configure PUBLIC_SERVER_URL en su servidor API.",
|
||||
"sso_required": "Inicie sesión con SSO. El inicio de sesión con contraseña está deshabilitado.",
|
||||
"sign_in_with_sso": "Iniciar sesión con {proveedor}",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "Actualiser",
|
||||
"unsaved_changes": {
|
||||
"message": "Vous avez des modifications non enregistrées. Êtes-vous sûr de vouloir partir ?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "Rechercher des leçons ou des exercices",
|
||||
"empty": "Aucun résultat trouvé"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "Retour au cours",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Date de création",
|
||||
"published": "Publié",
|
||||
"lessons": "Leçons"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "Tout effacer",
|
||||
"popover_title": "Filtres",
|
||||
"sort": "Trier",
|
||||
"order": "Ordre",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Balises",
|
||||
"empty_tags": "Aucune balise disponible"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "{provider} est activé pour votre domaine",
|
||||
"sso_redirect_error": "La connexion SSO est mal configurée. Veuillez définir PUBLIC_SERVER_URL sur votre serveur API.",
|
||||
"sso_required": "Veuillez vous connecter avec SSO. La connexion par mot de passe est désactivée.",
|
||||
"sign_in_with_sso": "Connectez-vous avec {provider}",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "रीफ़्रेश करें",
|
||||
"unsaved_changes": {
|
||||
"message": "आपके पास सहेजे नहीं गए परिवर्तन हैं. क्या आपकी वाकई छोड़ने की इच्छा है?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "पाठ या अभ्यास खोजें",
|
||||
"empty": "कोई परिणाम नहीं मिला"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "पाठ्यक्रम पर वापस जाएँ",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "दिनांक निर्मित",
|
||||
"published": "प्रकाशित",
|
||||
"lessons": "सबक"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "सब साफ़ करें",
|
||||
"popover_title": "फिल्टर",
|
||||
"sort": "क्रमबद्ध करें",
|
||||
"order": "क्रम",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "टैग",
|
||||
"empty_tags": "कोई टैग उपलब्ध नहीं है"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "आपके डोमेन के लिए {प्रदाता} सक्षम है",
|
||||
"sso_redirect_error": "SSO साइन-इन ग़लत कॉन्फ़िगर किया गया है. कृपया अपने एपीआई सर्वर पर PUBLIC_SERVER_URL सेट करें।",
|
||||
"sso_required": "कृपया एसएसओ के साथ साइन इन करें। पासवर्ड लॉगिन अक्षम है.",
|
||||
"sign_in_with_sso": "{प्रदाता} के साथ साइन इन करें",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "Odśwież",
|
||||
"unsaved_changes": {
|
||||
"message": "Masz niezapisane zmiany. Czy na pewno chcesz wyjść?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "Wyszukaj lekcje lub ćwiczenia",
|
||||
"empty": "Nie znaleziono żadnych wyników"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "Powrót na kurs",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Data utworzenia",
|
||||
"published": "Opublikowano",
|
||||
"lessons": "Lekcje"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "Wyczyść wszystko",
|
||||
"popover_title": "Filtry",
|
||||
"sort": "Sortuj",
|
||||
"order": "Kolejność",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Tagi",
|
||||
"empty_tags": "Brak dostępnych tagów"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "Usługa {provider} jest włączona w Twojej domenie",
|
||||
"sso_redirect_error": "Logowanie jednokrotne jest błędnie skonfigurowane. Ustaw PUBLIC_SERVER_URL na swój serwer API.",
|
||||
"sso_required": "Proszę zalogować się za pomocą SSO. Logowanie hasłem jest wyłączone.",
|
||||
"sign_in_with_sso": "Zaloguj się przez {provider}",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "Atualizar",
|
||||
"unsaved_changes": {
|
||||
"message": "Você tem alterações não salvas. Tem certeza de que deseja sair?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "Pesquise aulas ou exercícios",
|
||||
"empty": "Nenhum resultado encontrado"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "De volta ao curso",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Data de criação",
|
||||
"published": "Publicado",
|
||||
"lessons": "Lições"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "Limpar tudo",
|
||||
"popover_title": "Filtros",
|
||||
"sort": "Classificar",
|
||||
"order": "Ordem",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Etiquetas",
|
||||
"empty_tags": "Nenhuma tag disponível"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "{provider} está ativado para seu domínio",
|
||||
"sso_redirect_error": "O login do SSO está configurado incorretamente. Defina PUBLIC_SERVER_URL para seu servidor API.",
|
||||
"sso_required": "Faça login com SSO. O login por senha está desabilitado.",
|
||||
"sign_in_with_sso": "Faça login com {provedor}",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "Обновить",
|
||||
"unsaved_changes": {
|
||||
"message": "У вас есть несохраненные изменения. Вы уверены, что хотите уйти?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "Поиск уроков или упражнений",
|
||||
"empty": "Результаты не найдены"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "Вернуться к курсу",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Дата создания",
|
||||
"published": "Опубликовано",
|
||||
"lessons": "Уроки"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "Очистить все",
|
||||
"popover_title": "Фильтры",
|
||||
"sort": "Сортировать",
|
||||
"order": "Порядок",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Теги",
|
||||
"empty_tags": "Нет доступных тегов"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "{provider} включен для вашего домена",
|
||||
"sso_redirect_error": "Вход в систему единого входа настроен неправильно. Установите PUBLIC_SERVER_URL для вашего сервера API.",
|
||||
"sso_required": "Пожалуйста, войдите с помощью SSO. Вход по паролю отключен.",
|
||||
"sign_in_with_sso": "Войдите через {provider}",
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{
|
||||
"common": {
|
||||
"refresh": "Làm mới",
|
||||
"unsaved_changes": {
|
||||
"message": "Bạn có những thay đổi chưa được lưu. Bạn có chắc chắn muốn rời đi không?"
|
||||
}
|
||||
@@ -1508,6 +1509,10 @@
|
||||
"placeholder": "Tìm kiếm bài học hoặc bài tập",
|
||||
"empty": "Không tìm thấy kết quả nào"
|
||||
},
|
||||
"header": {
|
||||
"preview": "Preview course",
|
||||
"preview_missing_slug": "Generate and save a course slug before previewing."
|
||||
},
|
||||
"sidebar": {
|
||||
"back_to_course": "Quay lại khóa học",
|
||||
"content_count": {
|
||||
@@ -1582,6 +1587,12 @@
|
||||
}
|
||||
},
|
||||
"course_filter": {
|
||||
"date_created_newest": "Date Created: Newest first",
|
||||
"date_created_oldest": "Date Created: Oldest first",
|
||||
"published_first": "Published: Published first",
|
||||
"unpublished_first": "Published: Unpublished first",
|
||||
"most_lessons": "Lessons: Most first",
|
||||
"fewest_lessons": "Lessons: Fewest first",
|
||||
"date_created": "Ngày tạo",
|
||||
"published": "Đã xuất bản",
|
||||
"lessons": "Bài học"
|
||||
@@ -1592,6 +1603,9 @@
|
||||
"clear_all": "Xóa tất cả",
|
||||
"popover_title": "Bộ lọc",
|
||||
"sort": "Sắp xếp",
|
||||
"order": "Thứ tự",
|
||||
"ascending": "Asc",
|
||||
"descending": "Desc",
|
||||
"tags": "Thẻ",
|
||||
"empty_tags": "Không có thẻ nào"
|
||||
}
|
||||
@@ -2212,7 +2226,6 @@
|
||||
}
|
||||
},
|
||||
"login": {
|
||||
"sso_enabled": "{provider} đã được bật cho miền của bạn",
|
||||
"sso_redirect_error": "Đăng nhập SSO bị định cấu hình sai. Vui lòng đặt PUBLIC_SERVER_URL cho máy chủ API của bạn.",
|
||||
"sso_required": "Vui lòng đăng nhập bằng SSO. Đăng nhập bằng mật khẩu bị vô hiệu hóa.",
|
||||
"sign_in_with_sso": "Đăng nhập bằng {nhà cung cấp}",
|
||||
|
||||
Reference in New Issue
Block a user