mcpField
N
next-intl-app-router

next-intl-app-router

github.com/liuchiawei开发2603 次安装37 周前更新
代码仓库

关于 next-intl-app-router

next-intl-app-router 是面向 Next.js App Router 项目的 next-intl 配置与使用指南,采用前缀式语言路由。内容涵盖配置、语言感知导航、静态渲染和翻译加载,并提供可复制的示例。

主要功能

  1. 01前缀式语言路由
  2. 02插件与请求配置
  3. 03语言感知导航辅助项
  4. 04静态渲染设置
  5. 05客户端与服务端翻译 API
  6. 06按语言划分的 JSON 消息文件

适用场景

  1. 01为 Next.js 应用添加带语言前缀的 URL
  2. 02在 App Router 中配置 next-intl
  3. 03构建语言感知链接与重定向
  4. 04在客户端和服务端组件中加载翻译

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/liuchiawei/agent-skills --skill next-intl-app-router

安装后在 Claude Code 中输入/next-intl-app-router确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

reference.md
examples/
app-locale-about-page.tsx
app-locale-layout.tsx
app-locale-page.tsx
BackToHomeButton.tsx
messages-en.json
Nav-client.tsx
next.config.ts
proxy.ts
README.md
examples/i18n/
navigation.ts
request.ts
routing.ts

详细介绍

next-intl(App Router)

介绍如何在 Next.js App Router 项目中使用 next-intl 实现基于前缀的区域设置路由(例如 /en/about、/ja/about)。适用于任何 Next.js App Router 项目。

示例代码: 可直接复制粘贴的示例位于此技能的 examples/ 文件夹中。请参阅 examples/README.md,了解每个文件在项目中的存放位置。

文件布局

保持此结构:

├── messages/
│   ├── en.json
│   ├── ja.json
│   └── ...
├── next.config.ts
└── src/
    ├── i18n/
    │   ├── request.ts
    │   ├── routing.ts
    │   └── navigation.ts
    ├── proxy.ts          # Next.js 16+ (was middleware.ts)
    └── app/
        ├── layout.tsx    # Root layout, no NextIntlClientProvider here
        └── [locale]/
            ├── layout.tsx
            ├── page.tsx
            └── ...

根布局不会使用 NextIntlClientProvider 包裹内容;只有 app/[locale]/layout.tsx 会这样做。


1. Next 配置

接入插件(默认路径为 ./i18n/request.ts):

// next.config.ts
import type { NextConfig } from "next";
import createNextIntlPlugin from "next-intl/plugin";

const nextConfig: NextConfig = {
  /* ... */
};
const withNextIntl = createNextIntlPlugin();
export default withNextIntl(nextConfig);

自定义路径:createNextIntlPlugin('./src/i18n/request.ts')。


2. 路由配置

在 src/i18n/routing.ts 中集中配置:

import { defineRouting } from "next-intl/routing";

export const routing = defineRouting({
  locales: ["en", "ja", "zh-CN", "zh-TW"],
  defaultLocale: "en",
});

3. 请求配置

src/i18n/request.ts:从 [locale] 路径段解析区域设置并加载消息。

import { getRequestConfig } from "next-intl/server";
import { hasLocale } from "next-intl";
import { routing } from "./routing";

export default getRequestConfig(async ({ requestLocale }) => {
  const requested = await requestLocale;
  const locale = hasLocale(routing.locales, requested)
    ? requested
    : routing.defaultLocale;

  return {
    locale,
    messages: (await import(`../../messages/${locale}.json`)).default,
  };
});

4. Proxy / 中间件(Next.js 16)

Next.js 16 使用 proxy.ts,而不是 middleware.ts。API 相同:

// src/proxy.ts
import createMiddleware from "next-intl/middleware";
import { routing } from "./i18n/routing";

export const proxy = createMiddleware(routing);

export const config = {
  matcher: "/((?!api|trpc|_next|_vercel|.*\\..*).*)",
};

匹配器:匹配所有路径名,但排除 /api、/trpc、/_next、/_vercel 以及包含句点的路径(例如 favicon.ico)。


5. 导航辅助工具

使用项目的导航封装,让链接保留当前区域设置:

// src/i18n/navigation.ts
import { createNavigation } from "next-intl/navigation";
import { routing } from "./routing";

export const { Link, redirect, usePathname, useRouter, getPathname } =
  createNavigation(routing);

在组件中:请从 @/i18n/navigation 导入 Link(及其他辅助工具),以生成适配区域设置的 URL;不要从 next/navigation 或 next/link 导入。示例:examples/Nav-client.tsx、examples/BackToHomeButton.tsx。


6. 区域设置布局与静态渲染

app/[locale]/layout.tsx 必须(完整文件:examples/app-locale-layout.tsx):

  1. 使用 hasLocale 验证 locale → 如果无效,则调用 notFound()。
  2. 调用 setRequestLocale(locale) 以进行静态渲染。
  3. 使用 NextIntlClientProvider 和 getMessages() 包裹子内容。
// app/[locale]/layout.tsx
import { NextIntlClientProvider, hasLocale } from "next-intl";
import { setRequestLocale } from "next-intl/server";
import { notFound } from "next/navigation";
import { routing } from "@/i18n/routing";
import { getMessages } from "next-intl/server";

type Props = {
  children: React.ReactNode;
  params: Promise<{ locale: string }>;
};

export function generateStaticParams() {
  return routing.locales.map((locale) => ({ locale }));
}

export default async function LocaleLayout({ children, params }: Props) {
  const { locale } = await params;
  if (!hasLocale(routing.locales, locale)) notFound();

  setRequestLocale(locale);
  const messages = await getMessages();

  return (
    <NextIntlClientProvider messages={messages}>
      {children}
    </NextIntlClientProvider>
  );
}

7. [locale] 下的页面

要进行静态渲染,[locale] 下每个使用 next-intl 的页面都必须调用 setRequestLocale(locale)(并在需要时使用 use(params))。示例:app-locale-page.tsx、app-locale-about-page.tsx。(并在需要时使用 use(params)。)布局已设置该值;使用区域设置渲染服务器组件的页面也应设置该值。

// app/[locale]/page.tsx
import { use } from "react";
import { setRequestLocale } from "next-intl/server";

export default function IndexPage({
  params,
}: {
  params: Promise<{ locale: string }>;
}) {
  const { locale } = use(params);
  setRequestLocale(locale);
  return <TokyoPage />;
}
// app/[locale]/about/page.tsx
import { use } from "react";
import { setRequestLocale } from "next-intl/server";
import AboutContainer from "./components/AboutContainer";

export default function AboutPage({
  params,
}: {
  params: Promise<{ locale: string }>;
}) {
  const { locale } = use(params);
  setRequestLocale(locale);
  return <AboutContainer />;
}

在该布局或页面中调用任何 next-intl API 之前,先调用 setRequestLocale。


8. 使用翻译

客户端组件: useTranslations(namespace):

"use client";
import { useTranslations } from "next-intl";
import { Link } from "@/i18n/navigation";

export default function BackToHomeButton() {
  const t = useTranslations("BackToHomeButton");
  return (
    <Link href="/">
      <span>{t("buttonText")}</span>
    </Link>
  );
}
"use client";
import { useTranslations } from "next-intl";
import { Link } from "@/i18n/navigation";

export default function Nav() {
  const t = useTranslations("Navigation");
  return <Link href="/about">{t("links.about")}</Link>;
}

服务器组件: 使用 next-intl/server 中的 getTranslations(根据需要传入区域设置或命名空间,并使用 await)。


9. 消息格式

在 messages/ 下为每种区域设置创建一个 JSON 文件。嵌套键对应命名空间和键:

{
  "HomePage": {
    "title": "Hello world!"
  },
  "LandingPage": {
    "title": "Tokyo Sounds",
    "navbar": {
      "home": "Home",
      "about": "About"
    }
  },
  "BackToHomeButton": {
    "buttonText": "Back to Home",
    "tooltip": "Return to the main page"
  }
}
  • useTranslations("LandingPage") → t("title")、t("navbar.about")。
  • 插值:"selectColor": "Select {color} color" → t("selectColor", { color: "Blue" })。

检查清单

  • next.config.ts:使用 createNextIntlPlugin() 包装配置。
  • src/i18n/routing.ts:使用 defineRouting 配置 locales 和 defaultLocale。
  • src/i18n/request.ts:使用 getRequestConfig + hasLocale + 动态加载 messages/${locale}.json。
  • src/proxy.ts(或 middleware.ts):使用 createMiddleware(routing) 和匹配器。
  • src/i18n/navigation.ts:使用 createNavigation(routing) 并重新导出 Link 等。
  • app/[locale]/layout.tsx:使用 hasLocale → notFound、setRequestLocale、generateStaticParams、NextIntlClientProvider + getMessages()。
  • 每个 app/[locale]/**/page.tsx:使用静态渲染时调用 setRequestLocale(locale)。
  • 客户端组件:使用 useTranslations("Namespace");链接使用从 @/i18n/navigation 导入的 Link。

参考

评论

支持 Markdown