i18n for not-found page #50518
-
Beta Was this translation helpful? Give feedback.
Replies: 12 comments 28 replies
-
It is natural that your root Note that you need to call
Example code:
Then your "Localized Not Found" page could be used.
|
Beta Was this translation helpful? Give feedback.
-
Hi! This solution works to render the not-found located in the catch-all segment. However, how do we get the params in the NotFound function? In the docs it says it doesn't accept any props so I can't get the locale in the NotFound function, how I'm I supposed to localize the text? Any help would be appreciated. |
Beta Was this translation helpful? Give feedback.
-
Hey everyone I'm trying to open a feature request for this issue and work on it, and just to confirm, how are you guys currently translating the not-found page? |
Beta Was this translation helpful? Give feedback.
-
What worked for me was to create a 'Catch all route' inside '[locale]' and simply return 'notFound' This way if the route does not match any other route inside '[locale]' It will match this 'Catch all route' and return 'notFound' |
Beta Was this translation helpful? Give feedback.
-
I solved this by making a redirect in the app/not-found.tsx ( And have a not-found page.tsx localized: app/not-found/page.tsx Be sure to process paths that don't return a valid locale at level 1 to redirect to your default locale. |
Beta Was this translation helpful? Give feedback.
-
I found a solution that worked for me on https://next-intl-docs.vercel.app/docs/environments/error-files , I'm not using the same i18n library but the solution provided is global. |
Beta Was this translation helpful? Give feedback.
-
Any progress on this? Seems like a reasonable thing to expect. To get the locale as a prop to NotFound route. |
Beta Was this translation helpful? Give feedback.
-
Tossing my hat into the ring. Regardless of the means to redirect to it, if what we return is the |
Beta Was this translation helpful? Give feedback.
-
Came up with a somewhat elegant fix for my use case. For some context, I'm exporting the site as static assets currently. What I did was create a new page next to the catch-all segment called This page is created as a static asset and can be localized for every locale at build as a server component. I then created a top-level Downside to this approach is of course you will no longer see the original URL since it redirects. Upside is you get server components for your not found page and inheritance from the layout. Top-level export default function NotFound() {
const pathName = usePathname();
const locale = pathName.split('/')[1];
const finalLocale = locales.includes(locale) ? locale : DEF_LOCALE;
return redirect(`/${finalLocale}/not-found`, RedirectType.replace);
} Also, for this site every page will have a locale. That's why I make the assumption I can extract it from the pathname. |
Beta Was this translation helpful? Give feedback.
-
I read through the whole thread without seeing mention of a possible hack which pieces together the other solutions while having a localized custom error page and returning a 404 status code: the idea is still to have a catch-all route inside the from there you can detect the locale however you prefer (I'm doing it with obviously this looks and feels like a hack, a proper solution with the possibility to set a custom error code would be greatly welcome |
Beta Was this translation helpful? Give feedback.
-
Beta Was this translation helpful? Give feedback.
-
For anyone looking for a solution for this on First off, on the middleware i added the current path to the headers in order to use it later to get the locale // middleware.ts
...
const headers = new Headers(request.headers)
headers.set('x-current-path', request.nextUrl.pathname)
... After setting the headers i created a function called // utils/getLocaleFromPathname.tsx
import { headers } from 'next/headers'
import { DictionaryLanguages } from '@/dictionaries/dictionaries' // This is just the type of the locales - 'en' | 'gr'
export const locales: string[] = ['en', 'gr'] as const
export const defaultLocale: (typeof locales)[number] = 'en'
export const getLocaleFromPathname = async (): Promise<DictionaryLanguages> => {
const headerList = await headers()
const pathname = headerList.get('x-current-path') ?? ''
const locale =
locales.find(
(locale) =>
pathname.startsWith(`/${locale}/`) || pathname === `/${locale}`
) ?? defaultLocale
return locale as DictionaryLanguages
} I move both Now on both of them you can just run the // layout.tsx
import { getLocaleFromPathname } from '@/utils/getLocaleFromPathname'
export default async function RootLayout({
children,
}: Readonly<{
children: React.ReactNode
}>) {
const locale = await getLocaleFromPathname()
return (
<html lang={locale}>
<body>
{children}
</body>
</html>
)
} // not-found.tsx
import { getDictionary } from '@/dictionaries'
import { getLocaleFromPathname } from '@/utils/getLocaleFromPathname'
export default async function NotFound() {
const locale = await getLocaleFromPathname()
const dict = await getDictionary(locale)
return (
<div>
<h1>{dict['not-found'].title}</h1>
</div>
)
} Hope this helps. Happy Coding ! |
Beta Was this translation helpful? Give feedback.
When you set your
[locale]
folder, it means that the route catches only/something
.If you want to set the route as
/en_GB/some/dir/that/does/not/exist
,you need to change your
locale
folder name as Catch-all Segments, which is[...locale]
.Since the
notFound()
function renders within a route segment, your/en_GB/some/dir/that/does/not/exist
is technically out of range of your[locale]
folder, which is why the rootnot-found.tsx
is being rendered.In conclusion, change your
[locale]
folder name to[...locale]
.UPDATE
@simpel @nikkizol Apologies for providing an inefficient answer.
I have to update the answer since setting the locale to catch all segments is not the best practice & experie…