feat(i18n): update Cebuano localization for minigames and enhance UI text
All checks were successful
Deploy to production / deploy (push) Successful in 1m56s
All checks were successful
Deploy to production / deploy (push) Successful in 1m56s
- Added new localized strings for minigames in Cebuano, including loading hints, objectives, and play focus descriptions to improve user experience. - Updated existing translations for clarity and consistency across various game elements. - Enhanced the Match3Game component to utilize localized strings, ensuring dynamic text rendering based on user language preferences. - Included a new entry in .gitignore for the locale audit report to maintain a clean repository.
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -19,6 +19,7 @@ frontend/dist
|
|||||||
frontend/dist/*
|
frontend/dist/*
|
||||||
frontend/scripts/.i18n-de-fr-cache.json
|
frontend/scripts/.i18n-de-fr-cache.json
|
||||||
frontend/scripts/.falukant-fr-smooth-cache.json
|
frontend/scripts/.falukant-fr-smooth-cache.json
|
||||||
|
frontend/ceb-locale-audit-report.json
|
||||||
frontedtree.txt
|
frontedtree.txt
|
||||||
backend/dist/
|
backend/dist/
|
||||||
backend/data/model-cache
|
backend/data/model-cache
|
||||||
|
|||||||
140
frontend/scripts/audit-ceb-locale.mjs
Normal file
140
frontend/scripts/audit-ceb-locale.mjs
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
#!/usr/bin/env node
|
||||||
|
/**
|
||||||
|
* Vergleicht en- mit ceb-Locale-Chunks (wie in src/i18n/index.js).
|
||||||
|
* - identical: Blattstrings, die nach Merge noch gleich en sind (typisch: fehlende Bisaya-Übersetzung).
|
||||||
|
* - germanHints: Blattstrings in ceb mit deutschen Anzeichen (Umlaute / typische Wörter).
|
||||||
|
*
|
||||||
|
* Usage: node frontend/scripts/audit-ceb-locale.mjs
|
||||||
|
*/
|
||||||
|
import fs from 'fs';
|
||||||
|
import path from 'path';
|
||||||
|
import { fileURLToPath } from 'url';
|
||||||
|
|
||||||
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
||||||
|
const localesRoot = path.join(__dirname, '../src/i18n/locales');
|
||||||
|
|
||||||
|
const EN_CHUNKS = [
|
||||||
|
'general.json',
|
||||||
|
'header.json',
|
||||||
|
'navigation.json',
|
||||||
|
'home.json',
|
||||||
|
'chat.json',
|
||||||
|
'register.json',
|
||||||
|
'passwordReset.json',
|
||||||
|
'error.json',
|
||||||
|
'activate.json',
|
||||||
|
'settings.json',
|
||||||
|
'admin.json',
|
||||||
|
'socialnetwork.json',
|
||||||
|
'friends.json',
|
||||||
|
'falukant.json',
|
||||||
|
'blog.json',
|
||||||
|
'minigames.json',
|
||||||
|
'message.json',
|
||||||
|
'personal.json',
|
||||||
|
'seo.json',
|
||||||
|
];
|
||||||
|
|
||||||
|
function isPlainObject(value) {
|
||||||
|
return value !== null && typeof value === 'object' && !Array.isArray(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function deepMerge(target, source) {
|
||||||
|
if (!isPlainObject(source)) return target;
|
||||||
|
const base = isPlainObject(target) ? { ...target } : {};
|
||||||
|
for (const key of Object.keys(source)) {
|
||||||
|
const sv = source[key];
|
||||||
|
const tv = base[key];
|
||||||
|
if (isPlainObject(sv) && isPlainObject(tv)) {
|
||||||
|
base[key] = deepMerge(tv, sv);
|
||||||
|
} else if (isPlainObject(sv)) {
|
||||||
|
base[key] = deepMerge({}, sv);
|
||||||
|
} else {
|
||||||
|
base[key] = sv;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadJson(rel) {
|
||||||
|
const p = path.join(localesRoot, rel);
|
||||||
|
const raw = fs.readFileSync(p, 'utf8');
|
||||||
|
return JSON.parse(raw);
|
||||||
|
}
|
||||||
|
|
||||||
|
function flatten(obj, prefix = '', out = {}) {
|
||||||
|
if (!isPlainObject(obj)) return out;
|
||||||
|
for (const k of Object.keys(obj)) {
|
||||||
|
const v = obj[k];
|
||||||
|
const key = prefix ? `${prefix}.${k}` : k;
|
||||||
|
if (isPlainObject(v)) {
|
||||||
|
flatten(v, key, out);
|
||||||
|
} else if (typeof v === 'string') {
|
||||||
|
out[key] = v;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
const germanWordHints =
|
||||||
|
/\b(der|die|das|und|nicht|wird|werden|schon|keine|kein|Ziel|Ziele|Zug|Züge|Spiel|Level|Bitte|Hier|wurde|können|müssen)\b/i;
|
||||||
|
const germanChars = /[äöüÄÖÜß]/;
|
||||||
|
|
||||||
|
function audit() {
|
||||||
|
let enMerged = {};
|
||||||
|
let cebMerged = {};
|
||||||
|
|
||||||
|
for (const f of EN_CHUNKS) {
|
||||||
|
const enPath = path.join('en', f);
|
||||||
|
const cebPath = path.join('ceb', f);
|
||||||
|
if (!fs.existsSync(path.join(localesRoot, cebPath))) {
|
||||||
|
console.warn(`Warnung: fehlt ${cebPath} (übersprungen)`);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
enMerged = deepMerge(enMerged, loadJson(enPath));
|
||||||
|
cebMerged = deepMerge(cebMerged, loadJson(enPath));
|
||||||
|
cebMerged = deepMerge(cebMerged, loadJson(cebPath));
|
||||||
|
}
|
||||||
|
|
||||||
|
const enFlat = flatten(enMerged);
|
||||||
|
const cebFlat = flatten(cebMerged);
|
||||||
|
|
||||||
|
const identical = [];
|
||||||
|
const germanHints = [];
|
||||||
|
|
||||||
|
for (const key of Object.keys(cebFlat)) {
|
||||||
|
const ev = enFlat[key];
|
||||||
|
const cv = cebFlat[key];
|
||||||
|
if (typeof cv !== 'string') continue;
|
||||||
|
if (ev === cv && typeof ev === 'string') {
|
||||||
|
identical.push(key);
|
||||||
|
}
|
||||||
|
if (germanChars.test(cv) || germanWordHints.test(cv)) {
|
||||||
|
germanHints.push({ key, sample: cv.slice(0, 120) });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
identical.sort();
|
||||||
|
germanHints.sort((a, b) => a.key.localeCompare(b.key));
|
||||||
|
|
||||||
|
const report = {
|
||||||
|
generated: new Date().toISOString(),
|
||||||
|
summary: {
|
||||||
|
totalLeafStringsCeb: Object.keys(cebFlat).length,
|
||||||
|
identicalToEnCount: identical.length,
|
||||||
|
germanHintCount: germanHints.length,
|
||||||
|
},
|
||||||
|
identicalToEn: identical,
|
||||||
|
germanHintsInCeb: germanHints,
|
||||||
|
};
|
||||||
|
|
||||||
|
const outFile = path.join(__dirname, '../ceb-locale-audit-report.json');
|
||||||
|
fs.writeFileSync(outFile, JSON.stringify(report, null, 2), 'utf8');
|
||||||
|
console.log(`Bericht geschrieben: ${outFile}`);
|
||||||
|
console.log(
|
||||||
|
`Zusammenfassung: ${report.summary.identicalToEnCount} Blätter noch identisch mit EN, ` +
|
||||||
|
`${report.summary.germanHintCount} Strings mit DE-Hinweis (heuristisch).`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
audit();
|
||||||
@@ -73,15 +73,15 @@
|
|||||||
},
|
},
|
||||||
"character_illness": {
|
"character_illness": {
|
||||||
"title": "Sakit",
|
"title": "Sakit",
|
||||||
"description": "Nagsakit si {characterName} ug nawad-an og {healthChange} health."
|
"description": "Nagsakit si {characterName} ug nawad-an og {healthChange} panglawas."
|
||||||
},
|
},
|
||||||
"character_recovery": {
|
"character_recovery": {
|
||||||
"title": "Pagkamaayo",
|
"title": "Pagkamaayo",
|
||||||
"description": "Naayo si {characterName} gikan sa sakit ug nabawi ang {healthChange} health."
|
"description": "Naayo si {characterName} gikan sa sakit ug nabawi ang {healthChange} panglawas."
|
||||||
},
|
},
|
||||||
"character_accident": {
|
"character_accident": {
|
||||||
"title": "Aksidente",
|
"title": "Aksidente",
|
||||||
"description": "Ang grabe nga aksidente nakapasakit pag-ayo kang {characterName}. Health: {healthChange}."
|
"description": "Ang grabe nga aksidente nakapasakit pag-ayo kang {characterName}. Panglawas: {healthChange}."
|
||||||
},
|
},
|
||||||
"sudden_infant_death": {
|
"sudden_infant_death": {
|
||||||
"title": "Kalit nga pagkamatay sa masuso",
|
"title": "Kalit nga pagkamatay sa masuso",
|
||||||
@@ -124,6 +124,16 @@
|
|||||||
"children": "Mga anak",
|
"children": "Mga anak",
|
||||||
"children_unbaptised": "Mga anak nga wala pa mabunyagi"
|
"children_unbaptised": "Mga anak nga wala pa mabunyagi"
|
||||||
},
|
},
|
||||||
|
"create": {
|
||||||
|
"title": "Apil sa duwa",
|
||||||
|
"gender": "Sekso",
|
||||||
|
"male": "Lalaki",
|
||||||
|
"female": "Babaye",
|
||||||
|
"firstname": "Ngalan",
|
||||||
|
"lastname": "Apelyido",
|
||||||
|
"random": "Random",
|
||||||
|
"submit": "Apil"
|
||||||
|
},
|
||||||
"overview": {
|
"overview": {
|
||||||
"title": "Falukant - Overview",
|
"title": "Falukant - Overview",
|
||||||
"heroIntro": "Ang imong kahimtang sa ekonomiya, pamilya ug kabtangan sa usa ka mubo ug klarong overview.",
|
"heroIntro": "Ang imong kahimtang sa ekonomiya, pamilya ug kabtangan sa usa ka mubo ug klarong overview.",
|
||||||
@@ -211,7 +221,10 @@
|
|||||||
"branches": {
|
"branches": {
|
||||||
"title": "Mga branch",
|
"title": "Mga branch",
|
||||||
"level": {
|
"level": {
|
||||||
"city": "Siyudad"
|
"city": "Siyudad",
|
||||||
|
"production": "Produksyon",
|
||||||
|
"store": "Pagbaligya",
|
||||||
|
"fullstack": "Produksyon uban sa pagbaligya"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"routine": {
|
"routine": {
|
||||||
@@ -443,7 +456,46 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"sale": {
|
"sale": {
|
||||||
"runningGuards": "Mga guwardiya"
|
"title": "Imbentaryo",
|
||||||
|
"info": "Dinhi nimo makita ang katingbanan sa mga produkto sa branch.",
|
||||||
|
"region": "Rehiyon",
|
||||||
|
"product": "Produkto",
|
||||||
|
"quality": "Kalidad",
|
||||||
|
"quantity": "Kadaghanon",
|
||||||
|
"noInventory": "Walay imbentaryo nga available.",
|
||||||
|
"loadError": "Sayop sa pag-load sa imbentaryo.",
|
||||||
|
"sell": "Pagbaligya",
|
||||||
|
"sellButton": "Ibaligya",
|
||||||
|
"sellAllButton": "Ibaligya tanan",
|
||||||
|
"transportTitle": "Paghimo og transport",
|
||||||
|
"transportSource": "Artikulo",
|
||||||
|
"transportSourcePlaceholder": "Pilia ang artikulo",
|
||||||
|
"transportVehicle": "Sakyanan sa transport",
|
||||||
|
"transportVehiclePlaceholder": "Pilia ang sakyanan",
|
||||||
|
"transportTarget": "Target nga siyudad",
|
||||||
|
"transportTargetPlaceholder": "Pilia ang target",
|
||||||
|
"transportQuantity": "Kadaghanon",
|
||||||
|
"transportMax": "Pinakadaghan: {max}",
|
||||||
|
"transportCreate": "Sugdi ang transport",
|
||||||
|
"transportError": "Dili mahimo ang pag-set sa transport.",
|
||||||
|
"transportDuration": "Gidugayon sa transport: {duration}",
|
||||||
|
"transportArrival": "Oras sa pag-abot: {datetime}",
|
||||||
|
"transportRoute": "Ruta",
|
||||||
|
"transportCost": "Gasto sa transport: {cost}",
|
||||||
|
"transportStarted": "Nasugdan na ang transport.",
|
||||||
|
"runningTransportsTitle": "Nagdagan nga mga transport",
|
||||||
|
"runningDirection": "Direksyon",
|
||||||
|
"runningProduct": "Artikulo",
|
||||||
|
"runningQuantity": "Kadaghanon",
|
||||||
|
"runningNoProduct": "Transport sa sakyanan",
|
||||||
|
"runningSource": "Gigikanan",
|
||||||
|
"runningTarget": "Padulngan",
|
||||||
|
"runningEta": "Pag-abot",
|
||||||
|
"runningRemaining": "Nabiling oras",
|
||||||
|
"runningVehicleCount": "Mga sakyanan",
|
||||||
|
"runningGuards": "Mga guwardiya",
|
||||||
|
"runningDirectionOut": "Paingon gawas",
|
||||||
|
"runningDirectionIn": "Padulong sulod"
|
||||||
},
|
},
|
||||||
"storage": {
|
"storage": {
|
||||||
"buyPartialError": "Sayop sa pagpalit sa usa ka bahin sa kapasidad sa storage.",
|
"buyPartialError": "Sayop sa pagpalit sa usa ka bahin sa kapasidad sa storage.",
|
||||||
@@ -884,37 +936,37 @@
|
|||||||
"name": "Ngalan",
|
"name": "Ngalan",
|
||||||
"age": "Edad",
|
"age": "Edad",
|
||||||
"gender": "Sekso",
|
"gender": "Sekso",
|
||||||
"heir": "Heir",
|
"heir": "Manununod",
|
||||||
"isHeir": "Heir",
|
"isHeir": "Manununod",
|
||||||
"notHeir": "Not Heir",
|
"notHeir": "Dili manununod",
|
||||||
"setAsHeir": "Set as Heir",
|
"setAsHeir": "Himua nga manununod",
|
||||||
"heirSetSuccess": "Ang bata naay successfully set as heir.",
|
"heirSetSuccess": "Nailhan na ang bata isip manununod.",
|
||||||
"heirSetError": "Sayop setting heir.",
|
"heirSetError": "Napakyas ang pagtakda sa manununod.",
|
||||||
"actions": "Aksyons",
|
"actions": "Aksyons",
|
||||||
"none": "No bataren available.",
|
"none": "Walay anak nga ipakita.",
|
||||||
"detailButton": "Show Details",
|
"detailButton": "Ipakita ang detalye",
|
||||||
"addChild": "Add Bata",
|
"addChild": "Dugangi og anak",
|
||||||
"baptism": "Baptize",
|
"baptism": "Bunyagi",
|
||||||
"notBaptized": "Not yet baptized",
|
"notBaptized": "Wala pa mabunyagi",
|
||||||
"baptismNotice": "This bata naay dili baptized yet ug therefore naay no name.",
|
"baptismNotice": "Wala pa mabunyagi kining bata, busa wala pa siyay ngalan.",
|
||||||
"legitimacy": {
|
"legitimacy": {
|
||||||
"legitimate": "Legitimate",
|
"legitimate": "Lehitimo",
|
||||||
"acknowledged_bastard": "Ackahibalod illegitimate",
|
"acknowledged_bastard": "Giilang dili-lehitimo",
|
||||||
"hidden_bastard": "Illegitimate"
|
"hidden_bastard": "Dili-lehitimo"
|
||||||
},
|
},
|
||||||
"otherParent": "Other parent",
|
"otherParent": "Pikas nga ginikanan",
|
||||||
"otherParentUnknown": "Unknown",
|
"otherParentUnknown": "Wala mailhi",
|
||||||
"birthContextLabel": "Origin",
|
"birthContextLabel": "Gigikanan",
|
||||||
"birthContextShort": {
|
"birthContextShort": {
|
||||||
"marriage": "Kasal",
|
"marriage": "Kasal",
|
||||||
"lover": "Uyab"
|
"lover": "Uyab"
|
||||||
},
|
},
|
||||||
"birthContextLong": {
|
"birthContextLong": {
|
||||||
"marriage": "From kasal",
|
"marriage": "Gikan sa kasal",
|
||||||
"lover": "From usa ka uyab"
|
"lover": "Gikan sa usa ka uyab"
|
||||||
},
|
},
|
||||||
"details": {
|
"details": {
|
||||||
"title": "Bata Details"
|
"title": "Detalye sa bata"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"taxes": {
|
"taxes": {
|
||||||
|
|||||||
@@ -38,7 +38,20 @@
|
|||||||
"objectivesShow": "Ipakita ang mga tumong",
|
"objectivesShow": "Ipakita ang mga tumong",
|
||||||
"objectives": "Mga tumong",
|
"objectives": "Mga tumong",
|
||||||
"loadingBoard": "Ginaandam ang game board...",
|
"loadingBoard": "Ginaandam ang game board...",
|
||||||
"loadingHint": "Ang datos sa level, mga tumong ug layout sa board gi-sync pa."
|
"loadingHint": "Ang datos sa level, mga tumong ug layout sa board gi-sync pa.",
|
||||||
|
"badgeMinigames": "Mga minidula",
|
||||||
|
"objectivesProgress": "{completed}/{total} ka tumong",
|
||||||
|
"movesLeftBadge": "{count} ka lihok ang nahabilin",
|
||||||
|
"playFocus": {
|
||||||
|
"pausedTitle": "Gi-pause ang dula",
|
||||||
|
"pausedDescription": "Ipadayon ang level o sugdan pag-usab nga kontrolado nga dili mawala ang konteksto.",
|
||||||
|
"preparingTitle": "Nag-load ang level",
|
||||||
|
"preparingDescription": "Kung na-load na ang level, makita dinhi ang sunod nga tumong ug angunay nga aksyon.",
|
||||||
|
"defaultObjectiveTitle": "Humana ang kasamtangang tumong",
|
||||||
|
"finishLevelTitle": "Humana ang level nga tarong",
|
||||||
|
"focusDescription": "Unahon kini nga tumong. Nahuman na: {completed} sa {total}.",
|
||||||
|
"allObjectivesDoneDescription": "Nahuman na ang tanang makita nga tumong. Karon, humana lang ang level nga tarong."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"taxi": {
|
"taxi": {
|
||||||
"title": "Taxi Simulator",
|
"title": "Taxi Simulator",
|
||||||
|
|||||||
@@ -38,7 +38,20 @@
|
|||||||
"objectivesShow": "Ziele anzeigen",
|
"objectivesShow": "Ziele anzeigen",
|
||||||
"objectives": "Ziele",
|
"objectives": "Ziele",
|
||||||
"loadingBoard": "Spielbrett wird vorbereitet...",
|
"loadingBoard": "Spielbrett wird vorbereitet...",
|
||||||
"loadingHint": "Leveldaten, Ziele und Feldlayout werden gerade synchronisiert."
|
"loadingHint": "Leveldaten, Ziele und Feldlayout werden gerade synchronisiert.",
|
||||||
|
"badgeMinigames": "Minispiele",
|
||||||
|
"objectivesProgress": "{completed}/{total} Ziele",
|
||||||
|
"movesLeftBadge": "{count} Züge übrig",
|
||||||
|
"playFocus": {
|
||||||
|
"pausedTitle": "Spiel ist pausiert",
|
||||||
|
"pausedDescription": "Setze das Level fort oder starte es kontrolliert neu, ohne den aktuellen Kontext zu verlieren.",
|
||||||
|
"preparingTitle": "Level wird vorbereitet",
|
||||||
|
"preparingDescription": "Sobald das Level geladen ist, erscheinen hier das nächste Ziel und die passende Hauptaktion.",
|
||||||
|
"defaultObjectiveTitle": "Aktuelles Ziel abschließen",
|
||||||
|
"finishLevelTitle": "Level sauber zu Ende spielen",
|
||||||
|
"focusDescription": "Konzentriere dich zuerst auf dieses Ziel. Bereits erledigt: {completed} von {total}.",
|
||||||
|
"allObjectivesDoneDescription": "Alle sichtbaren Ziele sind erledigt. Jetzt zählt nur noch der saubere Abschluss des Levels."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"taxi": {
|
"taxi": {
|
||||||
"title": "Taxi Simulator",
|
"title": "Taxi Simulator",
|
||||||
|
|||||||
@@ -38,7 +38,20 @@
|
|||||||
"objectivesShow": "Show objectives",
|
"objectivesShow": "Show objectives",
|
||||||
"objectives": "Objectives",
|
"objectives": "Objectives",
|
||||||
"loadingBoard": "Preparing game board...",
|
"loadingBoard": "Preparing game board...",
|
||||||
"loadingHint": "Level data, objectives and board layout are being synchronized."
|
"loadingHint": "Level data, objectives and board layout are being synchronized.",
|
||||||
|
"badgeMinigames": "Mini games",
|
||||||
|
"objectivesProgress": "{completed}/{total} objectives",
|
||||||
|
"movesLeftBadge": "{count} moves left",
|
||||||
|
"playFocus": {
|
||||||
|
"pausedTitle": "Game is paused",
|
||||||
|
"pausedDescription": "Resume the level or restart in a controlled way without losing context.",
|
||||||
|
"preparingTitle": "Level is loading",
|
||||||
|
"preparingDescription": "Once the level loads, the next goal and main action will appear here.",
|
||||||
|
"defaultObjectiveTitle": "Complete the current objective",
|
||||||
|
"finishLevelTitle": "Finish the level cleanly",
|
||||||
|
"focusDescription": "Focus on this goal first. Already completed: {completed} of {total}.",
|
||||||
|
"allObjectivesDoneDescription": "All visible objectives are done. Now finish the level cleanly."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"taxi": {
|
"taxi": {
|
||||||
"title": "Taxi Simulator",
|
"title": "Taxi Simulator",
|
||||||
|
|||||||
@@ -38,7 +38,20 @@
|
|||||||
"objectivesShow": "Mostrar objetivos",
|
"objectivesShow": "Mostrar objetivos",
|
||||||
"objectives": "Objetivos",
|
"objectives": "Objetivos",
|
||||||
"loadingBoard": "Preparando el tablero…",
|
"loadingBoard": "Preparando el tablero…",
|
||||||
"loadingHint": "Sincronizando datos del nivel, objetivos y disposición del campo."
|
"loadingHint": "Sincronizando datos del nivel, objetivos y disposición del campo.",
|
||||||
|
"badgeMinigames": "Minijuegos",
|
||||||
|
"objectivesProgress": "{completed}/{total} objetivos",
|
||||||
|
"movesLeftBadge": "{count} movimientos restantes",
|
||||||
|
"playFocus": {
|
||||||
|
"pausedTitle": "Juego en pausa",
|
||||||
|
"pausedDescription": "Continúa el nivel o reinícialo de forma controlada sin perder el contexto.",
|
||||||
|
"preparingTitle": "Cargando nivel",
|
||||||
|
"preparingDescription": "Cuando el nivel esté cargado, aquí aparecerá el siguiente objetivo y la acción principal.",
|
||||||
|
"defaultObjectiveTitle": "Completa el objetivo actual",
|
||||||
|
"finishLevelTitle": "Termina el nivel limpiamente",
|
||||||
|
"focusDescription": "Concéntrate primero en este objetivo. Ya completados: {completed} de {total}.",
|
||||||
|
"allObjectivesDoneDescription": "Todos los objetivos visibles están hechos. Ahora solo importa terminar el nivel limpiamente."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"taxi": {
|
"taxi": {
|
||||||
"title": "Taxi Simulator",
|
"title": "Taxi Simulator",
|
||||||
|
|||||||
@@ -38,7 +38,20 @@
|
|||||||
"objectivesShow": "Afficher les objectifs",
|
"objectivesShow": "Afficher les objectifs",
|
||||||
"objectives": "Objectifs",
|
"objectives": "Objectifs",
|
||||||
"loadingBoard": "Le plateau de jeu est en préparation...",
|
"loadingBoard": "Le plateau de jeu est en préparation...",
|
||||||
"loadingHint": "Les données de niveau, les objectifs et la disposition du terrain sont actuellement en cours de synchronisation."
|
"loadingHint": "Les données de niveau, les objectifs et la disposition du terrain sont actuellement en cours de synchronisation.",
|
||||||
|
"badgeMinigames": "Mini-jeux",
|
||||||
|
"objectivesProgress": "{completed}/{total} objectifs",
|
||||||
|
"movesLeftBadge": "{count} coups restants",
|
||||||
|
"playFocus": {
|
||||||
|
"pausedTitle": "Jeu en pause",
|
||||||
|
"pausedDescription": "Reprends le niveau ou relance-le proprement sans perdre le contexte.",
|
||||||
|
"preparingTitle": "Chargement du niveau",
|
||||||
|
"preparingDescription": "Une fois le niveau chargé, le prochain objectif et l’action principale apparaîtront ici.",
|
||||||
|
"defaultObjectiveTitle": "Terminer l’objectif en cours",
|
||||||
|
"finishLevelTitle": "Terminer le niveau proprement",
|
||||||
|
"focusDescription": "Concentre-toi d’abord sur cet objectif. Déjà réalisés : {completed} sur {total}.",
|
||||||
|
"allObjectivesDoneDescription": "Tous les objectifs visibles sont faits. Il ne reste plus qu’à finir le niveau proprement."
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"taxi": {
|
"taxi": {
|
||||||
"title": "Simulateur de taxi",
|
"title": "Simulateur de taxi",
|
||||||
|
|||||||
@@ -2,28 +2,33 @@
|
|||||||
<div class="match3-view">
|
<div class="match3-view">
|
||||||
<!-- Spiel-Titel -->
|
<!-- Spiel-Titel -->
|
||||||
<section class="game-title surface-card">
|
<section class="game-title surface-card">
|
||||||
<span class="game-title__eyebrow">Minispiele</span>
|
<span class="game-title__eyebrow">{{ $t('minigames.match3.badgeMinigames') }}</span>
|
||||||
<h1>{{ $t('minigames.match3.title') }}</h1>
|
<h1>{{ $t('minigames.match3.title') }}</h1>
|
||||||
<p>{{ $t('minigames.match3.campaignDescription') }}</p>
|
<p>{{ $t('minigames.match3.campaignDescription') }}</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<section class="play-focus surface-card">
|
<section class="play-focus surface-card">
|
||||||
<div class="play-focus__main">
|
<div class="play-focus__main">
|
||||||
<span class="play-focus__eyebrow">Nächster Schritt</span>
|
<span class="play-focus__eyebrow">{{ $t('minigames.match3.nextStep') }}</span>
|
||||||
<h2>{{ playFocusTitle }}</h2>
|
<h2>{{ playFocusTitle }}</h2>
|
||||||
<p>{{ playFocusDescription }}</p>
|
<p>{{ playFocusDescription }}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="play-focus__stats">
|
<div class="play-focus__stats">
|
||||||
<span class="play-focus__pill">Level {{ currentLevel }}</span>
|
<span class="play-focus__pill">{{ $t('minigames.match3.level') }} {{ currentLevel }}</span>
|
||||||
<span class="play-focus__pill">{{ completedObjectivesCount }}/{{ totalObjectivesCount || 0 }} Ziele</span>
|
<span class="play-focus__pill">{{
|
||||||
<span class="play-focus__pill">{{ safeMovesLeft }} Züge übrig</span>
|
$t('minigames.match3.objectivesProgress', {
|
||||||
|
completed: completedObjectivesCount,
|
||||||
|
total: totalObjectivesCount || 0
|
||||||
|
})
|
||||||
|
}}</span>
|
||||||
|
<span class="play-focus__pill">{{ $t('minigames.match3.movesLeftBadge', { count: safeMovesLeft }) }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="play-focus__actions">
|
<div class="play-focus__actions">
|
||||||
<button class="btn btn-primary" @click="isPaused ? resumeGame() : pauseGame()">
|
<button class="btn btn-primary" @click="isPaused ? resumeGame() : pauseGame()">
|
||||||
{{ isPaused ? $t('minigames.match3.resume') : $t('minigames.match3.pause') }}
|
{{ isPaused ? $t('minigames.match3.resume') : $t('minigames.match3.pause') }}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary" @click="toggleLevelDescription">
|
<button class="btn btn-secondary" @click="toggleLevelDescription">
|
||||||
{{ levelDescriptionExpanded ? 'Ziele einklappen' : 'Ziele anzeigen' }}
|
{{ levelDescriptionExpanded ? $t('minigames.match3.objectivesCollapse') : $t('minigames.match3.objectivesShow') }}
|
||||||
</button>
|
</button>
|
||||||
<button class="btn btn-secondary" @click="restartLevel">
|
<button class="btn btn-secondary" @click="restartLevel">
|
||||||
{{ $t('minigames.match3.restartLevel') }}
|
{{ $t('minigames.match3.restartLevel') }}
|
||||||
@@ -140,8 +145,8 @@
|
|||||||
|
|
||||||
<!-- Loading State -->
|
<!-- Loading State -->
|
||||||
<div v-else class="game-board-loading">
|
<div v-else class="game-board-loading">
|
||||||
<p>Spielbrett wird vorbereitet...</p>
|
<p>{{ $t('minigames.match3.loadingBoard') }}</p>
|
||||||
<p class="game-board-loading__hint">Leveldaten, Ziele und Feldlayout werden gerade synchronisiert.</p>
|
<p class="game-board-loading__hint">{{ $t('minigames.match3.loadingHint') }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Power-Up Animationen (relativ zum Game-Board) -->
|
<!-- Power-Up Animationen (relativ zum Game-Board) -->
|
||||||
@@ -6062,27 +6067,33 @@ export default {
|
|||||||
},
|
},
|
||||||
playFocusTitle() {
|
playFocusTitle() {
|
||||||
if (this.isPaused) {
|
if (this.isPaused) {
|
||||||
return 'Spiel ist pausiert';
|
return this.$t('minigames.match3.playFocus.pausedTitle');
|
||||||
}
|
}
|
||||||
if (!this.currentLevelData) {
|
if (!this.currentLevelData) {
|
||||||
return 'Level wird vorbereitet';
|
return this.$t('minigames.match3.playFocus.preparingTitle');
|
||||||
}
|
}
|
||||||
if (this.nextPendingObjective) {
|
if (this.nextPendingObjective) {
|
||||||
return this.nextPendingObjective.description || 'Aktuelles Ziel abschließen';
|
return (
|
||||||
|
this.nextPendingObjective.description ||
|
||||||
|
this.$t('minigames.match3.playFocus.defaultObjectiveTitle')
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return 'Level sauber zu Ende spielen';
|
return this.$t('minigames.match3.playFocus.finishLevelTitle');
|
||||||
},
|
},
|
||||||
playFocusDescription() {
|
playFocusDescription() {
|
||||||
if (this.isPaused) {
|
if (this.isPaused) {
|
||||||
return 'Setze das Level fort oder starte es kontrolliert neu, ohne den aktuellen Kontext zu verlieren.';
|
return this.$t('minigames.match3.playFocus.pausedDescription');
|
||||||
}
|
}
|
||||||
if (!this.currentLevelData) {
|
if (!this.currentLevelData) {
|
||||||
return 'Sobald das Level geladen ist, erscheinen hier das nächste Ziel und die passende Hauptaktion.';
|
return this.$t('minigames.match3.playFocus.preparingDescription');
|
||||||
}
|
}
|
||||||
if (this.nextPendingObjective) {
|
if (this.nextPendingObjective) {
|
||||||
return `Konzentriere dich zuerst auf dieses Ziel. Bereits erledigt: ${this.completedObjectivesCount} von ${this.totalObjectivesCount}.`;
|
return this.$t('minigames.match3.playFocus.focusDescription', {
|
||||||
|
completed: this.completedObjectivesCount,
|
||||||
|
total: this.totalObjectivesCount
|
||||||
|
});
|
||||||
}
|
}
|
||||||
return 'Alle sichtbaren Ziele sind erledigt. Jetzt zählt nur noch der saubere Abschluss des Levels.';
|
return this.$t('minigames.match3.playFocus.allObjectivesDoneDescription');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user