diff --git a/src/middleware.ts b/src/middleware.ts new file mode 100644 index 0000000..c99ca8a --- /dev/null +++ b/src/middleware.ts @@ -0,0 +1,44 @@ +import { NextResponse } from 'next/server'; +import type { NextRequest } from 'next/server'; +import { i18n } from './i18n'; + +const { locales, defaultLocale } = i18n; + +function getLocaleFromHeaders(request: NextRequest): string { + const acceptLanguageHeader = request.headers.get('accept-language'); + if (acceptLanguageHeader) { + const languages = acceptLanguageHeader.split(',').map(l => l.split(';')[0].trim()); + for (const lang of languages) { + if (locales.includes(lang)) { + return lang; + } + } + } + return defaultLocale; +} + +export function middleware(request: NextRequest) { + const pathname = request.nextUrl.pathname; + + // Check if the pathname already contains a locale + const pathnameHasLocale = locales.some( + (locale) => pathname.startsWith(`/${locale}/`) || pathname === `/${locale}` + ); + + if (pathnameHasLocale) { + return; + } + + // Redirect if no locale + const locale = getLocaleFromHeaders(request); + request.nextUrl.pathname = `/${locale}${pathname}`; + return NextResponse.redirect(request.nextUrl); +} + +export const config = { + matcher: [ + // Skip all internal paths like /_next/ (static assets, api routes, etc.) + // Also skip favicon.ico + '/((?!api|_next/static|_next/image|favicon.ico).*)', + ], +};