diff --git a/backend/services/vocabService.js b/backend/services/vocabService.js index aeaa90d..36f5c24 100644 --- a/backend/services/vocabService.js +++ b/backend/services/vocabService.js @@ -321,6 +321,32 @@ export default class VocabService { return n ? n.target : ''; } + _enrichCorePatternsWithGloss(corePatterns = [], extractedVocabs = []) { + const glossByReference = new Map(); + + extractedVocabs.forEach((item) => { + const reference = this._normalizeLexeme(item?.reference); + const learning = String(item?.learning || '').trim(); + if (!reference || !learning) { + return; + } + if (!glossByReference.has(reference)) { + glossByReference.set(reference, learning); + } + }); + + return corePatterns + .map((entry) => this._normalizeCorePatternEntry(entry)) + .filter(Boolean) + .map((entry) => { + if (entry.gloss) { + return entry; + } + const gloss = glossByReference.get(this._normalizeLexeme(entry.target)) || ''; + return gloss ? { ...entry, gloss } : entry; + }); + } + _normalizeStructuredList(value, keys = ['title', 'text']) { if (!value) return []; if (Array.isArray(value)) { @@ -533,7 +559,11 @@ export default class VocabService { const uniquePatterns = [...new Set(patterns.map((item) => String(item || '').trim()).filter(Boolean))]; const learningGoals = this._normalizeStringList(plainLesson.learningGoals); - const corePatterns = this._normalizeCorePatternList(plainLesson.corePatterns); + const extractedTrainerVocabs = this._extractTrainerVocabsFromExercises(grammarExercises); + const corePatterns = this._enrichCorePatternsWithGloss( + this._normalizeCorePatternList(plainLesson.corePatterns), + extractedTrainerVocabs + ); const grammarFocus = this._normalizeStructuredList(plainLesson.grammarFocus, ['title', 'text', 'example']); const explicitSpeakingPrompts = this._normalizeStructuredList(plainLesson.speakingPrompts, ['title', 'prompt', 'cue']); const practicalTasks = this._normalizeStructuredList(plainLesson.practicalTasks, ['title', 'text']); @@ -548,7 +578,10 @@ export default class VocabService { ], corePatterns: corePatterns.length > 0 ? corePatterns - : uniquePatterns.slice(0, 5).map((s) => ({ target: String(s || '').trim(), gloss: '' })).filter((p) => p.target), + : this._enrichCorePatternsWithGloss( + uniquePatterns.slice(0, 5).map((s) => ({ target: String(s || '').trim(), gloss: '' })).filter((p) => p.target), + extractedTrainerVocabs + ), grammarFocus: grammarFocus.length > 0 ? grammarFocus : uniqueGrammarExplanations.slice(0, 4), speakingPrompts: explicitSpeakingPrompts.length > 0 ? explicitSpeakingPrompts : speakingPrompts.slice(0, 4), practicalTasks: practicalTasks.length > 0 diff --git a/frontend/src/views/social/VocabLessonView.vue b/frontend/src/views/social/VocabLessonView.vue index f96084f..51c710f 100644 --- a/frontend/src/views/social/VocabLessonView.vue +++ b/frontend/src/views/social/VocabLessonView.vue @@ -948,7 +948,18 @@ export default { }, prepItems() { if (this.normalizedCorePatterns.length > 0) { - return this.normalizedCorePatterns; + const glossByReference = new Map( + (this.importantVocab || []) + .map((item) => [String(item?.reference || '').trim().toLowerCase(), String(item?.learning || '').trim()]) + .filter(([reference, learning]) => reference && learning) + ); + return this.normalizedCorePatterns.map((item) => { + if (item.gloss) { + return item; + } + const gloss = glossByReference.get(String(item.target || '').trim().toLowerCase()) || ''; + return gloss ? { ...item, gloss } : item; + }); } return (this.importantVocab || []) .map((item) => ({