# hreflang: the common mistakes and how to find them

A wrong hreflang throws no error: Google drops the pair. The five recurring mistakes, the script that finds them and what no check can see.

> Page: https://ui.eneawork.it/blog/hreflang-errori-comuni
> Markdown: https://ui.eneawork.it/blog/hreflang-errori-comuni.md

*2026-11-01*

Un hreflang sbagliato non produce un errore visibile: Google scarta l'annotazione e serve la versione che ritiene adatta, spesso quella sbagliata. Gli errori ricorrenti sono cinque, e tre di questi si trovano con uno script prima del deploy.

Il catalogo EneUI conta 111.985 componenti, 1.556 blocchi e 12.808 icone da 1.472 librerie, letti da /api/stats il 1 novembre 2026. Sul blog le versioni inglesi vivono sotto /en/blog/<slug> e quelle italiane sotto /it/blog/<slug>; l'annotazione hreflang compare sia nell'head sia nella sitemap, con x-default puntato alla versione inglese, mentre un articolo senza traduzione tiene la sola coppia it + x-default. Il comportamento è stato letto in backend/seo.js e in backend/commercial.js il 1 novembre 2026. Le liste Autocomplete registrate il 31 ottobre 2026 non contengono la parola hreflang.

## Come si dichiara

Si dichiara con un elemento link nell'head, oppure con xhtml:link dentro la sitemap. Ogni pagina elenca sé stessa e tutte le altre versioni, con URL assoluti: un href relativo viene ignorato. Il codice lingua segue ISO 639-1, la regione ISO 3166-1 alpha-2, e x-default indica la pagina di fallback quando nessuna lingua è la scelta giusta.

## Errore 1: manca il ritorno

Una sola direzione non basta. Se la pagina italiana elenca quella inglese e la pagina inglese non elenca quella italiana, Google tratta l'annotazione come non confermata e può ignorarla. La variante più frequente è l'auto-riferimento mancante: ogni pagina deve elencare anche sé stessa.

## Errore 2: codici lingua inventati

en-UK non esiste: la regione del Regno Unito è GB. it-IT è valido ma inutile, perché it senza regione copre già l'italiano. Un codice come en-EU non corrisponde a nessuno stato e viene scartato. Il confronto è case-insensitive, ma la forma leggibile resta minuscola per la lingua e maiuscola per la regione.

## Errore 3: canonical che contraddice hreflang

Ogni versione linguistica dichiara sé stessa come canonical. Se la pagina inglese ha canonical verso l'italiana, Google considera l'inglese un duplicato e all'hreflang restano due URL che puntano allo stesso posto. Canonical e hreflang rispondono a due domande diverse: quale URL è quello giusto, e quale lingua serve a chi.

## Errore 4: la destinazione reindirizza o è noindex

Un hreflang che punta a un URL che reindirizza, che risponde 404 o che porta noindex viene ignorato. Succede quando cambia lo slug della traduzione e l'annotazione resta indietro. La verifica è meccanica: si segue ogni href e si controlla lo status della risposta.

## Errore 5: hreflang su contenuti non tradotti

hreflang collega versioni della stessa pagina in lingue diverse, non pagine che parlano dello stesso argomento. Due articoli diversi, uno italiano e uno inglese, non sono alternates: sono due pagine, e vanno collegate con un link normale.

## Controllarlo sulla sitemap

cat > check-hreflang.mjs ([\s\S]*?)/g)].map((m) => m[1]); const locs = new Set(blocks.map((b) => (b.match(/([^/) || [])[1])); let broken = 0; for (const block of blocks) { const loc = (block.match(/([^/) || [])[1]; const alts = [...block.matchAll(/hreflang="([^"]+)" href="([^"]+)"/g)] .map((m) => ({ lang: m[1].toLowerCase(), href: m[2] })); for (const alt of alts) { if (locs.has(alt.href)) continue; broken++; console.log("NOT DECLARED " + alt.href + " (from " + loc + ")"); } console.log(alts.map((a) => a.lang).join(",") + " " + loc); } console.log(blocks.length + " URLs · " + broken + " alternates without a target"); EOF node check-hreflang.mjs

Lo script legge la sitemap del blog, raccoglie per ogni URL le annotazioni hreflang e verifica che ogni destinazione sia dichiarata nel file. Un URL citato e mai dichiarato è una coppia rotta: Google legge l'annotazione ma non trova la pagina che dovrebbe confermarla.

## Il catalogo EneUI

Un selettore di lingua non è un componente SEO, ma è il punto in cui gli errori nascono: language-switcher-pill, licenza MIT, cambia URL senza ricaricare la pagina; language-selector-dropdown non dichiara una licenza nel record e va verificato prima dell'uso. I blocchi navbar mostrano dove quel selettore finisce. Dati verificati il 1 novembre 2026.

## La limitazione

hreflang è un segnale, non una direttiva: Google può ignorarlo se il contenuto non è davvero equivalente. Nessun validatore vede quella differenza, perché richiede di leggere entrambe le versioni. Search Console segnala le coppie senza ritorno, non le traduzioni fatte male.

## Dove continuare

Come si divide un indice di URL è in sitemap index o sitemap unico; la sequenza per entrare nell'indice è in indicizzare un sito su Google. Se la scelta è tra due stack per un sito marketing, il confronto è in Next.js o Vite per un sito marketing.

## FAQ

### hreflang deve stare nell'head?

No. Va bene nell'head con un elemento link, oppure nella sitemap con xhtml:link. Conta che ogni pagina elenchi sé stessa e tutte le altre versioni.

### Serve hreflang se il sito è solo in italiano?

No. hreflang collega lingue diverse della stessa pagina: con una sola lingua non c'è nulla da collegare e basta il canonical.

### Cosa fa x-default?

Indica la pagina di fallback per chi non corrisponde a nessuna lingua elencata, per esempio un selettore o una pagina di scelta.

### hreflang migliora il ranking?

No, non è un fattore di ranking. Serve a mostrare la versione giusta al lettore giusto, e un errore si paga in esperienza, non in posizione.

### Quante lingue posso dichiarare?

Non c'è un limite pratico: ogni pagina elenca tutte le versioni disponibili, con URL assoluti. Oltre una decina la verifica a mano non regge, e serve uno script.
