Merge PR #29: refactor(i18n): split translations into per-language files with lazy loading; add French

- Split monolithic i18n.js into per-language files under js/i18n/
- Lazy-load translations via dynamic import() with caching
- Add French (fr) language support
- Add error handling in _loadLang with English fallback
- Remove duplicated lang.name from per-language files (registry is single source of truth)
- Add dev-time key validation (warns on localhost when keys are missing vs en.js)
- Add missing alerts.fileTooLarge key from main to all language files
- Await async initLang() in main.js (supported by type=module)
This commit is contained in:
CNCKitchen
2026-04-07 10:46:35 +02:00
9 changed files with 1084 additions and 1967 deletions
+13 -9
View File
@@ -287,10 +287,10 @@ setViewerTheme(document.documentElement.getAttribute('data-theme') === 'light');
function populateLanguageSelector() {
if (!languageSelector) return;
languageSelector.innerHTML = '';
const select = document.createElement('select');
select.className = 'lang-dropdown';
for (const langKey in TRANSLATIONS) {
const opt = document.createElement('option');
opt.value = langKey;
@@ -298,23 +298,27 @@ function populateLanguageSelector() {
opt.textContent = TRANSLATIONS[langKey]['lang.name'] || langKey.toUpperCase();
select.appendChild(opt);
}
select.addEventListener('change', (e) => {
setLang(e.target.value);
select.addEventListener('change', async (e) => {
await setLang(e.target.value);
// Re-translate <option> elements (innerHTML won't reach these)
document.querySelectorAll('select[id="mapping-mode"] option[data-i18n-opt]').forEach(opt => {
document.querySelectorAll('#mapping-mode option[data-i18n-opt]').forEach(opt => {
opt.textContent = t(opt.dataset.i18nOpt);
});
// Refresh dynamic count text to current language
if (currentGeometry) refreshExclusionOverlay();
if (currentGeometry) {
refreshExclusionOverlay();
}
});
languageSelector.appendChild(select);
}
populateLanguageSelector();
// Initialise language (reads localStorage / browser preference, applies translations)
initLang();
await initLang();
// Sync lang dropdown to current language
(function() {