为什么要使用 next-i18n-router?
🧑💻
推荐全栈学习资源:
Next-i18n-router 是一个可选项,但在 Next.js 14+ 的 App Router 项目中,我建议使用它,因为它提供了一些重要的优势。
让我解释一下使用 next-i18n-router 的好处:
- 更简单的路由处理
- 无需编写复杂的中间件
- 自动处理语言切换重定向
- 更好的 SEO 支持
- 更好的类型支持
- 提供完整的 TypeScript 支持
- 路由参数类型安全
让我展示如何整合 next-i18n-router:
// middleware.ts
import { I18nMiddleware } from 'next-i18n-router';
import { languages } from '@/i18n/settings';
const middleware = I18nMiddleware({
defaultLocale: 'en',
locales: languages,
urlMappingStrategy: 'prefix'
});
export default middleware;
export const config = {
matcher: '/((?!api|static|.*\\..*|_next).*)'
};
// src/i18n/settings.ts
export const fallbackLng = 'en';
export const languages = ['en', 'zh', 'es'] as const; // 使用 const 断言
export type Lang = (typeof languages)[number]; // TypeScript 类型
export const defaultNS = 'common';
export const namespaces = ['common', 'home', 'product', 'cart', 'user'] as const;
// src/components/LanguageSwitcher.tsx
'use client';
import { useRouter, useParams } from 'next/navigation';
import { useTranslation } from 'react-i18next';
import { languages, type Lang } from '@/i18n/settings';
export default function LanguageSwitcher() {
const router = useRouter();
const params = useParams();
const { i18n } = useTranslation();
const currentLang = params.lng as Lang;
const handleLanguageChange = (lng: Lang) => {
// next-i18n-router 会自动处理路由更新
const currentPath = window.location.pathname;
const newPath = currentPath.replace(`/${currentLang}`, `/${lng}`);
router.push(newPath);
};
return (
<div>
{languages.map((lng) => (
<button
key={lng}
onClick={() => handleLanguageChange(lng)}
className={currentLang === lng ? 'active' : ''}
>
{lng.toUpperCase()}
</button>
))}
</div>
);
}
// app/[lng]/layout.tsx
import { dir } from 'i18next';
import { languages } from '@/i18n/settings';
export async function generateStaticParams() {
return languages.map((lng) => ({ lng }));
}
export async function generateMetadata({ params: { lng } }) {
return {
title: `My App - ${lng.toUpperCase()}`,
// 其他元数据...
};
}
export default function RootLayout({
children,
params: { lng }
}: {
children: React.ReactNode;
params: { lng: string };
}) {
return (
<html lang={lng} dir={dir(lng)}>
<body>{children}</body>
</html>
);
}
主要优势:
- 自动路由处理
// next-i18n-router 会自动处理这些场景:
// / -> /en
// /about -> /en/about
// /zh/about -> 保持不变
- 类型安全
// 类型错误会被及时捕获
const invalidLang: Lang = 'fr'; // TypeScript 错误:'fr' 不是有效的语言代码
- 更简洁的实现
- 不需要手动处理 cookie
- 不需要复杂的重定向逻辑
- 更少的样板代码
- 更好的维护性
- 集中的路由配置
- 清晰的类型定义
- 更少的潜在错误
不过,也有一些注意事项:
- 性能考虑
// 在 layout.tsx 中预生成路由
export async function generateStaticParams() {
return languages.map((lng) => ({ lng }));
}
- API 路由处理
// middleware.ts
export const config = {
// 排除 API 路由和静态文件
matcher: '/((?!api|static|.*\\..*|_next).*)'
};
所以,我的建议是:如果你的项目是新的 Next.js App Router 项目,使用 next-i18n-router 是一个很好的选择,因为它能:
- 简化路由逻辑
- 提供更好的类型安全
- 减少样板代码
- 提供更好的维护性
你觉得这个建议如何?或者你对具体实现还有什么疑问吗?
关于我
🧑💻独立开发|⛵️出海|Next.js手艺人
🖥️做过开源:http://github.com/weijunext
⌨️写过博客:https://weijunext.com
🛠️今年想做独立产品和课程
📘Nextjs中文文档:http://nextjscn.org
📙全栈开发教程:https://ship.weijunext.com
欢迎在以下平台关注我:
- Twitter: @weijunext
- Github: Github
- Blog: J实验室
- 即刻: BigYe程普
- 微信交流群: 全栈交流群