ADR-0038 — Préfixe de langue as-needed, sur les pages publiques seulement
L'ADR 0002 a constaté le problème et il n'a pas changé. La langue voyage dans le cookie NEXT_LOCALE et une même URL sert les six langues, donc Google n'indexe que l'anglais. Environ 31 000 mots traduits ne rankent nulle…
Statut
Accepté · 2026-09-25
Remplace : ADR-0002
Piliers : growth-web, security-identity, app-shell, platform-ops
Contexte
L'ADR 0002 a constaté le
problème et il n'a pas changé. La langue voyage dans le cookie
NEXT_LOCALE et une même URL sert les six langues, donc Google n'indexe
que l'anglais. Environ 31 000 mots traduits ne rankent nulle part.
L'ADR 0002 est restée proposed du 12 août au 25 septembre 2026, et
personne ne l'a portée (growth-web/0393).
Elle regroupait deux décisions en une :
- Le mode :
always(/en/pricing) ouas-needed(l'anglais reste/pricing, les autres langues passent en/fr/pricing). - Le périmètre : toute l'application (déplacer
src/app/sous[locale]/et réécrire les portes du proxy), ou les pages publiques seulement.
Elle choisissait always sur toute l'application. C'est la seule
combinaison qui déplace chaque URL existante, et donc la seule dont le
coût croît avec l'indexation : chaque URL indexée, chaque lien externe,
le user agent du scanner qui cite /about/scanner, l'URL que l'extension
Chrome ouvre et les liens des e-mails deviennent des redirections pour
toujours.
L'audit de nettoyage avant indexation du 2026-09-25
(docs/audits/2026-09-25-nettoyage-avant-indexation.md) a rouvert la
question au moment où elle coûte le moins, puisque le site est encore peu
indexé. Tranché le jour même.
Décision
La langue entre dans l'URL en mode as-needed, sur les pages
publiques seulement (groupes (marketing), (docs) et les pages
publiques de (minimal)) :
- l'anglais reste sans préfixe (
/pricing), et aucune URL existante ne bouge ; - les autres langues sont servies sous
/fr/…,/de/…,/es/…,/it/…et/pt/…; - le dashboard, l'admin et les écrans authentifiés ne portent pas de
préfixe, et les portes du proxy (
PROTECTED_PREFIXES, gate/admin, gate onboarding) restent telles quelles ; - une URL localisée n'est publiée qu'avec sa traduction (
growth-web/2949) : un MDX non traduit ne reçoit pas d'alternate hreflang ; - une fois la langue dans l'URL, un crawler n'est plus jamais redirigé
selon
Accept-Languageou le pays ; un humain voit un bandeau de langue.
Deux choses se font tout de suite, avant la couche elle-même :
- les six codes
en fr de es it ptsont réservés comme slugs d'organisation, parce qu'un préfixe de langue et[orgSlug]se disputent le même premier segment (security-identity/3004) ; - les renommages d'URL décidés par l'audit (vague 2) passent avant la couche de langue. Un renommage fait après coûterait six redirections au lieu d'une.
La couche est construite en vague 3, une fois les URLs définitives en
place. Le mécanisme (un segment [locale] limité aux groupes publics, ou
une réécriture du proxy qui retire /fr et transmet la langue par en-tête
à src/i18n/request.ts) est choisi dans l'item d'implémentation. Il doit
être vérifié sur une preview Vercel, comme l'ADR 0002 l'exigeait déjà.
Alternatives écartées
| Option | Pourquoi non |
|---|---|
always sur toute l'app (l'ADR 0002) | Toutes les URLs existantes passent en 308, pour toujours. Le proxy de sécurité doit devenir locale-aware, et une faute y ouvre un trou (/fr/account non reconnu comme protégé). Le dashboard n'a rien à gagner à l'indexation. |
always sur les pages publiques seulement | Mêmes 308 sur toutes les URLs publiques (sitemap, llms.txt, flux RSS, e-mails, user agent du scanner, extension) pour aucun gain par rapport à as-needed : l'anglais sans préfixe reste le x-default. |
| Rester sur le cookie | Cinq langues sur six restent invisibles pour les moteurs. Les traductions ne serviraient qu'aux utilisateurs déjà connectés. |
Sous-domaines (fr.boostecom.app) | Un domaine par langue divise l'autorité et ajoute un DNS, un certificat et un cookie de session par hôte, pour ce qu'un préfixe de chemin fait sans rien de tout ça. |
Conséquences
- Aucune URL anglaise ne change. Le coût de la couche ne dépend pas du moment où on la construit ; attendre ne retarde que l'acquisition non anglophone.
- Le rendu dynamique devient un levier. La langue lue dans l'URL
retire la lecture du cookie
getLocale()dans le layout racine, l'une des deux lectures de requête qui empêchent l'ISR (app-shell/0365). Il reste le nonce CSP. - Pour la communauté, les tutos et l'academy (anglais seulement aujourd'hui), aucun alternate n'est publié tant que la traduction n'existe pas.
growth-web/0393est tranché par cette ADR. L'ADR 0002 passe àsuperseded by 0038.
Mise en œuvre
growth-web/3023 (vague 3) a retenu la réécriture dans le proxy plutôt
qu'un segment [locale] : aucun fichier de src/app ne bouge, et un
préfixe devant autre chose qu'une page publique répond 307 vers le chemin
sans préfixe, donc les portes de sécurité du proxy restent celles
d'avant. Le détail vit dans AGENT.md, section « La langue dans l'URL »,
et dans src/i18n/locale-path.ts.