feat(vocab): add language and course dictionary endpoints and UI components
All checks were successful
Deploy to production / deploy (push) Successful in 2m53s

- Implemented `getLanguageDictionary` and `getCourseDictionary` methods in the VocabService to retrieve vocabulary entries filtered by search terms.
- Updated VocabController and vocabRouter to include new routes for accessing language and course dictionaries.
- Enhanced frontend components to navigate to the new dictionary views, including buttons in VocabCourseView and VocabLanguageView.
- Added localization entries for the dictionary feature in multiple languages, ensuring a consistent user experience across the platform.
This commit is contained in:
Torsten Schulz (local)
2026-04-10 13:08:18 +02:00
parent 9582e7b900
commit d17c8a341d
18 changed files with 443 additions and 16 deletions

View File

@@ -148,6 +148,7 @@
"subscribeLanguage": "Mag-subscribe sa pinulongan",
"language": "Pinulongan",
"chapter": "Kapitulo",
"vocabDictionary": "Dictionary",
"courses": "Mga kurso",
"course": "Kurso",
"lesson": "Leksiyon",

View File

@@ -785,6 +785,19 @@
"search": "Pangita",
"noResults": "Walay results.",
"error": "Pangita failed."
},
"dictionary": {
"open": "Dictionary",
"kicker": "Tan-awa",
"intro": "Tanang termino gikan sa imong mga kapitulo. Usa ka field para sa partial match sa duha ka pinulongan.",
"searchLabel": "Pangita (duha ka pinulongan)",
"searchPlaceholder": "Part sa pulong sa bisan unsang pinulongan …",
"empty": "Walay entry.",
"loadError": "Dili ma-load ang dictionary.",
"notFound": "Walay access o wala makita.",
"languageTitle": "Dictionary: {name}",
"courseTitle": "Dictionary sa kurso: {name}",
"courseLearningColumn": "Pagkat-on nga pinulongan (kurso)"
}
}
}

View File

@@ -148,6 +148,7 @@
"subscribeLanguage": "Sprache abonnieren",
"language": "Sprache",
"chapter": "Kapitel",
"vocabDictionary": "Wörterbuch",
"courses": "Kurse",
"course": "Kurs",
"lesson": "Lektion",

View File

@@ -468,6 +468,19 @@
"noResults": "Keine Treffer.",
"error": "Suche fehlgeschlagen."
},
"dictionary": {
"open": "Wörterbuch",
"kicker": "Nachschlagen",
"intro": "Alle Begriffe aus deinen Kapiteln. Ein Suchfeld filtert in beiden Sprachen nach Teilwörtern.",
"searchLabel": "Suche (beide Sprachen)",
"searchPlaceholder": "Teilwort in Lern- oder Muttersprache …",
"empty": "Keine Einträge.",
"loadError": "Wörterbuch konnte nicht geladen werden.",
"notFound": "Kein Zugriff oder nicht gefunden.",
"languageTitle": "Wörterbuch: {name}",
"courseTitle": "Kurs-Wörterbuch: {name}",
"courseLearningColumn": "Lernsprache (Kurs)"
},
"courses": {
"title": "Sprachlernkurse",
"create": "Kurs erstellen",

View File

@@ -148,6 +148,7 @@
"subscribeLanguage": "Subscribe to language",
"language": "Language",
"chapter": "Chapter",
"vocabDictionary": "Dictionary",
"courses": "Courses",
"course": "Course",
"lesson": "Lesson",

View File

@@ -468,6 +468,19 @@
"noResults": "No results.",
"error": "Search failed."
},
"dictionary": {
"open": "Dictionary",
"kicker": "Lookup",
"intro": "All terms from your chapters. One field filters both languages by partial matches.",
"searchLabel": "Search (both languages)",
"searchPlaceholder": "Part of a word in either language…",
"empty": "No entries.",
"loadError": "Could not load the dictionary.",
"notFound": "No access or not found.",
"languageTitle": "Dictionary: {name}",
"courseTitle": "Course dictionary: {name}",
"courseLearningColumn": "Learning language (course)"
},
"courses": {
"title": "Language Learning Courses",
"create": "Create Course",

View File

@@ -148,6 +148,7 @@
"subscribeLanguage": "Suscribirse al idioma",
"language": "Idioma",
"chapter": "Capítulo",
"vocabDictionary": "Diccionario",
"courses": "Cursos",
"course": "Curso",
"lesson": "Lección",

View File

@@ -466,6 +466,19 @@
"noResults": "Sin resultados.",
"error": "La búsqueda ha fallado."
},
"dictionary": {
"open": "Diccionario",
"kicker": "Consulta",
"intro": "Todos los términos de tus capítulos. Un solo campo filtra en ambos idiomas por coincidencias parciales.",
"searchLabel": "Búsqueda (ambos idiomas)",
"searchPlaceholder": "Parte de una palabra en cualquier idioma…",
"empty": "Sin entradas.",
"loadError": "No se pudo cargar el diccionario.",
"notFound": "Sin acceso o no encontrado.",
"languageTitle": "Diccionario: {name}",
"courseTitle": "Diccionario del curso: {name}",
"courseLearningColumn": "Idioma de aprendizaje (curso)"
},
"courses": {
"title": "Cursos de idiomas",
"create": "Crear curso",

View File

@@ -148,6 +148,7 @@
"subscribeLanguage": "Abonnez-vous à la langue",
"language": "Langue",
"chapter": "Chapitre",
"vocabDictionary": "Dictionnaire",
"courses": "Cours",
"course": "Kurs",
"lesson": "Lektion",

View File

@@ -466,6 +466,19 @@
"noResults": "Aucun coup sûr.",
"error": "La recherche a échoué."
},
"dictionary": {
"open": "Dictionnaire",
"kicker": "Consulter",
"intro": "Tous les termes de vos chapitres. Un seul champ filtre les deux langues par correspondances partielles.",
"searchLabel": "Recherche (les deux langues)",
"searchPlaceholder": "Fragment dans lune ou lautre langue…",
"empty": "Aucune entrée.",
"loadError": "Impossible de charger le dictionnaire.",
"notFound": "Pas daccès ou introuvable.",
"languageTitle": "Dictionnaire : {name}",
"courseTitle": "Dictionnaire du cours : {name}",
"courseLearningColumn": "Langue apprise (cours)"
},
"courses": {
"title": "Cours d'apprentissage des langues",
"create": "Créer un cours",