T
TanStack9mo ago
sunny-green

i18n

What's the best way to implement a redirect rule in a subsection of the website /$lang/... whereby I get the language from logged in user / cookies / request and redirect to that the /$lang/... equivalent route if it's different from the parameter? Example User navigates directly to /fr/a/b/c but user is logged in and their language is en. The code should redirect to /en/a/b/c. Use case Language is inferred from: 1) logged in user, 2) language cookie, 3) accept-language header in this order. I need this rule for when a link is shared from other websites which may be localized differently and I want it to automatically localize it for the given user. What have I tried? I tried to have this layout route:
import { getViewerQuery } from "~/client/queries/use-viewer";
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";

export const Route = createFileRoute("/$lang")({
component: Layout,
loader: async ({ context, params, location }) => {
const [viewer] = await Promise.all([
context.queryClient.ensureQueryData(getViewerQuery),
]);

if (viewer.language !== params.lang) {
const langRegex = new RegExp(`^/(${params.lang})(\/|$)`);
const pathnameWithoutLang = location.pathname.replace(
langRegex,
`/${viewer.language}/`
);
const newUrl = `${pathnameWithoutLang}${location.searchStr}`;
throw redirect({ to: newUrl, resetScroll: false });
}
},
});

function Layout() {
return <Outlet />;
}
import { getViewerQuery } from "~/client/queries/use-viewer";
import { createFileRoute, Outlet, redirect } from "@tanstack/react-router";

export const Route = createFileRoute("/$lang")({
component: Layout,
loader: async ({ context, params, location }) => {
const [viewer] = await Promise.all([
context.queryClient.ensureQueryData(getViewerQuery),
]);

if (viewer.language !== params.lang) {
const langRegex = new RegExp(`^/(${params.lang})(\/|$)`);
const pathnameWithoutLang = location.pathname.replace(
langRegex,
`/${viewer.language}/`
);
const newUrl = `${pathnameWithoutLang}${location.searchStr}`;
throw redirect({ to: newUrl, resetScroll: false });
}
},
});

function Layout() {
return <Outlet />;
}
but I've just realised this only runs once when loading the layout but then every route change within /$lang/... (e.g. from /en/a to /en/b) will not trigger the loader. This currently doesn't work if I trigger a client navigation. It does work if the page is reloaded though.
1 Reply
sunny-green
sunny-greenOP9mo ago
I was able to get it working by doing this instead:
import { getViewerQuery, useViewer } from "~/client/queries/use-viewer";
import {
createFileRoute,
Navigate,
Outlet,
useLocation,
} from "@tanstack/react-router";

export const Route = createFileRoute("/$lang")({
component: Layout,
loader: async ({ context }) => {
await Promise.all([context.queryClient.ensureQueryData(getViewerQuery)]);
},
});

function Layout() {
const location = useLocation();
const params = Route.useParams();
const viewer = useViewer();

if (viewer.language !== params.lang) {
const langRegex = new RegExp(`^/(${params.lang})(\/|$)`);
const newPathname = location.pathname.replace(
langRegex,
`/${viewer.language}/`
);
const newUrl = `${newPathname}${location.searchStr}`;
return <Navigate to={newUrl} resetScroll={false} />;
}

return <Outlet />;
}
import { getViewerQuery, useViewer } from "~/client/queries/use-viewer";
import {
createFileRoute,
Navigate,
Outlet,
useLocation,
} from "@tanstack/react-router";

export const Route = createFileRoute("/$lang")({
component: Layout,
loader: async ({ context }) => {
await Promise.all([context.queryClient.ensureQueryData(getViewerQuery)]);
},
});

function Layout() {
const location = useLocation();
const params = Route.useParams();
const viewer = useViewer();

if (viewer.language !== params.lang) {
const langRegex = new RegExp(`^/(${params.lang})(\/|$)`);
const newPathname = location.pathname.replace(
langRegex,
`/${viewer.language}/`
);
const newUrl = `${newPathname}${location.searchStr}`;
return <Navigate to={newUrl} resetScroll={false} />;
}

return <Outlet />;
}

Did you find this page helpful?