On this page
- What is the difference between canonical and hreflang?
- The rule in markup
- Five conflicts and how to fix each
- 1. Translated pages canonicalized to the original
- 2. Hreflang pointing at a URL that is not canonical
- 3. Hreflang attached to the canonical tag
- 4. A version in the set that is not indexable
- 5. Regional versions in the same language
- Where this goes wrong on WordPress
- How do you check a live page?
Give every language version of a page a canonical tag that points at itself, and give it an hreflang set that lists every version, itself included. The French page is canonical for French, the Spanish page for Spanish, and the hreflang set ties them together. On WordPress the usual break is a translated page whose canonical points back at the original.
What is the difference between canonical and hreflang?#
A canonical tag answers "which URL should be indexed when several URLs show the same content?" Google's documentation calls it a hint: Google can pick a different canonical than the one you declare.
An hreflang set answers a different question: "which of these URLs, each in its own language, should a given searcher see?" Google can only show a URL it has indexed, so the set helps only for versions that are.
Canonicalization only merges language versions when Google treats them as duplicates, and its canonicalization page says a translation isn't one: "Different language versions of a single page are considered duplicates only if the primary content is in the same language." A page with a translated menu and footer but an untranslated body counts as a duplicate. A page whose body is in French does not.
Both tags only matter once each language has its own URL. The article on subdomain vs subdirectory for a multilingual website compares the URL structures, and the one on machine translation and SEO covers when a machine-translated version is ready to join the set.
The rule in markup#
A ceramics shop sells in English, French and Spanish, with Australian English as a regional version. This is the head of its Spanish product page:
<link rel="canonical" href="https://www.tilestudio.example/es/handmade-tiles/">
<link rel="alternate" hreflang="en" href="https://www.tilestudio.example/handmade-tiles/">
<link rel="alternate" hreflang="en-AU" href="https://www.tilestudio.example/en-au/handmade-tiles/">
<link rel="alternate" hreflang="fr" href="https://www.tilestudio.example/fr/handmade-tiles/">
<link rel="alternate" hreflang="es" href="https://www.tilestudio.example/es/handmade-tiles/">
<link rel="alternate" hreflang="x-default" href="https://www.tilestudio.example/handmade-tiles/">The canonical names the Spanish URL. The es alternate names the same URL, character for character. The French page carries the same five alternate lines with a canonical naming the French URL, and so on for each version, as Google's page on localized versions asks: "Each language version must list itself as well as all other language versions." Google's documentation on canonical URLs states the hreflang half of this directly: when you use hreflang, specify a canonical page in the same language, or the closest substitute language if no same-language page exists.
Five conflicts and how to fix each#
1. Translated pages canonicalized to the original#
<!-- On https://www.tilestudio.example/fr/handmade-tiles/ -->
<link rel="canonical" href="https://www.tilestudio.example/handmade-tiles/">
<link rel="alternate" hreflang="fr" href="https://www.tilestudio.example/fr/handmade-tiles/">The canonical asks Google to index the English page instead of this one, while the alternate asks it to show this one to French searchers. Google receives two instructions that cannot both be followed. Since canonicals are hints, it may resolve them either way, and you lose control over which French URL, if any, appears in results.
This conflict often starts with a translation layer that serves /fr/ from the same WordPress post as the original. The theme or SEO plugin prints the canonical for the post it knows, which is the English one, and nothing rewrites it on the French response. Fix it by making each translated response carry its own URL as canonical.
2. Hreflang pointing at a URL that is not canonical#
<link rel="alternate" hreflang="fr" href="http://tilestudio.example/fr/handmade-tiles">The canonical French URL is https://www.tilestudio.example/fr/handmade-tiles/. This tag names a variant on HTTP, without www and without the trailing slash. Each difference leads to a redirect or a duplicate, and the return link from the French page names a different string. Google's canonical documentation asks for HTTPS URLs in hreflang annotations and says Google prefers URLs that are part of an hreflang cluster when it picks a canonical. Use exactly the URL each version declares as its own canonical.
3. Hreflang attached to the canonical tag#
<link rel="canonical" hreflang="es" href="https://www.tilestudio.example/es/handmade-tiles/">Google's documentation says rel="canonical" annotations carrying hreflang, lang, media or type attributes are not used for canonicalization. The tag above does nothing as a canonical. Keep the canonical as a plain tag and list languages in separate rel="alternate" tags.
4. A version in the set that is not indexable#
If the French page has noindex, its hreflang entries point at a page that will not be indexed. Google's canonical documentation also advises against noindex as a way to choose a canonical within a site, because it removes the page from Search altogether. Take a version out of the set until it is ready, rather than listing it and hiding it.
5. Regional versions in the same language#
en and en-AU versions of a product page may differ only in price, spelling and delivery details. Here the pages are close to duplicates, and Google's canonicalization page says to use both canonicalization and hreflang for same-language regional variants. In practice that means each regional page stays self-canonical and lists the others. If two regional pages are identical, consider whether you need both. For similar same-language content on two URLs, Google's guidance on multi-regional sites says to pick a preferred version and use canonical and hreflang tags so searchers get the right regional URL.
Where this goes wrong on WordPress#
WordPress core prints a canonical tag on single posts and pages (its rel_canonical() function), and an SEO plugin may print its own instead. A translation plugin that stores each language as a separate post gets a separate canonical per language from WordPress itself. A plugin that translates the rendered page serves /fr/ from the original post, so it has to rewrite the canonical in the response, or the French page goes out declaring the English one canonical, which is conflict 1 even though nobody chose it.
LangRelay's plugin translates the rendered page and handles that rewrite. On a translated response it points the existing canonical tag, and the og:url tag, at the page's own translated URL, and adds a canonical if the page had none. It sets lang on the <html> element to the language's tag and prints the hreflang set that LangRelay sends, which is the same on every version and includes the page itself and x-default on the original.
Once French is live on at least one page of the site, a /fr/ URL whose own French translation is not approved yet returns the original page's content, and the plugin prints no hreflang set on that response. Any canonical tag in it still names the original, which is correct for a page that is not in French. When the translation is approved and published, LangRelay fetches the translated URL and checks that the canonical points at that URL, that the page lists itself and x-default in its hreflang set, and that lang matches. A page that contradicts any of these is flagged on the release instead of being reported as delivered.
How do you check a live page?#
The browser's element inspector shows the page after scripts ran. Search engines start from the HTML your server sends, so check that first:
curl -s https://www.tilestudio.example/es/handmade-tiles/ \
| grep -iE 'rel="(canonical|alternate)"'Then work through the output:
- The canonical matches the URL you requested, scheme, host and trailing slash included.
- The hreflang entry for this page's language names that same URL.
- Each other URL in the set returns 200 when requested, without a redirect.
- Each of those pages has its own self-canonical and the same set.
- No
noindexappears on any version, in a meta tag or anX-Robots-Tagheader.
For pages that are already indexed, Search Console's URL Inspection tool shows the "User-declared canonical" next to the "Google-selected canonical". If Google picked the original for a translated URL, look for conflict 1 or for a body that is still mostly in the original language. The help page notes that the Google-selected canonical is only available from indexed data; a live test cannot predict it.
The hreflang guide covers the codes and the rest of the set's rules, and self-referencing hreflang and x-default covers the two entries this article only touches on. For the WordPress side, see hreflang in WordPress and the multilingual SEO overview. If you want to see the plugin's output on one of your own pages, book a demo.
Sources
The pages this one cites, with the day each was read.
- 01How to specify a canonical with rel="canonical" and other methods (Google Search Central, last updated 2026-07-10)developers.google.com, checked 6 October 2026
- 02What is URL canonicalization (Google Search Central, last updated 2026-08-20)developers.google.com, checked 6 October 2026
- 03Localized versions of your pages (Google Search Central, last updated 2026-09-21)developers.google.com, checked 6 October 2026
- 04Managing multi-regional and multilingual sites (Google Search Central, last updated 2025-12-10)developers.google.com, checked 6 October 2026
- 05URL Inspection tool (Search Console Help)support.google.com, checked 6 October 2026
- 06rel_canonical() (WordPress Developer Resources)developer.wordpress.org, checked 6 October 2026


