import { NextResponse } from "next/server"; const LOCALE_COOKIE = "rs_locale"; const SUPPORTED_LOCALES = new Set(["en", "pt"]); const PUBLIC_FILE = /\.(?:ico|png|jpg|jpeg|svg|webp|avif|gif|txt|xml|json|webmanifest|css|js|map|woff2?)$/i; const RESERVED_PREFIXES = [ "/_next", "/_a2a", "/.well-known", "/api", "/auth", "/invoke", "/mcp", "/message:send", "/message:stream", "/tasks", "/answers", "/input-requests", "/scope-grants", "/scope-denials", ]; function isReservedPath(pathname) { if (PUBLIC_FILE.test(pathname)) { return true; } return RESERVED_PREFIXES.some( (prefix) => pathname === prefix || pathname.startsWith(`${prefix}/`), ); } function normalizeLocale(value) { const locale = String(value || "").trim().toLowerCase(); if (SUPPORTED_LOCALES.has(locale)) { return locale; } return null; } function localeFromCountry(request) { const country = ( request.headers.get("x-vercel-ip-country") || request.headers.get("cf-ipcountry") || request.headers.get("x-country-code") || "" ).trim().toUpperCase(); if (country === "BR" || country === "PT") { return "pt"; } return null; } function localeFromAcceptLanguage(request) { const header = request.headers.get("accept-language") || ""; const ranked = header .split(",") .map((part) => { const [tag, ...params] = part.trim().split(";"); const q = params .map((param) => param.trim()) .find((param) => param.startsWith("q=")); const weight = q ? Number.parseFloat(q.slice(2)) : 1; return { language: tag.toLowerCase().split("-")[0], weight: Number.isFinite(weight) ? weight : 1, }; }) .filter((item) => SUPPORTED_LOCALES.has(item.language)) .sort((a, b) => b.weight - a.weight); return ranked[0]?.language || null; } function preferredLocale(request) { return ( normalizeLocale(request.cookies.get(LOCALE_COOKIE)?.value) || localeFromAcceptLanguage(request) || localeFromCountry(request) || "en" ); } function withLocaleCookie(response, locale) { response.cookies.set(LOCALE_COOKIE, locale, { path: "/", maxAge: 60 * 60 * 24 * 365, sameSite: "lax", }); return response; } export function middleware(request) { const url = request.nextUrl; const { pathname, searchParams } = url; if (isReservedPath(pathname)) { return NextResponse.next(); } const requestedLocale = normalizeLocale(searchParams.get("lang")); if (requestedLocale) { const cleanUrl = url.clone(); cleanUrl.searchParams.delete("lang"); const response = cleanUrl.toString() === url.toString() ? NextResponse.next() : NextResponse.redirect(cleanUrl); return withLocaleCookie(response, requestedLocale); } if (pathname === "/") { const locale = preferredLocale(request); if (locale === "pt") { const redirectUrl = url.clone(); redirectUrl.pathname = "/pt/"; return NextResponse.redirect(redirectUrl); } } return NextResponse.next(); } export const config = { matcher: ["/:path*"], };