Nous avons retiré une rubrique de deux langues cette semaine : un blog sans article traduit, qui ne servait qu’un gabarit vide. L’opération a pris dix minutes. Ce qu’elle a révélé en a pris davantage.
En vérifiant la page d’accueil anglaise après coup, cinq adresses françaises. Sur une page qu’on venait de nettoyer.
Le mécanisme, et pourquoi il paraît sage
Sur un site multilingue, chaque route existe en autant d’exemplaires que de langues. Quand le code demande l’adresse d’une page dans la langue courante, il peut arriver que cette route n’existe pas — parce que la rubrique n’est pas traduite, parce qu’elle est propre à un marché, parce qu’on vient de la retirer.
La plupart des implémentations font alors ceci :
if (! Route::has("{$locale}.{$name}")) {
// Route non traduite : on retombe sur la langue par défaut plutôt
// que de lever une exception en pleine page.
$qualified = Locale::default().'.'.$name;
}
Le commentaire dit vrai. Sans ce repli, un lien de pied de page vers une rubrique non traduite ferait tomber la page entière, en production, chez un visiteur. Personne ne veut ça.
Ce que ça produit réellement
Le repli ne distingue pas deux usages qui n’ont rien à voir.
Quand il sert à construire un gabarit — une URL de formulaire, une action de recherche — retomber sur la langue par défaut est acceptable : le visiteur ne voit rien, la page fonctionne.
Quand il sert à fabriquer un lien, il produit une adresse cliquable dans la mauvaise langue. Notre page d’accueil anglaise proposait « See client results » vers /fr/etudes-de-cas. Un bouton en anglais, une destination en français. Le lien fonctionne, la page s’ouvre, rien n’est cassé — et le visiteur est perdu.
Les cinq cas trouvés :
| Élément | Destination servie |
|---|---|
| Badge du bandeau d’accueil | /fr/blog |
| Bouton « See client results » | /fr/etudes-de-cas |
| Lien RSS du pied de page | /fr/feed.xml |
| Raccourcis de la page 404 | /fr/blog |
| Action de recherche du JSON-LD | /fr/blog?q= |
Le dernier n’avait aucun rapport avec l’opération du jour : il déclarait le blog français comme moteur de recherche du site, dans les trois langues, depuis toujours. Nous ne l’avions jamais vu parce que rien ne le montrait.
Pourquoi aucun test ne le voyait
C’est le point qui compte, et il vaut au-delà du multilingue.
Le test de fumée vérifiait que chaque page publique répond 200 dans chaque langue. Toutes répondaient 200. Les liens fonctionnaient — ils menaient simplement ailleurs que là où ils prétendaient. Un lien qui pointe vers la mauvaise langue est un lien valide. Aucun code d’erreur, aucune exception, aucune ligne dans les journaux.
C’est la même famille de défauts que celle d’une protection qui échoue en silence : le mécanisme s’exécute, retourne une réponse, et cette réponse est toujours acceptable. Ces défauts-là ne se découvrent pas, ils se cherchent.
Ce que ça coûte sur un site arabophone
Sur un site français qui bascule vers l’anglais, le visiteur comprend souvent la page d’arrivée. Le préjudice est réel mais amorti.
Sur un site trilingue avec de l’arabe, il ne l’est pas. Un visiteur arabophone qui clique sur un bouton en arabe et atterrit sur une page française ne bricole pas : il repart. Et la mise en page bascule avec lui — l’arabe s’écrit de droite à gauche, la page française de gauche à droite. Le changement est brutal, immédiatement lisible comme une erreur du site.
C’est une contrainte que nous rencontrons sur presque tous nos projets marocains, où le trilinguisme n’est pas une option de confort mais la condition d’accès à trois publics distincts. Une langue à moitié servie y coûte plus cher qu’une langue absente : l’absence est comprise, l’à-peu-près passe pour de la négligence.
Google en tire la même conclusion, par un autre chemin. Il suit ces liens, constate que la version arabe renvoie vers la version française, et en déduit que la version arabe n’est pas autonome. C’est exactement le raisonnement qui l’amène à écarter tout un balisage hreflang.
La règle, en deux temps
Le repli n’est pas à supprimer. Il est à cantonner.
Pour un gabarit, on le garde. Une URL d’action, une cible de formulaire : la langue par défaut ne se voit pas, la page tient.
Pour un lien, jamais. Là, la bonne question n’est pas « quelle adresse servir » mais « faut-il afficher ce lien ». Et la réponse est non quand la destination n’existe pas dans la langue affichée. Un menu qui perd une entrée est correct ; un menu qui pointe ailleurs ne l’est pas.
Concrètement, cela demande de tester l’existence avant de construire l’élément, et non de laisser la construction se débrouiller.
Le test qui ferme la porte
Un test suffit, et il vaut d’être écrit une fois pour toutes : charger chaque page publique dans chaque langue autre que la langue par défaut, retirer le sélecteur de langue et les balises alternates — les seuls endroits où une adresse étrangère est légitime — et refuser tout ce qui reste.
Chez nous il a immédiatement signalé les cinq liens d’un coup, y compris celui caché dans les données structurées, qu’aucune inspection visuelle n’aurait trouvé. Nous l’avons ensuite exécuté sans les correctifs pour vérifier qu’il échouait bien : un test qu’on n’a pas vu échouer ne prouve rien.
Il couvre aussi la page 404, qui proposait le blog français à un visiteur anglophone égaré. C’est précisément la page qu’atteint quelqu’un venu d’un lien vers une rubrique retirée — celle où l’erreur se répète au pire moment.
Ce qu’il faut en retenir
Un repli vers une valeur par défaut est un choix d’ingénierie légitime, et souvent le bon. Mais il transforme une erreur bruyante en comportement acceptable, et c’est exactement ce qui le rend dangereux : il ne supprime pas le problème, il supprime le signal.
Avant d’en écrire un, une question :
Si ce repli s’active en production, qu’est-ce qui me le dira ?
Si la réponse est « rien », ajoutez ce qui le dira — un journal, un test, une absence visible. Sinon vous n’avez pas écrit une tolérance, vous avez écrit une panne silencieuse qui attend son heure.