为什么要使用 next-i18n-router?

🧑‍💻
推荐全栈学习资源:
  • Next.js 中文文档:样式和官网一样的中文文档,创造沉浸式Next.js中文学习体验。
  • 《Chrome插件全栈开发》:真实出海项目的实战教学课,讲解Chrome插件和Next.js端的全栈开发,帮助你半个月内成为全栈出海工程师。
  • Next-i18n-router 是一个可选项,但在 Next.js 14+ 的 App Router 项目中,我建议使用它,因为它提供了一些重要的优势。

    让我解释一下使用 next-i18n-router 的好处:

    1. 更简单的路由处理
    • 无需编写复杂的中间件
    • 自动处理语言切换重定向
    • 更好的 SEO 支持
    1. 更好的类型支持
    • 提供完整的 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>
      );
    }

    主要优势:

    1. 自动路由处理
    // next-i18n-router 会自动处理这些场景:
    // /  -> /en
    // /about -> /en/about
    // /zh/about -> 保持不变
    1. 类型安全
    // 类型错误会被及时捕获
    const invalidLang: Lang = 'fr'; // TypeScript 错误:'fr' 不是有效的语言代码
    1. 更简洁的实现
    • 不需要手动处理 cookie
    • 不需要复杂的重定向逻辑
    • 更少的样板代码
    1. 更好的维护性
    • 集中的路由配置
    • 清晰的类型定义
    • 更少的潜在错误

    不过,也有一些注意事项:

    1. 性能考虑
    // 在 layout.tsx 中预生成路由
    export async function generateStaticParams() {
      return languages.map((lng) => ({ lng }));
    }
    1. API 路由处理
    // middleware.ts
    export const config = {
      // 排除 API 路由和静态文件
      matcher: '/((?!api|static|.*\\..*|_next).*)'
    };

    所以,我的建议是:如果你的项目是新的 Next.js App Router 项目,使用 next-i18n-router 是一个很好的选择,因为它能:

    1. 简化路由逻辑
    2. 提供更好的类型安全
    3. 减少样板代码
    4. 提供更好的维护性

    你觉得这个建议如何?或者你对具体实现还有什么疑问吗?

    关于我

    🧑‍💻独立开发|⛵️出海|Next.js手艺人

    🖥️做过开源:http://github.com/weijunext
    ⌨️写过博客:https://weijunext.com
    🛠️今年想做独立产品和课程
    📘Nextjs中文文档:http://nextjscn.org
    📙全栈开发教程:https://ship.weijunext.com

    欢迎在以下平台关注我: