fix sonar findings and translation structure
Sonarqube Scanner / Prepare environment (push) Successful in 19s
Sonarqube Scanner / Build and test (push) Successful in 43s
Sonarqube Scanner / SonarQube analysis (push) Failing after 2m28s
Sonarqube Scanner / Deploy to Server (push) Successful in 16s

This commit is contained in:
Florian Zumpe
2026-10-01 16:31:46 +02:00
parent 2b42507f13
commit 5c4d20bd1d
30 changed files with 1753 additions and 894 deletions
+30
View File
@@ -0,0 +1,30 @@
import fs from 'node:fs/promises';
import { fileURLToPath } from 'node:url';
const escapeText = value => value.replaceAll('&', '&amp;').replaceAll('<', '&lt;').replaceAll('>', '&gt;');
// Populate the checked-in German fallback while retaining all runtime i18n markers.
export function localizeHtml(source, translate) {
const result = source.replaceAll(/(<[^>]+\bdata-i18n="([^"]+)"[^>]*>)([^<]*)(<\/)/g,
(_match, opening, key, _text, closing) => opening + escapeText(translate(key)) + closing);
return result.replaceAll(/<[^>]+>/g, opening => {
let translated = opening;
for (const attribute of ['title', 'aria-label', 'placeholder', 'alt']) {
const key = new RegExp(`data-i18n-${attribute}="([^"]+)"`).exec(opening)?.[1];
if (!key) continue;
const value = escapeText(translate(key)).replaceAll('"', '&quot;');
// Match an actual attribute, never the suffix of its data-i18n marker.
translated = translated.replaceAll(new RegExp(`(\\s)${attribute}="[^"]*"`, 'g'), (_match, space) => `${space}${attribute}="${value}"`);
}
return translated;
});
}
if (process.argv[1] === fileURLToPath(import.meta.url)) {
await import('../public/js/texts-de.js');
await import('../public/js/i18n.js');
const file = new URL('../public/index.html', import.meta.url);
const source = await fs.readFile(file, 'utf8');
const translated = localizeHtml(source, key => globalThis.Wegwichtel.I18n.t(key));
await fs.writeFile(file, translated);
}