Next.js's App Router mode simplifies the configuration of pages and routes through a file system routing mechanism, enabling flexible routing management using specific file and folder naming conventions. This article will introduce the core conventional routing rules of the App Router and provide practical solutions for handling 404 pages in an internationalization scenario.

Conventional Routing Rules of App Router

Next.js App Router defines routes and page behaviors through the following file conventions:

  • page.tsx: The core entry file for a route, responsible for rendering the page content of a specific route. It is located in a subfolder under the app directory, and the folder path is directly mapped to the URL. For example, app/about/page.tsx corresponds to the /about route. Pages default to using server components and can be converted to client components via "use client".
  • layout.tsx: Defines the layout component for a route segment, wrapping the content of the current route and its child routes. The root layout app/layout.tsx is essential and applies to all pages; nested layouts only affect the corresponding route segments.
  • loading.tsx: Provides a loading state interface that is displayed while the page content is being loaded, such as a skeleton screen or loading animation. For example, app/tasks/loading.tsx is used for the loading feedback of the /tasks route.
  • error.tsx: Handles uncaught errors within a route segment and renders a custom error page. For example, app/tasks/error.tsx catches errors for the /tasks route.
  • not-found.tsx: Customizes the 404 page, which is rendered when an unexisting route is accessed. For example, app/not-found.tsx replaces the default 404 page.

Internationalization 404 Situation

In an internationalization (i18n) scenario, the current language is usually obtained through the dynamic route app/[lang] and corresponding resources are loaded. However, directly defining the 404 page in app/[lang]/not-found.tsx does not take effect, and when accessing an unmatched route, it will still jump to the default app/not-found.tsx.

Root Cause of the Problem

Next.js's not-found.tsx convention only takes effect at the root directory or specific route segments. Under the dynamic route [lang], not-found.tsx cannot capture all unmatched child routes, resulting in special handling required for internationalization 404 page configuration.

Solving the Internationalization 404 Page Problem

The following are the steps to implement multilingual 404 pages through the file system and componentization:

  1. Capture Unmatched Routes
    Create a file in app/[lang]/[...not_found]/page.tsx and use the notFound function to trigger a 404 status:

    // app/[lang]/[...not_found]/page.tsx
    import { notFound } from "next/navigation";
    export default function NotFoundCatchAll() {
    notFound();
    }
  2. Create a Multilingual 404 Component
    Since the notFound function does not accept parameters and cannot directly pass language information, a custom component (such as components/notFound.tsx) needs to be created to handle internationalized copywriting:

    // components/notFound.tsx
    import { useTranslation } from "@/i18n";
    export default async function NotFound({ lang }: { lang: string }) {
    const { t } = await useTranslation(lang, "not-found");
    return (
    <div>
    <h1>{t("title")}</h1>
    <p>{t("description")}</p>
    </div>
    );
    }
  3. Integrate the Custom Component
    Modify app/[lang]/[...not_found]/page.tsx to introduce the multilingual 404 component and pass the language parameter:

    // app/[lang]/[...not_found]/page.tsx
    import NotFound from "@/components/notFound";
    export default function NotFoundCatchAll({ params: { lang } }: { params: { lang: string } }) {
    return <NotFound lang={lang} />;
    }

Summary

Through the above steps, Next.js App Router can efficiently handle 404 page problems in an internationalization scenario. By using [...not_found]/page.tsx to capture unmatched routes and combining custom multilingual components, dynamic language support and a consistent user experience are achieved. This method is applicable to multilingual Next.js projects, meeting complex routing requirements while keeping the code concise.