Sharing url without [lang] is not a valid page
Unanswered
Pyr0Lover posted this in #help-forum
All of my pages are inside a [lang] folder. And inside my middleware, there is some code, that if the primary language is selected, then it will be removed from the url...
So .com/en/homepage can become .com/homepage and the middleware can handle this, and returns the english page corrctly. But when I share the url without the lang, then it will be a 500 Error, since that is not a valid page path. It only becomes valid after middleware is triggered, which I am assuming doesn't happen with crawlers?
So I'm not sure what would be the best approach to this, any thoughts are appreciated...
So .com/en/homepage can become .com/homepage and the middleware can handle this, and returns the english page corrctly. But when I share the url without the lang, then it will be a 500 Error, since that is not a valid page path. It only becomes valid after middleware is triggered, which I am assuming doesn't happen with crawlers?
So I'm not sure what would be the best approach to this, any thoughts are appreciated...
6 Replies
middleware.ts:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
import { i18n } from '@/i18next.config';
import { match as matchLocale } from '@formatjs/intl-localematcher';
import Negotiator from 'negotiator';
import NextAuth from 'next-auth';
function getLocale(request: NextRequest): string | undefined {
const negotiatorHeaders: Record<string, string> = {};
request.headers.forEach((value, key) => (negotiatorHeaders[key] = value));
// @ts-ignore locales are readonly
const locales: string[] = i18n.locales;
const languages = new Negotiator({ headers: negotiatorHeaders }).languages();
const locale = matchLocale(languages, locales, i18n.defaultLocale);
return locale;
}
export function middleware(request: NextRequest) {
const pathname = request.nextUrl.pathname;
const pathnameIsMissingLocale = i18n.locales.every(
(locale) =>
!pathname.startsWith(/${locale}/) && pathname !==/${locale},
);
// List of paths to exclude from locale handling
const excludedPaths = ['/sitemap.xml', '/robots.txt'];
// Check if the pathname matches any excluded path
if (excludedPaths.includes(pathname)) {
return NextResponse.next();
}
const {
nextUrl: { searchParams },
} = request;
const urlSearchParams = new URLSearchParams(searchParams);
const params = Object.fromEntries(urlSearchParams.entries());
const urlParams = '?' + new URLSearchParams(params);
// Redirect if there is no locale
if (pathnameIsMissingLocale) {
const locale = getLocale(request);
const url = new URL(/${locale}${pathname.startsWith('/') ? '' : '/'}${pathname}${urlParams},
request.url,
);
if (locale === i18n.defaultLocale) {
return NextResponse.rewrite(url);
}
return NextResponse.redirect(url);
}
}
export const config = {
matcher: ['/((?!api|_next/static|_next/image|.*\\.png$|.*\\.svg$|favicon.ico).*)'],
};@Pyr0Lover I am not sure if I understood you correctly but your approach doesn't look correct
so what you described is an expected one - what's the reason to remove
/en from your url?Because its the default language. And removing it makes the url shorter which looks cleaner. But in my specific case, the domain is .pt and so the url would be .pt/pt/homePage And it's just unecessary to have it twice.
This works fine, the problem is the link preview on social media. Because if someone copies the url, it will come without the lang parameter. And when a crawler looks at that page there is nothing there.