Lots of technical improvements
Some checks failed
Build, Test & Push Frontend / quality-check (pull_request) Failing after 41s
Build, Test & Push Frontend / docker (pull_request) Has been skipped

This commit is contained in:
Andreas Dahm
2026-06-02 15:48:31 +02:00
parent 102cdfcb52
commit a26443af8f
26 changed files with 1864 additions and 430 deletions

65
scripts/check-i18n.mjs Normal file
View File

@@ -0,0 +1,65 @@
#!/usr/bin/env node
// Verifies that all i18n translation files share the exact same set of keys.
// Exits with a non-zero status (and prints the differences) if any key is
// present in one language but missing in another, so CI can catch drift.
import { readFileSync, readdirSync } from 'node:fs';
import { join, dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
const scriptDir = dirname(fileURLToPath(import.meta.url));
const i18nDir = join(scriptDir, '..', 'src', 'assets', 'i18n');
function collectLeafKeys(value, prefix, keys) {
for (const key of Object.keys(value)) {
const fullKey = prefix ? `${prefix}.${key}` : key;
const child = value[key];
const isNestedObject = child !== null && typeof child === 'object' && !Array.isArray(child);
if (isNestedObject) {
collectLeafKeys(child, fullKey, keys);
} else {
keys.add(fullKey);
}
}
return keys;
}
function loadKeys(fileName) {
const content = readFileSync(join(i18nDir, fileName), 'utf8');
const parsed = JSON.parse(content);
return collectLeafKeys(parsed, '', new Set());
}
const files = readdirSync(i18nDir).filter((name) => name.endsWith('.json'));
if (files.length < 2) {
console.log('i18n check: nothing to compare (fewer than two language files).');
process.exit(0);
}
const keysByFile = new Map(files.map((file) => [file, loadKeys(file)]));
const allKeys = new Set();
for (const keys of keysByFile.values()) {
for (const key of keys) {
allKeys.add(key);
}
}
let hasError = false;
for (const [file, keys] of keysByFile) {
const missing = [...allKeys].filter((key) => !keys.has(key)).sort();
if (missing.length > 0) {
hasError = true;
console.error(`\n[${file}] missing ${missing.length} key(s):`);
for (const key of missing) {
console.error(` - ${key}`);
}
}
}
if (hasError) {
console.error('\ni18n check failed: translation files are out of sync.');
process.exit(1);
}
console.log(`i18n check passed: ${files.join(', ')} share ${allKeys.size} keys.`);