feat(bisaya-course): refine phase 4 didactics and enhance course content generation
All checks were successful
Deploy to production / deploy (push) Successful in 5m19s

- 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.
This commit is contained in:
Torsten Schulz (local)
2026-04-17 16:00:41 +02:00
parent 5c315c477f
commit 71d5922409
18 changed files with 410 additions and 86 deletions

View File

@@ -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');

View File

@@ -9,7 +9,7 @@
<ul v-else class="vocab-courses-widget__list">
<li v-for="c in courses" :key="c.courseId" class="vocab-courses-widget__item">
<div class="vocab-courses-widget__main">
<strong class="vocab-courses-widget__course-title">{{ c.title || $t('widgets.vocabCourses.unnamedCourse') }}</strong>
<strong class="vocab-courses-widget__course-title">{{ displayCourseTitle(c) }}</strong>
<span v-if="c.currentLesson" class="vocab-courses-widget__lesson">
{{ $t('widgets.vocabCourses.lessonLine', { number: c.currentLesson.lessonNumber, title: c.currentLesson.title }) }}
</span>
@@ -42,6 +42,8 @@
</template>
<script>
import { localizeVocabCourseTitle } from '@/utils/vocabCourseTitle.js';
export default {
name: 'VocabCoursesWidget',
props: {
@@ -58,6 +60,9 @@ export default {
}
},
methods: {
displayCourseTitle(course) {
return localizeVocabCourseTitle(course?.title, this.$i18n?.locale) || this.$t('widgets.vocabCourses.unnamedCourse');
},
goToLesson(courseId, lessonId) {
this.$router.push({
name: 'VocabLesson',