import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; const locales = ['zh-CN', 'zh-TW', 'en']; const defaultLocale = 'zh-CN'; // 获取首选语言 function getLocale(request: NextRequest): string { // 1. 检查URL路径中是否已包含语言代码 const pathname = request.nextUrl.pathname; const pathnameIsMissingLocale = locales.every( (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}` ); if (!pathnameIsMissingLocale) { return locales.find(locale => pathname.startsWith(`/${locale}`)) || defaultLocale; } // 2. 检查Accept-Language头 const acceptLanguage = request.headers.get('accept-language'); if (acceptLanguage) { const preferredLocale = locales.find(locale => acceptLanguage.toLowerCase().includes(locale.toLowerCase()) ); if (preferredLocale) { return preferredLocale; } } return defaultLocale; } export function middleware(request: NextRequest) { const pathname = request.nextUrl.pathname; // 检查路径是否已经包含语言代码 const pathnameIsMissingLocale = locales.every( (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}` ); // 如果路径缺少语言代码,则重定向 if (pathnameIsMissingLocale) { const locale = getLocale(request); return NextResponse.redirect( new URL(`/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}`, request.url) ); } } export const config = { // 匹配所有路径,除了api、_next/static、_next/image、favicon.ico等 matcher: [ /* * 匹配所有请求路径,除了以下开头的: * - api (API routes) * - _next/static (静态文件) * - _next/image (图片优化文件) * - favicon.ico (网站图标) * - locales (翻译文件) * - docs (文档文件) * - 各种静态资源文件 */ '/((?!api|_next/static|_next/image|favicon.ico|locales|docs|.*\\.png$|.*\\.jpg$|.*\\.jpeg$|.*\\.gif$|.*\\.svg$|.*\\.ico$|.*\\.css$|.*\\.js$|.*\\.json$|.*\\.md$).*)', ], };