Files
fotospiel-app/resources/js/lib/localizedPath.ts

87 lines
2.7 KiB
TypeScript

export type LocaleRewriteMap = Record<string, Record<string, string>>;
export const defaultLocaleRewrites: LocaleRewriteMap = {
'/': {},
'/kontakt': { en: '/contact' },
'/contact': { de: '/kontakt' },
'/so-funktionierts': { en: '/how-it-works' },
'/how-it-works': { de: '/so-funktionierts' },
'/bestellen': { en: '/checkout' },
'/checkout': { de: '/bestellen' },
'/anlaesse': { en: '/occasions' },
'/anlaesse/hochzeit': { en: '/occasions/wedding' },
'/anlaesse/geburtstag': { en: '/occasions/birthday' },
'/anlaesse/firmenevent': { en: '/occasions/corporate-event' },
'/anlaesse/konfirmation': { en: '/occasions/confirmation' },
'/occasions/wedding': { de: '/anlaesse/hochzeit' },
'/occasions/birthday': { de: '/anlaesse/geburtstag' },
'/occasions/corporate-event': { de: '/anlaesse/firmenevent' },
'/occasions/confirmation': { de: '/anlaesse/konfirmation' },
};
const sanitizePath = (input: string): string => {
if (!input || input.trim().length === 0) {
return '/';
}
const withLeading = input.startsWith('/') ? input : `/${input}`;
const withoutTrailing = withLeading.replace(/\/{2,}/g, '/');
return withoutTrailing;
};
const resolveRewrite = (
path: string,
targetLocale: string,
rewrites: LocaleRewriteMap,
): string => {
const exact = rewrites[path];
if (exact) {
return exact[targetLocale] ?? path;
}
const prefixKey = Object.keys(rewrites)
.filter((key) => key !== '/' && path.startsWith(`${key}/`))
.sort((a, b) => b.length - a.length)[0];
if (!prefixKey) {
return path;
}
const replacement = rewrites[prefixKey]?.[targetLocale];
if (!replacement) {
return path;
}
const suffix = path.slice(prefixKey.length);
return `${replacement}${suffix}`;
};
export const buildLocalizedPath = (
path: string | null | undefined,
targetLocale: string | undefined,
supportedLocales: string[],
defaultLocale = 'de',
rewrites: LocaleRewriteMap = defaultLocaleRewrites,
): string => {
const fallbackLocale = supportedLocales.length > 0 ? supportedLocales[0] : defaultLocale;
const nextLocale = targetLocale && supportedLocales.includes(targetLocale)
? targetLocale
: fallbackLocale;
if (typeof path !== 'string' || path.trim().length === 0) {
return `/${fallbackLocale}`;
}
const trimmed = path.trim();
const [rawPath, rawQuery] = trimmed.split('?');
const normalizedPath = sanitizePath(rawPath);
const rewrittenPath = resolveRewrite(normalizedPath, nextLocale, rewrites);
const base = rewrittenPath === '/' ? `/${nextLocale}` : `/${nextLocale}${rewrittenPath}`;
const sanitisedBase = base.replace(/\/{2,}/g, '/');
const query = rawQuery ? `?${rawQuery}` : '';
return `${sanitisedBase}${query}`;
};