feat(i18n): update Cebuano localization for minigames and enhance UI text
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:
Torsten Schulz (local)
2026-04-17 16:20:20 +02:00
parent 71d5922409
commit 9c121d2dc2
9 changed files with 316 additions and 47 deletions

View 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();