Add native language support in vocab course management

- Introduced a new field for native language in the VocabCourse model to allow learners to specify their native language.
- Updated the VocabService to handle native language during course creation and retrieval, including filtering options.
- Enhanced the database schema to include foreign key constraints for native language.
- Updated frontend components to support native language selection and display in course listings.
- Added internationalization strings for native language features in both German and English.
This commit is contained in:
Torsten Schulz (local)
2026-01-19 11:43:38 +01:00
parent 714e144329
commit 09e53244d9
8 changed files with 531 additions and 5 deletions

View File

@@ -538,7 +538,7 @@ export default class VocabService {
// ========== COURSE METHODS ==========
async createCourse(hashedUserId, { title, description, languageId, difficultyLevel = 1, isPublic = false }) {
async createCourse(hashedUserId, { title, description, languageId, nativeLanguageId, difficultyLevel = 1, isPublic = false }) {
const user = await this._getUserByHashedId(hashedUserId);
// Prüfe Zugriff auf Sprache
@@ -551,6 +551,7 @@ export default class VocabService {
title,
description,
languageId: Number(languageId),
nativeLanguageId: nativeLanguageId ? Number(nativeLanguageId) : null,
difficultyLevel: Number(difficultyLevel) || 1,
isPublic: Boolean(isPublic),
shareCode
@@ -559,7 +560,7 @@ export default class VocabService {
return course.get({ plain: true });
}
async getCourses(hashedUserId, { includePublic = true, includeOwn = true, languageId, search } = {}) {
async getCourses(hashedUserId, { includePublic = true, includeOwn = true, languageId, nativeLanguageId, search } = {}) {
const user = await this._getUserByHashedId(hashedUserId);
const where = {};
@@ -579,11 +580,21 @@ export default class VocabService {
where.isPublic = true;
}
// Filter nach Sprache
// Filter nach Zielsprache (die zu lernende Sprache)
if (languageId) {
where.languageId = Number(languageId);
}
// Filter nach Muttersprache (die Sprache des Lerners)
if (nativeLanguageId !== undefined) {
if (nativeLanguageId === null) {
// NULL bedeutet "für alle Sprachen" - zeige Kurse ohne native_language_id
where.nativeLanguageId = null;
} else {
where.nativeLanguageId = Number(nativeLanguageId);
}
}
// Suche nach Titel oder Beschreibung
if (search && search.trim()) {
const searchTerm = `%${search.trim()}%`;
@@ -698,7 +709,7 @@ export default class VocabService {
return courseData;
}
async updateCourse(hashedUserId, courseId, { title, description, difficultyLevel, isPublic }) {
async updateCourse(hashedUserId, courseId, { title, description, languageId, nativeLanguageId, difficultyLevel, isPublic }) {
const user = await this._getUserByHashedId(hashedUserId);
const course = await VocabCourse.findByPk(courseId);
@@ -717,6 +728,8 @@ export default class VocabService {
const updates = {};
if (title !== undefined) updates.title = title;
if (description !== undefined) updates.description = description;
if (languageId !== undefined) updates.languageId = Number(languageId);
if (nativeLanguageId !== undefined) updates.nativeLanguageId = nativeLanguageId ? Number(nativeLanguageId) : null;
if (difficultyLevel !== undefined) updates.difficultyLevel = Number(difficultyLevel);
if (isPublic !== undefined) {
updates.isPublic = Boolean(isPublic);