355ba944ad
getMarketingLocale() only ever read the marketing_locale cookie, defaulting anonymous first-time visitors to English until they manually used the language switcher — even though the switcher and a full French translation already existed. Now falls back to parsing Accept-Language when no cookie is set; an explicit switcher choice still wins on every later visit. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
50 lines
2.2 KiB
TypeScript
50 lines
2.2 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.
|
|
*/
|
|
/** Parses an `Accept-Language` header and returns the first supported
|
|
* locale it lists, in the browser's stated preference order — ignoring
|
|
* unsupported languages (e.g. "de", "es") rather than stopping at them. */
|
|
function localeFromAcceptLanguage(header: string | null): Locale | null {
|
|
if (!header) return null;
|
|
const tags = header
|
|
.split(",")
|
|
.map((part) => part.split(";")[0]!.trim().toLowerCase())
|
|
.filter(Boolean);
|
|
for (const tag of tags) {
|
|
if (tag.startsWith("fr")) return "fr";
|
|
if (tag.startsWith("en")) return "en";
|
|
}
|
|
return null;
|
|
}
|
|
|
|
export async function getMarketingLocale(): Promise<Locale> {
|
|
const store = await cookies();
|
|
const cookieValue = store.get(MARKETING_LOCALE_COOKIE)?.value;
|
|
if (cookieValue === "fr" || cookieValue === "en") return cookieValue;
|
|
|
|
// No explicit choice saved yet (first visit, or cookies cleared) — honor
|
|
// the visitor's browser language instead of always defaulting to English.
|
|
const headerStore = await headers();
|
|
return localeFromAcceptLanguage(headerStore.get("accept-language")) ?? "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();
|
|
}
|