5b40968c9d
App Router setup with next-intl (en/fr), Better Auth wiring, shadcn/ui components, Tailwind, AES-256-GCM encrypt util, Redis rate limiter, tier limit checker, site_settings helper for runtime .env overrides.
67 lines
1.9 KiB
TypeScript
67 lines
1.9 KiB
TypeScript
"use client";
|
|
|
|
import { createContext, useContext, useEffect, useState } from "react";
|
|
import { NextIntlClientProvider } from "next-intl";
|
|
|
|
export const SUPPORTED_LOCALES = [
|
|
{ code: "en", label: "English" },
|
|
{ code: "fr", label: "Français" },
|
|
] as const;
|
|
|
|
export type Locale = (typeof SUPPORTED_LOCALES)[number]["code"];
|
|
|
|
const STORAGE_KEY = "epicure-locale";
|
|
|
|
const LocaleContext = createContext<{
|
|
locale: Locale;
|
|
setLocale: (locale: Locale) => void;
|
|
}>({ locale: "en", setLocale: () => {} });
|
|
|
|
export function useLocale() {
|
|
return useContext(LocaleContext);
|
|
}
|
|
|
|
export function I18nProvider({
|
|
children,
|
|
messages,
|
|
initialLocale,
|
|
}: {
|
|
children: React.ReactNode;
|
|
messages: Record<string, Record<string, unknown>>;
|
|
initialLocale?: Locale;
|
|
}) {
|
|
const resolved = initialLocale ?? ("en" as Locale);
|
|
const [locale, setLocaleState] = useState<Locale>(resolved);
|
|
const [currentMessages, setCurrentMessages] = useState(messages[resolved] ?? messages["en"]!);
|
|
|
|
useEffect(() => {
|
|
// If no server-side locale, fall back to localStorage
|
|
if (!initialLocale) {
|
|
const stored = localStorage.getItem(STORAGE_KEY) as Locale | null;
|
|
if (stored && messages[stored]) {
|
|
setLocaleState(stored);
|
|
setCurrentMessages(messages[stored]!);
|
|
}
|
|
}
|
|
}, [messages, initialLocale]);
|
|
|
|
function setLocale(next: Locale) {
|
|
setLocaleState(next);
|
|
setCurrentMessages(messages[next]!);
|
|
localStorage.setItem(STORAGE_KEY, next);
|
|
fetch("/api/v1/users/me", {
|
|
method: "PATCH",
|
|
headers: { "Content-Type": "application/json" },
|
|
body: JSON.stringify({ locale: next }),
|
|
}).catch(() => {});
|
|
}
|
|
|
|
return (
|
|
<LocaleContext.Provider value={{ locale, setLocale }}>
|
|
<NextIntlClientProvider locale={locale} messages={currentMessages} timeZone="UTC">
|
|
{children}
|
|
</NextIntlClientProvider>
|
|
</LocaleContext.Provider>
|
|
);
|
|
}
|