import { NextFetchEvent, NextMiddleware, NextResponse } from 'next/server'; import settings from 'settings'; import { PzNextRequest } from '.'; import { LocaleUrlStrategy } from '../localization'; import { urlLocaleMatcherRegex } from '../utils'; import logger from '../utils/log'; import { getUrlPathWithLocale } from '../utils/localization'; const getMatchedLocale = (pathname: string, req: PzNextRequest) => { let matchedLocale = pathname.match(urlLocaleMatcherRegex)?.[0] ?? ''; matchedLocale = matchedLocale.replace('/', ''); const { localeUrlStrategy, defaultLocaleValue } = settings.localization; if (localeUrlStrategy === LocaleUrlStrategy.Subdomain) { const host = req.headers.get('x-forwarded-host') || req.headers.get('host') || ''; if (host) { const subDomain = host.split('.')[0] || ''; const subDomainLocaleMatched = `/${subDomain}`.match( urlLocaleMatcherRegex ); if (subDomainLocaleMatched && subDomainLocaleMatched[0]) { matchedLocale = subDomainLocaleMatched[0].slice(1); } } } if (!matchedLocale.length) { if (localeUrlStrategy !== LocaleUrlStrategy.ShowAllLocales) { matchedLocale = defaultLocaleValue; } } return matchedLocale; }; const withLocale = (middleware: NextMiddleware) => async (req: PzNextRequest, event: NextFetchEvent) => { const ip = req.headers.get('x-forwarded-for') ?? ''; try { const url = req.nextUrl.clone(); const matchedLocale = getMatchedLocale(url.pathname, req); let { localeUrlStrategy } = settings.localization; const { defaultLocaleValue, redirectToDefaultLocale } = settings.localization; localeUrlStrategy = localeUrlStrategy ?? LocaleUrlStrategy.HideDefaultLocale; if (!defaultLocaleValue) { logger.error('Default locale value is not defined in settings.', { ip }); throw new Error( 'Default locale value is not defined. Use `defaultLocaleValue` property in `localization` object in `settings.js` file.' ); } if ( !matchedLocale?.length && localeUrlStrategy === LocaleUrlStrategy.ShowAllLocales && redirectToDefaultLocale && req.method === 'GET' ) { // Redirect to existing or default locale url.pathname = getUrlPathWithLocale( url.pathname, req.cookies.get('pz-locale')?.value ); // Use 303 for POST requests return NextResponse.redirect(url, 303); } req.middlewareParams.rewrites.locale = matchedLocale; } catch (error) { logger.error('withLocale error', { error, ip }); } return middleware(req, event); }; export default withLocale;