Создание переключателя языка

Позвольте пользователям менять язык на любой странице

Проблема

Пользователь находится на определённой странице, например, /en/products/123, и хочет посмотреть эту же страницу на другом языке. При нажатии на переключатель языка (например, 'Français') его часто отправляет на главную страницу (/fr/) вместо соответствующей страницы продукта, что сбивает с толку и вынуждает заново искать нужную страницу.

Решение

Создайте клиентский компонент, который читает текущий путь URL. Он генерирует список ссылок для всех других поддерживаемых языков, заменяя текущий языковой сегмент в пути. Также при клике устанавливается cookie с выбранным языком, чтобы запомнить выбор для будущих посещений.

Шаги

1. Определите языковую конфигурацию

Убедитесь, что ваш файл i18n.config.ts содержит список локалей и имя cookie, который вы будете использовать.

// 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();

  // This function sets the cookie
  const setLocaleCookie = (locale: string) => {
    document.cookie = `${localeCookieName}=${locale}; path=/; max-age=31536000; samesite=lax`;
  };

  // This function strips the current locale from the path
  const getRedirectedPath = (locale: string) => {
    if (!pathname) return '/';
    const segments = pathname.split('/');
    segments[1] = locale; // The locale is always the first segment
    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. Добавьте переключатель в ваш layout

Импортируйте и разместите новый компонент в корневом layout-файле app/[lang]/layout.tsx. Так он будет виден на всех страницах.

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

export async function generateStaticParams() {
  // This tells Next.js to pre-render 'en', 'es', and '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>
          {/* Add the switcher to your header or nav */}
          <LanguageSwitcher />
        </header>
        <main>{children}</main>
      </body>
    </html>
  );
}

Теперь, когда пользователь находится на /es/products/123 и кликает "EN", компонент вычисляет новый путь как /en/products/123 и устанавливает cookie NEXT_LOCALE со значением 'en'.