fix(i18n): a locale edit hot-swaps the texts instead of re-running main.tsx

The locale JSON's importer did not accept HMR, so the update climbed to
main.tsx, whose re-run called createRoot on the live container again; the two
roots tore each other's DOM down ('removeChild ... not a child' by the dozen),
each a fatal toast evicting an old notification. Dev only.
This commit is contained in:
2026-09-27 06:35:40 +02:00
parent ae9c248987
commit 8f65bd184e
+20 -9
View File
@@ -40,15 +40,26 @@ function detectInitialLang(): LangCode {
return isSupported(nav) ? nav : "en";
}
const initial = detectInitialLang();
void i18n.use(initReactI18next).init({
resources,
lng: initial,
fallbackLng: "en",
interpolation: { escapeValue: false },
returnNull: false,
});
document.documentElement.lang = initial;
// Dev only: a locale edit re-runs THIS module (it accepts its own update, below) instead of climbing to
// main.tsx — a re-run main.tsx called createRoot on the live container a second time, and the two roots
// tore each other's DOM down ("removeChild … not a child" by the dozen, each one a fatal toast that evicted
// an old notification). On a re-run the i18next singleton is already up: swap the texts in and re-render.
if (i18n.isInitialized) {
for (const [lng, r] of Object.entries(resources))
i18n.addResourceBundle(lng, "translation", r.translation, true, true);
void i18n.changeLanguage(i18n.language);
} else {
const initial = detectInitialLang();
void i18n.use(initReactI18next).init({
resources,
lng: initial,
fallbackLng: "en",
interpolation: { escapeValue: false },
returnNull: false,
});
document.documentElement.lang = initial;
}
if (import.meta.hot) import.meta.hot.accept();
export function setLanguage(code: LangCode): void {
void i18n.changeLanguage(code);