Next.js 的 App Router 模式通过文件系统路由机制简化了页面和路由的配置,利用特定文件和文件夹命名约定实现灵活的路由管理。本文将介绍 App Router 的核心约定式路由规则,并提供在国际化场景下处理 404 页面的实用解决方案。

App Router 的约定式路由规则

Next.js App Router 通过以下文件约定定义路由和页面行为:

  • page.tsx:路由的核心入口文件,负责渲染特定路由的页面内容。位于 app 目录下的子文件夹中,文件夹路径直接映射到 URL。例如,app/about/page.tsx 对应 /about 路由。页面默认使用服务器组件,可通过 "use client" 转为客户端组件。
  • layout.tsx:定义路由段的布局组件,包裹当前路由及其子路由的内容。根布局 app/layout.tsx 为必备,应用于所有页面;嵌套布局仅影响对应路由段。
  • loading.tsx:提供加载状态界面,在页面内容加载时显示,如骨架屏或加载动画。例如,app/tasks/loading.tsx 用于 /tasks 路由的加载反馈。
  • error.tsx:处理路由段内的未捕获错误,渲染自定义错误页面。例如,app/tasks/error.tsx 捕获 /tasks 路由的错误。
  • not-found.tsx:自定义 404 页面,当访问不存在的路由时渲染。例如,app/not-found.tsx 替代默认 404 页面。

国际化 404 情况

在国际化(i18n)场景中,通常通过动态路由 app/[lang] 获取当前语言并加载相应资源。然而,直接在 app/[lang]/not-found.tsx 中定义 404 页面无法生效,访问未匹配路由时仍会跳转到默认的 app/not-found.tsx

问题根源

Next.js 的 not-found.tsx 约定仅在根目录或特定路由段生效。在动态路由 [lang] 下,not-found.tsx 无法捕获所有未匹配的子路由,导致国际化 404 页面配置需特殊处理。

解决国际化 404 页面问题

以下是通过文件系统和组件化方式实现多语言 404 页面的步骤:

  1. 捕获未匹配路由
    app/[lang]/[...not_found]/page.tsx 中创建文件,利用 notFound 函数触发 404 状态:

    // app/[lang]/[...not_found]/page.tsx
    import { notFound } from "next/navigation";
    export default function NotFoundCatchAll() {
    notFound();
    }
  2. 创建多语言 404 组件
    由于 notFound 函数不接受参数,无法直接传递语言信息。需创建自定义组件(如 components/notFound.tsx)处理国际化文案:

    // 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. 整合自定义组件
    修改 app/[lang]/[...not_found]/page.tsx,引入多语言 404 组件并传递语言参数:

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

总结

通过上述步骤,Next.js App Router 能够高效处理国际化场景下的 404 页面问题。利用 [...not_found]/page.tsx 捕获未匹配路由,并结合自定义多语言组件,实现动态语言支持和一致的用户体验。这种方法适用于多语言 Next.js 项目,保持代码简洁的同时满足复杂路由需求。