Маршрутизация на основе языка

Настройка маршрутизации на основе языка в Next.js (App Router)

Проблема

Один и тот же URL, например /about, становится неоднозначным, если приложение поддерживает несколько языков. Пользователь, заходя по этому адресу, видит контент на языке по умолчанию, но не может получить ссылку или добавить в закладки версию этой страницы на другом языке. Такая неоднозначность сбивает с толку поисковые системы: они могут не индексировать все языковые версии или смешивать их.

Решение

Добавьте идентификатор языка прямо в путь URL, например /en/about или /fr/about. Это делает каждый путь уникальным для определённого языка, устраняя неоднозначность как для пользователей, так и для поисковых систем.

Шаги

1. Создайте динамический сегмент для языка

В Next.js App Router маршрутизация по языкам реализуется через создание динамической папки-сегмента в корне вашего каталога app. Создайте новую папку с именем [lang] внутри app и переместите туда ваш основной файл page.tsx.

// app/[lang]/page.tsx

export default function Home({ params }: { params: { lang: string } }) {
  return (
    <div>
      <h1>Home page</h1>
      <p>Current language: {params.lang}</p>
    </div>
  );
}

Папка [lang] захватывает первую часть URL (например, 'en' или 'fr') и передаёт её как свойство lang внутри объекта params вашему компоненту страницы. Теперь вы можете открывать страницу по адресам вроде /en или /fr.

2. Обновите корневой layout

Ваш корневой layout.tsx тоже нужно переместить в папку app/[lang]. Он также получит параметр lang, который стоит использовать для установки атрибута lang на тег <html> для доступности и SEO.

// app/[lang]/layout.tsx

export default function RootLayout({
  children,
  params,
}: {
  children: React.ReactNode;
  params: { lang: string };
}) {
  return (
    <html lang={params.lang}>
      <body>{children}</body>
    </html>
  );
}

Теперь этот макет оборачивает все страницы внутри определённого языка. Указание атрибута lang здесь сообщает браузерам, на каком языке представлен контент страницы.

3. Укажите поддерживаемые языки

Чтобы сообщить Next.js, какие языковые сегменты допустимы, вы можете экспортировать функцию generateStaticParams из корневого макета. Это позволит Next.js статически генерировать эти маршруты во время сборки.

// app/[lang]/layout.tsx

export async function generateStaticParams() {
  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>{children}</body>
    </html>
  );
}

Эта функция сообщает Next.js, что ваше приложение поддерживает /en, /es и /fr. Запросы к другим путям (например, /de) приведут к странице 404 Not Found.

4. Добавьте вложенные маршруты

Все остальные страницы вашего приложения теперь создаются внутри папки [lang]. Например, чтобы создать страницу 'about', добавьте app/[lang]/about/page.tsx.

// app/[lang]/about/page.tsx

export default function AboutPage({ params }: { params: { lang: string } }) {
  return (
    <div>
      <h1>About page</h1>
      <p>Current language: {params.lang}</p>
    </div>
  );
}

Этот файл автоматически создаёт маршруты, доступные по адресам /en/about, /es/about и /fr/about. Параметр lang доступен на всех страницах, если он нужен для получения правильного переведённого контента.