Как сохранять локаль в навигационных ссылках в TanStack Start v1
Сохраняйте локаль при внутренней навигации
Проблема
Когда информация о локали закодирована в пути URL, каждая навигационная ссылка должна сохранять эту локаль, чтобы обеспечить пользователю единообразный опыт. Если пользователь просматривает французскую версию сайта по адресу /fr/products, а затем кликает по ссылке на /about, он попадает на сайт на языке по умолчанию, и его языковой контекст теряется. Жёстко прописывать параметры локали в каждую ссылку — это утомительно и чревато ошибками, особенно по мере роста приложения и увеличения числа ссылок в компонентах.
Без системного подхода к навигации с учётом локали разработчики сталкиваются с выбором: либо вручную передавать локаль через каждый компонент Link, либо смириться с тем, что пользователи будут неожиданно переключаться на язык по умолчанию в середине сессии. Оба варианта ухудшают пользовательский опыт и увеличивают нагрузку на поддержку.
Решение
Создайте обёртку-компонент вокруг Link фреймворка, который автоматически читает текущую локаль из URL и добавляет её в проп params каждой навигационной цели. Централизовав эту логику в одном переиспользуемом компоненте, все внутренние ссылки будут автоматически учитывать локаль, и разработчикам не придётся вручную передавать параметры локали в каждом месте вызова.
Этот подход работает так: активная локаль считывается из параметров маршрута с помощью хуков роутера, после чего она добавляется к параметрам целевой ссылки. Обёртка сохраняет всю остальную функциональность Link, обеспечивая при этом непрерывность локали при навигации.
Шаги
1. Создайте обёртку-компонент Link с поддержкой локали
Создайте компонент, который читает текущую локаль и автоматически добавляет её в параметры навигации.
import { Link, LinkProps, useParams } from "@tanstack/react-router";
type LocaleLinkProps = LinkProps & {
to: string;
};
export function LocaleLink(props: LocaleLinkProps) {
const params = useParams({ strict: false });
const currentLocale = params.locale;
const enhancedParams = {
...props.params,
...(currentLocale && { locale: currentLocale }),
};
return <Link {...props} params={enhancedParams} />;
}
Этот компонент использует useParams вместе с strict: false для доступа к параметрам любого маршрута в приложении, извлекает текущий locale и объединяет его с пропсом params, который передаётся в базовый Link. Оператор spread гарантирует, что любые явно переданные параметры будут иметь приоритет.
2. Используйте компонент LocaleLink для внутренней навигации
Замените стандартные компоненты Link на LocaleLink по всему вашему приложению.
import { createFileRoute } from "@tanstack/react-router";
import { LocaleLink } from "../components/LocaleLink";
export const Route = createFileRoute("/{-$locale}/products")({
component: ProductsPage,
});
function ProductsPage() {
return (
<div>
<h1>Products</h1>
<nav>
<LocaleLink to="/{-$locale}/about">About</LocaleLink>
<LocaleLink to="/{-$locale}/contact">Contact</LocaleLink>
<LocaleLink to="/{-$locale}/products/$id" params={{ id: "123" }}>
Product 123
</LocaleLink>
</nav>
</div>
);
}
Когда пользователь заходит на /fr/products, все компоненты LocaleLink автоматически преобразуются в /fr/about, /fr/contact и /fr/products/123. Параметр локали сохраняется без необходимости вручную указывать его в каждой ссылке.
3. Явно обрабатывайте переключение локали, когда это нужно
Для компонентов переключения языка используйте стандартный Link напрямую, чтобы обойти автоматическую подстановку локали.
import { Link, useParams } from "@tanstack/react-router";
export function LanguageSwitcher() {
const params = useParams({ strict: false });
const currentPath = window.location.pathname.replace(/^\/(en|fr|es)/, "");
return (
<div>
<Link to={`/{-$locale}${currentPath}`} params={{ locale: "en" }}>
English
</Link>
<Link to={`/{-$locale}${currentPath}`} params={{ locale: "fr" }}>
Français
</Link>
<Link to={`/{-$locale}${currentPath}`} params={{ locale: "es" }}>
Español
</Link>
</div>
);
}
Для переключателей языка требуется явный контроль параметра локали, поэтому они используют стандартный компонент Link и явно задают параметр locale. Это позволяет пользователям менять язык, оставаясь на той же логической странице.