Infrastructure i18n légère, sans deps externe : - lib/i18n/types.ts : LOCALES, DEFAULT_LOCALE, cookie name - lib/i18n/server.ts : getLocale (cookie > Accept-Language > FR), t(key) async server-side, dict(locale) - lib/i18n/client.tsx : LocaleProvider + useLocale + useT - messages/fr.json + messages/en.json : ~50 clés pour landing + header + footer - LocaleSwitcher component (cookie + router.refresh) Plugin gated : - Quand i18n-fr-en désactivé, getLocale() force FR. Le switcher ne s'affiche pas dans le hero. Pas d'impact sur le rendu existant. - Quand activé, switcher visible coin haut-droit du hero. Les composants landing/header/footer rendent en FR ou EN selon le cookie utilisateur. Composants i18n-isés : - HeroSection (eyebrow, titre, CTA) - ExperiencesSection (route/fleuve vs expédition, tous les bullets) - HowItWorksSection (3 étapes) - CESection (KPIs + body + CTA) - TestimonialsSection (eyebrow + titre, citations restent en VO) - Footer (taglines, colonnes) - SeasonBanner (3 saisons + messages) - AccessTypeBadge (labels + tooltips) Pour les ContentPage, le champ lang existait déjà. Une suite (PR ultérieure) ajoutera le filtre lang dans getContentPage + seed pages EN.
40 lines
1.3 KiB
TypeScript
40 lines
1.3 KiB
TypeScript
"use client";
|
|
|
|
import { useIsPluginEnabled } from "@/lib/plugins/client";
|
|
import { useT } from "@/lib/i18n/client";
|
|
import type { AccessType } from "@/generated/prisma/enums";
|
|
|
|
/**
|
|
* Badge route+fleuve vs fleuve only. Gated par le plugin `access-type`.
|
|
* Si le plugin est désactivé, rien n'est rendu. Label i18n via useT().
|
|
*/
|
|
export function AccessTypeBadge({
|
|
accessType,
|
|
size = "sm",
|
|
}: {
|
|
accessType: AccessType;
|
|
size?: "sm" | "md";
|
|
}) {
|
|
const enabled = useIsPluginEnabled("access-type");
|
|
const t = useT();
|
|
if (!enabled) return null;
|
|
|
|
const isExpedition = accessType === "RIVER_ONLY";
|
|
const label = isExpedition ? t("access.riverOnly") : t("access.roadAndRiver");
|
|
const styles = isExpedition
|
|
? "bg-[var(--color-karbe-laterite-300)]/25 text-[var(--color-karbe-laterite-700)] ring-[var(--color-karbe-laterite-500)]/30"
|
|
: "bg-[var(--color-karbe-canopy-50)] text-[var(--color-karbe-canopy-700)] ring-[var(--color-karbe-canopy-500)]/30";
|
|
const sizing =
|
|
size === "md"
|
|
? "px-3 py-1.5 text-xs"
|
|
: "px-2 py-0.5 text-[11px]";
|
|
|
|
return (
|
|
<span
|
|
className={`inline-flex items-center gap-1 rounded-full font-medium ring-1 ${styles} ${sizing}`}
|
|
title={isExpedition ? t("access.riverOnly.title") : t("access.roadAndRiver.title")}
|
|
>
|
|
{label}
|
|
</span>
|
|
);
|
|
}
|