How to validate locale parameters in URLs in TanStack Start v1
Handle unsupported locale codes gracefully
Problem
When language codes become part of the URL structure, they transform into user input that must be validated. Users can manually type any string into the locale segment—/xx/about, /gibberish/contact, or /typo123/products—just as easily as valid codes like /en/about or /fr/contact. Without validation, the application may attempt to load translations for nonexistent locales, display broken content, or crash. Each invalid locale represents a potential dead end where users cannot recover or navigate to working pages.
Unvalidated locale parameters create unpredictable behavior. The application might silently fail to load translations, render a mix of fallback and missing content, or throw runtime errors when translation keys are accessed. Users who follow broken links or mistype URLs are left without clear feedback about what went wrong or how to fix it.
Solution
Validate the locale parameter from the URL against a list of supported locales in the route's beforeLoad function. When the locale is invalid or missing, redirect the user to a valid URL with the default locale or throw a not-found error to display a helpful error page. This ensures that only supported locales are processed and that users always land on a valid, translatable page.
The beforeLoad function runs before the route loads, making it the ideal place to check the locale. By throwing a redirect() or notFound() error, you prevent the route from rendering with an invalid locale and guide users to a working state.
Steps
1. Define supported locales
Create a constant array of valid locale codes and a type-safe validation function.
const SUPPORTED_LOCALES = ["en", "fr", "es", "de"] as const;
type Locale = (typeof SUPPORTED_LOCALES)[number];
function isValidLocale(locale: string | undefined): locale is Locale {
return SUPPORTED_LOCALES.includes(locale as Locale);
}
This provides a single source of truth for supported locales and a reusable validation function that TypeScript can understand.
2. Create a layout route with locale validation
Use an optional locale parameter and validate it in beforeLoad.
import { createFileRoute, redirect } from "@tanstack/react-router";
const DEFAULT_LOCALE: Locale = "en";
export const Route = createFileRoute("/{-$locale}")({
beforeLoad: ({ params }) => {
const { locale } = params;
if (locale && !isValidLocale(locale)) {
throw redirect({
to: "/{-$locale}",
params: { locale: undefined },
replace: true,
});
}
return {
locale: (locale as Locale) || DEFAULT_LOCALE,
};
},
});
The beforeLoad function checks the locale parameter. If it exists but is invalid, the user is redirected to the same path without the locale prefix, which resolves to the default locale. The validated locale is returned in the context for child routes to use.
3. Validate locale in nested routes
For routes that require a locale, validate it and throw notFound() if invalid.
import { createFileRoute, notFound } from "@tanstack/react-router";
export const Route = createFileRoute("/{-$locale}/products")({
beforeLoad: ({ params }) => {
const { locale } = params;
if (locale && !isValidLocale(locale)) {
throw notFound();
}
return {
locale: (locale as Locale) || DEFAULT_LOCALE,
};
},
component: ProductsPage,
});
function ProductsPage() {
const { locale } = Route.useRouteContext();
return <div>Products in {locale}</div>;
}
This approach shows a not-found page for invalid locales instead of redirecting, which is useful when you want to signal that the URL is malformed rather than silently correcting it.
4. Add a not-found component for invalid locales
Define a notFoundComponent on the root route to handle invalid locale errors gracefully.
import { createRootRoute } from "@tanstack/react-router";
export const Route = createRootRoute({
notFoundComponent: () => {
return (
<div>
<h1>Page Not Found</h1>
<p>The language or page you requested does not exist.</p>
<a href="/">Go to home page</a>
</div>
);
},
});
This component renders when notFound() is thrown from beforeLoad, giving users a clear message and a way to navigate back to a valid page.