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:
Capture Unmatched Routes
Create a file inapp/[lang]/[...not_found]/page.tsx
and use thenotFound
function to trigger a 404 status:// app/[lang]/[...not_found]/page.tsximport { notFound } from "next/navigation";export default function NotFoundCatchAll() {notFound();}Create a Multilingual 404 Component
Since thenotFound
function does not accept parameters and cannot directly pass language information, a custom component (such ascomponents/notFound.tsx
) needs to be created to handle internationalized copywriting:// components/notFound.tsximport { 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>);}Integrate the Custom Component
Modifyapp/[lang]/[...not_found]/page.tsx
to introduce the multilingual 404 component and pass the language parameter:// app/[lang]/[...not_found]/page.tsximport 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.