// The single source of truth for this app's locales + the URL-prefix // helpers. `app.config.ts` lists the same codes for the build pipeline; // the [locale] mirror pages + the layout's read THIS file. // // Keep SUPPORTED_LOCALES / DEFAULT_LOCALE in sync with `locales` / // `defaultLocale` in app.config.ts. import { useLocation } from '@voltro/web' import en from '../locales/en' import de from '../locales/de' export const SUPPORTED_LOCALES = ['en', 'de'] as const export const DEFAULT_LOCALE = 'en' export type Locale = (typeof SUPPORTED_LOCALES)[number] // The catalogs, keyed by code. The layout picks one to feed the inner // ; `meta` (build-time, per locale) reads one via getCatalog. export const CATALOGS = { en, de } as const // Every catalog mirrors `en`'s keys (defineLocale enforces it), so a // plain string-record over en's keys is the common type both satisfy — // what `meta` reads at build time (`c['meta.home.title']` → string). export type Messages = Record const isSupported = (v: string): v is Locale => (SUPPORTED_LOCALES as ReadonlyArray).includes(v) export const getCatalog = (locale: string): Messages => isSupported(locale) ? CATALOGS[locale] : CATALOGS[DEFAULT_LOCALE] // `/de/about` → 'de'; `/about` → 'en' (default lives at the bare path). export const localeFromPathname = (pathname: string): Locale => { const match = /^\/([a-z]{2})(?:\/|$)/.exec(pathname) return match && isSupported(match[1]!) ? (match[1] as Locale) : DEFAULT_LOCALE } // Reactive: useLocation re-renders on client-side nav, so the layout's // provider swaps catalogs when you move between /about and /de/about // without a full reload. export const useUrlLocale = (): Locale => localeFromPathname(useLocation()) // '/about' + 'de' → '/de/about'; the default locale stays bare ('/about'). export const withLocalePrefix = (path: string, locale: string): string => { if (locale === DEFAULT_LOCALE) return path const p = path.startsWith('/') ? path : `/${path}` return p === '/' ? `/${locale}` : `/${locale}${p}` } // '/de/about' → '/about'; '/about' → '/about'. The inverse of the above, // used to keep the active path when switching language. export const stripLocalePrefix = (pathname: string): string => { const match = /^\/([a-z]{2})(\/.*|$)/.exec(pathname) return match && isSupported(match[1]!) ? match[2] || '/' : pathname }