Pose una domanda e ottieni un riassunto del documento facendo riferimento a questa pagina e al provider AI di tua scelta
Il contenuto di questa pagina è stato tradotto con un'IA.
Vedi l'ultima versione del contenuto originale in ingleseSe hai un’idea per migliorare questa documentazione, non esitare a contribuire inviando una pull request su GitHub.
Collegamento GitHub alla documentazioneCopia il Markdown del documento nella porta-documenti
Hreflang: la guida per il SEO multilingue
Hai tradotto la tua app. Hai deployato /en, /fr, /es. E gli utenti francesi atterrano ancora sulla pagina in inglese.
La traduzione è la parte facile. La parte difficile è dire ai motori di ricerca che queste pagine sono la stessa pagina in un'altra lingua, non tre documenti che competono tra loro. Questo è quello che fa hreflang, ed è dove la maggior parte dei siti multilingue perdono silenziosamente il loro traffico.
Cosa è effettivamente hreflang
Un'annotazione su una pagina che dice: questo URL ha versioni equivalenti laggiù, per quelle lingue.
Copiare il codice nella clipboard
Ti offre due cose: la versione corretta mostrata all'utente giusto, e le tue locale consolidate in un cluster unico invece di cannibalizzarsi a vicenda come duplicati.
Vale la pena essere chiari su cosa non è. Non è un redirect — è un suggerimento, e Google potrebbe ignorarlo. Non è un ranking boost — cambia quale versione si posiziona, non se ti posizioni. E Bing lo ignora completamente, affidandosi invece a content-language e geo-targeting.
Dove dichiararlo
Tre posizionamenti, tutti validi. Scegliere uno e rimanere lì — lo stesso cluster dichiarato in due posti è come gli insiemi si divergono.
HTML <head> è la scelta abituale. Un avvertenza: i tag iniettati dopo l'idratazione sono inaffidabili. Se il tuo framework li aggiunge solo lato client, il crawler potrebbe non vederli mai.
XML sitemap è migliore su larga scala. Dieci locale su 5 000 pagine significa 50 000 elementi <link> inviati ai browser per niente; in una sitemap costa alle tue pagine zero byte.
HTTP Link header è l'unica opzione per file non HTML come i PDF.
Le regole
Auto-riferimento e reciprocità
L'insieme su /fr/about deve includere hreflang="fr" che punta a /fr/about. E se /about punta a /fr/about, /fr/about deve puntare indietro. Google chiama un riferimento unidirezionale un "no return tag" e lo scarta.
In pratica questo significa che ogni pagina in un cluster spedisce l'insieme identico di link. Generarli da una lista locale condivisa non è una comodità, è l'unico modo per rimanere corretti una volta che hai più di due locale.
URL assoluti, sempre
Copiare il codice nella clipboard
Il vale la pena comprendere il motivo piuttosto che memorizzarlo. hreflang è un riferimento cross-document: i motori di ricerca costruiscono un cluster identificato dall'URL, condiviso su ogni pagina in esso. Un percorso relativo ha significato solo relativamente al documento in cui si trova, quindi non può esprimerlo. Non può nemmeno attraversare un host — e un alternate spesso lo fa, quando una locale vive su example.fr o fr.example.com. In una sitemap o in un header HTTP non c'è alcun documento base su cui risolvere.
Questo ha una conseguenza diretta nel codice. getLocalizedUrl("/about", "fr") restituisce /fr/about — relativo in ingresso, relativo in uscita. Per hreflang devi fornirgli un URL assoluto:
Copiare il codice nella clipboard
L'unica eccezione è un framework che risolve i valori relativi per te prima del rendering: Next.js espande gli alternates relativi rispetto a metadataBase. Va bene — ma la regola si applica all'HTML emesso, quindi verifica con curl, non l'inspector di DevTools.
Codici linguistici
ISO 639-1 per la lingua, ISO 3166-1 Alpha 2 per la regione opzionale: fr, fr-CA, pt-BR.
Due trappole catturano quasi tutti. Una regione da sola è invalida — hreflang="ca" è catalano, non Canada; hai bisogno di en-CA o fr-CA. E en-UK non esiste: il codice del paese per il Regno Unito è GB, quindi è en-GB.
Aggiungi una regione solo quando servi genuinamente contenuti diversi per quella regione — prezzi diversi, avvisi legali diversi. fr e fr-FR su contenuto identico è rumore.
x-default
Copiare il codice nella clipboard
Un concetto che è il più frequentemente dimenticato, e male interpretato, è x-default — meno del 30% delle app lo implementano correttamente.
È il fallback per gli utenti la cui lingua non corrisponde a nulla nel tuo set. Un parlante olandese su un sito che offre inglese, francese e spagnolo non corrisponde a nessuna voce; senza x-default, Google sceglie per te.
Quello che le persone non capiscono è il significato. x-default non è "la versione in inglese" e non è "la locale predefinita", anche se di solito punta lì. Significa la pagina per gli utenti che questo set non copre. Ecco perché è legittimo — e spesso migliore — farla puntare a un selettore di lingua o a una pagina di destinazione con reindirizzamento geografico piuttosto che a /en. Se non hai una tale pagina, la tua lingua principale è la risposta sensata.
Due cose da tenere distinte: x-default è una voce aggiuntiva nel set, non un sostituto di quella auto-referenziale, e come tutte le altre voci deve apparire identicamente su ogni pagina nel cluster.
La trappola del canonical
Ogni pagina localizzata deve essere il proprio canonical:
Copiare il codice nella clipboard
Puntare il canonical di ogni locale alla versione in inglese invece:
Copiare il codice nella clipboard
dice che la pagina francese è un duplicato che non deve essere indicizzato, mentre hreflang dice che è la pagina da servire agli utenti francesi. I segnali sono contraddittori, il canonical vince, e le tue pagine francesi escono dall'indice.
Il canonical è auto-referenziale per locale. hreflang descrive il cluster.
Scelta di una struttura URL
hreflang annota gli URL, quindi la struttura viene prima.
Apri la tabella in una finestra modale per visualizzare tutti i dati in modo chiaro
| Struttura | Esempio | Trade-off |
|---|---|---|
| Sottodirectory | example.com/fr/ | Un dominio, autorità condivisa — segnale geo più debole |
| Sottodomini | fr.example.com | Facile aggiungere o rimuovere una locale — può essere letto come un sito separato |
| ccTLD | example.fr | Segnale paese più forte — autorità costruita per dominio |
Le sottodirectory sono la scelta predefinita giusta per la maggior parte dei progetti. Ricorri ai ccTLD solo quando operi davvero come aziende in paesi separati.
L'unica struttura da evitare: servire lingue diverse nello stesso URL basandosi su Accept-Language o IP. I crawler vedono una versione e indicizzano una versione; tutto il resto è invisibile.
Intlayer copre tutti e tre attraversorouting.modeerouting.domains. Vedi custom domains e configuration reference.
Implementazione
Scrivere manualmente questi tag non funziona quando si aggiunge una seconda lingua. Deriva questi tag dalla tua lista di locale.
Emetti il cluster su ogni pagina
Lo stesso set ovunque, canonical per locale, URL assoluti,
x-defaultincluso.La Metadata API espone
alternates.languages, egetMultilingualUrlscostruisce l'intero record dalle tue locale configurate:src/app/[locale]/about/page.tsxCopiare il codiceCopiare il codice nella clipboard
Configurazione completa: Guida i18n Next.js 16.
La funzione
headdella route costruisce i link.localeMapitera sulle tue locale configurate, quindi aggiungere una locale alla config la aggiunge ovunque in una volta:src/routes/{-$locale}/about.tsxCopiare il codiceCopiare il codice nella clipboard
headviene eseguito sul server, quindi i tag finiscono nell'HTML iniziale. Setup completo: Guida i18n TanStack.Oppure spostalo tutto nella sitemap
Su larga scala, mantieni le annotazioni completamente fuori dalle tue pagine.
generateSitemapemette alternatixhtml:linkper ogni voce, leggendo locale e modalità di routing dalla tua configurazione:src/routes/sitemap[.]xml.tsCopiare il codiceCopiare il codice nella clipboard
Due opzioni da conoscere:
xhtmlLinks(defaulttrue) — gli alternates vengono emessi solo dove gli URL delle locale differiscono effettivamente. In modalitàno-prefixogni locale condivide un URL, quindi vengono saltati a meno cherouting.domainsnon dia alle locale i loro hostname.entryPerLocale(defaultfalse) — per default un'entry<url>contiene tutti gli alternati. Entrambe le forme sono valide, ma solo un URL elencato come<loc>conta come submitted in Search Console; le locale alternate rimangono scopribili ma attribuite a nessuna sitemap. Attivando questa opzione ogni URL localizzato ottiene la propria entry con l'intero set di alternati ripetuto. Moltiplica le entry per il numero di locale, quindi fai attenzione al limite di 50 000 URL / 50 MB e dividi in un indice sitemap oltre questo limite.
Verifica cosa riceve il crawler
hreflangfallisce silenziosamente, quindi controllalo piuttosto che darla per scontata.Leggi il source, non l'inspector —
curl https://example.com/fr/about | grep hreflangmostra quello che riceve un crawler; DevTools mostra il DOM dopo che JavaScript è stato eseguito. Quindi segui ogni alternate e conferma che punta indietro con lo stesso insieme, e che nessuno di loro reindirizza. Il rapporto International Targeting di Search Console cattura il resto su tutto il sito.Per una crawl specifica per multilingua, lo Intlayer SEO Scanner verifica tag mancanti, alternate rotti e conflitti canonici nelle tue pagine localizzate.
Checklist
- Ogni locale ha un URL distinto e crawlabile
- Ogni pagina auto-riferisce, e ogni riferimento è reciproco
- Lo stesso set viene spedito su ogni pagina nel cluster
- Tutti i valori
hrefsono assoluti nell'HTML emesso - I codici sono ISO 639-1 + ISO 3166-1 Alpha 2 (
en-GB, nonen-UK) -
x-defaultè presente e punta a dove gli utenti non corrispondenti dovrebbero andare - Il canonical è auto-referenziale per locale
- I tag sono renderizzati lato server, non iniettati dopo l'idratazione
- Dichiarati esattamente in un unico posto
- Nessun redirect degli alternati
Conclusioni
hreflang è semplice e intransigente. Un tag di ritorno mancante, un URL relativo, un canonical cross-locale, e il cluster viene scartato senza errori da nessuna parte. Ognuno di questi problemi deriva dalla scrittura manuale dei tag.
Deriva l'insieme da un singolo elenco di locale, renderizzalo lato server, mantieni il canonical auto-referenziale e dai a x-default la considerazione che merita. Fallo una volta e la correttezza smette di essere qualcosa che devi mantenere.
Approfondimenti
- SEO e Internazionalizzazione — il quadro più ampio della SEO multilingue
- SEO e i18n in Next.js —
next-intlvsnext-i18nextvs Intlayer - Guida Next.js 16 i18n
- Guida i18n TanStack Start
- Domini personalizzati per locale
- Riferimento della configurazione
Commenti
Ancora nessun commento. Sii il primo a condividere i tuoi pensieri.
