Un site e-commerce catalan de 8 000 pages produit voit son trafic organique chuter de 23% en trois mois — sans aucun changement technique, sans pénalité manuelle, sans mise à jour d'algorithme identifiée. La cause : les AI Overviews de Google citent systématiquement les pages espagnoles (es) au lieu des pages catalanes (ca), parce que le modèle de langue sous-jacent ne distingue pas correctement les deux langues. Ce n'est pas un bug isolé. C'est un problème structurel qui touche toutes les régions multilingues, et qui redéfinit les règles du SEO technique pour l'ère de la recherche IA.
Le problème fondamental : la language identification dans les LLMs
Les moteurs de recherche traditionnels s'appuient sur des signaux explicites pour déterminer la langue d'une page : la balise lang, les annotations hreflang, la locale détectée via l'IP ou les préférences navigateur. Ces signaux sont structurés, déclaratifs, et le crawler les respecte (en théorie).
Les LLMs fonctionnent différemment. Quand un modèle comme Gemini génère une AI Overview, il effectue un processus de retrieval-augmented generation (RAG) qui implique une étape de compréhension du contenu source. Cette compréhension passe par le tokenizer du modèle, qui transforme le texte en tokens avant tout traitement. Et c'est là que le problème commence.
Le biais du tokenizer sur les langues proches
Le catalan et l'espagnol partagent environ 85% de leur vocabulaire courant. Pour un tokenizer entraîné majoritairement sur des corpus anglais, espagnols et français, le catalan est sous-représenté. Le modèle n'a pas assez de données d'entraînement pour distinguer fiablement les deux langues dans des contextes courts (descriptions produit, FAQ, extraits de 200-300 mots).
Le résultat concret : quand un utilisateur effectue une recherche en catalan, l'AI Overview peut puiser dans des sources espagnoles jugées "sémantiquement équivalentes" par le modèle, même si une source catalane parfaitement pertinente existe et est indexée.
Ce problème ne se limite pas au catalan. Il affecte :
- Le galicien vs. le portugais
- Le luxembourgeois vs. l'allemand
- Le bokmål vs. le nynorsk (Norvège)
- Le serbe latinisé vs. le croate
- Le hindi vs. l'ourdou en script latin
Toute paire de langues avec une proximité lexicale élevée est vulnérable.
Pourquoi hreflang ne suffit plus
L'annotation hreflang indique à Googlebot quelle version servir à quel utilisateur. Mais dans le pipeline RAG d'une AI Overview, le contenu est déjà extrait et indexé dans un embedding vectoriel. L'annotation hreflang n'est pas un signal dans l'espace vectoriel — c'est une métadonnée de serving, pas de retrieval.
Dit autrement : hreflang dit "sers cette page aux utilisateurs catalans", mais le LLM qui construit l'AI Overview ne "sert" pas — il "cite". Et sa décision de citation repose sur la proximité sémantique dans l'espace d'embeddings, pas sur les annotations HTML.
Audit technique : détecter les confusions de langue sur votre site
Avant de corriger, il faut diagnostiquer. Voici une méthodologie pour identifier si votre site multilingue est affecté par des erreurs de language identification dans les résultats IA.
Étape 1 : extraire les AI Overviews par langue
Utilisez un script qui interroge les SERPs pour vos mots-clés principaux dans chaque langue cible, puis compare les sources citées dans les AI Overviews avec la langue attendue.
import requests
from bs4 import BeautifulSoup
import json
# Configuration pour un site catalan/espagnol
KEYWORDS = {
"ca": ["sabates de cuir", "roba de muntanya", "motxilles impermeables"],
"es": ["zapatos de cuero", "ropa de montaña", "mochilas impermeables"]
}
DOMAIN = "botiga-outdoor.cat"
def check_aio_citations(keyword: str, lang: str, gl: str = "ES") -> dict:
"""
Vérifie si les citations d'AI Overview matchent la langue attendue.
Nécessite un proxy SERP API (SerpAPI, ValueSERP, etc.)
"""
params = {
"q": keyword,
"hl": lang,
"gl": gl,
"engine": "google",
"api_key": "VOTRE_CLE_API"
}
response = requests.get("https://serpapi.com/search", params=params)
data = response.json()
ai_overview = data.get("ai_overview", {})
citations = ai_overview.get("citations", [])
mismatches = []
for citation in citations:
url = citation.get("link", "")
# Détecter la langue de la page citée via le path ou subdomain
if DOMAIN in url:
page_lang = detect_lang_from_url(url)
if page_lang != lang:
mismatches.append({
"keyword": keyword,
"expected_lang": lang,
"cited_url": url,
"cited_lang": page_lang
})
return {
"keyword": keyword,
"lang": lang,
"total_citations": len(citations),
"own_citations": len([c for c in citations if DOMAIN in c.get("link", "")]),
"lang_mismatches": mismatches
}
def detect_lang_from_url(url: str) -> str:
"""Détecte la langue à partir de la structure URL"""
if "/ca/" in url or url.startswith("https://ca."):
return "ca"
elif "/es/" in url or url.startswith("https://es."):
return "es"
return "unknown"
# Exécution
results = []
for lang, kws in KEYWORDS.items():
for kw in kws:
result = check_aio_citations(kw, lang)
results.append(result)
if result["lang_mismatches"]:
print(f"⚠ MISMATCH: '{kw}' ({lang}) → {len(result['lang_mismatches'])} citations en mauvaise langue")
Ce script est un point de départ. En production, vous voudrez l'exécuter de manière hebdomadaire et stocker les résultats pour suivre l'évolution. Un outil de monitoring comme Seogard peut automatiser cette détection en suivant les régressions de citations dans les AI Overviews par marché linguistique.
Étape 2 : vérifier la cohérence des signaux de langue
Crawlez votre site avec Screaming Frog en filtrant les incohérences entre l'attribut lang, le contenu réel de la page, et les annotations hreflang. Configurez un custom extraction :
Dans Screaming Frog → Configuration → Custom → Extraction :
- Extraction 1 :
//html/@lang(XPath) — récupère l'attribut lang déclaré - Extraction 2 :
//meta[@http-equiv='content-language']/@content(XPath) — récupère le content-language s'il existe - Extraction 3 :
//link[@rel='alternate'][@hreflang]/@hreflang(XPath) — récupère tous les hreflang déclarés
Exportez en CSV et croisez avec la détection de langue réelle du contenu. Un script rapide avec la bibliothèque langdetect de Python sur le texte extrait révèle les pages où le contenu ne correspond pas à la langue déclarée :
from langdetect import detect, DetectorFactory
import csv
# Reproductibilité des résultats
DetectorFactory.seed = 0
def audit_language_consistency(crawl_export: str) -> list:
"""
Croise la langue déclarée (html lang) avec la langue détectée
dans le contenu textuel extrait par Screaming Frog.
"""
issues = []
with open(crawl_export, "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
url = row.get("Address", "")
declared_lang = row.get("Lang 1", "").strip().lower() # custom extraction
body_text = row.get("Body Text 1", "") # si extrait
if not body_text or len(body_text) < 100:
continue
try:
detected_lang = detect(body_text)
except Exception:
detected_lang = "unknown"
# Normaliser : langdetect retourne 'ca' pour catalan, 'es' pour espagnol
# Mais attention : langdetect confond souvent ca/es sur des textes courts
if declared_lang and detected_lang != declared_lang:
# Vérifier si c'est une confusion connue (ca↔es, gl↔pt, etc.)
confused_pairs = [("ca", "es"), ("gl", "pt"), ("bs", "hr"), ("no", "da")]
is_confused_pair = any(
{declared_lang, detected_lang} == set(pair)
for pair in confused_pairs
)
issues.append({
"url": url,
"declared": declared_lang,
"detected": detected_lang,
"is_confused_pair": is_confused_pair,
"text_length": len(body_text),
"severity": "HIGH" if is_confused_pair else "MEDIUM"
})
return issues
# Utilisation
issues = audit_language_consistency("screaming_frog_export.csv")
high_severity = [i for i in issues if i["severity"] == "HIGH"]
print(f"{len(high_severity)} pages avec confusion de langue à haut risque")
Le point clé : si langdetect confond la langue de vos pages, les LLMs le font probablement aussi. Ces pages sont les premières candidates à une optimisation des signaux de langue.
Renforcer les signaux de langue au-delà de hreflang
Puisque les signaux déclaratifs (hreflang, lang) ne sont pas suffisants dans le pipeline RAG, il faut renforcer les signaux implicites — ceux que le LLM peut capter pendant l'extraction et l'embedding du contenu.
Stratégie 1 : densifier les marqueurs linguistiques distinctifs
Chaque langue a des structures grammaticales et des mots-outils qui la distinguent de ses langues sœurs. En catalan, les articles "el/la/els/les", les pronoms faibles ("em", "et", "en", "hi"), et les suffixes verbaux ("-ar", "-er", "-ir" vs. "-ar", "-er", "-ir" en espagnol mais avec des conjugaisons différentes) sont des signaux distinctifs.
L'idée n'est pas de sur-optimiser le texte — c'est de s'assurer que le contenu utilise naturellement les formes propres à la langue cible, plutôt que des calques de la langue dominante. En pratique, cela signifie :
- Éviter le "català light" (catalan truffé d'hispanismes) dans les descriptions produit
- Utiliser les pronoms faibles catalans là où un locuteur natif les utiliserait
- Privilégier le vocabulaire spécifiquement catalan quand il existe (ex: "ordinador" vs. "computadora")
Stratégie 2 : structured data avec indication de langue explicite
Le JSON-LD permet de spécifier la langue du contenu de manière granulaire via la propriété inLanguage. Ce signal est lisible par les crawlers traditionnels ET par les systèmes RAG qui parsent le structured data.
<script type="application/ld+json">
{
"@context": "https://schema.org",
"@type": "Product",
"name": "Motxilla impermeable de muntanya 45L",
"description": "Motxilla lleugera amb teixit impermeable de 3 capes. Dissenyada per a rutes d'alta muntanya als Pirineus catalans.",
"inLanguage": "ca",
"brand": {
"@type": "Brand",
"name": "Botiga Outdoor"
},
"offers": {
"@type": "Offer",
"priceCurrency": "EUR",
"price": "129.95",
"availability": "https://schema.org/InStock",
"areaServed": {
"@type": "AdministrativeArea",
"name": "Catalunya",
"inDefinedTermSet": "NUTS",
"termCode": "ES51"
}
},
"isPartOf": {
"@type": "WebPage",
"inLanguage": "ca",
"url": "https://botiga-outdoor.cat/ca/motxilles/impermeable-45l"
}
}
</script>
Trois points techniques à noter dans ce markup :
inLanguage: "ca"est déclaré à la fois sur le Product et sur la WebPage — redondance intentionnelle pour maximiser la captation du signalareaServedavec le code NUTS (ES51 = Catalunya) crée une association géographique explicite qui aide à la désambiguïsation- La description produit utilise des termes spécifiquement catalans ("lleugera", "teixit", "Pirineus catalans") qui renforcent le signal linguistique implicite
Stratégie 3 : en-têtes HTTP Content-Language
Ce signal est souvent oublié alors qu'il est lu avant même le parsing HTML. Configurez-le au niveau du serveur.
Pour Nginx, avec une architecture en sous-répertoires (/ca/, /es/) :
server {
listen 443 ssl;
server_name botiga-outdoor.cat;
# Langue par défaut
set $content_lang "ca";
# Détection basée sur le path
location ~ ^/es/ {
set $content_lang "es";
}
location ~ ^/fr/ {
set $content_lang "fr";
}
# Appliquer le header à toutes les réponses HTML
location / {
# Ne pas ajouter Content-Language sur les assets statiques
if ($uri ~* \.(css|js|png|jpg|svg|woff2)$) {
break;
}
add_header Content-Language $content_lang always;
# Vary header pour que les CDN cachent par langue
add_header Vary "Accept-Language" always;
proxy_pass http://backend;
}
# Pages spécifiques : forcer le catalan sur la homepage
location = / {
add_header Content-Language "ca" always;
add_header Vary "Accept-Language" always;
proxy_pass http://backend;
}
}
L'en-tête Content-Language est spécifié dans la documentation MDN comme un signal destiné aux systèmes de traitement automatique, pas uniquement aux navigateurs. C'est exactement ce dont les crawlers IA ont besoin.
Scénario réel : migration multilingue et effondrement des citations IA
Prenons un cas réaliste. BotigaraDeco est un e-commerce catalan de décoration intérieure : 12 400 pages produit, 850 pages catégorie, 320 pages éditoriales. Le site existe en catalan (ca) et espagnol (es), avec une architecture en sous-répertoires.
Situation initiale (janvier 2026) :
- 68% du trafic organique vient de requêtes en catalan
- Le site apparaît dans les AI Overviews pour 142 requêtes catalanes (mesuré via un suivi SERP hebdomadaire)
- Les citations AI pointent vers la version
/ca/dans 89% des cas
Événement déclencheur (février 2026) :
L'équipe technique migre le frontend de Nuxt 2 vers Nuxt 3. Pendant la migration, un changement dans la configuration SSR modifie la façon dont la page est rendue : le composant <html lang="ca"> est maintenant injecté côté client au lieu d'être présent dans le HTML initial.
Impact mesuré sur 8 semaines :
- Les citations AI en catalan chutent de 142 à 51 requêtes (-64%)
- Les citations vers
/es/pour des requêtes catalanes passent de 11% à 47% - Le trafic organique catalan baisse de 23% (mesuré dans GA4 en segmentant par paramètre
hl=cadans les referrers Search) - Le trafic espagnol reste stable — le problème est asymétrique
Diagnostic : le SSR de Nuxt 3 générait le <html> initial sans attribut lang, qui n'était ajouté qu'après hydration côté client. GoogleBot et les systèmes RAG qui crawlent le HTML pré-hydration voyaient une page sans signal de langue explicite. Combined avec le contenu textuel ambiguë (noms de produits internationaux, descriptions courtes), le modèle classifiait ces pages comme "espagnol" par défaut — la langue dominante de la région selon les données d'entraînement.
Correction :
Dans nuxt.config.ts, forcer la langue dans le rendu SSR :
// nuxt.config.ts
export default defineNuxtConfig({
app: {
head: {
htmlAttrs: {
// Langue par défaut, sera overridée par le middleware
lang: 'ca'
}
}
},
// Plugin SSR pour injecter la langue dynamiquement
nitro: {
plugins: ['~/server/plugins/lang-header.ts']
}
})
// server/plugins/lang-header.ts
export default defineNitroPlugin((nitroApp) => {
nitroApp.hooks.hook('render:html', (html, { event }) => {
const path = event.path || ''
let lang = 'ca' // défaut catalan
if (path.startsWith('/es/') || path.startsWith('/es?')) {
lang = 'es'
} else if (path.startsWith('/fr/')) {
lang = 'fr'
}
// Injecter lang dans la balise html AVANT l'hydration client
html.htmlAttrs = html.htmlAttrs || []
html.htmlAttrs.push(`lang="${lang}"`)
// Ajouter le header HTTP également
event.node.res.setHeader('Content-Language', lang)
})
})
Après déploiement de la correction et re-crawl (forcé via l'API d'indexation de Search Console pour les 200 pages les plus critiques), les citations AI sont revenues au niveau initial en 4 semaines.
Ce scénario illustre un problème que les audits SEO techniques classiques ne couvrent pas encore : la cohérence des signaux de langue dans le HTML pré-hydration n'est testée ni par Lighthouse, ni par la plupart des outils de crawl qui exécutent JavaScript.
L'impact structurel sur les AI Overviews et la GEO
Ce que révèle le cas catalan dépasse la simple correction technique. C'est un signal d'un problème structurel dans la façon dont les moteurs IA traitent les contenus multilingues.
Le biais de la langue dominante
Les LLMs ont un biais statistique en faveur des langues pour lesquelles ils disposent de plus de données d'entraînement. L'espagnol dispose d'un corpus web environ 15 fois plus large que le catalan. Ce ratio crée un prior bayésien implicite : quand le modèle hésite entre "c'est du catalan" et "c'est de l'espagnol", il penche vers l'espagnol par défaut.
En termes de SEO, cela signifie que les pages dans des langues minoritaires doivent fournir des signaux de langue plus forts que les pages dans des langues dominantes pour obtenir la même attribution. L'asymétrie est structurelle et ne sera pas corrigée par un simple update d'algorithme.
La fragmentation des citations
Les frameworks de mesure GEO doivent intégrer la dimension linguistique. Quand une AI Overview cite une source en espagnol pour répondre à une requête catalane, trois choses se produisent :
- L'utilisateur catalan reçoit une réponse dans une langue qu'il n'a pas demandée — dégradation de l'expérience utilisateur que Google dit vouloir éviter
- Le site catalan perd la citation — même si son contenu est pertinent et mieux adapté
- Les métriques de visibilité AI sont faussées — le site apparaît moins visible en catalan alors que le problème est côté moteur, pas côté contenu
Ce phénomène est documenté de façon plus large dans la problématique de la propagation d'information incorrecte dans l'IA de recherche : quand le système RAG sélectionne la mauvaise source, il propage une erreur en cascade.
Le consensus gap linguistique
Le concept de consensus gap prend une dimension nouvelle en contexte multilingue. Si les sources catalanes et espagnoles disent la même chose mais avec des nuances culturelles ou terminologiques, le LLM peut percevoir un désaccord artificiel et soit omettre la citation, soit créer une synthèse confuse.
Exemple concret : pour la requête "millors rutes senderisme Pirineus" (meilleures randonnées Pyrénées), les sources catalanes mentionnent des noms de lieux en catalan (Aigüestortes, Cadí-Moixeró) tandis que les sources espagnoles utilisent parfois les noms castillans. Le LLM peut traiter ces noms comme des entités différentes, créant un consensus gap artificiel qui dilue la visibilité de toutes les sources.
Stratégie de monitoring continu pour les sites multilingues
La détection ponctuelle ne suffit pas. Les confusions de langue dans les résultats IA sont dynamiques — elles changent avec chaque mise à jour du modèle, chaque re-crawl, chaque modification du contenu.
Métriques à suivre
Ajoutez ces KPIs à votre tableau de bord de mesure de la visibilité IA :
- Language Match Rate : % des citations AI qui pointent vers la bonne version linguistique de votre site, par langue cible
- Cross-Language Cannibalization : nombre de requêtes où la version es apparaît dans les AI Overviews à la place de la version ca (ou inversement)
- Citation Language Drift : évolution du Language Match Rate sur le temps — un drift négatif indique un problème de crawl ou de mise à jour du modèle
Vérifier le rendu SSR par langue
Un test simple mais critique : vérifier que chaque version linguistique retourne les bons signaux dans le HTML initial, sans exécution JavaScript.
# Vérifier le HTML SSR pour la version catalane
curl -s -o /dev/null -D - "https://botiga-outdoor.cat/ca/motxilles/" \
-H "User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1)" \
| grep -i "content-language"
# Extraire l'attribut lang du HTML pré-hydration
curl -s "https://botiga-outdoor.cat/ca/motxilles/" \
-H "User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1)" \
| grep -oP '<html[^>]*lang="[^"]*"' | head -1
# Comparer avec la version espagnole
curl -s "https://botiga-outdoor.cat/es/mochilas/" \
-H "User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1)" \
| grep -oP '<html[^>]*lang="[^"]*"' | head -1
# Vérifier le hreflang dans le HTML (pas dans le sitemap uniquement)
curl -s "https://botiga-outdoor.cat/ca/motxilles/" \
-H "User-Agent: Mozilla/5.0 (compatible; Googlebot/2.1)" \
| grep -oP 'hreflang="[^"]*"' | sort -u
Exécutez ces vérifications après chaque déploiement. Si le lang disparaît ou si le Content-Language ne correspond plus au path, vous avez une régression critique — le type exact de régression que Seogard détecte automatiquement en comparant le HTML rendu entre deux crawls.
Anticiper les prochaines mises à jour
Le core update de mai 2026 est en cours de déploiement au moment de la publication de cet article. Historiquement, les core updates modifient les poids relatifs des signaux utilisés dans le retrieval. Pour les sites multilingues, chaque core update est un risque de voir les seuils de language identification bouger.
La stratégie défensive : maintenir un snapshot hebdomadaire de vos citations AI par langue, et corréler toute variation avec les dates de rollout des updates. Si votre Language Match Rate chute de plus de 5 points pendant un update, c'est un signal que les critères de sélection de langue dans le RAG ont changé — et que votre contenu a besoin de signaux de langue plus forts.
Au-delà du catalan : ce que ça change pour tout le SEO multilingue
Le cas catalan est un canari dans la mine. Aujourd'hui, ce sont les langues minoritaires qui souffrent. Demain, à mesure que les AI Overviews s'étendent et que les agents IA deviennent des visiteurs réguliers du web, le problème touchera des marchés plus larges.
Les sites opérant en français canadien vs. français européen, en portugais brésilien vs. européen, ou même en anglais britannique vs. américain, verront des phénomènes similaires — plus subtils, mais avec un impact commercial réel sur la pertinence des réponses IA pour leur audience.
La recommandation technique est claire : ne traitez plus la langue comme un signal déclaratif passif. Traitez-la comme un signal actif qui doit être renforcé à chaque couche — HTML, HTTP headers, structured data, contenu textuel, et monitoring continu. Les sites qui maîtrisent cette stack multilingue complète seront ceux que les LLMs citent correctement. Les autres seront invisibles dans les réponses IA, remplacés par la version linguistique dominante de leur marché.