How to implement locale-based routing in TanStack Start v1
Configure routing with locale segments
Problem
When building a multilingual application, one fundamental decision shapes everything else: how will the application know which language to display? Without an explicit mechanism, the URL /about becomes ambiguous—it could represent content in any language. Users cannot share links to specific language versions, and search engines struggle to understand which version belongs to which audience. This ambiguity creates problems for both user experience and SEO, as there is no clear way to distinguish between language variants of the same content.
Solution
Put a language identifier directly into the URL path, such as /en/about or /fr/about. This makes every path unique to a specific language, removing the ambiguity for both users and search engines. By using a locale parameter in the route structure, each URL becomes self-describing and shareable, allowing users to bookmark or share links to content in their preferred language while enabling search engines to properly index each language variant.
Steps
1. Create a locale layout route
Define an optional locale parameter using the {-$locale} syntax to create flexible routing patterns where the locale parameter is optional. TanStack Start uses file-based routing where routes are defined in the src/routes directory.
import { createFileRoute, Outlet } from "@tanstack/react-router";
export const Route = createFileRoute("/{-$locale}")({
component: LocaleLayout,
});
function LocaleLayout() {
return <Outlet />;
}
This route matches both /about (locale is undefined) and /en/about (locale is "en"), allowing you to support URLs with or without a locale prefix.
2. Create child routes under the locale layout
TanStack Router uses nested routing to match the URL with the correct component tree to render. Create route files as children of the locale parameter to inherit the locale from the URL.
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/{-$locale}/about")({
component: AboutPage,
});
function AboutPage() {
const { locale } = Route.useParams();
const currentLocale = locale || "en";
return (
<div>
<h1>About Us</h1>
<p>Current locale: {currentLocale}</p>
</div>
);
}
The route file structure {-$locale}/about.tsx creates paths like /about and /en/about that both render the same component with access to the locale parameter.
3. Access the locale parameter in components
Use the useParams hook to read the locale from the URL and determine which language to display.
import { createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/{-$locale}/products")({
component: ProductsPage,
});
function ProductsPage() {
const { locale } = Route.useParams();
const displayLocale = locale || "en";
return (
<div>
<h1>{displayLocale === "fr" ? "Produits" : "Products"}</h1>
</div>
);
}
When the locale parameter is undefined, the component defaults to a base language, allowing the application to handle both localized and non-localized URLs.
4. Create links that preserve the locale
Use the Link component with the locale parameter to navigate between pages while maintaining the current language.
import { Link, createFileRoute } from "@tanstack/react-router";
export const Route = createFileRoute("/{-$locale}/")({
component: HomePage,
});
function HomePage() {
const { locale } = Route.useParams();
return (
<nav>
<Link to="/{-$locale}/about" params={{ locale }}>
About
</Link>
<Link to="/{-$locale}/products" params={{ locale }}>
Products
</Link>
</nav>
);
}
By passing the current locale in the params prop, links automatically generate URLs that match the user's current language context, such as /fr/about when viewing the French version.