49 lines
1.3 KiB
TypeScript
49 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { createContext, type ReactNode, useContext, useMemo } from "react";
|
|
import { i18n as signalI18n } from "@signal/i18n";
|
|
import { type i18nConfig, type Translate } from "../actions/locale.ts";
|
|
|
|
// This is the type for a single locale's dictionary, e.g., i18nConfig['en_GB']
|
|
type LocaleDictionary = (typeof i18nConfig)[keyof typeof i18nConfig];
|
|
|
|
interface LocaleContextValue {
|
|
t: Translate;
|
|
}
|
|
|
|
const LocaleContext = createContext<LocaleContextValue | undefined>(undefined);
|
|
|
|
/**
|
|
* Provides the translation dictionary to client components.
|
|
* It takes the server-resolved dictionary and creates a `t` function from it.
|
|
*/
|
|
export const LocaleProvider = ({
|
|
dictionary,
|
|
children,
|
|
}: {
|
|
dictionary: LocaleDictionary;
|
|
children: ReactNode;
|
|
}) => {
|
|
const value = useMemo(() => {
|
|
const { t } = signalI18n(dictionary);
|
|
return { t };
|
|
}, [dictionary]);
|
|
|
|
return (
|
|
<LocaleContext.Provider value={value}>
|
|
{children}
|
|
</LocaleContext.Provider>
|
|
);
|
|
};
|
|
|
|
/**
|
|
* A client-side hook to access the translation function `t`.
|
|
* Must be used within a <LocaleProvider>.
|
|
*/
|
|
export const useClientLocale = (): LocaleContextValue => {
|
|
const context = useContext(LocaleContext);
|
|
if (context === undefined) {
|
|
throw new Error("useClientLocale must be used within a LocaleProvider");
|
|
}
|
|
return context;
|
|
};
|