Next.js国际化开发秘籍:打造多语言网站
Next.js 作为一个流行的 React 框架,为构建多语言支持的应用程序提供了强大的支持。本指南将引导你完成在 Next.js 项目中实现国际化(i18n)的步骤。我们将涵盖路由设置、本地化处理和翻译内容管理。
理解国际化术语
区域设置(Locale)
区域设置是一组语言和格式化偏好的标识符。它包括用户的首选语言,也可能指示他们的地理区域。例如:
- ‘en-US’:美国使用的英语
- ‘nl-NL’:荷兰使用的荷兰语
- ‘en’:没有特定区域的英语
设置 Next.js 国际化
创建新的 Next.js 应用
如果你还没有,使用以下命令创建一个新的 Next.js 项目:
npm install @formatjs/intl-localematcher negotiator
实现基于区域设置的路由
Next.js 允许你通过子路径(/fr/products)
或域名(my-site.fr/products)
来国际化路由。这些信息使你能够在中间件中根据用户的首选区域设置重定向用户。
在src/
目录下创建middleware.ts
文件:
// middleware.ts import { match } from '@formatjs/intl-localematcher' import Negotiator from 'negotiator' import { NextRequest, NextResponse } from 'next/server' let defaultLocale = 'en' let locales = ['cn', 'de', 'en'] // 获取首选区域设置,类似上面或使用库 function getLocale(request: NextRequest) { const acceptedLanguage = request.headers.get('accept-language') ?? undefined let headers = { 'accept-language': acceptedLanguage } let languages = new Negotiator({ headers }).languages() return match(languages, locales, defaultLocale) // -> 'en-US' } export function middleware(request: NextRequest) { // 检查路径中是否有任何支持的区域设置 const pathname = request.nextUrl.pathname const pathnameIsMissingLocale = locales.every( (locale) => !pathname.startsWith(`/${locale}/`) && pathname !== `/${locale}` ) // 如果没有区域设置则重定向 if (pathnameIsMissingLocale) { const locale = getLocale(request) // 例如,传入的请求是/products // 新的 URL 现在是/en-US/products return NextResponse.redirect(new URL(`/${locale}/${pathname}`, request.url)) } } export const config = { matcher: [ // 跳过所有内部路径 (_next, assets, api) '/((?!api|assets|.*\\..*|_next).*)', // 可选:只在根 (/) URL 上运行 // '/' ], }
组织文件以进行基于区域设置的处理
为了使 Next.js 能够在路由中动态管理不同的区域设置,将所有特殊文件嵌套在app/[lang]
中。
例如:
// app/[lang]/page.tsx export default async function Page({ params: { lang } }) { return ... }
实现本地化
本地化涉及根据用户的首选区域设置调整显示的内容。这可以通过为每种支持的语言维护单独的字典来实现。
创建字典
例如,我们考虑 Next.js 主页的英语、荷兰语和中文翻译。
app/[lang]/dictionaries
dictionaries/en.json
:
{ "get_started": "Get started by editing", "doc": "Find in-depth information about Next.js features and API.", "learn": "Learn about Next.js in an interactive course with quizzes!", "template": "Explore the Next.js 13 playground.", "deploy": "Instantly deploy your Next.js site to a shareable URL with Vercel." }
dictionaries/de.json:
{ "get_started": "Beginnen Sie, indem Sie bearbeiten", "doc": "Finden Sie ausführliche Informationen zu den Funktionen und der API von Next.js.", "learn": "Erfahren Sie mehr über Next.js in einem interaktiven Kurs mit Quizfragen!", "template": "Erkunden Sie den Next.js 13-Spielplatz.", "deploy": "Bereiten Sie Ihre Next.js-Website sofort für die Bereitstellung auf einer gemeinsam nutzbaren URL mit Vercel vor." }
dictionaries/cn.json:
{ "get_started": "通过编辑开始", "doc": "查找关于 Next.js 功能和 API 的深入信息。", "learn": "通过互动课程学习 Next.js,包括测验!", "template": "探索 Next.js 13 的示范环境。", "deploy": "使用 Vercel 立即部署您的 Next.js 网站到可共享的 URL。" }
加载翻译
创建一个 getDictionary 函数来加载请求的区域设置的翻译。
import 'server-only' export type Locale = keyof typeof dictionaries const dictionaries = { en: () => import('./dictionaries/en.json').then((module) => module.default), de: () => import('./dictionaries/de.json').then((module) => module.default), cn: () => import('./dictionaries/cn.json').then((module) => module.default), } export const getDictionary = async (locale: Locale) => dictionaries[locale]()
在组件中使用翻译
现在你可以在布局或页面中获取字典以显示翻译后的内容。
import SwitchLang from '@/components/SwitchLang/SwitchLang' import Image from 'next/image' import { Locale, getDictionary } from './dictionaries' import styles from './page.module.css' type Props = { params: { lang: Locale } } export default async function Home({ params: { lang } }: Props) { const intl = await getDictionary(lang) return ( <main className={styles.main}> <div className={styles.description}> <p> {intl.get_started} <code className={styles.code}>src/app/page.tsx</code> </p> <SwitchLang /> {/* ... 其余代码 ... */} </div> {/* ... 其余代码 ... */} <div className={styles.grid}> <a href="" className={styles.card} target="_blank" rel="noopener noreferrer" > <h2> Docs <span>-></span> </h2> <p>{intl.doc}</p> </a> {/* ... 其他卡片 ... */} </div> </main> ) }
为多个区域设置进行静态生成
要为一组区域设置生成静态路由,在任何页面或布局中使用 generateStaticParams。这可以全局设置,例如在根布局中:
// app/[lang]/layout.ts export async function generateStaticParams() { return [{ lang: 'en' }, { lang: 'de' }, { lang: 'cn' }] } export default function Root({ children, params }) { return ( <html lang={params.lang}> <body>{children}</body> </html> ) }
结语
在 Next.js 中实现国际化为来自不同语言背景的用户提供了无缝体验。通过调整路由,你可以为全球用户创建更加包容和易于访问的应用程序。
如需完整的源代码,包括所有文件和依赖关系,请访问 GitHub 代码库。请随时探索、fork 或克隆该仓库,以深入了解该项目。
码云笔记 » Next.js国际化开发秘籍:打造多语言网站