123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100 |
- // middleware.ts
- import { createI18nMiddleware } from "next-international/middleware";
- import { NextRequest, NextResponse } from "next/server";
- import { getSessionCookie } from "better-auth/cookies";
- function detectUserLocale(request: NextRequest): string {
- const acceptLanguage = request.headers.get("accept-language");
- if (!acceptLanguage) return "en";
- // Parse Accept-Language header
- const languages = acceptLanguage
- .split(",")
- .map((lang) => {
- const [locale, quality = "1"] = lang.trim().split(";q=");
- return { locale: locale.toLowerCase(), quality: parseFloat(quality) };
- })
- .sort((a, b) => b.quality - a.quality);
- // Map browser locales to supported locales
- const supportedLocales = ["en", "fr", "es", "zh-cn", "ru", "pt"];
- for (const { locale } of languages) {
- // Exact match
- if (supportedLocales.includes(locale)) {
- return locale === "zh-cn" ? "zh-CN" : locale;
- }
- // Language match (fr-FR -> fr)
- const lang = locale.split("-")[0];
- if (supportedLocales.includes(lang)) {
- return lang;
- }
- // Chinese variants
- if (locale.startsWith("zh")) {
- return "zh-CN";
- }
- }
- return "en"; // fallback
- }
- const I18nMiddleware = createI18nMiddleware({
- locales: ["en", "fr", "es", "zh-CN", "ru", "pt"],
- defaultLocale: "en",
- urlMappingStrategy: "rewrite",
- });
- export async function middleware(request: NextRequest) {
- const pathname = request.nextUrl.pathname;
- const detectedLocale = detectUserLocale(request);
- // If on root path and no locale detected yet, redirect to detected locale
- if (pathname === "/" && !request.cookies.get("detected-locale")) {
- const url = new URL(`/${detectedLocale}`, request.url);
- const response = NextResponse.redirect(url);
- response.cookies.set("detected-locale", detectedLocale, {
- maxAge: 60 * 60 * 24 * 365, // 1 year
- httpOnly: false,
- secure: process.env.NODE_ENV === "production",
- sameSite: "lax",
- });
- return response;
- }
- // Normal i18n middleware processing
- const response = I18nMiddleware(request);
- // Store detected locale in cookie for future visits
- if (!request.cookies.get("detected-locale")) {
- response.cookies.set("detected-locale", detectedLocale, {
- maxAge: 60 * 60 * 24 * 365, // 1 year
- httpOnly: false,
- secure: process.env.NODE_ENV === "production",
- sameSite: "lax",
- });
- }
- const searchParams = request.nextUrl.searchParams.toString();
- response.headers.set("searchParams", searchParams);
- if (request.nextUrl.pathname.includes("/dashboard")) {
- const session = getSessionCookie(request);
- if (!session) {
- return NextResponse.redirect(new URL("/", request.url));
- }
- }
- return response;
- }
- export const config = {
- matcher: [
- "/((?!api|static|_next|manifest.json|favicon.ico|robots.txt|sw.js|apple-touch-icon.png|android-chrome-.*\\.png|images|icons|sitemap.xml).*)",
- ],
- };
|