import { StrictMode } from 'react' import { createRoot, hydrateRoot } from 'react-dom/client' import '@fontsource-variable/outfit' import './styles/tokens.css' import './styles/base.css' import { CookieConsentProvider } from './context/CookieConsent' import App from './App' import { I18nProvider, splitLocale, DEFAULT_LOCALE, canonicalRoute, initFx, localePath, preloadVariant } from './i18n' import { BrowserRouter } from './i18n/router' import { loadSlugs } from './i18n/slugs-load' import { bcp47 } from './i18n/format' import { loadMessages } from './i18n/load' const root = document.getElementById('root')! // Langue de la page, d'après le préfixe de l'adresse (« /en/… ») ; sans préfixe : la langue par défaut. const { locale } = splitLocale(window.location.pathname) document.documentElement.lang = bcp47(locale) const clean = (p: string) => p.replace(/\/+$/, '') || '/' // Adresses de la langue (voir src/i18n/slugs.ts) : « /de/privatkredit » ; une adresse écrite avec le nom français (« /de/pret-personnel ») est redirigée vers celle de la langue. await loadSlugs(locale) { const here = splitLocale(window.location.pathname).path const wanted = localePath(canonicalRoute(here, locale), locale) if (locale !== DEFAULT_LOCALE && clean(wanted) !== clean(`/${locale}${here === '/' ? '' : here}`)) { window.location.replace(wanted + window.location.search + window.location.hash) await new Promise(() => {}) // la page change : rien d'autre à faire } } // Page préconstruite : elle annonce les domaines de textes « extra » dont elle a besoin (calculés au build) ; sinon (adresse non // préconstruite, rendue par le navigateur), tout le catalogue est chargé avant l'affichage. const win = window as unknown as { __PRERENDERED__?: string; __I18N_DOMAINS__?: string[] } const prerendered = win.__PRERENDERED__ === clean(window.location.pathname) const domains: readonly string[] | 'all' = prerendered ? win.__I18N_DOMAINS__ ?? [] : 'all' const catalogs = { [locale]: await loadMessages(locale, domains) } // Pays et taux écrits dans la page (voir src/i18n/fx.ts) : même état initial qu'au build, donc rien ne change au branchement de la page. const fx = (window as unknown as { __FNB_FX__?: { country?: string; date?: string; rates?: unknown } }).__FNB_FX__ initFx(prerendered && fx ? fx : fx ? { date: fx.date, rates: fx.rates } : null) if (prerendered && fx?.country) await preloadVariant(locale, fx.country) const app = ( ) // Adresse avec « / » final (selon l'hébergeur) : on la ramène à la forme sans « / » avant de démarrer, sinon les comparaisons // d'adresse (en-tête transparent sur les pages à photo, lien actif du menu) échouent et la photo se retrouve cachée. if (window.location.pathname !== clean(window.location.pathname)) { window.history.replaceState(window.history.state, '', clean(window.location.pathname) + window.location.search + window.location.hash) } // Page préconstruite pour cette adresse : le contenu est déjà affiché, l'application s'y branche sans rien redessiner. if (root.hasChildNodes() && prerendered) { hydrateRoot(root, app) } else { root.replaceChildren() createRoot(root).render(app) }