import React, { createContext, useContext, useMemo } from 'react' import type { I18nString } from '@pikku/react' import type { SupportedLocale } from '@/config' import { mKey } from '@/i18n/messages' import { setRouteLocale, supportedLocales, defaultLocale } from '@/i18n/config' export type GetNamespaced = ( key: string, variables?: Record ) => I18nString export interface I18nContextType { locale: SupportedLocale get: GetNamespaced getEnumOptions: ( e: Record, enumName: string ) => { value: string; label: I18nString }[] } // Resolve any dotted i18n key through Paraglide (mKey snake_cases it and calls // the compiled message). Replaces the old i18next `t`. const get: GetNamespaced = (key, variables) => mKey(key, variables) const getEnumOptions = (enumObject: Record, enumName: string) => Object.values(enumObject).map((value) => ({ value, label: mKey(`enums.${enumName}.${value}`.toLowerCase()), })) export const I18nContext = createContext({ locale: defaultLocale as SupportedLocale, get, getEnumOptions, }) // useI18n() returns a callable `t` (Paraglide-backed) augmented with the same // helpers components used under i18next: `t('key')`, `t.getEnumOptions(...)`, // `t.locale`. export const useI18n = () => { const ctx = useContext(I18nContext) const t = (key: string, variables?: Record): I18nString => mKey(key, variables) return Object.assign(t, { get: ctx.get, getEnumOptions: ctx.getEnumOptions, locale: ctx.locale, }) } interface I18nProviderProps { children: React.ReactNode lang?: string } const normalize = (lang: string): SupportedLocale => { const short = lang.slice(0, 2).toLowerCase() return ( supportedLocales.includes(short as (typeof supportedLocales)[number]) ? short : defaultLocale ) as SupportedLocale } export function I18nProvider({ children, lang = 'en' }: I18nProviderProps) { const locale = normalize(lang) // Set the active Paraglide locale before children resolve messages (SSR-safe: // synchronous, ahead of the children's render in this pass). setRouteLocale(locale as (typeof supportedLocales)[number]) const value = useMemo( () => ({ locale, get, getEnumOptions }), [locale] ) return {children} }