TanStack i18n
Guides

TanStack Router

Integrate TanStack i18n with TanStack Router. Set up localized route trees and configure type-safe navigation helpers like createNavigation.

To organize routing in your app, TanStack Router needs a route tree and navigation helpers so components can use "/about" instead of hard-coding "/en/about". This guide explains how to add a `{-$locale}` route folder, map de-localized paths with createToLocalizedRoute, and replace Link, navigate, and loader redirects with localized helpers.

Prerequisites

Create the localized route folder

Mirror HTTP prefix always with a dynamic segment in the file tree:

src/routes/
  __root.tsx
  {-$locale}/
    index.tsx       # /en/, /ar/
    about.tsx       # /en/about, /ar/about
    pricing.tsx

Route ids in the generated tree include the locale prefix — e.g. `/{-$locale}/about`. Set url.segment in config if you rename the segment (URL prefix modes).

Map de-localized paths — createToLocalizedRoute

App code should not hard-code "/en/about". Create a mapper from config:

// src/i18n/routes.ts
import { createToLocalizedRoute } from "@Wadiou/tanstack-i18n/react-router"; // or /solid-router
import { config } from "../locale-config";

export const toLocalizedRoute = createToLocalizedRoute(config);

Usage in the marketing site:

toLocalizedRoute("/");       // → "/{-$locale}"
toLocalizedRoute("/about");   // → "/{-$locale}/about"
toLocalizedRoute("/pricing");

Type helpers (DeLocalizedTo, etc.) keep to props aligned with your route tree while you author paths without the locale prefix.

Create navigation helpers once:

import { createNavigation } from "@Wadiou/tanstack-i18n/react-router"; // or /solid-router

export const { LocalizedLink, useLocalizedNavigate, localizedRedirect } =
  createNavigation({ toLocalizedRoute });

Replace header nav links:

// Before
<Link to="/$locale/about" params={{ locale: "en" }}>About</Link>

// After — active locale comes from routing + getLocale()
<LocalizedLink to="/about">About</LocalizedLink>

LocalizedLink accepts the same props as TanStack Router Link except to is de-localized.

Programmatic navigation

CTA button on the marketing home page:

function StartTrialButton() {
  const navigate = useLocalizedNavigate();
  return (
    <button type="button" onClick={() => navigate({ to: "/pricing" })}>
      Start trial
    </button>
  );
}

The helper maps /pricing`/{-$locale}/pricing` using the current route context.

Loader redirects

Protect a dashboard route — redirect anonymous users to login with a de-localized target:

// routes/{-$locale}/dashboard.tsx
export const Route = createFileRoute("/{-$locale}/dashboard")({
  beforeLoad: ({ context }) => {
    if (!context.user) {
      throw localizedRedirect({ to: "/login" });
    }
  },
});

localizedRedirect throws TanStack Router redirect() with the mapped route id.

If you use prefix: "as-needed", de-localized "/about" still maps correctly — the helper uses route ids, not raw HTTP paths. When links 404 after a prefix change, re-check URL prefix modes and that toLocalizedRoute uses the same config as defineLocaleConfig.

Keep config and helpers in one module

Export everything from src/i18n/routes.ts so layout, CTAs, and loaders share one toLocalizedRoute:

export { toLocalizedRoute, LocalizedLink, useLocalizedNavigate, localizedRedirect };

Importing createToLocalizedRoute in multiple files with different config slices causes subtle route id mismatches on the marketing site.

Solid apps

A dedicated @Wadiou/tanstack-i18n/solid-router subpath is fully supported! It exports the exact same createNavigation API, but wraps Solid Router's Link, useNavigate, and redirect with idiomatic Solid JS patterns. Use it exactly as shown above.

How it works

HTTP locale segments come from url.prefix. Router ids come from url.segment. Both must agree with your file tree.

User-initiated locale changes update URL + router: Change locale.

Complete example (so far)

// src/i18n/routes.ts
import { createNavigation, createToLocalizedRoute } from "@Wadiou/tanstack-i18n/react-router"; // or /solid-router
import { config } from "../locale-config";

export const toLocalizedRoute = createToLocalizedRoute(config);
export const { LocalizedLink, useLocalizedNavigate, localizedRedirect } =
  createNavigation({ toLocalizedRoute });

Use these exports in marketing site layout, CTAs, and protected loaders.

API reference

createToLocalizedRoute(config)

Returns (to) => routeId using config.url.segment (default `{-$locale}`).

createNavigation({ toLocalizedRoute })

ExportRole
LocalizedLinkLink with de-localized to
useLocalizedNavigateHook; navigate({ to: "/path" })
localizedRedirectLoader redirect with de-localized to

Type helpers

DeLocalizedTo, LocalePrefixedRoutes, LocalizedLinkProps, etc. — exported from @Wadiou/tanstack-i18n/react-router and @Wadiou/tanstack-i18n/solid-router for typed route trees.

What's next

Add a language switcher that updates persist, URL, and router together: Change locale.

Edit on GitHub