let headers = { 'accept-language': 'en-US,en;q=0.5' };
let languages = new Negotiator({ headers }).languages();
let locales = ['en', 'de'];
let defaultLocale = 'en';
match(languages, locales, defaultLocale);
function getLocale(request) {
// Extract the language from the request headers
const acceptLanguage = request.headers.get('accept-language');
// Parse the accept language header to get the preferred languages
const preferredLanguages = acceptLanguage
? acceptLanguage.split(',').map((language) => {
const [locale, q] = language.trim().split(';q=');
return { locale, q: parseFloat(q || '1') };
})
: [];
// Sort the preferred languages by quality (q) in descending order
preferredLanguages.sort((a, b) => b.q - a.q);
// Find the first supported language from the preferred languages
const supportedLanguage = preferredLanguages.find((language) =>
locales.includes(language.locale),
);
// Return the supported language or the default locale if none found
return supportedLanguage ? supportedLanguage.locale : defaultLocale;
}
export function middleware(request) {
// Check if there is any supported locale in the pathname
const { pathname } = request.nextUrl;
const pathnameHasLocale = locales.some(
(locale) =>
pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`,
);
if (pathnameHasLocale) return;
// Redirect if there is no locale
const locale = getLocale(request);
const newPathname = locale === 'en' ? pathname : `/${locale}${pathname}`;
request.nextUrl.pathname = newPathname;
// e.g. incoming request is /products
// The new URL is now /en/products if locale is not 'en'
return Response.redirect(request.nextUrl);
}
export const config = {
matcher: [
(_next)
'/((?!_next).*)',
// Optional: only run on root (/) URL
// '/'
],
};