## Summary

Adds **FR/EN/ES multilingual** support to the headless WordPress + Next.js site via **Polylang**, for the 26 main pages (the ~349 `lieu` local-SEO pages stay FR). Translations are ported **verbatim** from the Vite maquette (already localized — not machine translation).

### WordPress backend — already deployed to `covalba-admin`
- **Polylang** (free) + a **custom WPGraphQL extension** (`inc/graphql-i18n.php`) exposing `language` + `translations` (the `wp-graphql-polylang` plugin needs a composer build and doesn't target WPGraphQL 2.x).
- Seed engine extended: language-aware lookups (deterministic `_cvbseed_key` meta + PHP language fallback — Polylang's `lang` query-var is unreliable in WP-CLI), **3-pass run** linking FR↔EN↔ES, plus `register-languages.php` and `assign-fr.php`.
- **Deployed state**: full backup first (`backups/pre-polylang-i18n-20260623.sql.gz`), Polylang installed, `fr`/`en`/`es` registered, **387 FR posts assigned**, **25 pages × EN/ES seeded + linked**. GraphQL verified returning per-language `seo` / `ficheProduit` / `sections` (FR/EN/ES taglines + 10 sections each on covatherm).

### Next.js front
- Additive `/en` + `/es` localized routes (`app/en|es/[[...slug]]`) — **zero change to FR routes**. They resolve a localized URL → FR identity → Polylang translation → render with the **same** components (parité pixel).
- **Neutral** language codes `fr`/`en`/`es` everywhere (URLs, hreflang, `<html lang>`, og:locale — no `fr_FR`).
- `language` param + `translations` on the WP queries, gated by `WP_I18N_ENABLED` so the GraphQL schema stays valid before Polylang exists.
- Dynamic `<html lang>` (middleware + layout), hreflang + localized `sitemap.ts` with alternates, `LanguageSwitcher`, locale-aware `Navbar`/`Footer` (copy ported verbatim from the maquette).
- Language-qualified revalidation tags (FR tags unchanged; en/es add `:{lang}:`).

### ⚠️ Required before EN/ES render
Set **`WP_I18N_ENABLED=true`** in Vercel — **Preview** to validate this branch, **Production** on merge. Without it the front stays FR-only (safe default), and `/en` `/es` return 404.

## Test plan
- [ ] Set `WP_I18N_ENABLED=true` on the Vercel **Preview** env, redeploy this branch.
- [ ] `/`, `/en`, `/es` render their localized home.
- [ ] A produit (`/en/solutions/covatherm`, `/es/soluciones/covatherm`), a toiture (`/en/roofs/steel-deck`, `/es/cubiertas/chapa-de-acero`), an industrie, and a one-off (`/en/contact`) render **localized** content.
- [ ] View source: `<html lang>`, hreflang `fr`/`en`/`es`/`x-default`, canonical per locale, `/sitemap.xml` alternates.
- [ ] `LanguageSwitcher` swaps FR/EN/ES on a translated page.
- [ ] FR site unchanged (no regression).

## Notes / known minor items
- Polylang assigns internal suffixed slugs to same-slug translations (`covatherm-2`/`-3`) — purely internal; the front anchors on the FR slug and follows `translations`.
- EN/ES legitimately drop France-specific content (CEE subsidy FAQ rows, BAT-EN-112) exactly as the maquette does.
- A few SVG logos failed to upload on industrie pages (Safe-SVG blocks CLI SVG sideload, FR-side too) — decorative.
- `/en/blog` `/es/blog` are out of scope (blog index is a front-only view, not seeded).

🤖 Generated with [Claude Code](https://claude.com/claude-code)
