|
1 | 1 | import { NextResponse } from 'next/server'; |
2 | | -import createMiddleware from './next.middleware'; |
3 | | -import detectLanguage from './middlewares/detectLanguage'; |
| 2 | +import { availableLocales } from './next.locales.mjs'; |
| 3 | +import type { NextRequest } from 'next/server'; |
4 | 4 |
|
5 | | -const nextMiddleware = createMiddleware(NextResponse); |
| 5 | +// This Middleware is responsible for handling automatic language detection from a user's Browser |
| 6 | +// This middleware should only run on "/" requests coming to the Website |
| 7 | +export const middleware = async (request: NextRequest) => { |
| 8 | + const { pathname, search } = request.nextUrl; |
6 | 9 |
|
7 | | -const { middleware, matcher } = nextMiddleware([detectLanguage]); |
| 10 | + // This function allows us to redirect with a Locale Code |
| 11 | + const redirectWithLocale = (_locale: string) => { |
| 12 | + const redirectUrl = `/${_locale}${pathname}${search}`; |
8 | 13 |
|
9 | | -export { middleware, matcher }; |
| 14 | + return NextResponse.redirect(new URL(redirectUrl, request.url)); |
| 15 | + }; |
| 16 | + |
| 17 | + const localeCookie = request.cookies.get('NEXT_LOCALE'); |
| 18 | + |
| 19 | + // If we already have a NEXT_LOCALE Cookie, then Redirect to the stored Locale Code |
| 20 | + if (localeCookie?.value && localeCookie.value !== 'default') { |
| 21 | + return redirectWithLocale(localeCookie.value); |
| 22 | + } |
| 23 | + |
| 24 | + // If not, we try to check if the Browser is sending `Accept-Language` Header |
| 25 | + const acceptedLanguagesRaw = request.headers.get('Accept-Language') || 'en'; |
| 26 | + |
| 27 | + // If present, we try to split the format into ['code', 'q=order', ...] |
| 28 | + // Where q= is the precedence of the Accepted Language |
| 29 | + // We then filter those out as we don't want them |
| 30 | + const acceptedLanguages = acceptedLanguagesRaw |
| 31 | + .split(';') |
| 32 | + .map(collection => collection.split(',')) |
| 33 | + .flat() |
| 34 | + .filter(locale => !locale.startsWith('q=')); |
| 35 | + |
| 36 | + // We check if we have any matching Language in the order of preference given |
| 37 | + // And if yes, we return that Locale Code |
| 38 | + const matchedLocaleCode = acceptedLanguages.find(acceptedLocale => |
| 39 | + availableLocales.some(locale => locale.code === acceptedLocale) |
| 40 | + ); |
| 41 | + |
| 42 | + // We create a new Response Object containing the Locale Match or the default Language |
| 43 | + const responseWithCookie = redirectWithLocale(matchedLocaleCode || 'en'); |
| 44 | + |
| 45 | + // Then we set a Cookie to avoid this calculation from happening on every / hit |
| 46 | + responseWithCookie.cookies.set('NEXT_LOCALE', matchedLocaleCode || 'en'); |
| 47 | + |
| 48 | + return responseWithCookie; |
| 49 | +}; |
| 50 | + |
| 51 | +export const config = { matcher: '/' }; |
0 commit comments