fix(frontend): always default first-time visitors to Persian

Drop Accept-Language detection from the locale middleware. A first
visit (no NEXT_LOCALE cookie) now always serves the default locale
(fa-IR) instead of guessing from the browser. The user's last explicit
choice, persisted in the cookie by the language switcher, remains the
sole signal on subsequent visits.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
keyhan
2026-06-18 13:27:29 +03:30
parent bb6049a067
commit 585fdbc9b7
+5 -24
View File
@@ -1,19 +1,6 @@
import { NextRequest, NextResponse } from 'next/server'; import { NextRequest, NextResponse } from 'next/server';
import { locales, defaultLocale, isLocale, LOCALE_COOKIE, type Locale } from '@/i18n/config'; import { locales, defaultLocale, isLocale, LOCALE_COOKIE, type Locale } from '@/i18n/config';
// Parse the Accept-Language header into an ordered list of base language codes.
function parseAcceptLanguage(header: string | null): string[] {
if (!header) return [];
return header
.split(',')
.map((part) => {
const [tag, q] = part.trim().split(';q=');
return { tag: tag.trim().toLowerCase(), q: q ? parseFloat(q) : 1 };
})
.sort((a, b) => b.q - a.q)
.map((x) => x.tag);
}
// Host-based separation between the marketing landing site and the // Host-based separation between the marketing landing site and the
// authenticated panel. Configured at runtime (server-side) so the same // authenticated panel. Configured at runtime (server-side) so the same
// frontend image can serve both hosts. When PANEL_HOST is unset (local dev), // frontend image can serve both hosts. When PANEL_HOST is unset (local dev),
@@ -42,20 +29,14 @@ function hostOf(request: NextRequest): string {
} }
function detectLocale(request: NextRequest): Locale { function detectLocale(request: NextRequest): Locale {
// 1. Explicit choice via cookie // Honour the user's last explicit choice, persisted in a cookie by the
// language switcher. On the very first visit (no cookie) we always serve the
// default locale (fa-IR) rather than guessing from Accept-Language, so the
// browser's language preference never overrides the default. From then on,
// the user's last selection is what determines the language.
const cookieLocale = request.cookies.get(LOCALE_COOKIE)?.value; const cookieLocale = request.cookies.get(LOCALE_COOKIE)?.value;
if (isLocale(cookieLocale)) return cookieLocale; if (isLocale(cookieLocale)) return cookieLocale;
// 2. Browser preference via Accept-Language
const accepted = parseAcceptLanguage(request.headers.get('accept-language'));
for (const tag of accepted) {
const exact = locales.find((l) => l.toLowerCase() === tag);
if (exact) return exact;
const base = locales.find((l) => l.toLowerCase().split('-')[0] === tag.split('-')[0]);
if (base) return base;
}
// 3. Fallback
return defaultLocale; return defaultLocale;
} }