mirror of
https://github.com/sern-handler/website
synced 2026-06-23 08:12:22 +00:00
122 lines
4.1 KiB
TypeScript
122 lines
4.1 KiB
TypeScript
import config from 'virtual:starlight/user-config';
|
|
|
|
export interface LocaleData {
|
|
/** Writing direction. */
|
|
dir: 'ltr' | 'rtl';
|
|
/** BCP-47 language tag. */
|
|
lang: string;
|
|
/** The base path at which a language is served. `undefined` for root locale slugs. */
|
|
locale: string | undefined;
|
|
}
|
|
|
|
/**
|
|
* Get the “locale” of a slug. This is the base path at which a language is served.
|
|
* For example, if French docs are in `src/content/docs/french/`, the locale is `french`.
|
|
* Root locale slugs will return `undefined`.
|
|
* @param slug A collection entry slug
|
|
*/
|
|
function slugToLocale(slug: string): string | undefined {
|
|
const locales = Object.keys(config.locales || {});
|
|
const baseSegment = slug.split('/')[0];
|
|
if (baseSegment && locales.includes(baseSegment)) return baseSegment;
|
|
return undefined;
|
|
}
|
|
|
|
/** Get locale information for a given slug. */
|
|
export function slugToLocaleData(slug: string): LocaleData {
|
|
const locale = slugToLocale(slug);
|
|
return { dir: localeToDir(locale), lang: localeToLang(locale), locale };
|
|
}
|
|
|
|
/**
|
|
* Get the BCP-47 language tag for the given locale.
|
|
* @param locale Locale string or `undefined` for the root locale.
|
|
*/
|
|
export function localeToLang(locale: string | undefined): string {
|
|
const lang = locale ? config.locales?.[locale]?.lang : config.locales?.root?.lang;
|
|
const defaultLang = config.defaultLocale?.lang || config.defaultLocale?.locale;
|
|
return lang || defaultLang || 'en';
|
|
}
|
|
|
|
/**
|
|
* Get the configured writing direction for the given locale.
|
|
* @param locale Locale string or `undefined` for the root locale.
|
|
*/
|
|
function localeToDir(locale: string | undefined): 'ltr' | 'rtl' {
|
|
const dir = locale ? config.locales?.[locale]?.dir : config.locales?.root?.dir;
|
|
return dir || config.defaultLocale.dir;
|
|
}
|
|
|
|
export function slugToParam(slug: string): string | undefined {
|
|
return slug === 'index' || slug === ''
|
|
? undefined
|
|
: slug.endsWith('/index')
|
|
? slug.replace(/\/index$/, '')
|
|
: slug;
|
|
}
|
|
|
|
export function slugToPathname(slug: string): string {
|
|
const param = slugToParam(slug);
|
|
return param ? '/' + param + '/' : '/';
|
|
}
|
|
|
|
/**
|
|
* Convert a slug to a different locale.
|
|
* For example, passing a slug of `en/home` and a locale of `fr` results in `fr/home`.
|
|
* An undefined locale is treated as the root locale, resulting in `home`
|
|
* @param slug A collection entry slug
|
|
* @param locale The target locale
|
|
* @example
|
|
* localizedSlug('en/home', 'fr') // => 'fr/home'
|
|
* localizedSlug('en/home', undefined) // => 'home'
|
|
*/
|
|
export function localizedSlug(slug: string, locale: string | undefined): string {
|
|
const slugLocale = slugToLocale(slug);
|
|
if (slugLocale === locale) return slug;
|
|
locale = locale || '';
|
|
if (slugLocale === slug) return locale;
|
|
if (slugLocale) {
|
|
return slug.replace(slugLocale + '/', locale ? locale + '/' : '').replace(/\/$/, '');
|
|
}
|
|
return slug ? locale + '/' + slug : locale;
|
|
}
|
|
|
|
/**
|
|
* Convert a collection entry ID to a different locale.
|
|
* For example, passing an ID of `en/home.md` and a locale of `fr` results in `fr/home.md`.
|
|
* An undefined locale is treated as the root locale, resulting in `home.md`.
|
|
* @param id A collection entry ID
|
|
* @param locale The target locale
|
|
* @example
|
|
* localizedSlug('en/home.md', 'fr') // => 'fr/home.md'
|
|
* localizedSlug('en/home.md', undefined) // => 'home.md'
|
|
*/
|
|
export function localizedId(id: string, locale: string | undefined): string {
|
|
const idLocale = slugToLocale(id);
|
|
if (idLocale) {
|
|
return id.replace(idLocale + '/', locale ? locale + '/' : '');
|
|
} else if (locale) {
|
|
return locale + '/' + id;
|
|
} else {
|
|
return id;
|
|
}
|
|
}
|
|
|
|
/** Extract the slug from a URL. */
|
|
export function urlToSlug(url: URL): string {
|
|
let pathname = url.pathname;
|
|
const base = import.meta.env.BASE_URL.replace(/\/$/, '');
|
|
if (pathname.startsWith(base)) pathname = pathname.replace(base, '');
|
|
const segments = pathname.split('/');
|
|
const htmlExt = '.html';
|
|
if (segments.at(-1) === 'index.html') {
|
|
// Remove trailing `index.html`.
|
|
segments.pop();
|
|
} else if (segments.at(-1)?.endsWith(htmlExt)) {
|
|
// Remove trailing `.html`.
|
|
const last = segments.pop();
|
|
if (last) segments.push(last.slice(0, -1 * htmlExt.length));
|
|
}
|
|
return segments.filter(Boolean).join('/');
|
|
}
|