import { NextRequest, NextResponse } from 'next/server'; import { locales, defaultLocale } from './lib/i18n'; export function middleware(request: NextRequest) { // Check if there is any supported locale in the pathname const pathname = request.nextUrl.pathname; // Check if the pathname already includes a locale const pathnameIsMissingLocale = locales.every( (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`, ); // Redirect if there is no locale if (pathnameIsMissingLocale) { // Try to get locale from Accept-Language header const locale = getLocale(request) || defaultLocale; return NextResponse.redirect(new URL(`/${locale}${pathname}`, request.url)); } } function getLocale(request: NextRequest): string | undefined { // Get locale from Accept-Language header const acceptLanguage = request.headers.get('accept-language'); if (!acceptLanguage) return undefined; // Parse Accept-Language header const languages = acceptLanguage.split(',').map((lang) => lang.split(';')[0].trim()); // Find matching locale for (const lang of languages) { if (locales.includes(lang as any)) { return lang; } // Check for language without region (e.g., 'zh' matches 'zh-CN') const langWithoutRegion = lang.split('-')[0]; const matchingLocale = locales.find((locale) => locale.startsWith(langWithoutRegion)); if (matchingLocale) { return matchingLocale; } } return undefined; } export const config = { matcher: [ // Skip all internal paths (_next) '/((?!_next|api|favicon.ico|.*\\..*).*)', ], };