On a multilingual WordPress site, CrawlWP Premium can add hreflang references to your XML sitemaps when it detects WPML, Polylang, or TranslatePress. These references tell search engines which language versions of a URL are available.
The important point is that CrawlWP does not normally create the hreflang tags in the page <head>. Your multilingual plugin does that. CrawlWP adds the corresponding links to XML sitemaps, giving search engines the same language information in another supported format.
What hreflang tells search engines
An hreflang link associates a page with an alternate version in another language or locale. For example, an English page can point to its French equivalent, while the French page points back to the English version.
- In the page
<head>, it appears as a<link rel="alternate" hreflang="…" href="…" />element. - In an XML sitemap, it appears as an
<xhtml:link>element associated with the URL.
Both methods can be used at the same time. What matters is that the URLs and language codes are consistent. When the page and sitemap versions disagree—for example, because one translation is unpublished—the result can be confusing to search engines and to anyone debugging the setup.
Who is responsible for each hreflang location?
| Location | Generated by |
|---|---|
Page <head> | WPML, Polylang, or TranslatePress |
| XML sitemap | CrawlWP Premium when one of those multilingual plugins is detected |
This division is intentional. Keep your multilingual plugin’s own hreflang output enabled. CrawlWP does not replace those page-level tags; it adds sitemap-level references automatically.
To see whether CrawlWP has detected a supported multilingual plugin, go to CrawlWP > Settings, open Sitemap, and look for Multilingual Sitemaps (WPML, Polylang, TranslatePress).
What CrawlWP adds to each sitemap entry
When CrawlWP generates a sitemap entry for a post, page, or taxonomy term on a supported multilingual site, it asks the multilingual plugin for the URLs belonging to the same content in the available languages.
- If the content exists in only one language, CrawlWP does not add multilingual sitemap links.
- When multiple language URLs are available, CrawlWP adds an
<xhtml:link>entry for each language. - The current URL is included alongside the alternate URLs, so each sitemap entry identifies all of its language versions.
For a page available in English and French, a sitemap entry can look like this:
<url>
<loc>https://example.com/how-to-grow-tomatoes-in-pots/</loc>
<xhtml:link rel="alternate" hreflang="en" href="https://example.com/how-to-grow-tomatoes-in-pots/"/>
<xhtml:link rel="alternate" hreflang="fr" href="https://example.com/fr/cultiver-tomates-en-pot/"/>
</url>
Notice that the English URL lists itself as en as well as listing the French URL. The alternate set describes the complete group of language versions, not just links away from the current page.
The three multilingual plugins do not behave identically
CrawlWP uses the information supplied by the multilingual plugin, so the set of language links can differ depending on whether you use Polylang, WPML, or TranslatePress.
| Plugin | What CrawlWP lists |
|---|---|
| Polylang | Languages for which a translation exists. |
| WPML | Active languages where a translation exists. Each language also has its own sitemap, such as /fr/wp-sitemap.xml. |
| TranslatePress | Every published language, whether or not the specific page has been translated. |
This difference matters when you inspect the sitemap. For example, seeing a language listed by TranslatePress does not necessarily mean the page has a separately translated piece of content; TranslatePress can list every published language.
How language codes are normalized
CrawlWP takes the language or locale supplied by the multilingual plugin and normalizes its formatting before putting it into the hreflang attribute.
- Underscores become hyphens. For example,
pt_BRbecomespt-BR. - For two-part codes, the language remains lowercase and the region is uppercase. For example,
en-usbecomesen-US. - Longer codes are written in lowercase. For example,
zh-Hans-CNbecomeszh-hans-cn.
The value ultimately depends on the multilingual plugin. Polylang commonly provides a short language code such as en, TranslatePress can provide a full locale such as en-US, and WPML can provide values such as en or zh-hans.
What happens with x-default?
CrawlWP does not add an x-default alternate to the XML sitemap. Whether you see x-default in the page <head> depends on your multilingual plugin and its configuration.
For example, Polylang can add x-default to the home page in some setups, while WPML can add it to individual pages. When you need x-default on other pages, check the documentation and settings for your multilingual plugin.
Pages that do not receive sitemap hreflang links
- Dynamic blog home pages: when the home page displays the latest posts, it appears at the top of the page sitemap and does not receive sitemap hreflang links. A static front page is treated as a normal page and can receive them.
- Post type and date archives: these are not included in WordPress’s sitemaps, so CrawlWP does not add sitemap hreflang links to them. Hreflang tags added by your multilingual plugin in the page
<head>can still apply. - Noindexed or password-protected content: these entries are left out of the sitemap, so they do not get sitemap hreflang links.
- Unpublished or noindexed translations: CrawlWP does not verify whether every translation returned by the multilingual plugin is published or indexable before adding it to another URL’s hreflang set.
The last case is particularly useful when troubleshooting. You can have a valid-looking hreflang set that contains a translation that is still a draft or has a noindex directive, because CrawlWP is using the language URLs provided by the multilingual plugin rather than independently validating each translation.
How to check the sitemap hreflang output
- Open one of the sitemaps, such as
https://your-site.com/wp-sitemap-posts-post-1.xml. - If the browser presents the XML as a formatted table, use View Page Source to see the actual XML.
- Search for
xhtml:linkorhreflangand inspect the language URLs associated with a translated page.
Each translated entry should contain the language versions supplied by your multilingual plugin. To inspect the page-level version instead, view the source of the page and search for hreflang.
Keeping the page tags and sitemap tags consistent
Using hreflang in both the page <head> and the XML sitemap is fine. The important part is that the two sources describe the same language relationships.
For example, if the page source says an article is available in English and French but the sitemap lists English, French, and an unpublished German URL, investigate the multilingual plugin’s translation relationships. Do not add a second set of hreflang tags just to compensate for the mismatch.
For developers: adding page-level hreflang with CrawlWP
CrawlWP provides the crawlwp_hreflang_links filter for developers who need to add page-level hreflang links themselves. It is empty by default, and it is separate from the multilingual sitemap integration.
add_filter( 'crawlwp_hreflang_links', function ( $links ) {
if ( is_page( 'about' ) ) {
$links['en'] = 'https://example.com/about/';
$links['fr'] = 'https://example.com/fr/a-propos/';
}
return $links;
} );
The filter runs on every page and also receives a second argument containing CrawlWP’s data for the current page. The filter can return either an associative array in the form language code => URL or a list of arrays containing hreflang and href keys.
Use this filter only when your multilingual setup does not already generate page-level hreflang tags. Adding another set on top of WPML, Polylang, or TranslatePress can create duplicate tags.
Troubleshooting missing or unexpected hreflang links
There are no hreflang links in the sitemap. Go to CrawlWP > Settings > Sitemap and check Multilingual Sitemaps (WPML, Polylang, TranslatePress). Make sure a supported multilingual plugin is active and that you are using CrawlWP Premium. Then check that the content has a translation according to the behavior of your multilingual plugin.
The page has hreflang tags but the sitemap does not. This is possible because the two locations are generated separately. The page <head> is controlled by your multilingual plugin, while the sitemap links are added by CrawlWP Premium. Check whether the page belongs to a sitemap and whether the multilingual plugin supplies multiple language URLs for it.
The sitemap has hreflang links but the page has none. CrawlWP’s sitemap integration does not add the page <head> tags. Keep the hreflang feature enabled in your multilingual plugin and check that its page-level output is working.
A hreflang URL points to something like /fr/?p=74. Check the translation in your multilingual plugin. This can happen when the translated version is not published yet. Publish the translation when it is ready, or remove the translation relationship until the URL is usable.
The same page has two sets of page-level hreflang tags. Look for another SEO plugin, theme code, or custom code using crawlwp_hreflang_links. CrawlWP should not be combined with another system that is independently adding the same page-level tags.
A translation that should not be indexable appears in the sitemap’s hreflang links. CrawlWP does not independently verify the publication or indexability of each translation before adding the URLs supplied by the multilingual plugin. Check the translation status and hreflang relationship in that plugin.
A practical way to verify a multilingual setup
- Check the multilingual plugin’s page-level
hreflangoutput in the page source. - Check the corresponding
xhtml:linkentries in the XML sitemap. - Compare the two sets of language URLs and make sure they describe the same translations.
- Pay particular attention to drafts, noindexed translations, archive URLs, and sites using different language behaviors in WPML, Polylang, and TranslatePress.
Once the page source and sitemap agree, you have a much clearer hreflang setup: the multilingual plugin handles the page-level relationships, while CrawlWP Premium provides the equivalent information in the sitemap.