# hreflang in plain English — how Google knows which language version goes where

Topic: [Multilingual website](https://btlabs.dev/en/multilingual-website)

> An address per language, two-way references, x-default and a sitemap: how hreflang works, which mistakes break it, and what it can't do for you.

Anyone searching for your business from Bolzano, Milan or Munich expects the answer in their own language. For Google, that isn't a given. **hreflang** is the annotation a website uses to tell Google at which addresses the same content exists in other languages. That's all it does: it matches versions to each other — it doesn't push them up the rankings.

For the matching to work, you need four things: a separate address for each language, references in both directions, a fallback version called x-default, and a sitemap that knows every version. This article walks through them one by one, using a winery in Kaltern (Caldaro) with a wine-tasting page in German, Italian and English. After that come the three mistakes that most often break hreflang in practice.

## What hreflang is, in one sentence.

hreflang is an invisible reference in the head section of a page that says: "This page also exists in Italian, at this address." Google describes its purpose in its [guide to localized versions of a page](https://developers.google.com/search/docs/specialty/international/localized-versions): the annotations help Search point users to the most appropriate version by language or region.

For the winery, the English page lists three addresses:

- German: /de/weinverkostung
- Italian: /it/degustazione-vini
- English: /en/wine-tasting

The language is given as a short code: de, it, en. An extra country code such as de-AT is only needed if you maintain different versions in the same language for different countries. For most businesses in South Tyrol, that isn't the case.

## No address of its own, nothing to link.

hreflang can only point to addresses: if the Italian version doesn't live at its own address and only exists as a switch in the browser, the reference has nowhere to go. Why the same limit applies to AI systems is covered in [A translate button doesn't turn one website into three](https://btlabs.dev/en/posts/translate-button-doesnt-make-three-languages).

The clearest approach is a language prefix: every address starts with the language — /de/, /it/ or /en/. That way the language shows in the address itself, and no version hides behind the bare domain. In btlabs Core this prefix is mandatory, even for the main language, German. Ideally the rest of the address is translated too: for people searching in Italian, /it/degustazione-vini reads more naturally than /it/weinverkostung.

## References only count both ways.

hreflang only works when the versions name each other: the German page points to the Italian one, and the Italian page points back to the German one. Google states that if two pages don't both point to each other, the annotations are ignored. Google's reasoning is simple: otherwise any unrelated website could claim to be the Italian version of your page.

One detail often goes missing: every version also names itself. So the winery's Italian page carries the same list as the German one — all three addresses, its own included.

## x-default: the version for everyone else.

x-default is the version for everyone whose language you don't offer — say, a guest from the Netherlands whose browser is set to Dutch. Google calls it optional but recommended, because it lets you decide what appears in that case.

Which page that should be is a decision, not a rule. Common choices are the main language, the English version or a dedicated language picker. For a winery with lots of international guests, English may be the obvious pick; for a tradesperson in the South Tyrolean Unterland, German or Italian is more likely. What matters is that x-default is set and points to the same page from every version.

## The sitemap keeps every version together.

Instead of sitting in the head of each page, hreflang annotations can also live in the sitemap — the file that lists every address of a website for search engines. Google names three methods: the page's head section, the server's response (meant for files such as PDFs), or the sitemap. There, each address carries the list of all its language versions, again including itself.

The advantage of the sitemap: one file shows whether the linking is complete, instead of you opening thirty pages one by one. In btlabs Core, sitemaps are generated separately for each content type — pages and posts, for example — and every address in them carries its language versions with hreflang annotations. What the system doesn't do for you: submit the sitemap to Google. That's a one-time step in Google Search Console, and it's the only place where you can see whether Google was able to read it.

## Three mistakes that break hreflang.

The most common hreflang mistakes aren't in the code; they're in well-meant decisions.

### Automatic redirects based on browser language

A website that automatically redirects visitors based on their browser language hides the other versions — from people and from Google alike. Google explicitly advises against it in its [guidance on multilingual sites](https://developers.google.com/search/docs/specialty/international/managing-multi-regional-sites). There's a technical reason too: according to Google, its crawler [sends no language preference](https://developers.google.com/search/docs/specialty/international/locale-adaptive-pages) and usually crawls from addresses in the United States. A redirect by language or location may therefore only ever show it the same version.

South Tyrol adds an everyday problem: the browser language isn't always the preferred one. The office computer is set to German, but the bookkeeper would rather read Italian. Better than any automation is a clearly visible language switcher that leads to the matching version of the same page — not back to the start page.

### Translations without an address, addresses without a translation

The first half is familiar: a translation that only appears in the browser has no address, so hreflang has nothing to point to. Less familiar is the reverse: an Italian address showing German text because the translation isn't there yet. Google says it determines a page's language from its visible content, not from the address or from annotations in the code. To Google, that page is German — and an hreflang that labels it Italian contradicts what Google reads for itself.

btlabs Core is deliberately strict here: a page that hasn't been translated simply isn't reachable in the other language, rather than serving German text under an Italian address. You could see that as a gap. It's a decision in favour of signals that are true.

### Missing return links

Return links are rarely missing from the start; they get lost in later changes. A new English page is added, but the German and Italian pages are never updated. Or an address is renamed in one language, and the other versions keep pointing to the old one. Since Google ignores one-way references, the matching for that page quietly disappears, and nothing on the website itself gives it away.

The spot check takes two minutes: open a page, view the page source (right-click or Ctrl+U) and search for "hreflang". Are all languages there, x-default included? Then run the same check on the Italian and German versions.

## What hreflang doesn't do.

hreflang isn't a lever for better positions — it's a lever for the right version. Google describes it as a way to show searchers the appropriate language version; better rankings aren't mentioned. A page that isn't found in Italian won't suddenly be found thanks to hreflang. But where Google would show one of your versions anyway, hreflang helps make sure it's the right one.

Nor does hreflang translate anything or force anything. Even with clean annotations, Google decides which version to show to whom.

For AI assistants, there's no guide comparable to Google's: whether and how they use hreflang is an open question. What's certain is the foundation underneath — a machine can only read what it can fetch at an address of its own. Why three well-kept versions pay off in South Tyrol in particular is covered in [Three languages, one citability](https://btlabs.dev/en/posts/three-languages-one-citability).

## The quick check.

Whether Google can match the versions correctly comes down to five points on any multilingual website:

- Every language has its own address, ideally with a language prefix.
- Every version names all the others and itself.
- x-default is set and points to the same page everywhere.
- The sitemap lists every language version.
- Nobody gets redirected by browser language without asking.

How btlabs Core anchors language versions in its foundation is shown on the [multilingual website](https://btlabs.dev/en/multilingual-website) page. And if you'd like to know whether the language references on your own website are right: [drop us a line](https://btlabs.dev/en/contact), and we'll look at the source code together.

---
Source: https://btlabs.dev/en/posts/hreflang-in-plain-english
Last-Modified: 2026-10-21T07:00:01.809Z
Languages: [de](https://btlabs.dev/llms/de/posts/hreflang-ohne-fachchinesisch) · [it](https://btlabs.dev/llms/it/posts/hreflang-senza-tecnicismi)
See also: [llms.txt](https://btlabs.dev/llms.txt) · [ai.txt (Policy)](https://btlabs.dev/ai.txt) · [identity.json](https://btlabs.dev/identity.json)
