Как сохранять локаль в навигационных ссылках в Next.js (Pages Router) v16

Сохраняйте локаль при внутренней навигации

Проблема

Когда веб-приложение указывает язык в пути URL, любая внутренняя ссылка должна сохранять этот языковой контекст на протяжении всей сессии пользователя. Если явно не обрабатывать локаль, ссылки, написанные как обычные пути, могут случайно потерять языковой префикс, из-за чего пользователь теряет выбранный язык при переходах. Это нарушает локализованный опыт и вынуждает пользователя снова и снова выбирать нужный язык.

Решение

Убедитесь, что каждая внутренняя ссылка автоматически включает текущую локаль, считывая её из контекста роутера. В Next.js Pages Router есть встроенная поддержка локалей через систему маршрутизации: активная локаль доступна через хук useRouter. По умолчанию компонент Link сохраняет текущую локаль при клиентских переходах, но важно понимать это поведение и применять его во всём приложении для бесшовной навигации с учётом локали.

Шаги

1. Получите текущую локаль из роутера

Хук useRouter предоставляет locale (текущую активную локаль), locales (все настроенные локали) и defaultLocale (локаль по умолчанию).

import { useRouter } from "next/router";

export default function Navigation() {
  const router = useRouter();
  const currentLocale = router.locale;

  return (
    <nav>
      <p>Current locale: {currentLocale}</p>
    </nav>
  );
}

Этот компонент получает активную локаль из роутера и делает её доступной для навигационной логики.

Если не передавать проп локали в Link, при клиентских переходах будет использоваться текущая активная локаль.

import Link from "next/link";

export default function Navigation() {
  return (
    <nav>
      <Link href="/about">About</Link>
      <Link href="/products">Products</Link>
      <Link href="/contact">Contact</Link>
    </nav>
  );
}

Эти ссылки автоматически сохраняют текущую локаль. Если пользователь просматривает /fr/products, при клике на «О нас» произойдёт переход на /fr/about.

3. Создайте помощник для ссылок с учётом локали для явного контроля

В случаях, когда нужен явный контроль или хочется сделать работу с локалью более прозрачной, создайте обёртку-компонент, который явно передаёт текущую локаль.

import Link from "next/link";
import { useRouter } from "next/router";
import { ReactNode } from "react";

interface LocaleLinkProps {
  href: string;
  children: ReactNode;
}

export function LocaleLink({ href, children }: LocaleLinkProps) {
  const { locale } = useRouter();

  return (
    <Link href={href} locale={locale}>
      {children}
    </Link>
  );
}

Этот компонент явно сохраняет локаль и при необходимости может быть расширен дополнительной логикой для работы с локалями.

4. Обрабатывайте программную навигацию с сохранением локали

При прямом использовании методов роутера можно указать локаль через параметры перехода или сохранить всю информацию о маршруте, включая локаль, передав href как объект.

import { useRouter } from "next/router";

export default function NavigationButton() {
  const router = useRouter();
  const { pathname, asPath, query, locale } = router;

  const handleNavigate = () => {
    router.push({ pathname: "/dashboard", query }, asPath, { locale });
  };

  return <button onClick={handleNavigate}>Go to Dashboard</button>;
}

Такой подход гарантирует, что программная навигация сохраняет текущую локаль и все существующие параметры запроса.

5. Используйте единый паттерн ссылок по всему приложению

Используйте стандартный компонент Link во всём приложении, полагаясь на его встроенное поведение по сохранению локали.

import Link from "next/link";

export default function ProductCard({ productId }: { productId: string }) {
  return (
    <article>
      <h2>Product {productId}</h2>
      <Link href={`/products/${productId}`}>View Details</Link>
      <Link href="/products">Back to Products</Link>
    </article>
  );
}

И статические, и динамические маршруты автоматически включают префикс текущей локали, чтобы пользователь оставался на выбранном языке при навигации по приложению.