Как реализовать маршрутизацию на основе локали в React Router v7
Настройка маршрутизации с сегментами локали
Проблема
При создании многоязычного приложения один фундаментальный вопрос определяет всё остальное: как приложение будет знать, на каком языке отображать контент? Без явного механизма URL /about становится неоднозначным — он может представлять контент на любом языке. Пользователи не могут делиться ссылками на конкретные языковые версии, а поисковые системы затрудняются понять, какая версия предназначена для какой аудитории. Эта неоднозначность создаёт проблемы как для пользовательского опыта, так и для обнаруживаемости.
Решение
Добавьте идентификатор языка прямо в путь URL, например, /en/about или /fr/about. Это делает каждый путь уникальным для конкретного языка, устраняя неоднозначность как для пользователей, так и для поисковых систем. Определяя маршруты с параметром локали в качестве первого сегмента, приложение может извлекать локаль из URL и использовать её для определения языка отображаемого контента. Этот подход гарантирует, что каждый URL однозначно идентифицирует как страницу, так и её язык.
Шаги
1. Определите маршруты с параметром локали
Настройте маршруты в app/routes.ts, чтобы включить параметр локали в качестве первого сегмента каждого пути.
import { type RouteConfig, route, index } from "@react-router/dev/routes";
export default [
route(":locale", "./localized-layout.tsx", [
index("./home.tsx"),
route("about", "./about.tsx"),
route("contact", "./contact.tsx"),
]),
] satisfies RouteConfig;
Префикс с двоеточием делает locale динамическим сегментом, который будет извлекаться из URL и передаваться в качестве параметра компонентам маршрута. Эта конфигурация создаёт маршруты, такие как /en, /en/about, /fr/contact, где первый сегмент всегда является локалью.
2. Создайте компонент макета для извлечения локали
Дочерние маршруты отображаются через компонент Outlet в родительском маршруте. Создайте макет, который извлекает параметр локали и отображает вложенные маршруты.
import { Outlet, useParams } from "react-router";
export default function LocalizedLayout() {
const { locale } = useParams();
return (
<div>
<nav>
<a href={`/${locale}`}>Главная</a>
<a href={`/${locale}/about`}>О нас</a>
<a href={`/${locale}/contact`}>Контакты</a>
</nav>
<Outlet />
</div>
);
}
Хук useParams извлекает значение динамического сегмента из URL. Макет использует эту локаль для построения навигационных ссылок и передаёт управление отображением дочерним маршрутам через Outlet.
3. Доступ к локали в компонентах страницы
Используйте хук useParams в любом компоненте маршрута, чтобы получить доступ к параметру локали.
import { useParams } from "react-router";
export default function About() {
const { locale } = useParams();
return (
<div>
<h1>О нас</h1>
<p>Текущая локаль: {locale}</p>
</div>
);
}
Каждый компонент, отображаемый в локализованном макете, может извлечь локаль из URL. Это значение можно использовать для загрузки соответствующих переводов, форматирования дат и чисел или принятия любых других решений, зависящих от локали.
4. Использование компонентов Link для навигации на стороне клиента
Замените теги <a> на компоненты Link, чтобы включить навигацию с маршрутизацией на стороне клиента.
import { Outlet, useParams, Link } from "react-router";
export default function LocalizedLayout() {
const { locale } = useParams();
return (
<div>
<nav>
<Link to={`/${locale}`}>Главная</Link>
<Link to={`/${locale}/about`}>О нас</Link>
<Link to={`/${locale}/contact`}>Контакты</Link>
</nav>
<Outlet />
</div>
);
}
Компонент Link обрабатывает маршрутизацию на стороне клиента и предотвращает перезагрузку веб-страницы, обеспечивая плавную навигацию между страницами. Каждая ссылка включает параметр локали, чтобы сохранить языковой контекст при навигации.