From 71d5922409b797b05b1ba94e59edc793f29da481 Mon Sep 17 00:00:00 2001 From: "Torsten Schulz (local)" Date: Fri, 17 Apr 2026 16:00:41 +0200 Subject: [PATCH] feat(bisaya-course): refine phase 4 didactics and enhance course content generation - Corrected grammatical errors and improved the phrasing in the BISAYA_PHASE4_DIDACTICS, ensuring clarity and accuracy in the learning materials. - Updated the course content generation script to include lessons from phase 5, enhancing the overall structure and flow of the course. - Introduced a new vocabulary course content synchronization process, improving the integration of vocabulary resources across different modules. - Enhanced the VocabService to dynamically adjust temperature settings based on the mode, optimizing response generation for different contexts. - Added new localized titles and vocabulary entries in multiple languages, enriching the learning experience for users. --- .../scripts/bisaya-course-phase4-extension.js | 82 ++++---- .../scripts/create-bisaya-course-content.js | 5 +- backend/scripts/sync-vocab-course-content.js | 1 + backend/services/vocabService.js | 9 +- docs/OLLAMA_LANGUAGE_ASSISTANT_SETUP.md | 22 +-- .../src/components/widgets/FalukantWidget.vue | 45 ++++- .../components/widgets/VocabCoursesWidget.vue | 7 +- frontend/src/i18n/locales/ceb/falukant.json | 90 +++++++++ .../src/i18n/locales/ceb/socialnetwork.json | 4 + .../src/i18n/locales/de/socialnetwork.json | 4 + .../src/i18n/locales/en/socialnetwork.json | 4 + .../src/i18n/locales/es/socialnetwork.json | 4 + .../src/i18n/locales/fr/socialnetwork.json | 4 + frontend/src/utils/vocabCourseTitle.js | 17 ++ .../views/settings/LanguageAssistantView.vue | 4 +- .../src/views/social/VocabCourseListView.vue | 6 +- frontend/src/views/social/VocabCourseView.vue | 6 +- frontend/src/views/social/VocabLessonView.vue | 182 +++++++++++++++--- 18 files changed, 410 insertions(+), 86 deletions(-) create mode 100644 frontend/src/utils/vocabCourseTitle.js diff --git a/backend/scripts/bisaya-course-phase4-extension.js b/backend/scripts/bisaya-course-phase4-extension.js index c0b88b7..fb51860 100644 --- a/backend/scripts/bisaya-course-phase4-extension.js +++ b/backend/scripts/bisaya-course-phase4-extension.js @@ -31,8 +31,8 @@ export const BISAYA_PHASE4_DIDACTICS = { ], practicalTasks: [ { - title: 'Routine in 5 Saetzen', - text: 'Sprich eine Routine mit fuenf kurzen Saetzen (Essen, Tasche, Haende, Schule, Losgehen).' + title: 'Routine in 5 Sätzen', + text: 'Sprich eine Routine mit fünf kurzen Sätzen (Essen, Tasche, Hände, Schule, Losgehen).' } ] }, @@ -79,7 +79,7 @@ export const BISAYA_PHASE4_DIDACTICS = { { target: 'Kinsa ni?', gloss: 'Wer ist das?' }, { target: 'Asa imong bag?', gloss: 'Wo ist deine Tasche?' }, { target: 'Andam na ka?', gloss: 'Bist du fertig?' }, - { target: 'Ganahan ka?', gloss: 'Moechtest du?' }, + { target: 'Ganahan ka?', gloss: 'Möchtest du?' }, { target: 'Ali diri.', gloss: 'Komm her.' }, { target: 'Ayaw.', gloss: 'Nicht (tu das nicht).' } ], @@ -100,7 +100,7 @@ export const BISAYA_PHASE4_DIDACTICS = { practicalTasks: [ { title: 'Frage oder Aufforderung', - text: 'Forme drei deutsche Saetze einmal als Frage und einmal als kurze Aufforderung auf Bisaya.' + text: 'Forme drei deutsche Sätze einmal als Frage und einmal als kurze Aufforderung auf Bisaya.' } ] }, @@ -146,7 +146,7 @@ export const BISAYA_PHASE4_DIDACTICS = { { target: 'Andam na ka?', gloss: 'Bist du fertig?' }, { target: 'Asa imong bag?', gloss: 'Wo ist deine Tasche?' }, { target: 'Magtuon ta.', gloss: 'Lass uns lernen.' }, - { target: 'Hugas sa kamot.', gloss: 'Wasch dir die Haende.' }, + { target: 'Hugas sa kamot.', gloss: 'Wasch dir die Hände.' }, { target: 'Pagkahuman, magdula ta.', gloss: 'Danach spielen wir.' }, { target: 'Sunod, matulog na ta.', gloss: 'Danach gehen wir schlafen.' } ], @@ -160,7 +160,7 @@ export const BISAYA_PHASE4_DIDACTICS = { practicalTasks: [ { title: '8 Situationen', - text: 'Beantworte acht Situationen: Hunger, Tasche, Haende, Hausaufgaben, Spielen, Schlafen.' + text: 'Beantworte acht Situationen: Hunger, Tasche, Hände, Hausaufgaben, Spielen, Schlafen.' } ] }, @@ -177,20 +177,20 @@ export const BISAYA_PHASE4_DIDACTICS = { { target: 'pamilya', gloss: 'Familie' }, { target: 'eskwela', gloss: 'Schule' }, { target: 'tabang', gloss: 'Hilfe' }, - { target: 'Kapoy na ka?', gloss: 'Bist du muede?' }, + { target: 'Kapoy na ka?', gloss: 'Bist du müde?' }, { target: 'Ayaw kabalaka.', gloss: 'Mach dir keine Sorgen.' } ], speakingPrompts: [ { - title: 'Familien-Fuersorge', - prompt: 'Sprich zwei kurze Fuersorgesetze zu Kind und Schule.', + title: 'Familien-Fürsorge', + prompt: 'Sprich zwei kurze Fürsorgesätze zu Kind und Schule.', cue: 'Ayaw kabalaka. Andam na ka sa eskwela?' } ], practicalTasks: [ { title: 'Spiralabruf', - text: 'Nimm vier alte Woerter (Nanay/Tatay/bata/eskwela) und baue vier kurze Saetze.' + text: 'Nimm vier alte Wörter (Nanay/Tatay/bata/eskwela) und baue vier kurze Sätze.' } ] }, @@ -202,8 +202,8 @@ export const BISAYA_PHASE4_DIDACTICS = { ], corePatterns: [ { target: 'Magdula ta.', gloss: 'Lass uns spielen.' }, - { target: 'Ganahan ka modula?', gloss: 'Moechtest du spielen?' }, - { target: 'Lingaw ka?', gloss: 'Hast du Spass?' }, + { target: 'Ganahan ka modula?', gloss: 'Möchtest du spielen?' }, + { target: 'Lingaw ka?', gloss: 'Hast du Spaß?' }, { target: 'Human na ang duwa.', gloss: 'Das Spiel ist vorbei.' }, { target: 'Pahuway sa.', gloss: 'Mach erst mal Pause.' }, { target: 'Dali na.', gloss: 'Komm, beeil dich.' }, @@ -238,19 +238,19 @@ export const BISAYA_PHASE4_DIDACTICS = { { target: 'sayaw', gloss: 'Tanz' }, { target: 'drawing', gloss: 'Malen/Zeichnen' }, { target: 'Ganahan ka ani?', gloss: 'Magst du das?' }, - { target: 'Pilia.', gloss: 'Waehle.' } + { target: 'Pilia.', gloss: 'Wähle.' } ], speakingPrompts: [ { title: 'Auswahl anbieten', - prompt: 'Biete zwei Aktivitaeten an und lasse das Kind waehlen.', + prompt: 'Biete zwei Aktivitäten an und lasse das Kind wählen.', cue: 'Ganahan ka og kanta o sayaw? Pilia.' } ], practicalTasks: [ { title: 'Wortschatz aktiv', - text: 'Nenne sechs Spielsachen/Aktivitaeten und bilde zwei kurze Fragen dazu.' + text: 'Nenne sechs Spielsachen/Aktivitäten und bilde zwei kurze Fragen dazu.' } ] }, @@ -266,7 +266,7 @@ export const BISAYA_PHASE4_DIDACTICS = { { target: 'Magdula ta.', gloss: 'Lass uns spielen.' }, { target: 'Human na ka?', gloss: 'Bist du fertig?' }, { target: 'Naa kay assignment?', gloss: 'Hast du Hausaufgaben?' }, - { target: 'Hugas sa kamot.', gloss: 'Wasch dir die Haende.' }, + { target: 'Hugas sa kamot.', gloss: 'Wasch dir die Hände.' }, { target: 'Ayaw pagdali.', gloss: 'Kein Stress.' }, { target: 'Sunod, matulog na ta.', gloss: 'Danach schlafen wir.' } ], @@ -280,7 +280,7 @@ export const BISAYA_PHASE4_DIDACTICS = { practicalTasks: [ { title: 'Tempo', - text: 'Sag acht Saetze laut und schnell (aber klar), ohne zu stolpern.' + text: 'Sag acht Sätze laut und schnell (aber klar), ohne zu stolpern.' } ] }, @@ -303,14 +303,14 @@ export const BISAYA_PHASE4_DIDACTICS = { speakingPrompts: [ { title: 'Checkpoint-Szene', - prompt: 'Loese eine kurze Szene: Schule, Tasche, Hausaufgabe, Routine.', + prompt: 'Löse eine kurze Szene: Schule, Tasche, Hausaufgabe, Routine.', cue: 'Asa imong bag? Andam na ka sa eskwela? Naa kay assignment? Sunod, matulog na ta.' } ], practicalTasks: [ { title: 'Diagnose', - text: 'Markiere die Saetze, die nicht sofort kamen, und wiederhole sie dreimal im Typing.' + text: 'Markiere die Sätze, die nicht sofort kamen, und wiederhole sie dreimal im Typing.' } ] }, @@ -324,7 +324,7 @@ export const BISAYA_PHASE4_DIDACTICS = { { target: 'Adto ta sa doktor.', gloss: 'Wir gehen zum Arzt.' }, { target: 'Naa mi appointment.', gloss: 'Wir haben einen Termin.' }, { target: 'Naa moy appointment?', gloss: 'Haben Sie einen Termin?' }, - { target: 'Unsay gibati nimo?', gloss: 'Was fuehlst du / was hast du?' }, + { target: 'Unsay gibati nimo?', gloss: 'Was fühlst du / was hast du?' }, { target: 'Sakit diri.', gloss: 'Es tut hier weh.' }, { target: 'Pila ka oras ang hulat?', gloss: 'Wie lange ist die Wartezeit?' }, { target: 'Maghulat ta.', gloss: 'Wir warten.' }, @@ -340,7 +340,7 @@ export const BISAYA_PHASE4_DIDACTICS = { practicalTasks: [ { title: '3 Fragen', - text: 'Uebe drei Fragen fuer den Arztbesuch: Termin, Beschwerden, Wartezeit.' + text: 'Übe drei Fragen für den Arztbesuch: Termin, Beschwerden, Wartezeit.' } ] }, @@ -357,7 +357,7 @@ export const BISAYA_PHASE4_DIDACTICS = { { target: 'dose', gloss: 'Dosis' }, { target: 'Pila ang dose?', gloss: 'Wie ist die Dosierung?' }, { target: 'Pila ka adlaw?', gloss: 'Wie viele Tage?' }, - { target: 'Naa moy tambal ani?', gloss: 'Haben Sie Medizin dafuer?' }, + { target: 'Naa moy tambal ani?', gloss: 'Haben Sie Medizin dafür?' }, { target: 'Unsaon pag-inom?', gloss: 'Wie nimmt man das ein?' } ], speakingPrompts: [ @@ -437,7 +437,7 @@ export const BISAYA_PHASE4_DIDACTICS = { practicalTasks: [ { title: 'Notfallanker', - text: 'Uebe vier Notfallsaetze, bis sie ohne Lesen kommen.' + text: 'Übe vier Notfallsätze, bis sie ohne Lesen kommen.' } ] }, @@ -450,7 +450,7 @@ export const BISAYA_PHASE4_DIDACTICS = { corePatterns: [ { target: 'Adto ta sa doktor.', gloss: 'Wir gehen zum Arzt.' }, { target: 'Naa mi appointment.', gloss: 'Wir haben einen Termin.' }, - { target: 'Naa moy tambal ani?', gloss: 'Haben Sie Medizin dafuer?' }, + { target: 'Naa moy tambal ani?', gloss: 'Haben Sie Medizin dafür?' }, { target: 'Unsaon pag-inom?', gloss: 'Wie nimmt man das ein?' }, { target: 'Sakit kaayo.', gloss: 'Es tut sehr weh.' }, { target: 'Nagsugod ganiha.', gloss: 'Es fing vorhin an.' }, @@ -467,7 +467,7 @@ export const BISAYA_PHASE4_DIDACTICS = { practicalTasks: [ { title: 'Tempo-Mix', - text: 'Sag acht Saetze schnell hintereinander, ohne zu stolpern.' + text: 'Sag acht Sätze schnell hintereinander, ohne zu stolpern.' } ] }, @@ -489,15 +489,15 @@ export const BISAYA_PHASE4_DIDACTICS = { ], speakingPrompts: [ { - title: 'Fuersorgefolge', - prompt: 'Reagiere mit drei Fuersorgesatzen auf eine Beschwerde.', + title: 'Fürsorgefolge', + prompt: 'Reagiere mit drei Fürsorgesätzen auf eine Beschwerde.', cue: 'Ayaw kabalaka. Magpahuway sa. Uminom og tubig.' } ], practicalTasks: [ { title: 'Problem -> Antwort', - text: 'Bilde fuenf Paare aus Problem und Antwort (z.B. sakit -> magpahuway).' + text: 'Bilde fünf Paare aus Problem und Antwort (z.B. sakit -> magpahuway).' } ] }, @@ -519,7 +519,7 @@ export const BISAYA_PHASE4_DIDACTICS = { ], speakingPrompts: [ { - title: 'Pflegegespraech', + title: 'Pflegegespräch', prompt: 'Biete Essen, Wasser, Ruhe an und frage nach Besserung.', cue: 'Mokaon sa ka. Uminom og tubig. Magpahuway sa. Mas maayo na ka?' } @@ -527,7 +527,7 @@ export const BISAYA_PHASE4_DIDACTICS = { practicalTasks: [ { title: 'Pflegekette', - text: 'Sprich eine Pflegekette mit mindestens fuenf kurzen Saetzen.' + text: 'Sprich eine Pflegekette mit mindestens fünf kurzen Sätzen.' } ] }, @@ -540,7 +540,7 @@ export const BISAYA_PHASE4_DIDACTICS = { corePatterns: [ { target: 'ulo', gloss: 'Kopf' }, { target: 'tiyan', gloss: 'Bauch' }, - { target: 'likod', gloss: 'Ruecken' }, + { target: 'likod', gloss: 'Rücken' }, { target: 'tutunlan', gloss: 'Hals' }, { target: 'hilanat', gloss: 'Fieber' }, { target: 'ubo', gloss: 'Husten' }, @@ -550,15 +550,15 @@ export const BISAYA_PHASE4_DIDACTICS = { ], speakingPrompts: [ { - title: 'Koerper + Schmerz', - prompt: 'Sage drei Saetze: wo es weh tut und was du brauchst.', + title: 'Körper + Schmerz', + prompt: 'Sage drei Sätze: wo es weh tut und was du brauchst.', cue: 'Sakit akong ulo. Sakit akong tiyan. Asa ang tambal?' } ], practicalTasks: [ { - title: 'Koerperrunde', - text: 'Nenne vier Koerperteile und bilde zu jedem einen kurzen Satz mit sakit.' + title: 'Körperrunde', + text: 'Nenne vier Körperteile und bilde zu jedem einen kurzen Satz mit sakit.' } ] }, @@ -611,14 +611,14 @@ export const BISAYA_PHASE4_DIDACTICS = { speakingPrompts: [ { title: 'Checkpoint-Szene', - prompt: 'Loese eine Szene: Termin, Beschwerden, Apotheke, Notfall.', + prompt: 'Löse eine Szene: Termin, Beschwerden, Apotheke, Notfall.', cue: 'Naa mi appointment. Sakit kaayo. Naa moy tambal ani? Tawag ug doktor.' } ], practicalTasks: [ { title: 'Diagnose', - text: 'Markiere die unsicheren Saetze und wiederhole sie im Typing bis sie sofort kommen.' + text: 'Markiere die unsicheren Sätze und wiederhole sie im Typing bis sie sofort kommen.' } ] }, @@ -980,17 +980,17 @@ export const BISAYA_PHASE4_LESSONS = [ { week: 7, day: 3, num: 68, type: 'review', title: 'Woche 7 - Intensivwiederholung I', desc: 'Kinder, Schule und Familienroutine intensiv wiederholen (Abruf + Rollenwechsel)', targetMin: 34, targetScore: 82, review: false, cultural: null }, { week: 7, day: 3, num: 69, type: 'vocab', title: 'Spiralwiederholung - Familie, Kinder & Fürsorge', desc: 'Frühe Kernmuster in Kinder-/Schulszenen reaktivieren', targetMin: 24, targetScore: 85, review: true, cultural: null }, { week: 7, day: 4, num: 70, type: 'conversation', title: 'Spielen & Freizeit', desc: 'Spiel, Pause, Regeln und ruhige Korrektur im Kinderalltag sprechen', targetMin: 24, targetScore: 80, review: false, cultural: null }, - { week: 7, day: 4, num: 71, type: 'vocab', title: 'Spielsachen & Aktivitäten', desc: 'Spiel- und Freizeitwortschatz aktiv nutzen (Auswahl, Fragen, kurze Saetze)', targetMin: 24, targetScore: 85, review: true, cultural: null }, + { week: 7, day: 4, num: 71, type: 'vocab', title: 'Spielsachen & Aktivitäten', desc: 'Spiel- und Freizeitwortschatz aktiv nutzen (Auswahl, Fragen, kurze Sätze)', targetMin: 24, targetScore: 85, review: true, cultural: null }, { week: 7, day: 5, num: 72, type: 'review', title: 'Woche 7 - Intensivwiederholung II', desc: 'Große Mischwiederholung zur Kinder- und Schulwoche (Szene bauen)', targetMin: 34, targetScore: 82, review: false, cultural: null }, { week: 7, day: 5, num: 73, type: 'vocab', title: 'Woche 7 - Checkpoint', desc: 'Checkpoint zu Kindern, Schule, Hausaufgaben und Routine (Diagnose + freie Szene)', targetMin: 24, targetScore: 84, review: true, cultural: null }, { week: 8, day: 1, num: 74, type: 'conversation', title: 'Arzt & Termin', desc: 'Arzttermine, Beschwerden und Wartezeit als Mini-Dialog organisieren', targetMin: 26, targetScore: 80, review: false, cultural: null }, { week: 8, day: 1, num: 75, type: 'vocab', title: 'Apotheke & Medikamente', desc: 'Apotheke, Rezept, Dosierung und Einnahmefragen aktiv abrufen', targetMin: 24, targetScore: 85, review: true, cultural: null }, - { week: 8, day: 2, num: 76, type: 'grammar', title: 'Beschwerden genauer beschreiben', desc: 'Staerke, Verlauf, Zeitpunkte und wiederkehrende Beschwerden ausdruecken', targetMin: 26, targetScore: 78, review: true, cultural: null }, + { week: 8, day: 2, num: 76, type: 'grammar', title: 'Beschwerden genauer beschreiben', desc: 'Stärke, Verlauf, Zeitpunkte und wiederkehrende Beschwerden ausdrücken', targetMin: 26, targetScore: 78, review: true, cultural: null }, { week: 8, day: 2, num: 77, type: 'conversation', title: 'Notfälle & Hilfe', desc: 'Hilfe rufen, kurze Anweisungen geben und Notfallanker sicher sprechen', targetMin: 26, targetScore: 80, review: false, cultural: null }, { week: 8, day: 3, num: 78, type: 'review', title: 'Woche 8 - Intensivwiederholung I', desc: 'Arzt, Apotheke, Beschwerden und Hilfe intensiv wiederholen (Tempo + Abruf)', targetMin: 34, targetScore: 82, review: false, cultural: null }, { week: 8, day: 3, num: 79, type: 'vocab', title: 'Spiralwiederholung - Gesundheit', desc: 'Fürsorge und Gesundheit als Langzeitabruf (Problem -> Antwort)', targetMin: 24, targetScore: 85, review: true, cultural: null }, - { week: 8, day: 4, num: 80, type: 'conversation', title: 'Essen, Ruhe & Genesung', desc: 'Pflegegespraeche: Essen, Wasser, Ruhe, Medizin und Besserung verbinden', targetMin: 24, targetScore: 80, review: false, cultural: null }, - { week: 8, day: 4, num: 81, type: 'vocab', title: 'Körper, Symptome & Pflege', desc: 'Koerper, Symptome und Pflegewortschatz mit kurzen Schmerzsaetzen kombinieren', targetMin: 24, targetScore: 85, review: true, cultural: null }, + { week: 8, day: 4, num: 80, type: 'conversation', title: 'Essen, Ruhe & Genesung', desc: 'Pflegegespräche: Essen, Wasser, Ruhe, Medizin und Besserung verbinden', targetMin: 24, targetScore: 80, review: false, cultural: null }, + { week: 8, day: 4, num: 81, type: 'vocab', title: 'Körper, Symptome & Pflege', desc: 'Körper, Symptome und Pflegewortschatz mit kurzen Schmerzsätzen kombinieren', targetMin: 24, targetScore: 85, review: true, cultural: null }, { week: 8, day: 5, num: 82, type: 'review', title: 'Woche 8 - Intensivwiederholung II', desc: 'Große Mischwiederholung zu Gesundheit und Hilfe (Kontraste + freie Antworten)', targetMin: 34, targetScore: 82, review: false, cultural: null }, { week: 8, day: 5, num: 83, type: 'vocab', title: 'Woche 8 - Checkpoint', desc: 'Checkpoint zu Arzt, Apotheke, Beschwerden und Notfall (Diagnose + Typing)', targetMin: 24, targetScore: 84, review: true, cultural: null }, { week: 9, day: 1, num: 84, type: 'conversation', title: 'Einkaufen vertiefen', desc: 'Komplexere Einkaufs- und Auswahlgespräche führen', targetMin: 18, targetScore: 80, review: false, cultural: null }, diff --git a/backend/scripts/create-bisaya-course-content.js b/backend/scripts/create-bisaya-course-content.js index d059f66..17da6a3 100644 --- a/backend/scripts/create-bisaya-course-content.js +++ b/backend/scripts/create-bisaya-course-content.js @@ -16,7 +16,7 @@ import User from '../models/community/user.js'; import { BISAYA_DIDACTICS_24_43, BISAYA_RELATIONSHIP_ANCHOR_DIDACTICS } from './bisaya-course-plan-24-43.js'; import { BISAYA_PHASE3_DIDACTICS, BISAYA_PHASE3_LESSONS } from './bisaya-course-phase3-extension.js'; import { BISAYA_PHASE4_DIDACTICS, BISAYA_PHASE4_LESSONS } from './bisaya-course-phase4-extension.js'; -import { BISAYA_PHASE5_DIDACTICS } from './bisaya-course-phase5-extension.js'; +import { BISAYA_PHASE5_DIDACTICS, BISAYA_PHASE5_LESSONS } from './bisaya-course-phase5-extension.js'; function withTypeName(exerciseTypeName, exercise) { return { @@ -35,7 +35,8 @@ const GENERATED_BISAYA_DIDACTICS = { const SAFE_EXERCISE_UPDATE_TITLES = new Set([ ...BISAYA_PHASE3_LESSONS.map((lesson) => lesson.title), - ...BISAYA_PHASE4_LESSONS.map((lesson) => lesson.title) + ...BISAYA_PHASE4_LESSONS.map((lesson) => lesson.title), + ...BISAYA_PHASE5_LESSONS.map((lesson) => lesson.title) ]); function normalizeText(value) { diff --git a/backend/scripts/sync-vocab-course-content.js b/backend/scripts/sync-vocab-course-content.js index 13657ca..5a15799 100644 --- a/backend/scripts/sync-vocab-course-content.js +++ b/backend/scripts/sync-vocab-course-content.js @@ -31,6 +31,7 @@ const SAFE_SYNC_STEPS = { 'backend/scripts/create-bisaya-course-content.js' ], 'german-for-bisaya': [ + 'backend/scripts/create-german-for-bisaya-course.js', 'backend/scripts/extend-german-for-bisaya-course-phase3.js', 'backend/scripts/extend-german-for-bisaya-course-phase4.js', 'backend/scripts/extend-german-for-bisaya-course-phase5.js', diff --git a/backend/services/vocabService.js b/backend/services/vocabService.js index d8eb19f..a7283ee 100644 --- a/backend/services/vocabService.js +++ b/backend/services/vocabService.js @@ -2798,6 +2798,13 @@ export default class VocabService { const controller = new AbortController(); const timeout = setTimeout(() => controller.abort(), 30000); + const temperatureByMode = { + explain: 0.4, + practice: 0.5, + correct: 0.1 + }; + const temperature = Number.isFinite(temperatureByMode[mode]) ? temperatureByMode[mode] : 0.5; + let response; try { response = await fetch(endpoint, { @@ -2806,7 +2813,7 @@ export default class VocabService { signal: controller.signal, body: JSON.stringify({ model: config.model, - temperature: 0.7, + temperature, messages: [ { role: 'system', diff --git a/docs/OLLAMA_LANGUAGE_ASSISTANT_SETUP.md b/docs/OLLAMA_LANGUAGE_ASSISTANT_SETUP.md index c93ae3f..8fc2f8a 100644 --- a/docs/OLLAMA_LANGUAGE_ASSISTANT_SETUP.md +++ b/docs/OLLAMA_LANGUAGE_ASSISTANT_SETUP.md @@ -24,18 +24,18 @@ ollama --version ## 2) Modell laden -Empfohlen fuer freien Schreib- und Korrekturmodus: - -```bash -ollama pull qwen2.5:7b-instruct -``` - -Optional kleinere Alternative (weniger RAM): +Empfohlen fuer freien Schreib- und Korrekturmodus (CPU-freundlich): ```bash ollama pull qwen2.5:3b-instruct ``` +Optional groessere Alternative (bessere Qualitaet, aber langsamer auf CPU): + +```bash +ollama pull qwen2.5:7b-instruct +``` + ## 3) Ollama-Server starten ```bash @@ -55,7 +55,7 @@ Der Server laeuft dann standardmaessig auf: Der Preset setzt: - Base URL: `http://127.0.0.1:11434/v1` -- Modell: `qwen2.5:7b-instruct` +- Modell: `qwen2.5:3b-instruct` - API-Key: nicht erforderlich ## 5) Funktionstest @@ -79,12 +79,12 @@ Wenn die Antwort kommt, ist alles korrekt verbunden. - Modell erneut laden: ```bash -ollama pull qwen2.5:7b-instruct +ollama pull qwen2.5:3b-instruct ``` -### Antwort langsam +### Antwort langsam (haeufig bei CPU-only Servern) -- Kleineres Modell nutzen (`qwen2.5:3b-instruct`) +- `qwen2.5:3b-instruct` als Standard nutzen - Andere GPU/CPU-Auslastung reduzieren ## Hinweise fuer A2-Ziel diff --git a/frontend/src/components/widgets/FalukantWidget.vue b/frontend/src/components/widgets/FalukantWidget.vue index 42413ba..21d586c 100644 --- a/frontend/src/components/widgets/FalukantWidget.vue +++ b/frontend/src/components/widgets/FalukantWidget.vue @@ -63,8 +63,8 @@ export default { falukantDisplayName() { const d = this.falukantData; if (!d) return this.$t('widgets.falukant.emptyValue'); - const titleKey = d.titleLabelTr; - const gender = d.gender; + const gender = this._normalizeGenderKey(d.gender); + const titleKey = this._normalizeTitleKey(d.titleLabelTr, gender); const nameWithoutTitle = d.nameWithoutTitle ?? d.characterName; if (titleKey && gender) { const key = `falukant.titles.${gender}.${titleKey}`; @@ -74,7 +74,7 @@ export default { return d.characterName || nameWithoutTitle || this.$t('widgets.falukant.emptyValue'); }, falukantGenderLabel() { - const g = this.falukantData?.gender; + const g = this._normalizeGenderKey(this.falukantData?.gender); if (g == null || g === '') return this.$t('widgets.falukant.emptyValue'); // Altersabhängige, (auf Wunsch) altertümlichere Bezeichnungen @@ -143,6 +143,45 @@ export default { // Fallback, falls Konfig kaputt ist return 'adult'; }, + _normalizeGenderKey(rawGender) { + const g = String(rawGender || '').trim(); + if (!g) return ''; + const lower = g.toLowerCase(); + const direct = new Set(['male', 'female', 'transmale', 'transfemale', 'nonbinary']); + if (direct.has(lower)) return lower; + // Legacy/locale labels that can appear from backend data drifts. + if (['mann', 'männlich', 'lalaki'].includes(lower)) return 'male'; + if (['frau', 'weiblich', 'babaye'].includes(lower)) return 'female'; + if (['trans-mann', 'transmann'].includes(lower)) return 'transmale'; + if (['trans-frau', 'transfrau'].includes(lower)) return 'transfemale'; + if (['non-binary', 'nichtbinär', 'dili binaryo'].includes(lower)) return 'nonbinary'; + return lower; + }, + _normalizeTitleKey(rawTitle, genderKey) { + const title = String(rawTitle || '').trim(); + if (!title) return ''; + const known = new Set([ + 'noncivil', 'civil', 'sir', 'townlord', 'by', 'landlord', + 'knight', 'baron', 'count', 'palsgrave', 'margrave', 'landgrave', + 'ruler', 'elector', 'imperial-prince', 'duke', 'grand-duke', + 'prince-regent', 'king' + ]); + if (known.has(title)) return title; + + const candidates = []; + const locale = this.$i18n?.locale; + if (locale) candidates.push(locale); + if (!candidates.includes('de')) candidates.push('de'); + if (!candidates.includes('en')) candidates.push('en'); + + for (const loc of candidates) { + const entries = this.$i18n?.messages?.[loc]?.falukant?.titles?.[genderKey]; + if (!entries || typeof entries !== 'object') continue; + const found = Object.entries(entries).find(([, value]) => String(value || '').trim().toLowerCase() === title.toLowerCase()); + if (found?.[0]) return found[0]; + } + return title; + }, formatMoney(value) { const n = Number(value); if (Number.isNaN(n)) return this.$t('widgets.falukant.emptyValue'); diff --git a/frontend/src/components/widgets/VocabCoursesWidget.vue b/frontend/src/components/widgets/VocabCoursesWidget.vue index 264f2a0..a0b7b21 100644 --- a/frontend/src/components/widgets/VocabCoursesWidget.vue +++ b/frontend/src/components/widgets/VocabCoursesWidget.vue @@ -9,7 +9,7 @@