I have a problem with Next.js 14 project, which uses app router. I use [lang] folder to localize my app. So, I have all my pages, including page.tsx and layout.tsx inside of [lang] folder. This way, I get locale passed to all of my pages like this:
export default function Home({ params }: { params: { lang: string } }) {
const s = dictionary[params.lang];
return (
<main className="flex min-h-screen flex-col items-center justify-between p-24">
<p>{s.home.title}</p>
</main>
);
}
This is my middleware.ts file:
let locales = ["en", "de"];
export let defaultLocale = "en";
function getLocale(request: Request): string {
const headers = new Headers(request.headers);
const acceptLanguage = headers.get("accept-language");
if (acceptLanguage) {
headers.set("accept-language", acceptLanguage.replaceAll("_", "-"));
}
const headersObject = Object.fromEntries(headers.entries());
const languages = new Negotiator({ headers: headersObject }).languages();
return match(languages, locales, defaultLocale);
}
// Without /locale in path
export function middleware(request: NextRequest) {
let locale = getLocale(request) ?? defaultLocale;
const pathname = request.nextUrl.pathname;
const newUrl = new URL(`/${locale}${pathname}`, request.nextUrl);
return NextResponse.rewrite(newUrl);
}
export const config = {
matcher: [
// Skip all internal paths (_next)
"/((?!_next|api|favicon.ico|robots.txt|sitemap.xml).*)",
// Optional: only run on root (/) URL
// '/'
],
};
My folder structure is:
my-app/
├─ ...
├─ public/
│ ├─ favicon.ico
│ ├─ robots.txt
├─ src/
│ ├─ app/
│ │ ├─ [lang]/
│ │ │ ├─ page.tsx
│ │ │ ├─ layout.tsx
│ │ │ ├─ not-found.tsx
│ ├─ api/
├─ ...
The problem is, when I put not-found.tsx inside of a [lang] folder, it does not work. On unknown route I get default 404 page. But, when I put it outside of [lang], in app folder directly, it does work, but I do not get locale, and I get the page without layout. The workaround would be to create yet another layout.tsx in app directory, but again without the possibility to localize it, which is just bad user experience.
I tried to copy not-found.tsx into [lang] folder to be able to get app locale to localize my content. According to Next.js documentation, this should work out of the box.
Has anyone encountered a problem like this?
First of all, put your main
not-found.tsxlocalized atapp/[lang]/not-found.tsx.At the root, create a
app/layout.tsxthat doesn't do anything except returning itschildrenprop:not-found.tsx:Here you have two options: