feat: add language switcher with cookie persistence and browser detection

Changes:
- Root page.tsx now detects browser language (Accept-Language header)
  and cookie preference to redirect to correct locale (/sr or /en)
- Middleware handles old Serbian URLs (/products, /about, etc.) with
  301 redirects to /sr/* while respecting locale cookie
- Header component now includes language switcher dropdown with
  flag icons (Serbian and English)
- Language selection sets NEXT_LOCALE cookie and persists preference

Behavior:
- User visits / → redirects to /sr or /en based on cookie/browser
- User selects English from dropdown → cookie set, redirects to /en/*
- User visits /products with en cookie → /en/products (301)
- User visits /products with sr/no cookie → /sr/products (301)
This commit is contained in:
Unchained
2026-03-24 08:09:27 +02:00
parent 8244ba161b
commit a84647db6c
3 changed files with 107 additions and 29 deletions

View File

@@ -1,28 +1,25 @@
import createMiddleware from "next-intl/middleware";
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { routing } from "./src/i18n/routing";
const LOCALE_COOKIE = "NEXT_LOCALE";
export default function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
const hasLocalePrefix = routing.locales.some(
(locale) => pathname === `/${locale}` || pathname.startsWith(`/${locale}/`)
);
if (hasLocalePrefix) {
const intlMiddleware = createMiddleware({
...routing,
});
return intlMiddleware(request);
}
const cookieLocale = request.cookies.get(LOCALE_COOKIE)?.value;
const acceptLanguage = request.headers.get("accept-language") || "";
if (pathname === "/" || pathname === "") {
const intlMiddleware = createMiddleware({
...routing,
localeDetection: true,
});
return intlMiddleware(request);
let locale = "sr";
if (cookieLocale && ["sr", "en", "de", "fr"].includes(cookieLocale)) {
locale = cookieLocale;
} else if (acceptLanguage.includes("en")) {
locale = "en";
}
const url = request.nextUrl.clone();
url.pathname = `/${locale}`;
return NextResponse.redirect(url, 302);
}
const oldSerbianPaths = ["products", "about", "contact", "checkout"];
@@ -31,16 +28,20 @@ export default function middleware(request: NextRequest) {
);
if (isOldSerbianPath) {
const newPathname = `/sr${pathname}`;
let locale = "sr";
if (cookieLocale && ["sr", "en", "de", "fr"].includes(cookieLocale)) {
locale = cookieLocale;
} else if (acceptLanguage.includes("en")) {
locale = "en";
}
const url = request.nextUrl.clone();
url.pathname = newPathname;
url.pathname = `/${locale}${pathname}`;
return NextResponse.redirect(url, 301);
}
const intlMiddleware = createMiddleware({
...routing,
});
return intlMiddleware(request);
return NextResponse.next();
}
export const config = {