Files
2026-08-01 16:07:57 +02:00

67 lines
2.1 KiB
TypeScript

// proxy.ts (was middleware.ts)
import { NextRequest, NextResponse } from "next/server";
import { defaultLocale, isValidLocale } from "@/lib/dictionaries";
// RENAMED: middleware → proxy (Next.js 16 convention)
export function proxy(request: NextRequest) {
const { pathname } = request.nextUrl;
// Skip static files, API routes, Next.js internals
if (
pathname.startsWith("/_next") ||
pathname.startsWith("/api") ||
pathname.startsWith("/favicon") ||
pathname.includes(".")
) {
return NextResponse.next();
}
// Check if path already has a valid locale prefix
const pathLocale = pathname.split("/")[1];
if (isValidLocale(pathLocale)) {
// Serve directly — NEVER redirect locale-prefixed URLs.
// Forward the URL locale as a request header so server components
// without params access (e.g. not-found.tsx) can read it.
const requestHeaders = new Headers(request.headers);
requestHeaders.set("x-locale", pathLocale);
requestHeaders.set("x-preferred-locale", detectPreferredLocale(request));
return NextResponse.next({ request: { headers: requestHeaders } });
}
// No locale prefix — redirect to default (or cookie preference)
const cookieLocale = request.cookies.get("NEXT_LOCALE")?.value;
const targetLocale =
cookieLocale && isValidLocale(cookieLocale) ? cookieLocale : defaultLocale;
const url = request.nextUrl.clone();
url.pathname = `/${targetLocale}${pathname}`;
return NextResponse.redirect(url, 307);
}
function detectPreferredLocale(request: NextRequest): string {
const acceptLang = request.headers.get("accept-language") || "";
const segments = acceptLang
.split(",")
.map((part) => {
const [lang, q] = part.trim().split(";q=");
return {
lang: lang.toLowerCase().trim(),
quality: q ? parseFloat(q) : 1.0,
};
})
.sort((a, b) => b.quality - a.quality);
for (const { lang } of segments) {
const base = lang.split("-")[0];
if (["sr", "bs", "hr"].includes(base)) return "sr";
if (base === "en") return "en";
}
return defaultLocale;
}
export const config = {
matcher: ["/((?!_next|api|favicon\\.ico|.*\\..*).*)"],
};