diff --git a/AGENTS.md b/AGENTS.md index 95fb296..64cbc0a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -20,7 +20,7 @@ - UI: Tailwind CSS v4 (brand tokens: `--color-brand`, `--color-brand-600`). - Icons: `lucide-astro` inline SVGs; use `text-brand` for accent. - JS: vanilla only (no jQuery). Prefer lightweight patterns (e.g., scrollBy carousels). -- i18n: use `hrefFor()` and `siblingPath()` for all internal links and language toggles. +- i18n: prefer `getRelativeLocaleUrl()` from `astro:i18n` for links; use `siblingPath()` for toggles when slugs differ. - Content slugs differ by locale (e.g., FR `avis` ↔ EN `reviews`) — never hardcode. ## Testing Guidelines diff --git a/astro.config.mjs b/astro.config.mjs index 508cbec..1405559 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -1,11 +1,19 @@ // @ts-check -import { defineConfig } from 'astro/config'; +import { defineConfig } from "astro/config"; -import tailwindcss from '@tailwindcss/vite'; +import tailwindcss from "@tailwindcss/vite"; // https://astro.build/config export default defineConfig({ + i18n: { + locales: ["fr", "en"], + defaultLocale: "fr", + routing: { + prefixDefaultLocale: true, + redirectToDefaultLocale: true, + }, + }, vite: { - plugins: [tailwindcss()] - } -}); \ No newline at end of file + plugins: [tailwindcss()], + }, +}); diff --git a/dist/index.html b/dist/index.html index e69de29..e6797cf 100644 --- a/dist/index.html +++ b/dist/index.html @@ -0,0 +1 @@ +Redirecting to: /fr Redirecting from / to /fr \ No newline at end of file diff --git a/src/i18n/routes.ts b/src/i18n/routes.ts index 4c05c94..c965b52 100644 --- a/src/i18n/routes.ts +++ b/src/i18n/routes.ts @@ -1,78 +1,67 @@ -export type Locale = 'fr' | 'en'; +export type Locale = "fr" | "en"; export type RouteKey = - | 'home' - | 'apartments' - | 'apartment_t2' - | 'apartment_t3' - | 'reviews' - | 'location' - | 'rates' - | 'contact' - | 'thank_you' - | 'terms' - | 'privacy' - | 'cancellation' - | 'house_rules'; + | "home" + | "apartments" + | "apartment_t2" + | "apartment_t3" + | "reviews" + | "location" + | "rates" + | "contact" + | "thank_you" + | "terms" + | "privacy" + | "cancellation" + | "house_rules"; export const routes: Record> = { - home: { fr: '/fr/', en: '/en/' }, - apartments: { fr: '/fr/appartements/', en: '/en/apartments/' }, - apartment_t2: { fr: '/fr/appartements/t2-corail/', en: '/en/apartments/t2-corail/' }, - apartment_t3: { fr: '/fr/appartements/t3-azur/', en: '/en/apartments/t3-azur/' }, - reviews: { fr: '/fr/avis/', en: '/en/reviews/' }, - location: { fr: '/fr/acces/', en: '/en/location-access/' }, - rates: { fr: '/fr/tarifs-disponibilites/', en: '/en/rates-availability/' }, - contact: { fr: '/fr/contact/', en: '/en/contact/' }, - thank_you: { fr: '/fr/merci/', en: '/en/thank-you/' }, - terms: { fr: '/fr/politiques/conditions/', en: '/en/policies/terms/' }, - privacy: { fr: '/fr/politiques/confidentialite/', en: '/en/policies/privacy/' }, - cancellation: { fr: '/fr/politiques/annulation/', en: '/en/policies/cancellation/' }, - house_rules: { fr: '/fr/politiques/reglement/', en: '/en/policies/house-rules/' }, + home: { fr: "/fr/", en: "/en/" }, + apartments: { fr: "/fr/appartements/", en: "/en/apartments/" }, + apartment_t2: { + fr: "/fr/appartements/t2-corail/", + en: "/en/apartments/t2-corail/", + }, + apartment_t3: { + fr: "/fr/appartements/t3-azur/", + en: "/en/apartments/t3-azur/", + }, + reviews: { fr: "/fr/avis/", en: "/en/reviews/" }, + location: { fr: "/fr/acces/", en: "/en/location-access/" }, + rates: { fr: "/fr/tarifs-disponibilites/", en: "/en/rates-availability/" }, + contact: { fr: "/fr/contact/", en: "/en/contact/" }, + thank_you: { fr: "/fr/merci/", en: "/en/thank-you/" }, + terms: { fr: "/fr/politiques/conditions/", en: "/en/policies/terms/" }, + privacy: { + fr: "/fr/politiques/confidentialite/", + en: "/en/policies/privacy/", + }, + cancellation: { + fr: "/fr/politiques/annulation/", + en: "/en/policies/cancellation/", + }, + house_rules: { + fr: "/fr/politiques/reglement/", + en: "/en/policies/house-rules/", + }, }; -const normalize = (p: string) => { - if (!p) return '/'; - let out = p.startsWith('/') ? p : `/${p}`; - if (!out.endsWith('/')) out = `${out}/`; - return out; -}; - -export function keyForPath(pathname: string): RouteKey | null { - const n = normalize(pathname); - for (const key of Object.keys(routes) as RouteKey[]) { - const localizations = routes[key]; - if (n === localizations.fr || n === localizations.en) return key; - } - return null; -} - -export function siblingPath(pathname: string, locale: Locale): string { - const key = keyForPath(pathname); - if (key) return routes[key][locale]; - return routes.home[locale]; -} - -export function hrefFor(key: RouteKey, locale: Locale): string { - return routes[key][locale]; -} - export function navFor(locale: Locale): Array<{ label: string; href: string }> { - return locale === 'en' + return locale === "en" ? [ - { label: 'Apartments', href: routes.apartments.en }, - { label: 'Reviews', href: routes.reviews.en }, - { label: 'Location & Access', href: routes.location.en }, - { label: 'Rates', href: routes.rates.en }, + { label: "Apartments", href: routes.apartments.en }, + { label: "Reviews", href: routes.reviews.en }, + { label: "Location & Access", href: routes.location.en }, + { label: "Rates", href: routes.rates.en }, ] : [ - { label: 'Appartements', href: routes.apartments.fr }, - { label: 'Avis', href: routes.reviews.fr }, - { label: 'Accès', href: routes.location.fr }, - { label: 'Tarifs', href: routes.rates.fr }, + { label: "Appartements", href: routes.apartments.fr }, + { label: "Avis", href: routes.reviews.fr }, + { label: "Accès", href: routes.location.fr }, + { label: "Tarifs", href: routes.rates.fr }, ]; } export function ctaLabelFor(locale: Locale): string { - return locale === 'en' ? 'Send a Request' : 'Envoyer une demande'; + return locale === "en" ? "Send a Request" : "Envoyer une demande"; } diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro index cfb8ae5..7ad4a99 100644 --- a/src/layouts/BaseLayout.astro +++ b/src/layouts/BaseLayout.astro @@ -1,13 +1,13 @@ --- import '../styles/global.css'; -import { siblingPath, hrefFor, navFor, ctaLabelFor } from '../i18n/routes'; +import { navFor, ctaLabelFor } from '../i18n/routes'; +import { getRelativeLocaleUrl } from 'astro:i18n'; const { title = 'VillaFleurie', lang = 'fr', description = 'Séjours confortables au Gosier pour couples et petites familles' } = Astro.props; -const pathname = Astro.url.pathname; -const altFr = siblingPath(pathname, 'fr'); -const altEn = siblingPath(pathname, 'en'); +const altFr = "/fr/" +const altEn = "/en/" const nav = navFor(lang); const ctaLabel = ctaLabelFor(lang); -const homeHref = hrefFor('home', lang); +const homeHref = getRelativeLocaleUrl(lang, '/'); --- @@ -36,7 +36,7 @@ const homeHref = hrefFor('home', lang);