hreflang Tag Generator

The rule is reciprocity, and it is unforgiving. If the English page lists the Spanish one, the Spanish page has to list the English one back, and both have to list themselves. A set where one page forgets is not partially correct — the unreciprocated entries are discarded, and the annotation stops working for the whole group.

Language first, then the full URL, separated by a space, tab or comma.
Used to check that this page appears in its own set — the most common way a set breaks.
Leave blank to omit x-default. It names the fallback for visitors no listed language fits.
hreflang Tag Generator — Reciprocal Language Tags with Self-Reference CheckBuildFigure

What the annotation is for

hreflang does not tell anything which language a page is in — that is what the lang attribute on the html element does, and it is what screen readers and translation tools read. hreflang does something narrower: it says that this page and these other pages are the same content for different audiences, so a search engine that has decided to show one of them can pick the version matching the visitor.

The consequence is that it only makes sense across a set. A single page with a single hreflang tag is doing nothing. Two pages, each listing both, is the smallest arrangement that means anything.

Reciprocity, and the self-reference

Every page in the set must list every page in the set, itself included. Miss the self-reference and the page is announcing a group it does not claim membership of, and the entries pointing at it from elsewhere have no return link. Unreciprocated entries are ignored, which means one page with a missing tag can degrade the annotation for everything around it.

The practical form of this rule is pleasant: the block is identical on every page. Generate it once, include the same partial everywhere, done. If your templating produces a different block per page, you have almost certainly built a set where each page lists the others but not itself, which is the failure this page checks for by asking which URL you are working on.

The codes

The value is a language code, optionally followed by a region: en, en-GB, pt-BR, zh-Hant. The language part comes from ISO 639-1, the region from ISO 3166-1 alpha-2. A region on its own is not valid and never has been, so there is no way to say "this version is for Canada" without saying which language it is in.

WrittenProblemMeant
en_USUnderscore. That is the og:locale format.en-US
ukThat is Ukrainian.en-GB
cnNot a language code at all.zh, or zh-Hans
en-ukWrong on both counts — lowercase region, and UK is not the code.en-GB
euThat is Basque.List each country separately
USRegion with no language.en-US

Case is conventionally language lowercase, script in title case, region uppercase. Parsers are not supposed to care, and writing it the conventional way costs nothing and makes a diff readable, so this tool normalises it.

x-default

x-default is the entry for visitors that none of the listed versions fits — the address the set falls back to. It is usually a language selector page or the international English version. It is optional, it is not a language code, and it should not appear as one of the versions in your list. One per set.

Where to put the tags

Three places, and you pick exactly one. Link elements in the head are the obvious choice for HTML. HTTP Link headers are the only option for files that have no head, such as a PDF. An XML sitemap carries the whole annotation in one file, which for a set of thirty languages across two thousand pages is the difference between one deploy and sixty thousand edited page heads.

What you must not do is use more than one method for the same page, or emit the tags with client-side JavaScript. Both produce a set that is right in the source and wrong in practice.

Before you reach for it at all

hreflang solves one problem: several versions of the same content aimed at different languages or regions. It does not solve near-duplicate content in the same language, it is not a substitute for translating anything, and machine-translated pages listed as language versions tend to be a liability rather than an asset. If your pages differ only by currency and phone number, consider whether a single page with sensible localisation is the smaller thing to maintain.

The neighbouring tags are handled elsewhere: canonical and robots directives — and note that a canonical pointing across languages will undo the whole annotation — plus the meta tag generator for the rest of the head, and the sitemap generator if you are going the sitemap route. When URLs move between language versions, build the map with the redirect rule generator.

Questions people ask

Do I need a self-referencing tag?

Yes, and it is the entry people leave out. A page that does not list itself is not part of the set it is describing, so the references to it from the other pages have no return link and get discarded. The tidy way to guarantee it is to generate one identical block and include it on every version, which is what this tool produces.

Can I use hreflang instead of translating the page?

No. The annotation says these pages are equivalents for different audiences. If they are the same English text at different URLs, that claim is false and the tags will not make a page appear in a market it is not written for. What you have in that case is duplicate content, which is a canonical question rather than an hreflang one.

What happens if one page in the set is missing its tags?

The entries pointing at it stop being reciprocated, so they are dropped. Depending on how the rest of the set is wired, that can cascade — if the missing page was the hub everything referenced, the whole group degrades. This is why hreflang is one of the few annotations worth auditing across every page after a deploy rather than spot-checking one.

Should hreflang and canonical point at each other?

No, and getting this wrong is a fast way to remove pages from an index. Each language version should have a self-referencing canonical, pointing at itself, alongside the hreflang set. A canonical from the Spanish page to the English page says the Spanish page is a duplicate that should not be shown, which is the opposite of what the hreflang set is claiming.

Is x-default required?

No. Leave it out and visitors who match no listed version get whatever a search engine decides. Set it and you name the fallback yourself, which is worth doing when you have a language selector or an international English version. What it is not is a default language declaration — it does not say what language x-default is in, because that is not a question it answers.

Related