Files
Epicure/apps/web/lib/marketing-locale.ts
T
Arnaud 8dccd8898b feat: vitrine language/theme switching, missing features, disabled-signups handling
Language switcher (flag toggle) and dark-mode toggle in the marketing
header, both usable by logged-out visitors -- the marketing pages
previously hardcoded English (getMessages(undefined)) regardless of
any preference, and had no theme control since the authenticated
Nav's toggle isn't rendered there. New cookie-based locale resolution
(lib/marketing-locale.ts) separate from the authenticated app's
useLocale/setLocale, which persists via an authenticated PATCH that
would just 401 and revert for an anonymous visitor. Root layout now
falls back to that cookie for <html lang> when there's no session.

Features/Home now cover cook mode, recipe variations, personalized
recommendations, and ingredient substitution -- all real, shipped
features that were missing from the page copy.

Signup CTAs check isSignupsDisabled() and swap to "Signups closed"
instead of "Get started free" -- still linking to /signup, since that
page already handles the invite-token exception correctly.

Fixed along the way: importing the cookie-name constant from
marketing-locale.ts in the client-side LanguageSwitcher pulled that
file's server-only imports (lib/auth/server -> the DB client ->
`postgres`) into the client bundle, breaking the build on Node
built-ins. Split the constant into its own client-safe file
(marketing-locale-cookie.ts). Caught by `pnpm build`, not typecheck.

Verified with typecheck, lint, and a full production build (clean
compile) -- no DB in this sandbox to click through a real dev server.

v0.48.1
2026-07-18 10:55:06 +02:00

29 lines
1.3 KiB
TypeScript

import { headers, cookies } from "next/headers";
import { auth } from "@/lib/auth/server";
import type { Locale } from "@/lib/i18n/provider";
import { MARKETING_LOCALE_COOKIE } from "@/lib/marketing-locale-cookie";
export { MARKETING_LOCALE_COOKIE };
/**
* Locale for the public marketing pages — cookie-based, not tied to a user
* account (visitors there have no session). Separate from the authenticated
* app's locale system (`lib/i18n/provider.tsx`'s `useLocale`/`setLocale`),
* which persists to `users.locale` via an authenticated PATCH that would
* just 401 for an anonymous visitor and revert the UI.
*/
export async function getMarketingLocale(): Promise<Locale> {
const store = await cookies();
const value = store.get(MARKETING_LOCALE_COOKIE)?.value;
return value === "fr" ? "fr" : "en";
}
/** A logged-in visitor's own saved locale wins (matches what they see
* everywhere else in the app); otherwise the marketing cookie. */
export async function getEffectiveMarketingLocale(): Promise<Locale> {
const session = await auth.api.getSession({ headers: await headers() }).catch(() => null);
const sessionLocale = (session?.user as { locale?: string } | undefined)?.locale;
if (sessionLocale === "en" || sessionLocale === "fr") return sessionLocale;
return getMarketingLocale();
}