Machine translation makes a multilingual site cheap to produce and easy to get wrong. The pages are generated in a loop, the hreflang tags are generated in the same loop, and the result looks complete: every URL points at every other URL, every language is declared, and nothing is checked. hreflang is a declaration of alternatives, not a quality signal, and a declaration that names pages which do not exist is a broken promise a single fetch cannot catch.
This article is about the cluster as a system: what has to be true for it to be valid, what machine translation adds to the failure list, and what this site does when a page is translated into some languages but not others.
What hreflang declares
An hreflang annotation says: this URL is the version of the page for this language (and optionally region), and these other URLs are the other versions. The set is a cluster, and the rules are about the cluster rather than any single tag.
- Every version lists every version, including itself. The relationship is reciprocal; a one-way declaration is ignored or only half-applied.
x-defaultnames the fallback — the version to show when no language matches. It is not a language code and does not count as one.- Each version canonicalises to itself. The Chinese page’s canonical is the Chinese URL, not the English one; the hreflang cluster is what connects them.
- Only pages that exist and are indexable belong in the cluster. A version that 404s, redirects, or is noindexed is not an alternate.
- Codes are language tags, not marketing names.
zh-Hansandpt-BRare tags;chineseandinternationalare not.
What machine translation adds to the failure list
| Failure | Why it happens | What to do instead |
|---|---|---|
| Every page translated, including the thin ones | Translation is cheap, so the loop covers legal pages, tag archives and empty categories. | Translate the pages that carry value; leave the rest in the source language or out of the index. |
| One-way hreflang | The template emits the full list on the source page but a partial one on the translated page. | Generate the cluster from one list, not from per-page logic. |
| Declared versions that were never built | The cluster is generated from the locale list, not from the pages that exist. | Read the translations from the same registry that drives routing. |
| x-default missing or pointing at a redirect | The fallback is copied from the source URL before a locale prefix is added. | Point x-default at the language selector or the canonical default page, and check it resolves. |
| Canonical pointing across languages | A template canonicalises every version to the source language. | Self-canonical per version; let hreflang do the connecting. |
| Auto-redirect by IP or Accept-Language | It feels helpful to show the "right" language. | Keep every version crawlable at its own URL; offer a switch instead of a redirect. |
| Weak translations indexed for every market | hreflang is treated as a publishing decision. | Apply a quality bar; noindex or unpublish a language that does not meet it. |
Partial translation is normal; declaring it wrong is not
Most sites are not uniformly translated. A blog may have thirty English posts and five Chinese ones; a product may have six locales on the homepage and one on the legal pages. That is fine. What is not fine is emitting a six-language cluster on a page that exists in two.
This site handles it with a registry field rather than a locale list: a piece declares the languages it actually exists in, and everything downstream reads that field. The English-only posts in this series declare ["en"]; their alternate block is English plusx-default, the sitemap lists no Chinese or Japanese alternate, and the localized archives do not show them. The Chinese and Japanese pages of the older pieces declare their own three-language cluster. Nothing claims a version that is not there.
What the scanner checks — and what it does not
The rule is hreflang, worth 2 points in the multilingual dimension. The condition is at least two distinct language codes; repeated attributes for the same language do not count, and x-default is not a language, so en plus x-default does not satisfy it. A page with no hreflang at all is marked not applicable rather than failed, because one fetched page cannot tell a single-language site from a multilingual one that forgot to declare.
The rule page states the limit plainly: the codes are read from the attributes and the pages they point at are not fetched, so two tags naming versions that were never built satisfy the check. It is a declaration check. The cluster can be perfectly declared and still be wrong.
There is a separate lang-region rule (1 point) for a tag with a region subtag, and an html-lang rule for the document language. They are different questions: what the page says about itself, and what it says about its siblings.
Auditing a cluster
# 1. The alternates declared on one version
curl -sS https://your-domain.com/blog/post/ \
| grep -oE 'hreflang="[^"]+" href="[^"]+"'
# 2. The same for a translated version — the sets must match
curl -sS https://your-domain.com/zh/blog/post/ \
| grep -oE 'hreflang="[^"]+" href="[^"]+"'
# 3. Every declared URL should be 200 and self-canonical
curl -sS https://your-domain.com/blog/post/ \
| grep -oE 'hreflang="[^"]+" href="[^"]+"' | grep -oE 'https://[^"]+' \
| while read u; do curl -sS -o /dev/null -w "%{http_code} %{url_effective}\n" "$u"; done
# 4. Does each version canonicalise to itself?
for u in /blog/post/ /zh/blog/post/ /ja/blog/post/; do
curl -sS "https://your-domain.com$u" | grep -oE 'rel="canonical"[^>]*'
doneThe comparison in step 2 is the one that catches most real failures: the two sets should be identical. A missing return link, a language declared on one side only, or a cluster that includes a version which does not exist all show up as a difference.
What hreflang does not do
It does not improve the translation, it does not guarantee the right version is shown, and it does not make a page citable in a language where the content is weak. It is a declaration that reduces a specific error — showing a Korean reader the English page — and it is only as good as the cluster behind it.
The same standard as the rest of this series: declare only what the site can honour, make the declaration checkable, and do not let a tag imply a quality that the page does not have.