65 lines
2.2 KiB
TypeScript
65 lines
2.2 KiB
TypeScript
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$).*)',
|
||
],
|
||
};
|