Files

65 lines
1.8 KiB
TypeScript

import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
import { i18n } from "./i18n-config";
function getLocale(request: NextRequest): string {
const acceptLanguage = request.headers.get("accept-language");
if (!acceptLanguage) return i18n.defaultLocale;
// Simple and ultra-robust parsing for accept-language header
const preferredLocales = acceptLanguage
.split(",")
.map((lang) => {
const [locale, q] = lang.split(";q=");
return {
locale: locale.trim().split("-")[0].toLowerCase(), // e.g. "tr", "en"
priority: q ? parseFloat(q) : 1.0,
};
})
.sort((a, b) => b.priority - a.priority);
for (const pref of preferredLocales) {
if (i18n.locales.includes(pref.locale as any)) {
return pref.locale;
}
}
return i18n.defaultLocale;
}
export function proxy(request: NextRequest) {
const pathname = request.nextUrl.pathname;
// Skip static assets, internal paths, and favicon
if (
pathname.startsWith("/_next") ||
pathname.startsWith("/api") ||
pathname.startsWith("/favicon.ico") ||
pathname.match(/\.(png|jpg|jpeg|gif|svg|webp|ico|css|js|woff|woff2|ttf|otf|json|xml|txt)$/)
) {
return;
}
// Check if pathname already contains a supported locale prefix
const pathnameIsMissingLocale = i18n.locales.every(
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`
);
if (pathnameIsMissingLocale) {
const locale = getLocale(request);
// Redirect /xxx to /locale/xxx
return NextResponse.redirect(
new URL(
`/${locale}${pathname.startsWith("/") ? "" : "/"}${pathname}`,
request.url
)
);
}
}
export const config = {
// Matcher ignoring static items and api routes
matcher: ["/((?!api|_next/static|_next/image|favicon.ico).*)"],
};