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$).*)',
|
|||
|
|
],
|
|||
|
|
};
|