// Root layout. The framework's auto-wired is COOKIE-driven // (Strategy A). For URL-prefix routing (Strategy B) we add an INNER provider // that reads the locale FROM THE URL, so client-side navigation between // /about and /de/about swaps the catalog without a full reload. At build // time it resolves to the same locale the SSG pipeline pre-rendered. // // ``/``/`` are owned by the framework shell — don't render // them here. Page + meta come from each page's `meta` export. import type { ReactNode } from 'react' import { I18nProvider, T } from '@voltro/i18n' import { useLocation } from '@voltro/web' import { CATALOGS, DEFAULT_LOCALE, SUPPORTED_LOCALES, stripLocalePrefix, useUrlLocale, withLocalePrefix, } from '../lib/locale' import '../globals.css' function TopNav(): ReactNode { const locale = useUrlLocale() // The path WITHOUT its locale prefix — so the language switch keeps you // on the same page (e.g. /de/about → /about, then re-prefix per locale). const barePath = stripLocalePrefix(useLocation()) // Plain <a> (not <Link>): these hrefs are COMPUTED per locale, and // <Link to> wants a statically-known `VoltroUrl` literal. The Router's // global click interceptor SPA-navigates internal <a> anyway, so the // inner provider still swaps catalogs without a full reload. return ( <nav className="topnav"> <a href={withLocalePrefix('/', locale)}> <T id="nav.home" /> </a> <a href={withLocalePrefix('/about', locale)}> <T id="nav.about" /> </a> <span className="spacer" /> <span className="lang"> <span className="label"> <T id="nav.language" />: </span> {SUPPORTED_LOCALES.map((code) => ( <a key={code} href={withLocalePrefix(barePath, code)} aria-current={code === locale ? 'true' : undefined} > {code.toUpperCase()} </a> ))} </span> </nav> ) } export default function Layout({ children }: { readonly children: ReactNode }): ReactNode { const locale = useUrlLocale() return ( <I18nProvider locale={locale} messages={CATALOGS[locale]} defaultLocale={DEFAULT_LOCALE}> <div className="shell"> <TopNav /> <main>{children}</main> </div> </I18nProvider> ) }