NebulaCloud/middleware.ts

55 lines
1.7 KiB
TypeScript
Raw Permalink Normal View History

2025-09-15 17:28:58 +08:00
import { NextRequest, NextResponse } from 'next/server';
import { locales, defaultLocale } from './lib/i18n';
export function middleware(request: NextRequest) {
// Check if there is any supported locale in the pathname
const pathname = request.nextUrl.pathname;
// Check if the pathname already includes a locale
const pathnameIsMissingLocale = locales.every(
(locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}`,
);
// Redirect if there is no locale
if (pathnameIsMissingLocale) {
// Try to get locale from Accept-Language header
const locale = getLocale(request) || defaultLocale;
return NextResponse.redirect(new URL(`/${locale}${pathname}`, request.url));
}
}
function getLocale(request: NextRequest): string | undefined {
// Get locale from Accept-Language header
const acceptLanguage = request.headers.get('accept-language');
if (!acceptLanguage) return undefined;
// Parse Accept-Language header
const languages = acceptLanguage.split(',').map((lang) => lang.split(';')[0].trim());
// Find matching locale
for (const lang of languages) {
if (locales.includes(lang as any)) {
return lang;
}
// Check for language without region (e.g., 'zh' matches 'zh-CN')
const langWithoutRegion = lang.split('-')[0];
const matchingLocale = locales.find((locale) => locale.startsWith(langWithoutRegion));
if (matchingLocale) {
return matchingLocale;
}
}
return undefined;
}
export const config = {
matcher: [
// Skip all internal paths (_next)
'/((?!_next|api|favicon.ico|.*\\..*).*)',
],
};