How to create a multilingual not-found page using route groups and nested layouts
Unanswered
Sun bear posted this in #help-forum
Sun bearOP
I'm struggling to get the localized
### The first solution I have tried
##### The issue with this solution
When I call the
### The other solution I have tried
I also tried to append a header to each response via a custom
##### The issue with this solution
The problem in this approach is that the
not-found page to work with NextJS 13 (app-dir). I'm following the [official guide](https://nextjs.org/docs/app/building-your-application/routing/internationalization) on internationalization, as well as [this solution](https://github.com/vercel/next.js/discussions/50034#discussioncomment-6174116) from GitHub.### The first solution I have tried
[locale]
-- [...not-found]
- page.tsx <- empty page, just calls notFound()
-- (browse)
- someFolder1 <- may multiple pages and maybe nested layouts
- layout.tsx
-- (private)
- someFolder3
- layout.tsx
-- layout.tsx
-- not-found.tsx <- should be served for all notFound() errors##### The issue with this solution
When I call the
notFound method from any of the route groups or visit an unmatched route; I receive an error stating: Unsupported Server Component type: Null. What seems pretty strange since both files definitely have a react component as default export.import { notFound } from "next/navigation";
export default function CatchAllUnmatched(): JSX.Element {
notFound();
}### The other solution I have tried
I also tried to append a header to each response via a custom
X-Language-Preference property I am adding inside my middleware file. In doing so I have moved the root layout as direct descendant of the app folder and retrieved the locale as follows:export const getLocale = cache((): Language => {
const preference = headers().get("X-Language-Preference");
return (preference ?? fallbackLanguage) as Language;
});##### The issue with this solution
The problem in this approach is that the
lang property on the main html tag does not reset on client side navigation from /de to /fr for example. Also the 404 page is only displayed when an unmatched route is visited, calling the notFound method still results in the same error. So this solution is not viable as well.1 Reply
Sun bearOP
If anyone has this problem for a similarly advanced use case I now finally have the solution. Using the 2nd approach is the correct way to address this issue.
Move the root layout out of the
Implement inside your middleware
Add a
Why does this approach suddenly work?
After updating to version v13.4.12 containing [this PR](https://github.com/vercel/next.js/pull/52985) the 2nd solution suddenly started working, may been related to a bug or unwanted behavior.
Move the root layout out of the
[locale] folder and define a global not-found.tsx file containing all of your UI. Inside your layout you can then call the following function to retrieve the locale:export const getLocale = cache((): Language => {
const preference = headers().get("X-Language-Preference");
return (preference ?? fallbackLanguage) as Language;
});Implement inside your middleware
Add a
X-Language-Preference header (or however you want to call it) to each response passing through your middleware, here you can define your own resolution strategy to retrieve the locale that shall be saved.const headerName = "X-Language-Preference";
function getRequestLocale(request: NextRequest) {
// ...
}
export default async function middleware(request: NextRequest) {
const locale = getRequestLocale(request);
const response = NextResponse.next();
response.headers.set(headerName, locale);
return response;
}Why does this approach suddenly work?
After updating to version v13.4.12 containing [this PR](https://github.com/vercel/next.js/pull/52985) the 2nd solution suddenly started working, may been related to a bug or unwanted behavior.