T
TanStack2mo ago
extended-salmon

Optional locale param with wildcard

I have /{$-lang}/$ -like routes. When user access /hello page, how would router know that "hello" is not a lang? Do I need to manually check and somehow redirect to the splat route? I tried to do:
export const Route = createFileRoute("/_main/{-$lang}/")({
component: Index,

beforeLoad: ({ params }) => {
// if there some prefix that is not a lang, redirect to splat route, becaue that is document id.
if (!!params.lang && !i18n.locales.includes(params.lang as Locale)) {
throw redirect({
to: "/{-$lang}/$",
params: { lang: undefined, _splat: params.lang },
});
}
},
export const Route = createFileRoute("/_main/{-$lang}/")({
component: Index,

beforeLoad: ({ params }) => {
// if there some prefix that is not a lang, redirect to splat route, becaue that is document id.
if (!!params.lang && !i18n.locales.includes(params.lang as Locale)) {
throw redirect({
to: "/{-$lang}/$",
params: { lang: undefined, _splat: params.lang },
});
}
},
but that would send the server into infinite loop.
4 Replies
extended-salmon
extended-salmonOP2mo ago
Anyone? Kindly bump I got the workaround. I'm not sure if it Start-specific or Router specific, but I'll post that here just in case somebody has similar usecase. The key is to set rewrite of the createRouter. router.tsx
function localeRewrite(): LocationRewrite {
return {
input: ({ url }) => {
const parts = url.pathname.split("/").filter(Boolean);
if (!parts.length) return url;

const [maybeLocale] = parts;

if (
maybeLocale.startsWith(".") ||
maybeLocale === "api" ||
maybeLocale === "assets" ||
maybeLocale === "favicon.ico"
) {
return url;
}

if (!i18n.locales.includes(maybeLocale as Locale)) {
url.pathname = `/${i18n.defaultLocale}/${parts.join("/")}`;
}
return url;
},
output: ({ url }) => {
const parts = url.pathname.split("/").filter(Boolean);
if (parts[0] === i18n.defaultLocale) {
parts.shift();
url.pathname = parts.length ? `/${parts.join("/")}` : "/";
}
return url;
},
};
}
export function getRouter() {
const queryClient = new QueryClient();

const router = createRouter({
routeTree,
context: {
queryClient,
} as Context,
defaultPreload: "intent",
scrollRestoration: true,
rewrite: localeRewrite(),
});

setupRouterSsrQueryIntegration({
router,
queryClient,
});

return router;
}
function localeRewrite(): LocationRewrite {
return {
input: ({ url }) => {
const parts = url.pathname.split("/").filter(Boolean);
if (!parts.length) return url;

const [maybeLocale] = parts;

if (
maybeLocale.startsWith(".") ||
maybeLocale === "api" ||
maybeLocale === "assets" ||
maybeLocale === "favicon.ico"
) {
return url;
}

if (!i18n.locales.includes(maybeLocale as Locale)) {
url.pathname = `/${i18n.defaultLocale}/${parts.join("/")}`;
}
return url;
},
output: ({ url }) => {
const parts = url.pathname.split("/").filter(Boolean);
if (parts[0] === i18n.defaultLocale) {
parts.shift();
url.pathname = parts.length ? `/${parts.join("/")}` : "/";
}
return url;
},
};
}
export function getRouter() {
const queryClient = new QueryClient();

const router = createRouter({
routeTree,
context: {
queryClient,
} as Context,
defaultPreload: "intent",
scrollRestoration: true,
rewrite: localeRewrite(),
});

setupRouterSsrQueryIntegration({
router,
queryClient,
});

return router;
}
stormy-gold
stormy-gold2mo ago
you should look into params.parse might just do the trick for validating the actual language
extended-salmon
extended-salmonOP2mo ago
Would that mean that accessing /hello would throw an error then? I just need the router to assume that the lang in undefined and skip to the wildcard route.. Docs :If this function throws, the route will be put into an error state and the error will be thrown during render.
RouteOptions type | TanStack Router React Docs
The RouteOptions type is used to describe the options that can be used when creating a route. RouteOptions properties The RouteOptions type accepts an object with the following properties: getParentRo...
stormy-gold
stormy-gold2mo ago
do you have a minimal complete example ?

Did you find this page helpful?