If Google keeps showing your French page to English users (or your Spanish product page to German buyers), you don’t have a “Google problem.” You have a signals problem. And hreflang is one of the loudest signals you can send—when it’s correct. When it’s wrong, it’s basically a bullhorn shouting contradictions into the index.
Multilingual WordPress makes this worse: plugins inject tags, themes override headers, caches serve stale HTML, CDNs normalize headers, and suddenly your carefully curated language map becomes a choose-your-own-adventure novel. Google hates those.
What hreflang actually does (and what it doesn’t)
hreflang is not a ranking cheat code. It’s not a magic “rank me in Germany” switch. It’s a disambiguation signal that tells Google: “These URLs are equivalent pages in different languages or regional variants. Please show the right one to the right user.”
In operational terms: hreflang is a routing table for search results. If the routing table is inconsistent, the packets still flow—just to the wrong place.
What hreflang influences
- Language/region targeting in search results: helps Google pick the correct variant.
- Duplicate content handling across locales: reduces the chance Google treats translations as duplicates fighting each other.
- Index hygiene: helps cluster variants into a clean set.
What hreflang does not do
- It doesn’t replace translation quality. Machine-garbage content still performs like machine-garbage content.
- It doesn’t override canonical. Canonical is a stronger consolidation signal; if canonical conflicts with hreflang, Google usually follows canonical and shrugs at hreflang.
- It doesn’t fix geolocation/IP problems. If your server redirects based on IP or Accept-Language without stable URLs, hreflang can’t save you.
Opinionated guidance: if you’re doing multilingual, you need stable, crawlable URLs for each locale. If you don’t have that, stop fiddling with tags and redesign the URL strategy first.
One quote worth keeping on your desk, because it applies painfully well to SEO signaling:
John Allspaw (paraphrased idea): “Reliability comes from designing systems that expect failure—and handle it gracefully.”
hreflang is reliability engineering for search targeting. You’re designing for the failure mode where Google gets confused, because Google will get confused.
Interesting facts and historical context
Some context helps, because hreflang problems are rarely “just a plugin bug.” They’re usually old web decisions colliding with modern indexing behavior.
- hreflang predates most WordPress multilingual plugins. It became popular in the early 2010s, when global sites realized canonical alone couldn’t handle language variants cleanly.
- Google and other engines implemented hreflang differently at first. That legacy is why you still see weird “works for Bing, fails for Google” reports.
- “x-default” was introduced as an escape hatch. It’s for a generic selector page or fallback, not as a dumping ground for “I don’t know.”
- hreflang is a hint, not a directive. Even when perfect, Google can choose a different URL if other signals disagree (canonicals, internal links, sitemaps, redirects).
- Return tags are mandatory in practice. The spec can be read loosely, but Google expects reciprocal linking between alternates (A points to B, B points back to A).
- Locale codes are strict. “en-UK” is wrong; “en-GB” is right. These tiny mistakes cause outsized chaos.
- XML sitemaps can carry hreflang too. This is useful when HTML is cached or templated inconsistently, but it introduces a second place to break things.
- WordPress historically wasn’t built for multilingual URLs. Multisite, directory-based locales, and plugin-based translations all bolt onto a core that assumes one site = one language.
Fast diagnosis playbook
If you’re on-call for SEO fires (congrats, you’ve joined a special club), you need a short path to truth. Here’s the quickest way to find the bottleneck without reading 40 pages of Search Console UI.
First: determine whether Google is seeing the wrong HTML
- Fetch the page HTML as a bot-like client and inspect hreflang tags.
- Compare HTML served with and without cookies, and with different Accept-Language headers.
- Verify that caches aren’t serving the wrong locale (Vary headers, CDN rules, full-page cache keys).
Second: check canonical and redirects (the “strong signals”)
- Confirm each locale URL self-canonicals (or canonicals to the correct locale target) consistently.
- Confirm there’s no redirect chain that collapses locales back to one URL.
- Confirm trailing slash and query normalization doesn’t create duplicates without matching hreflang.
Third: validate reciprocity and completeness
- For each language variant: all alternates present, correct codes, correct absolute URLs.
- Every alternate returns the link back (return tags).
- x-default exists only when you actually have a default experience.
Fourth: cross-check sitemaps vs HTML
- If you use hreflang in sitemaps, confirm it matches HTML exactly.
- Pick a few representative URLs; don’t try to eyeball 10,000 lines.
Fifth: confirm Google’s clustering behavior
- Look for “Duplicate, Google chose different canonical than user” symptoms.
- Spot-check index results per locale. Are the right pages indexed? Or are they being folded into one?
Joke #1: hreflang debugging is like DNS—eventually you find it wasn’t “Google,” it was you, six weeks ago, after one beer.
Failure modes: how hreflang breaks in WordPress
1) Plugin generates hreflang, theme also generates hreflang
This is the classic “two sources of truth” problem. You get duplicate link rel="alternate" tags, sometimes with different URLs. Google doesn’t politely pick the best one; it treats the set as unreliable.
What to do: pick exactly one generator: WPML/Polylang/MultilingualPress/your custom SEO plugin. Disable all other hreflang injection points (theme, custom functions, SEO plugin modules).
2) Canonical points to the wrong locale
If your English page canonicals to the default language homepage, you’ve told Google “these are the same, consolidate.” hreflang tries to say “these are different variants.” Canonical usually wins.
3) Automatic redirects based on browser language
Browser-language redirects seem “user-friendly” until you realize they block crawling, break stable URLs, and cause Googlebot to see different content depending on headers. If you must do it, do it softly (banner/suggestion) and keep locale URLs accessible.
4) Cache keys don’t vary by locale
Full-page caches and CDNs often cache by URL only. If your language selection is cookie-based or header-based, you can serve German HTML at an English URL—complete with German hreflang tags. That’s not “multilingual.” That’s roulette.
5) Trailing slash and URL normalization mismatches
If hreflang points to /fr/page but the canonical is /fr/page/, you’re manufacturing duplicates. Same with http/https, www/non-www, uppercase/lowercase, and query parameters like tracking tags.
6) Missing return tags from one locale
A common pattern: English lists alternates for all languages, but one translated page is missing the alternates entirely (template override, noindex, or content built with a different post type template). That breaks the cluster.
7) Wrong language-region codes
“en-UK” is the greatest hit. Also “es-LA” (not a valid region) and “cn” (China is “CN”, language is “zh”). Google won’t fix your homework.
8) You’re mixing translation models
Directory locales (/en/, /fr/) plus separate domains plus parameters. Don’t. Pick one model and implement it cleanly, because every hybrid becomes a debugging career.
Practical tasks: commands, outputs, and decisions (12+)
These are the bread-and-butter checks you can run from a terminal. They won’t replace Search Console, but they will tell you what your servers are actually shipping. Each task includes: command, sample output, what it means, and what decision you make.
Task 1: Fetch HTML and extract hreflang tags
cr0x@server:~$ curl -sS -A "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)" https://example.com/en/product/widget/ | grep -i 'rel="alternate"'
<link rel="alternate" hreflang="en" href="https://example.com/en/product/widget/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/produit/widget/" />
<link rel="alternate" hreflang="de" href="https://example.com/de/produkt/widget/" />
<link rel="alternate" hreflang="x-default" href="https://example.com/product/widget/" />
What it means: hreflang exists in HTML for this page. Good start.
Decision: If tags are missing or obviously wrong, fix generation at the source (plugin/theme). If they look right, move on to reciprocity and canonical checks.
Task 2: Verify canonical on each locale page
cr0x@server:~$ curl -sS https://example.com/fr/produit/widget/ | grep -i 'rel="canonical"'
<link rel="canonical" href="https://example.com/en/product/widget/" />
What it means: French page canonicals to English. That tells Google to consolidate French into English.
Decision: Fix canonical to be self-referential per locale (or canonicals to the correct locale URL). Then revalidate hreflang.
Task 3: Check redirect behavior (are locales collapsing?)
cr0x@server:~$ curl -sS -I https://example.com/de/produkt/widget/ | sed -n '1,10p'
HTTP/2 301
date: Sat, 27 Dec 2025 10:11:12 GMT
location: https://example.com/en/product/widget/
cache-control: max-age=3600
What it means: German URL redirects to English. hreflang can’t work if the target doesn’t stay put.
Decision: Remove or scope redirects. Each locale URL must return 200 with the locale content.
Task 4: Detect cookie-based language switching issues
cr0x@server:~$ curl -sS -I https://example.com/product/widget/ | grep -i 'set-cookie'
set-cookie: pll_language=fr; path=/; secure; HttpOnly
What it means: The “default” URL is setting a language cookie. That can be okay, but it’s a red flag for caching and bot consistency.
Decision: Ensure bots still get consistent hreflang and canonical tags, and ensure caching varies appropriately (or avoid cookie-based locale on shared URLs).
Task 5: Compare output with different Accept-Language headers
cr0x@server:~$ curl -sS -H "Accept-Language: de-DE,de;q=0.9" https://example.com/en/product/widget/ | grep -i 'html lang=' | head -n 1
<html lang="de-DE">
What it means: You asked for /en/ but got German HTML. That’s a severe bug: URL and language should not disagree.
Decision: Disable header-driven switching for locale URLs; reserve it for a selector page, or only for the root with proper x-default.
Task 6: Check Vary header (cache correctness)
cr0x@server:~$ curl -sS -I https://example.com/en/product/widget/ | grep -i '^vary:'
Vary: Accept-Encoding
What it means: Cache does not vary by cookies or Accept-Language. If your site changes language based on either, your cache can mix languages.
Decision: Either stop varying content by cookie/header for the same URL, or add correct Vary behavior and cache segmentation (often hard with CDNs).
Task 7: Confirm sitemap contains expected locale URLs
cr0x@server:~$ curl -sS https://example.com/sitemap_index.xml | grep -Eo '<loc>[^<]+' | head
<loc>https://example.com/page-sitemap.xml
<loc>https://example.com/product-sitemap.xml
<loc>https://example.com/fr/page-sitemap.xml
<loc>https://example.com/de/page-sitemap.xml
What it means: You have per-locale sitemap entries (good). Now verify they contain the right URLs and hreflang extensions if used.
Decision: If sitemap lacks locale URLs, fix the SEO plugin config; don’t rely on discovery.
Task 8: Extract hreflang annotations from a sitemap (if present)
cr0x@server:~$ curl -sS https://example.com/product-sitemap.xml | grep -i 'xhtml:link' | head -n 6
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/en/product/widget/" />
<xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/produit/widget/" />
<xhtml:link rel="alternate" hreflang="de" href="https://example.com/de/produkt/widget/" />
What it means: Sitemap-level hreflang exists. Great—unless it disagrees with HTML.
Decision: Make HTML and sitemap match. Pick one canonical source of URL mapping (usually the translation plugin) and feed both outputs from it.
Task 9: Check for multiple hreflang generators (duplicate tags)
cr0x@server:~$ curl -sS https://example.com/en/product/widget/ | grep -ic 'rel="alternate"'
12
What it means: Twelve alternate tags is suspicious unless you truly have many variants. Often it’s duplicated blocks.
Decision: View the head section and identify which component emits each set. Disable the extra emitter.
Task 10: Confirm HTTP status is 200 for all alternates
cr0x@server:~$ for u in \
https://example.com/en/product/widget/ \
https://example.com/fr/produit/widget/ \
https://example.com/de/produkt/widget/ ; do
printf "%s " "$u"
curl -sS -o /dev/null -w "%{http_code}\n" "$u"
done
https://example.com/en/product/widget/ 200
https://example.com/fr/produit/widget/ 200
https://example.com/de/produkt/widget/ 404
What it means: One alternate is broken (404). That breaks the cluster and causes “no return tags” / “invalid hreflang” symptoms.
Decision: Fix the missing translation URL or remove it from hreflang until it exists. Don’t advertise dead endpoints.
Task 11: Validate language-region codes used on the site
cr0x@server:~$ curl -sS https://example.com/en/product/widget/ | grep -Eo 'hreflang="[^"]+"' | sort -u
hreflang="de-DE"
hreflang="en-UK"
hreflang="fr-FR"
hreflang="x-default"
What it means: “en-UK” is invalid. Use “en-GB”. Also decide whether you truly need region variants; if not, stick to language-only (en, fr, de).
Decision: Normalize codes across your whole site. In WordPress plugins, this is usually a setting per language.
Task 12: Detect canonical/hreflang target mismatch quickly
cr0x@server:~$ curl -sS https://example.com/fr/produit/widget/ | awk 'BEGIN{IGNORECASE=1} /rel="canonical"/{print} /rel="alternate"/{print}'
<link rel="canonical" href="https://example.com/en/product/widget/" />
<link rel="alternate" hreflang="fr" href="https://example.com/fr/produit/widget/" />
<link rel="alternate" hreflang="en" href="https://example.com/en/product/widget/" />
What it means: The page claims it’s French, but canonical says “treat me as English.” That’s a conflict.
Decision: Fix canonical rules. For multilingual pages, self-canonical per locale is the default safe pattern.
Task 13: Confirm robots directives aren’t blocking a locale
cr0x@server:~$ curl -sS https://example.com/de/produkt/widget/ | grep -i 'meta name="robots"' || echo "no meta robots tag found"
<meta name="robots" content="noindex,follow" />
What it means: You’re telling Google not to index the German page. hreflang can’t show a page that isn’t indexed.
Decision: Remove accidental noindex from production locale pages; keep noindex for staging only.
Task 14: Verify robots.txt isn’t blocking locale paths
cr0x@server:~$ curl -sS https://example.com/robots.txt | sed -n '1,120p'
User-agent: *
Disallow: /wp-admin/
Disallow: /de/
Sitemap: https://example.com/sitemap_index.xml
What it means: /de/ is blocked. That’s an own-goal.
Decision: Remove the disallow for production locales. Re-crawl will take time, but you must stop blocking first.
Task 15: Find mixed hostnames (www vs non-www) in alternates
cr0x@server:~$ curl -sS https://example.com/en/product/widget/ | grep -i 'hreflang' | grep -Eo 'https?://[^"]+' | sort -u
https://example.com/en/product/widget/
https://www.example.com/fr/produit/widget/
What it means: Alternates mix hostnames. That creates duplicate URL identities and makes clusters flaky.
Decision: Normalize site URL settings in WordPress and enforce redirects so hreflang always uses the canonical host.
Common mistakes: symptoms → root cause → fix
1) Symptom: Search results show the wrong language page for many users
Root cause: Canonical points to one “primary” language, collapsing all locales. Or redirects force users to one locale.
Fix: Self-canonical per locale. Remove locale-collapsing redirects. Ensure each locale URL returns 200 and is indexable.
2) Symptom: Search Console reports “No return tags”
Root cause: One or more alternates don’t link back (template missing tags, 404, or noindex). Sometimes only specific post types break.
Fix: Ensure the translation mapping is complete. Confirm every locale variant emits the full alternate set, including itself.
3) Symptom: “Unknown language code” or “invalid hreflang”
Root cause: Wrong ISO codes (“en-UK”), fake regions (“es-LA”), or using underscores (“en_US”) instead of hyphens.
Fix: Normalize to valid BCP 47-style tags used by Google: language-region with hyphen, region in uppercase (en-GB), or language-only (en).
4) Symptom: hreflang tags present, but Google ignores them
Root cause: Conflicting strong signals: canonical mismatch, inconsistent internal linking, mixed hosts, or sitemap vs HTML disagreement.
Fix: Align canonical + hreflang + internal links + sitemaps. Google trusts consistency more than any single tag.
5) Symptom: One locale indexes fine; others barely index at all
Root cause: robots.txt disallow, noindex meta, or server blocks (WAF rules) applied only to certain paths.
Fix: Verify robots and headers per locale, not just “site-wide.” Remove blocks, then request reindexing for key pages.
6) Symptom: Alternates lead to 301/302 chains
Root cause: Plugin emits non-canonical URLs (http vs https, missing slash), or the CDN enforces redirects after the fact.
Fix: Make hreflang URLs final-destination URLs (200). Fix WordPress “Site URL,” permalink settings, and any edge redirect rules.
7) Symptom: Users bounce because they’re dropped into the wrong locale after clicking
Root cause: Browser-language redirect triggers after landing from search, sending users elsewhere (sometimes to homepage). That breaks intent and analytics attribution.
Fix: Stop forced redirects. Use a banner: “Looks like you prefer German—switch?” with a persistent choice.
8) Symptom: Many “Duplicate, Google chose different canonical than user” warnings
Root cause: Similar pages across locales with canonicals pointing incorrectly, or identical content across “translations” (lazy copy) making Google consolidate.
Fix: Correct canonical. Ensure translations are actually translated. If content is intentionally identical across regions, consider whether you really need separate URLs.
Checklists / step-by-step plan
Step 1: Choose and document your URL model
- One domain, directories:
/en/,/fr/(common for WordPress). - Separate domains:
example.fr,example.de(strong separation, more ops work). - Subdomains:
fr.example.com(middle ground).
Do: pick one and stick to it.
Avoid: mixing directories and parameters and separate domains “because marketing asked.” Marketing asks for many things.
Step 2: Make canonicals boring
- Each locale page should usually have a self-referential canonical.
- If you have region variants that are true duplicates, canonicalization can consolidate them—but then hreflang must match that logic carefully.
Step 3: Generate hreflang from one authoritative mapping
- Translation plugin mapping (post IDs linked across languages) is the usual source of truth.
- Don’t hand-edit hreflang per page in production unless you enjoy permanent toil.
Step 4: Enforce consistency at the edge
- Force https and one hostname (www or not).
- Normalize trailing slashes to the WordPress permalink style.
- Make sure hreflang uses the normalized URLs.
Step 5: Prevent cache poisoning across languages
- If locale varies by URL path, caching is straightforward.
- If locale varies by cookie/header, you must vary cache keys correctly—or you will serve mixed-language HTML on the same URL.
Step 6: Validate reciprocity on a sample set
- Pick 20 URLs across templates: homepage, category, product, blog post, landing page.
- For each, confirm: alternates complete, return tags present, targets are 200, canonicals sane.
Step 7: Decide how to use x-default
- Use x-default when there is a language selector or generic landing page not tied to a locale.
- Don’t use x-default as “the English page,” unless English truly is your global default experience.
Joke #2: x-default is not a trash can. If you treat it like one, Google will recycle your traffic elsewhere.
Step 8: Roll out changes safely
- Change one thing at a time: canonical logic first, then hreflang, then sitemaps.
- Purge caches after deployment (app cache, object cache if relevant, CDN).
- Re-crawl a test set with your command checks before you celebrate.
Three corporate mini-stories from the trenches
Mini-story 1: The incident caused by a wrong assumption
They assumed Google would “figure it out.” The company had a multilingual WordPress site: English, French, German. The implementation was clean enough visually. Users could switch languages. The exec dashboard showed international traffic. Everyone relaxed.
Then a regional team complained that German search traffic fell off a cliff. The SEO team pulled Search Console and saw a swamp: German pages were indexed, but they kept showing up for English queries, and English pages were ranking in Germany. hreflang was present, so the assumption was: “hreflang is working.”
It wasn’t. The canonical on every translated page pointed to the English original because someone configured the SEO plugin with “canonicalize translations to original.” That setting sounds tidy. It’s also catastrophic if your goal is language targeting. Google did exactly what it was told: consolidate signals to English, then occasionally surface the German page anyway because the content looked relevant.
The fix was painfully unglamorous: make canonicals self-referential, regenerate hreflang from the translation mappings, purge caches, and resubmit sitemaps. Rankings stabilized over weeks. Not overnight—because indexing systems are distributed and patient in the worst way.
The lesson: if canonical and hreflang disagree, canonical usually wins. Don’t “assume Google will understand.” Google is a machine that rewards consistency, not optimism.
Mini-story 2: The optimization that backfired
A different org wanted faster global performance. They put a CDN in front of WordPress and enabled “cache everything.” Time-to-first-byte improved instantly. Everyone high-fived. Then customer support started getting weird complaints: users in Spain were seeing German pages. Germans were seeing English UI strings. The brand team claimed the site looked “random.”
The site used a cookie to store language preference. The CDN cached HTML by URL only. So the first visitor to hit /product/widget/ in German would prime the cache with German HTML. The next visitor—regardless of language—got that cached page. With the German hreflang set. At the English URL.
Search bots crawled a mix of these versions depending on timing. Some pages ended up indexed with the wrong language signals, and the hreflang clusters became inconsistent. Search Console reported return tag errors and “alternate page with proper canonical” inconsistently. Nothing lined up because the system wasn’t deterministic anymore.
The “optimization” was undone: caching was reconfigured to vary by cookie for the small set of URLs where cookie-based locale existed, and they moved to path-based locale URLs for the rest. Performance stayed good, and the randomness stopped.
The lesson: caching is an amplifier. If your language selection isn’t part of the cache key, you’re not running multilingual—you’re running a language lottery.
Mini-story 3: The boring but correct practice that saved the day
One enterprise team did something that looks painfully slow in a meeting: they wrote a one-page “Locale URL Contract.” It documented the allowed language codes, URL patterns, canonical rules, and who owned hreflang generation. It also included a tiny test script run in CI that fetched 10 representative pages per locale and checked for: 200 status, self-canonical, presence of all alternates, and no mixed hostnames.
Months later, a theme update changed the header template and removed the plugin hook that injected hreflang tags—but only for a custom post type used by campaigns. The campaign team would have launched a multilingual landing set with no hreflang and inconsistent canonicals, right into paid search and organic.
The CI check caught it the same day. The release was blocked. People grumbled, because blocking releases is unpopular until it saves you from explaining revenue swings to leadership. The fix was a small theme patch: restore the hook, confirm output, ship.
The lesson: boring checks prevent expensive drama. hreflang isn’t a one-time setup; it’s a contract you keep enforcing.
How to think about hreflang in WordPress: architecture choices that reduce pain
Directory-based locales are the least operationally surprising
For WordPress, path-based locales (/en/, /fr/) are usually the sweet spot: easy caching, clear separation, and fewer cross-domain complications. Separate domains are fine too, but operationally heavier: certificates, redirects, Search Console properties, and more points to misconfigure.
One translation mapping system, one SEO system, one cache strategy
If you take anything from this: avoid overlapping responsibilities. WPML/Polylang maintains translation relationships. An SEO plugin might output canonicals and sitemaps. Your theme might output meta tags. Your CDN might rewrite headers. If two of these layers “help” with hreflang, you get duplication or conflict.
Don’t rely on automatic language detection for crawlers
Language detection for humans is a UX feature. For bots, it’s a source of nondeterminism. Keep stable locale URLs. Offer a switcher. If you must detect, do it on the root URL only and keep the locale URLs deterministic and crawlable.
Operational validation: what “correct” looks like
A correct hreflang cluster (minimal viable)
- Each locale URL returns 200.
- Each locale URL includes
rel="alternate"for all locale variants including itself. - Each locale URL includes a canonical that matches the intended indexing URL for that locale.
- All alternate targets are canonical, final URLs (not redirecting, not blocked, not noindex).
- Language/region codes are valid and consistent.
- Internal links mostly point to same-locale pages (don’t crosslink everything to English).
When to use language-only vs language-region
If you don’t have meaningful regional differences, don’t invent them. Use en, fr, de. Region variants (en-GB, en-US) are for real differences: pricing, legal terms, spelling, shipping constraints, or truly regional content.
Opinionated take: region targeting is expensive. If you can’t articulate the difference in a sentence, you’re probably creating needless URLs that compete with each other.
FAQ
1) Do I need hreflang if I only have one language but multiple countries?
If the content is truly the same and you just want one English page worldwide, don’t create multiple country URLs. If you do have separate URLs (pricing, shipping, legal), then yes: hreflang with region variants can help.
2) Should I put hreflang in HTML, in sitemaps, or both?
Pick one method unless you have a strong operational reason. HTML is direct and easy to audit. Sitemaps are useful if HTML is hard to control or heavily cached. If you do both, they must match exactly, or you’ll create split-brain signals.
3) What’s the relationship between hreflang and canonical?
Canonical tells Google which URL is the preferred representative for indexing. hreflang tells Google how to choose among equivalents for different locales. If canonical collapses variants into one URL, hreflang loses most of its value.
4) Is x-default required?
No. It’s optional. Use it when there’s a neutral fallback page (like a language selector) or when your root experience isn’t a specific locale. Don’t force it into the setup “because best practices.” Best practices without context are how you get incidents.
5) Can I use hreflang with automatic translation plugins?
Technically yes, but don’t confuse “translated” with “useful.” Google can still decide the pages are low quality or too similar and consolidate them. Hreflang won’t rescue poor content.
6) Why does Search Console show hreflang errors but traffic seems okay?
Because the web is messy and Google compensates—until it stops compensating. Errors often indicate fragility: a theme update, cache change, or migration can turn “mostly fine” into “wrong language everywhere.” Fix it while it’s a warning, not an outage.
7) Do I need to translate slugs for hreflang to work?
No. Slugs can remain the same across locales. What matters is that each locale has a stable URL and correct hreflang mapping. Translating slugs can improve UX and CTR in some markets, but it also increases migration risk.
8) How long does it take Google to reflect hreflang fixes?
Expect days to weeks depending on crawl frequency and site size. You can speed up discovery with updated sitemaps and internal links. You cannot force instant re-clustering. If someone promises instant, they’re selling you a feeling.
9) What if a translation doesn’t exist for a page?
Don’t include an hreflang alternate for a page that doesn’t exist. Either omit that language for that URL, or point users to a locale-appropriate fallback page—carefully. Fake alternates create return tag errors and mis-clustering.
10) Does WordPress multisite make hreflang easier?
Sometimes. It can make locale separation cleaner (separate sites per language), but it adds operational complexity (deployments, plugins, user management, cross-site mapping). “Easier” depends on your team’s ability to operate it.
Conclusion: next steps that actually move the needle
hreflang errors in multilingual WordPress are rarely a single broken tag. They’re usually a consistency failure across layers: plugin output, canonical logic, redirects, caching, and sitemap generation. Treat it like you’d treat a production incident: establish one source of truth, eliminate conflicting signals, and validate behavior from the outside.
Practical next steps (do these in order)
- Pick 10 representative URLs across templates and locales. Run the command checks above and save output.
- Fix canonical conflicts first. If canonical is wrong, hreflang will never feel stable.
- Ensure each locale URL is deterministic: no forced redirects, no language switching on locale paths.
- Make hreflang generation single-source (one plugin/module), then purge caches.
- Normalize codes and hosts (en-GB not en-UK; https only; www vs non-www).
- Align sitemap and HTML if you publish hreflang in both.
- Set up a small automated check (CI or cron) to detect regressions after theme/plugin updates.
If you do those steps, Google will still be Google—slow, distributed, occasionally mysterious—but your system will stop feeding it contradictions. That’s when language targeting starts behaving like engineering instead of folklore.