Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How do you render the not-found page? #36

Closed
HamedBahram opened this issue Nov 21, 2023 · 18 comments
Closed

How do you render the not-found page? #36

HamedBahram opened this issue Nov 21, 2023 · 18 comments

Comments

@HamedBahram
Copy link

I cannot find a way to implement the not-found page with this folder structure in the App router.

@i18nexus
Copy link
Owner

i18nexus commented Nov 22, 2023

This is a duplicate of #32. But I'll elaborate and show a workaround here.

Essentially the issue is that automatic redirects to not-found do not work inside of a dynamic segment like [locale]. So you need to use a catch-all that calls notFound().

Another problem is that inside of your not-found page you will not have access to page params. So you cannot access the locale from page params. You can instead use the locale from the header x-next-i18n-router-locale if you want to localize this not-found page.

These are not issues specific to next-i18n-router. They are quirks in Next.js app router.

You will need:

  • Catch all component: [...not_found]/page.tsx
  • Not found page: not-found.tsx

[...not_found]/page.tsx:

import { notFound } from 'next/navigation';

export default function NotFoundCatchAll() {
  notFound();
}

not-found.tsx:

import { headers } from 'next/headers';

export default async function NotFound() {
  const headersList = headers();
  const locale = headersList.get('x-i18n-router-locale') || 'en';
  
  ...
}

@Zerebokep
Copy link

@i18nexus x-i18n-router-locale always seems to be null, is there any requirement for it? I'm using 5.0.2.

@i18nexus
Copy link
Owner

i18nexus commented Nov 29, 2023

@Zerebokep Sorry, just saw this. The most common reason this occurs is that the middleware is not running. If you are using the /src directory, make sure your middleware.js file is inside of the /src directory. If you're not using /src, please check your config matcher in your middleware. It should look like this:

export const config = {
  matcher: '/((?!api|static|.*\\..*|_next).*)'
};

If neither of these solve your problem, please paste your middleware.js file here as well as your config file.

@Zerebokep
Copy link

Zerebokep commented Nov 30, 2023

@i18nexus No worries.

this is my middleware.ts which is inside the src/app/ folder

export async function middleware(request: NextRequest) {
  return i18nRouter(request, i18nConfig)
}

export const config = {
  matcher: '/((?!api|static|.*\\..*|_next).*)',
}

btw. I'm still using the "old" useEffect method of the TranslationProvider, maybe this has something to do with it?

@i18nexus
Copy link
Owner

@Zerebokep Ah, your problem is that your middleware needs to be outside of the /app folder. It should be directly inside of /src.

Side note, I highly recommend switching to the new version of the i18next example. It's quite easy to change.

@Zerebokep
Copy link

@i18nexus oh my bad, it is actually there, I misdescribed it in my earlier post.

@i18nexus
Copy link
Owner

@Zerebokep Can you put a console log in your middleware function to make sure its being called?

@Zerebokep
Copy link

@i18nexus Yes, middleware is definitely running.

I've also put console.log(headers().get('x-i18n-router-locale')) into other pages (beside not-found), no luck.

@i18nexus
Copy link
Owner

i18nexus commented Dec 1, 2023

@Zerebokep Oh shoot, sorry I wrote the header wrong in my original comment. It should be x-next-i18n-router-locale. Sorry about that. I'll correct it in my original comment.

@Zerebokep
Copy link

Haha, all good, it works for me now, thanks for checking it out :)

@yannjor
Copy link

yannjor commented Oct 21, 2024

Hey @i18nexus ! Your suggested solution works, but it broke my SSG routes. Any ideas why this might be?

Removing

import { headers } from 'next/headers';
const headersList = headers();
const locale = headersList.get('x-next-i18n-router-locale')

Seems to fix it, so the issue might be with the header trick? 🤔

@i18nexus
Copy link
Owner

@yannjor Can you elaborate on what you mean by it breaking your SSG routes? Any error messages?

@yannjor
Copy link

yannjor commented Oct 21, 2024

@i18nexus of course, sorry my original message was not so clear.

This is how I'm trying to render the not-found page. src/app/[locale]/not-found.tsx:

import React from 'react';
import styles from './NotFoundPage.module.css';
import Hero from '@/components/Hero';
import { PrismicRichText } from '@prismicio/react';
import typography from '@/styles/typography.module.css';
import i18nConfig from '@/i18nConfig';
import { fetchSingleStaticPage } from '@/model/staticPage/fetch';
import { headers } from 'next/headers';

export default async function NotFound() {
  const headersList = headers();
  const locale =
    headersList.get('x-next-i18n-router-locale') || i18nConfig.defaultLocale;
  const page = await fetchSingleStaticPage('not-found', locale);

  return (
    <main>
      <Hero doc={page} />
      <article className={styles.notFound}>
        <p className={typography.body2}>
          <PrismicRichText field={page.description} />
        </p>
      </article>
    </main>
  );
}

and src/app/[locale]/[...not-found]/page.tsx:

import { notFound } from 'next/navigation';

export default function NotFoundCatchAll() {
  notFound();
}

When I build the app, everything looks good, no error messages, except that when I look in the built .next directory, none of my statically generated routes have been built. The weird thing is, when I remove the next/headers code, it builds correctly. But then I don't get my localized 404 pages 🫠

@i18nexus
Copy link
Owner

Interesting, we'll look into this. Are you using generateStaticParams for the locales?

@yannjor
Copy link

yannjor commented Oct 22, 2024

Interesting, we'll look into this. Are you using generateStaticParams for the locales?

Yes

@yannjor
Copy link

yannjor commented Oct 25, 2024

@i18nexus It says in the Next.js docs that:

"headers is a Dynamic API whose returned values cannot be known ahead of time. Using it in will opt a route into dynamic rendering."

So perhaps this is the reason.

@i18nexus
Copy link
Owner

Sorry on the delay digging into this. But in the meantime, I think this comment may be the best solution. But again, we will look further into this by next week and report if there's a better solution. This thread is basically a bunch of people with the same problem.

@yannjor
Copy link

yannjor commented Nov 11, 2024

@i18nexus I found this workaround that works: vercel/next.js#43179 (comment)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants