SEO

PerfLocale ships a full modern-SEO stack designed specifically for multilingual sites. Hreflang, sitemap alternates, schema enrichment, the Content-Language header, and the fallback nosnippet guard are on by default; the two experimental features — Speculation Rules prerender and View Transitions — are opt-in and disabled out of the box to keep the plugin lightweight. Configure all of it at Settings → SEO.

Hreflang alternates

Every frontend page automatically emits <link rel="alternate" hreflang="..."> tags for every translation that exists, plus hreflang="x-default" pointing at the default-language version. Generated from the translation group and cached per-request. The supported SEO plugins (Yoast, Rank Math, AIOSEO, SEOPress, Slim SEO, The SEO Framework) don’t emit head-stage hreflang of their own, so there is never a second set fighting PerfLocale’s. Nothing to configure.

Tag values use canonical BCP 47 form — lowercase language + UPPERCASE region (en-US, en-GB, de-DE, pt-BR). The HTML5 spec is case-insensitive at match time, but every reference site, SEO validator, and Google Search Central example uses the canonical form, and lowercase region codes (en-us) trigger soft warnings in Screaming Frog and Ahrefs Site Audit. The same canonical form is used across the <html lang> attribute, the Content-Language response header, JSON-LD inLanguage, sitemap alternates, and the REST API hreflang field, so all surfaces agree.

Coexistence with SEO plugins

PerfLocale registers no hreflang-suppression filters against the supported SEO plugins, because none of them emit head- or header-stage hreflang natively for it to collide with:

  • Yoast SEO — has never output hreflang; it defers to the multilingual plugin.
  • Rank Math — only emits hreflang through a multilingual integration, which PerfLocale is not registered as.
  • AIOSEO 4.x — emits none in the head or headers; only in its sitemap, which is exactly where PerfLocale wants alternates to appear.
  • SEOPress, Slim SEO, The SEO Framework — the addons register only sitemap-stage alternates; head-stage hreflang is left to PerfLocale.

Earlier builds did call wpseo_output_hreflang, rank_math/frontend/disable_hreflang and aioseo_conflicting_shortcodes defensively. Those calls were removed: the first two gate hooks no current version of either plugin fires, and the AIOSEO one was actively harmful — it force-executed every shortcode during meta and sitemap generation.

PerfLocale’s own hreflang HTTP Link header is emitted at send_headers priority 1, so its headers land before any other plugin’s on the same hook.

If you want to keep the SEO plugin’s hreflang and disable PerfLocale’s, toggle Hreflang Tags off at Settings → SEO.

Sitemap alternates

PerfLocale hooks into WordPress core’s XML sitemap and attaches <xhtml:link rel="alternate"> entries for translations of every listed URL. If your SEO plugin supplies the sitemap instead, PerfLocale detects that and integrates via its extension point rather than emitting a competing sitemap. No setup needed.

Choosing the sitemap source

The seo_sitemap_source setting selects which sitemap tree carries the xhtml:link alternates when both WP core and an SEO plugin’s native sitemap could serve them. It has no field on the Settings screen — the default (auto) is right for almost every site; override it with the perflocale/sitemap/inject_into_core filter below, or write the key directly with wp option patch update perflocale_settings seo_sitemap_source core:

  • auto (default) — if a supported SEO plugin (Yoast, Rank Math, AIOSEO) is detected, PerfLocale skips the WP core sitemap injection. The SEO plugin’s own sitemap receives the alternates via the per-addon integration. This is the right answer for almost every site.
  • core — always inject into the WP core sitemap, even when an SEO plugin is active. Use this if your SEO plugin’s native sitemap is disabled in its own settings and the core sitemap is the only one being served.
  • plugin — never inject into the WP core sitemap. Use this if you serve a custom or third-party sitemap that PerfLocale doesn’t auto-detect and you want to handle alternates exclusively through it.

For unusual setups, override the auto-detection programmatically with the perflocale/sitemap/inject_into_core filter.

Independent of the source choice, the three SEO sitemap addons (Yoast, Rank Math, AIOSEO) register their entry-capture filters at PHP_INT_MAX so third-party URL-rewriting plugins between priorities 10–999 (canonical-URL plugins, CDN rewriters, etc.) can no longer break PerfLocale’s URL-keyed lookup and silently emit alternates pointing at pre-rewrite URLs.

JSON-LD Schema Enrichment

Adds two small pieces of structured data to whatever JSON-LD your SEO plugin is already emitting: inLanguage (the current page’s language, BCP-47 normalised) and workTranslation (array of URLs pointing at sibling translations). Helps Google surface the right language in search results and lets AI crawlers understand your site’s structure. On by default. See SEO Schema Enrichment for the deep-dive.

Content-Language header

Emits the W3C-standard Content-Language HTTP response header on every frontend request, BCP-47 normalised (de_DEde-DE). Honoured by Google, Yandex, CDN layers, and some assistive tech in addition to the <html lang> attribute. On by default; filter perflocale/content_language/value customises the value.

data-nosnippet fallback guard

When the Missing Translation Action is set to Show default language, a visitor to /de/mypost/ might see the English content. Without protection, Google indexes that English text under the /de/ URL and shows English snippets in German SERPs. PerfLocale wraps the fallback content with <div data-nosnippet> so Google keeps the URL indexed but omits the mismatched snippet. Only activates when fallback is actually happening. On by default.

Speculation Rules prerender

When a visitor hovers a language-switcher link, Chromium prerenders the target translation in the background so clicking it feels instant. On WP 6.8+, integrates with Core’s native Speculation Rules API (our rule lands inside Core’s single output script); on older WP, emits a standalone script. Moderate eagerness - prerenders fire only on hover/focus, so visitors who never interact with the switcher never trigger a fetch. Disabled by default.

View Transitions

Smooth 240 ms crossfade between languages using the cross-document View Transitions API (Chrome 126+, Safari 18.2+). Progressive enhancement - unsupported browsers navigate normally. The emitted CSS respects prefers-reduced-motion, zeroing the animation for users with that OS preference (WCAG 2.1 SC 2.3.3). Disabled by default; enable when your theme doesn’t run its own on-navigation animations.

← Back to Docs