言語切替機能の構築

ユーザーがどのページでも言語を切り替えられるようにする

問題

ユーザーが特定のページ(例:/en/products/123)にいて、同じページを別の言語で表示したいとします。言語切り替えリンク(例:「Français」)をクリックすると、対応する製品ページではなく、ホームページ(/fr/)に戻されることが多く、ワークフローが中断され、再度ナビゲーションを強いられます。

解決策

現在のURL パスネームを読み取るクライアントコンポーネントを作成します。パス内の現在の言語セグメントを置き換えることで、他のサポートされているすべての言語へのリンクリストを生成します。また、クリック時に設定クッキーを設定し、将来の訪問でも選択が記憶されるようにします。

ステップ

1. 言語設定を定義する

i18n.config.tsファイルにロケールのリストと使用するクッキーの名前が含まれていることを確認します。

// i18n.config.ts

export const locales = ['en', 'es', 'fr'];
export const defaultLocale = 'en';
export const localeCookieName = 'NEXT_LOCALE';

2. 言語切り替えコンポーネントを作成する

例えば、app/components/LanguageSwitcher.tsxという新しいファイルを作成します。これはusePathnameのようなフックを使用するためのクライアントコンポーネントである必要があります。

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

import { usePathname } from 'next/navigation';
import Link from 'next/link';
import { locales, localeCookieName } from '@/i18n.config';

export default function LanguageSwitcher() {
  const pathname = usePathname();

  // この関数はクッキーを設定します
  const setLocaleCookie = (locale: string) => {
    document.cookie = `${localeCookieName}=${locale}; path=/; max-age=31536000; samesite=lax`;
  };

  // この関数はパスから現在のロケールを削除します
  const getRedirectedPath = (locale: string) => {
    if (!pathname) return '/';
    const segments = pathname.split('/');
    segments[1] = locale; // ロケールは常に最初のセグメントです
    return segments.join('/');
  };

  return (
    <div>
      {locales.map((locale) => (
        <Link
          key={locale}
          href={getRedirectedPath(locale)}
          onClick={() => setLocaleCookie(locale)}
          style={{
            display: 'inline-block',
            padding: '0.5rem',
            textDecoration: 'underline',
          }}
        >
          {locale.toUpperCase()}
        </Link>
      ))}
    </div>
  );
}

3. 言語切替機能をレイアウトに追加する

新しく作成したコンポーネントをルートレイアウトファイル app/[lang]/layout.tsx にインポートして配置します。これによりすべてのページで表示されるようになります。

// app/[lang]/layout.tsx
import LanguageSwitcher from '@/app/components/LanguageSwitcher';

export async function generateStaticParams() {
  // これによりNext.jsは'en'、'es'、'fr'を事前レンダリングします
  return [{ lang: 'en' }, { lang: 'es' }, { lang: 'fr' }];
}

export default function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  return (
    <html lang={params.lang}>
      <body>
        <header>
          {/* 言語切替機能をヘッダーまたはナビゲーションに追加 */}
          <LanguageSwitcher />
        </header>
        <main>{children}</main>
      </body>
    </html>
  );
}

これで、ユーザーが /es/products/123 にいるときに「EN」をクリックすると、コンポーネントは新しいパスを /en/products/123 として計算し、NEXT_LOCALE クッキーを 'en' に設定します。