CloudTech/middleware.ts

65 lines
2.2 KiB
TypeScript
Raw Normal View History

2025-09-16 18:00:27 +08:00
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$).*)',
],
};