fix: vitrine/marketing pages use visitor's browser locale, not always English (v0.78.0)
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>
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
// Mirrors CHANGELOG.md at the repo root — update both together.
|
||||
export const APP_VERSION = "0.77.0";
|
||||
export const APP_VERSION = "0.78.0";
|
||||
|
||||
export type ChangelogEntry = {
|
||||
version: string;
|
||||
@@ -11,6 +11,13 @@ export type ChangelogEntry = {
|
||||
};
|
||||
|
||||
export const CHANGELOG: ChangelogEntry[] = [
|
||||
{
|
||||
version: "0.78.0",
|
||||
date: "2026-07-24 13:40",
|
||||
fixed: [
|
||||
"Marketing/vitrine pages now honor a first-time visitor's browser language (Accept-Language) instead of always defaulting to English until they manually switch. An explicit choice from the language switcher still wins on every later visit.",
|
||||
],
|
||||
},
|
||||
{
|
||||
version: "0.77.0",
|
||||
date: "2026-07-24 13:00",
|
||||
|
||||
@@ -12,10 +12,31 @@ export { MARKETING_LOCALE_COOKIE };
|
||||
* 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 value = store.get(MARKETING_LOCALE_COOKIE)?.value;
|
||||
return value === "fr" ? "fr" : "en";
|
||||
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
|
||||
|
||||
Reference in New Issue
Block a user