ローカライズされたページ間のリンク

ユーザーが選択した言語を維持する

問題

言語コードがURLの一部になっている場合、内部リンクの作成が複雑になります。<a href="/about">のような単純なリンクは、ローカライズされたルートを壊してしまい、ユーザーを/fr/contactから/fr/aboutではなく/aboutに送ってしまいます。これによりユーザーは選択した言語から外れてしまいます。

解決策

Next.jsのLinkコンポーネントをラップするカスタムコンポーネントを作成します。この新しいコンポーネントはuseParamsフックを使用してURLから現在の言語を取得し、受け取ったhrefに自動的に言語コードを先頭に追加することで、すべての内部リンクが正しくローカライズされるようにします。

手順

1. LocalizedLinkコンポーネントを作成する

新しいファイルapp/components/LocalizedLink.tsxを作成します。これはuseParamsフックを使用するためにクライアントコンポーネントである必要があります。

// 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プロパティをインポートします。hrefが文字列(/aboutのような)かオブジェクト({ pathname: '/about' }のような)かをチェックし、現在のlang(例えばes)を先頭に追加します。

2. ページでコンポーネントを使用する

次に、ページ内で標準のnext/linkの代わりにLocalizedLinkをインポートします。通常の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>
            {/* これは /en/about または /es/about などとしてレンダリングされます */}
            <LocalizedLink href="/about">About page</LocalizedLink>
          </li>
          <li>
            {/* これも機能します */}
            <LocalizedLink href={{ pathname: '/contact' }}>
              Contact page
            </LocalizedLink>
          </li>
        </ul>
      </nav>
    </div>
  );
}

<LocalizedLink href="/about">を使用することで、ユーザーがサイト内を移動する際に、選択した言語内に留まるよう/{current_lang}/aboutへのリンクが正しくレンダリングされます。