feat(i18n): add scripts for locale translation and patching
All checks were successful
Deploy tt-tagebuch / deploy (push) Successful in 45s

- Implemented `fill-de-extended-gaps.js` to fill missing billing/orders keys in de-extended from de.
- Created `fill-i18n-deep.py` for deep translation of locale JSONs using deep-translator with fallback options.
- Added `fill-i18n-locales.js` to translate locale JSONs and write overrides for untranslated keys.
- Introduced `fix-en-leaks.py` to translate keys that still match the en-US merge, addressing English leaks.
- Developed `patch-de-ch-swiss.js` to replace 'ß' with 'ss' in de-CH.json without deleting existing entries.
- Created `patch-en-gb-au.js` to apply UK/AU spelling corrections in en-GB and en-AU locales.
- Added shell scripts `run-fix-en-leaks.sh` and `run-i18n-deep-fill.sh` for sequential execution of translation tasks.
- Implemented `update-i18n-todo-stats.js` to update statistics in the I18N_TODO.md file based on translation completeness.
This commit is contained in:
Torsten Schulz (local)
2026-05-15 15:52:54 +02:00
parent 320010b94e
commit eb54b4f7cf
54 changed files with 58003 additions and 30665 deletions

View File

@@ -72,6 +72,28 @@ function loadJson(filePath) {
return JSON.parse(fs.readFileSync(filePath, 'utf8'));
}
function deepMerge(base, override) {
if (!base || typeof base !== 'object' || Array.isArray(base)) {
return override ?? base;
}
const result = { ...base };
for (const [key, value] of Object.entries(override || {})) {
if (
value &&
typeof value === 'object' &&
!Array.isArray(value) &&
result[key] &&
typeof result[key] === 'object' &&
!Array.isArray(result[key])
) {
result[key] = deepMerge(result[key], value);
} else {
result[key] = value;
}
}
return result;
}
function getLocaleCode(localeFile) {
return localeFile.replace(/\.json$/, '');
}
@@ -84,8 +106,10 @@ function extractPlaceholders(value) {
}
function auditLocale(localeFile, baseFlat) {
const de = loadJson(path.join(LOCALES_DIR, BASE_LOCALE));
const data = loadJson(path.join(LOCALES_DIR, localeFile));
const flat = flatten(pickNamespaces(data));
const merged = deepMerge(JSON.parse(JSON.stringify(de)), data);
const flat = flatten(pickNamespaces(merged));
const localeCode = getLocaleCode(localeFile);
const missing = Object.keys(baseFlat).filter(key => !(key in flat));
const sameAsDe = Object.keys(baseFlat).filter(key => flat[key] === baseFlat[key]);