本地化页面之间的链接处理

确保用户停留在所选语言环境中

问题

当语言代码作为 URL 的一部分时,创建内部链接会变得复杂。像 <a href="/about"> 这样简单的链接是错误的,因为它会破坏本地化路由,将用户从 /fr/contact 跳转到 /about,而不是 /fr/about。这样会导致用户离开他们选择的语言环境。

解决方案

围绕 Next.js 的 Link 组件创建一个自定义包装组件。这个新组件会使用 useParams hook,从 URL 中获取当前语言,并自动将其添加到收到的每个 href 前面,确保所有内部链接都正确本地化。

步骤

新建一个文件 app/components/LocalizedLink.tsx。该组件必须是客户端组件,以便使用 useParams hook。

// app/components/LocalizedLink.tsx
'use client';

import Link from 'next/link';
import { useParams } from 'next/navigation';
import type { ComponentProps } from 'react';

type LinkProps = ComponentProps<typeof Link>;

export default function LocalizedLink({ href, ...rest }: LinkProps) {
  const params = useParams();
  const lang = params.lang as string;

  let localizedHref = href;

  // Check if href is a string and needs prefixing
  if (typeof href === 'string' && href.startsWith('/')) {
    localizedHref = `/${lang}${href}`;
  } else if (
    typeof href === 'object' &&
    href !== null &&
    href.pathname?.startsWith('/')
  ) {
    // Re-create the object with a prefixed pathname
    localizedHref = {
      ...href,
      pathname: `/${lang}${href.pathname}`,
    };
  }
  // Absolute URLs or other cases are passed through

  return <Link href={localizedHref} {...rest} />;
}

该组件会导入标准的 Link props。它会判断 href 是字符串(如 /about)还是对象(如 { pathname: '/about' }),并智能地将当前 lang(例如 es)添加到前面。

2. 在页面中使用该组件

现在,在你的页面中,导入 LocalizedLink,而不是标准的 next/link。你可以像使用普通 Link 组件一样使用它,无需担心语言前缀。

// app/[lang]/page.tsx
import LocalizedLink from '@/app/components/LocalizedLink';

export default function Home({ params }: { params: { lang: string } }) {
  return (
    <div>
      <h1>Home page</h1>
      <p>Current language: {params.lang}</p>
      
      <nav>
        <ul>
          <li>
            {/* This will render as /en/about or /es/about, etc. */}
            <LocalizedLink href="/about">About page</LocalizedLink>
          </li>
          <li>
            {/* This also works */}
            <LocalizedLink href={{ pathname: '/contact' }}>
              Contact page
            </LocalizedLink>
          </li>
        </ul>
      </nav>
    </div>
  );
}

现在使用 <LocalizedLink href="/about"> 可以正确渲染到 /{current_lang}/about 的链接,确保用户在站点内导航时始终保持在所选语言环境中。