In addition to the official route translation documentation I wrote, I would like to explain the steps for translating routes for content collections and subpages.
See the example below
// ui.ts
export const routes = {
de: {
services: "leistungen",
blog: "blog", // content collection index
"blog.how-to-become-a-scrum-master": "blog.wie-werde-ich-scrum-master",
},
fr: {
services: "prestations-de-service",
blog: "blog", // content collection index
"blog.how-to-become-a-scrum-master": "blog.comment-devenir-un-scrum-master",
},
};
Multi-tier routes are separated with a dot. When translating the route, the dot is replaced with a slash. Update the methods below to enable translation logic for multi-tier routes.
// utils.ts
// Add dot/slash replacement for translatedPath
export function useTranslatedPath(lang: keyof typeof ui) {
return function translatePath(path: string, l: string = lang) {
const pathName = path.replaceAll("/", "");
const hasTranslation =
defaultLang !== l &&
routes[l] !== undefined &&
routes[l][pathName] !== undefined;
const translatedPath = hasTranslation ? "/" + routes[l][pathName] : path;
const translatedPathReplaced = translatedPath.replaceAll(".", "/");
return !showDefaultLang && l === defaultLang
? translatedPathReplaced
: `/${l}${translatedPathReplaced}`;
};
}
// Add support for multi-tier routes by checking the entire pathname and skipping the language directory
export function getRouteFromUrl(url: URL): string | undefined {
const pathname = new URL(url)?.pathname;
const path = pathname
?.split("/")
.filter(Boolean)
.filter((part) => !Object.keys(languages).includes(part))
.join(".");
if (!path) {
return undefined;
}
const currentLang = getLangFromUrl(url);
if (defaultLang === currentLang) {
const route = Object.values(routes)[0];
const pathTyped = path as keyof typeof route;
return pathTyped in route ? pathTyped : undefined
}
const getKeyByValue = (
obj: Record<string, string>,
value: string,
): string | undefined => {
return Object.keys(obj).find((key) => obj[key] === value);
};
const reversedKey = getKeyByValue(routes[currentLang], path);
if (reversedKey !== undefined) {
return reversedKey;
}
return undefined;
}
The official documentation and the recipe above only works without page configuration trailingSlash or deviant base.
For example, if you want to use trailingSlash: always
, see the integration source code here. Or the live preview.