Serve the site in English, Spanish and Arabic, add a captcha, make the message optional
- Move every route under app/[lang]; a proxy keeps English on unprefixed URLs and serves /es and /ar - Interface strings and homepage copy per locale; content pages load a translated JSON when one exists - Language switch in the header, hreflang alternates and a multilingual sitemap - Right-to-left layout for Arabic with logical CSS properties, Noto Sans Arabic and no letter-spacing - Self-hosted proof-of-work "I'm not a robot" check (no third-party account) replaces Turnstile - The message field is optional; failed attempts refill the form instead of clearing it
This commit is contained in:
@@ -0,0 +1,32 @@
|
||||
// Locale settings shared by the proxy, server components and client components.
|
||||
|
||||
export const locales = ["en", "es", "ar"] as const;
|
||||
export type Locale = (typeof locales)[number];
|
||||
|
||||
/** English is served from the root (`/about`); the others carry a prefix (`/es/about`). */
|
||||
export const defaultLocale: Locale = "en";
|
||||
|
||||
export const localeNames: Record<Locale, string> = { en: "English", es: "Español", ar: "العربية" };
|
||||
export const localeShort: Record<Locale, string> = { en: "EN", es: "ES", ar: "ع" };
|
||||
/** Open Graph locale tags. */
|
||||
export const ogLocale: Record<Locale, string> = { en: "en_US", es: "es_ES", ar: "ar_AE" };
|
||||
|
||||
export const isLocale = (value: string | undefined): value is Locale =>
|
||||
(locales as readonly string[]).includes(value ?? "");
|
||||
|
||||
export const dirOf = (locale: Locale) => (locale === "ar" ? "rtl" : "ltr");
|
||||
|
||||
/** Prefix an internal path with the locale. Hashes and external URLs pass through untouched. */
|
||||
export function localize(path: string, locale: Locale): string {
|
||||
if (locale === defaultLocale || !path.startsWith("/")) return path;
|
||||
return path === "/" ? `/${locale}` : `/${locale}${path}`;
|
||||
}
|
||||
|
||||
/** Split a browser pathname into its locale and the locale-free path. */
|
||||
export function splitLocale(pathname: string): { locale: Locale; path: string } {
|
||||
const first = pathname.split("/")[1];
|
||||
if (isLocale(first)) {
|
||||
return { locale: first, path: pathname.slice(first.length + 1) || "/" };
|
||||
}
|
||||
return { locale: defaultLocale, path: pathname };
|
||||
}
|
||||
Reference in New Issue
Block a user