fix(i18n): correct translation directions in socialnetwork.json files
All checks were successful
Deploy to production / deploy (push) Successful in 3m24s

- Updated translation keys in German, English, and Spanish localization files to accurately reflect the intended language direction for vocabulary translation.
- Adjusted the `translateTo` and `translateFrom` keys to ensure consistency across all language files.
This commit is contained in:
Torsten Schulz (local)
2026-03-30 16:03:23 +02:00
parent 3d9bca099c
commit 4ebff4dc17
4 changed files with 34 additions and 42 deletions

View File

@@ -457,8 +457,8 @@
"vocabTrainerDescription": "Übe die wichtigsten Begriffe dieser Lektion interaktiv.", "vocabTrainerDescription": "Übe die wichtigsten Begriffe dieser Lektion interaktiv.",
"startVocabTrainer": "Vokabeltrainer starten", "startVocabTrainer": "Vokabeltrainer starten",
"stopTrainer": "Trainer beenden", "stopTrainer": "Trainer beenden",
"translateTo": "Übersetze ins Deutsche", "translateTo": "Übersetze ins Bisaya",
"translateFrom": "Übersetze ins Bisaya", "translateFrom": "Übersetze ins Deutsche",
"next": "Weiter", "next": "Weiter",
"totalAttempts": "Versuche", "totalAttempts": "Versuche",
"successRate": "Erfolgsrate", "successRate": "Erfolgsrate",

View File

@@ -457,8 +457,8 @@
"vocabTrainerDescription": "Practice the most important terms of this lesson interactively.", "vocabTrainerDescription": "Practice the most important terms of this lesson interactively.",
"startVocabTrainer": "Start Vocabulary Trainer", "startVocabTrainer": "Start Vocabulary Trainer",
"stopTrainer": "Stop Trainer", "stopTrainer": "Stop Trainer",
"translateTo": "Translate to English", "translateTo": "Translate into Bisaya",
"translateFrom": "Translate to Target Language", "translateFrom": "Translate into German",
"next": "Next", "next": "Next",
"totalAttempts": "Attempts", "totalAttempts": "Attempts",
"successRate": "Success Rate", "successRate": "Success Rate",

View File

@@ -455,8 +455,8 @@
"vocabTrainerDescription": "Practica los términos clave de esta lección de forma interactiva.", "vocabTrainerDescription": "Practica los términos clave de esta lección de forma interactiva.",
"startVocabTrainer": "Iniciar entrenador", "startVocabTrainer": "Iniciar entrenador",
"stopTrainer": "Detener entrenador", "stopTrainer": "Detener entrenador",
"translateTo": "Traduce al alemán", "translateTo": "Traduce al bisaya",
"translateFrom": "Traduce desde bisaya", "translateFrom": "Traduce al alemán",
"next": "Siguiente", "next": "Siguiente",
"totalAttempts": "Intentos", "totalAttempts": "Intentos",
"successRate": "Tasa de acierto", "successRate": "Tasa de acierto",

View File

@@ -1699,49 +1699,43 @@ export default {
return matches; return matches;
}, },
buildChoiceOptions(correctAnswers, allVocabs, excludePrompt = null) { /**
* @param {'L2R'|'R2L'} direction L2R: Antwort = reference (Zielsprache, z. B. Bisaya). R2L: Antwort = learning (Muttersprache, z. B. Deutsch).
* Distraktoren kommen immer nur aus derselben Sprache wie die richtige Antwort.
*/
buildChoiceOptions(correctAnswers, allVocabs, excludePrompt = null, direction = 'L2R') {
const normalizedCorrectAnswers = Array.isArray(correctAnswers) ? correctAnswers : [correctAnswers]; const normalizedCorrectAnswers = Array.isArray(correctAnswers) ? correctAnswers : [correctAnswers];
const options = new Set(normalizedCorrectAnswers.filter(Boolean)); const options = new Set(normalizedCorrectAnswers.filter(Boolean));
// Normalisiere alle Werte für den Vergleich (trim + lowercase)
const normalizedExcludeSet = new Set(); const normalizedExcludeSet = new Set();
normalizedCorrectAnswers.forEach((answer) => { normalizedCorrectAnswers.forEach((answer) => {
normalizedExcludeSet.add(this.normalizeVocab(answer)); normalizedExcludeSet.add(this.normalizeVocab(answer));
}); });
// Wichtig: Der Prompt (die Frage) darf nicht in den Optionen erscheinen
if (excludePrompt) { if (excludePrompt) {
normalizedExcludeSet.add(this.normalizeVocab(excludePrompt)); normalizedExcludeSet.add(this.normalizeVocab(excludePrompt));
} }
// Sammle alle verfügbaren Distraktoren aus beiden Richtungen const answerField = direction === 'L2R' ? 'reference' : 'learning';
const allDistractors = []; const allDistractors = [];
allVocabs.forEach(vocab => { allVocabs.forEach((vocab) => {
// Füge beide Richtungen hinzu (learning und reference) const candidate = vocab[answerField];
if (vocab.learning && vocab.learning.trim()) { if (!candidate || !candidate.trim()) return;
const normalized = this.normalizeVocab(vocab.learning); const normalized = this.normalizeVocab(candidate);
if (!normalizedExcludeSet.has(normalized)) { if (!normalizedExcludeSet.has(normalized)) {
allDistractors.push(vocab.learning); allDistractors.push(candidate);
}
}
if (vocab.reference && vocab.reference.trim()) {
const normalized = this.normalizeVocab(vocab.reference);
if (!normalizedExcludeSet.has(normalized)) {
allDistractors.push(vocab.reference);
}
} }
}); });
// Entferne Duplikate
const uniqueDistractors = [...new Set(allDistractors)]; const uniqueDistractors = [...new Set(allDistractors)];
// Füge Distraktoren hinzu, bis wir 4 Optionen haben
let attempts = 0; let attempts = 0;
const maxAttempts = 200; const maxAttempts = 200;
while (options.size < 4 && uniqueDistractors.length > 0 && attempts < maxAttempts) { while (options.size < 4 && uniqueDistractors.length > 0 && attempts < maxAttempts) {
attempts++; attempts++;
const randomIndex = Math.floor(Math.random() * uniqueDistractors.length); const randomIndex = Math.floor(Math.random() * uniqueDistractors.length);
const distractor = uniqueDistractors[randomIndex]; const distractor = uniqueDistractors[randomIndex];
if (distractor && distractor.trim()) { if (distractor && distractor.trim()) {
const normalizedDistractor = this.normalizeVocab(distractor); const normalizedDistractor = this.normalizeVocab(distractor);
if (!normalizedExcludeSet.has(normalizedDistractor) && !options.has(distractor)) { if (!normalizedExcludeSet.has(normalizedDistractor) && !options.has(distractor)) {
@@ -1749,18 +1743,15 @@ export default {
} }
} }
} }
// Falls immer noch nicht genug Optionen: Verwende auch die andere Richtung der aktuellen Vokabeln
if (options.size < 4 && allVocabs.length > 0) { if (options.size < 4 && allVocabs.length > 0) {
allVocabs.forEach(vocab => { allVocabs.forEach((vocab) => {
if (options.size >= 4) return; if (options.size >= 4) return;
const candidate = vocab[answerField];
// Verwende die andere Richtung als Distraktor if (candidate && candidate.trim()) {
const otherDirection = this.vocabTrainerDirection === 'L2R' ? vocab.learning : vocab.reference; const normalized = this.normalizeVocab(candidate);
if (otherDirection && otherDirection.trim()) { if (!normalizedExcludeSet.has(normalized) && !options.has(candidate)) {
const normalized = this.normalizeVocab(otherDirection); options.add(candidate);
if (!normalizedExcludeSet.has(normalized) && !options.has(otherDirection)) {
options.add(otherDirection);
} }
} }
}); });
@@ -1845,9 +1836,10 @@ export default {
debugLog('[VocabLessonView] Answer:', this.currentVocabQuestion.answer); debugLog('[VocabLessonView] Answer:', this.currentVocabQuestion.answer);
// Wichtig: Der Prompt (die Frage) darf nicht in den Optionen erscheinen // Wichtig: Der Prompt (die Frage) darf nicht in den Optionen erscheinen
this.vocabTrainerChoiceOptions = this.buildChoiceOptions( this.vocabTrainerChoiceOptions = this.buildChoiceOptions(
this.currentVocabQuestion.answers, this.currentVocabQuestion.answers,
allTrainerVocabs, allTrainerVocabs,
this.currentVocabQuestion.prompt // Exkludiere den Prompt this.currentVocabQuestion.prompt,
this.vocabTrainerDirection
); );
debugLog('[VocabLessonView] Choice-Optionen erstellt:', this.vocabTrainerChoiceOptions); debugLog('[VocabLessonView] Choice-Optionen erstellt:', this.vocabTrainerChoiceOptions);
} }