All files / src/i18n index.ts

100% Statements 32/32
100% Branches 30/30
100% Functions 8/8
100% Lines 30/30

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93          1x 1x   1x           1x                     1x 8x       3x       3x 3x 1x   2x       3x 3x 1x                 11x 11x 3x   11x     11x 11x 4x 7x 1x     11x   5x     6x 11x       4x                 2x       2x    
import type { Locale } from "@/types";
import { fr } from "./fr";
import { en } from "./en";
import type { Translations } from "./fr";
 
export const DEFAULT_LOCALE: Locale = "fr";
export const LOCALES: readonly Locale[] = ["fr", "en"] as const;
 
const translations: Record<Locale, Translations> = { fr, en };
 
/**
 * Table de correspondance des routes entre FR et EN.
 * Clé = chemin FR (sans prefix), Valeur = slug EN (sans /en/).
 */
const routeMap: Record<string, string> = {
  "/": "/",
  "/fonctionnalites": "/features",
  "/tarifs": "/pricing",
  "/a-propos": "/about",
  "/contact": "/contact",
  "/mentions-legales": "/legal",
  "/cgv": "/terms",
  "/confidentialite": "/privacy",
};
 
const reverseRouteMap: Record<string, string> = Object.fromEntries(
  Object.entries(routeMap).map(([fr, en]) => [en, fr])
);
 
export function t(locale: Locale): Translations {
  return translations[locale] ?? translations[DEFAULT_LOCALE];
}
 
export function getLocaleFromUrl(url: URL): Locale {
  const [, segment] = url.pathname.split("/");
  if (LOCALES.includes(segment as Locale) && segment !== DEFAULT_LOCALE) {
    return segment as Locale;
  }
  return DEFAULT_LOCALE;
}
 
export function localePath(path: string, locale: Locale): string {
  const cleanPath = path.startsWith("/") ? path : `/${path}`;
  if (locale === DEFAULT_LOCALE) return cleanPath;
  return `/${locale}${cleanPath}`;
}
 
/**
 * Retourne le chemin équivalent dans l'autre langue.
 * Ex: "/en/features" → "/fonctionnalites", "/tarifs" → "/en/pricing"
 */
export function getAlternatePath(currentPath: string, currentLocale: Locale, targetLocale: Locale): string {
  // Normaliser : retirer le trailing slash (sauf pour "/")
  let normalized = currentPath;
  while (normalized.length > 1 && normalized.endsWith("/")) {
    normalized = normalized.slice(0, -1);
  }
  normalized = normalized || "/";
 
  // Extraire le chemin "nu" (sans prefix de locale)
  let barePath = normalized;
  if (currentLocale !== DEFAULT_LOCALE && barePath.startsWith(`/${currentLocale}/`)) {
    barePath = barePath.slice(currentLocale.length + 1);
  } else if (currentLocale !== DEFAULT_LOCALE && barePath === `/${currentLocale}`) {
    barePath = "/";
  }
 
  if (targetLocale === "fr") {
    // EN → FR : chercher dans reverseRouteMap
    return reverseRouteMap[barePath] ?? barePath;
  }
  // FR → EN : chercher dans routeMap
  const enSlug = routeMap[barePath] ?? barePath;
  return `/en${enSlug}`;
}
 
export function getAlternateLocales(currentPath: string, currentLocale: Locale): { locale: Locale; href: string }[] {
  return LOCALES.map((locale) => ({
    locale,
    href: locale === currentLocale
      ? currentPath
      : getAlternatePath(currentPath, currentLocale, locale),
  }));
}
 
export function getLocaleLabel(locale: Locale): string {
  const labels: Record<Locale, string> = {
    fr: "Français",
    en: "English",
  };
  return labels[locale];
}