78 lines
2.4 KiB
TypeScript
78 lines
2.4 KiB
TypeScript
'use client'
|
|
|
|
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<string, any>
|
|
) => I18nString
|
|
|
|
export interface I18nContextType {
|
|
locale: SupportedLocale
|
|
get: GetNamespaced
|
|
getEnumOptions: (
|
|
e: Record<string, string>,
|
|
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<string, string>, enumName: string) =>
|
|
Object.values(enumObject).map((value) => ({
|
|
value,
|
|
label: mKey(`enums.${enumName}.${value}`.toLowerCase()),
|
|
}))
|
|
|
|
export const I18nContext = createContext<I18nContextType>({
|
|
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<string, any>): 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<I18nContextType>(
|
|
() => ({ locale, get, getEnumOptions }),
|
|
[locale]
|
|
)
|
|
return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>
|
|
}
|