Edge Integration

Run PerfLocale behind a Cloudflare Worker, Vercel Edge function, or Netlify Edge function, and route visitors to the correct language before the request reaches PHP. Two pieces: a public JSON endpoint the edge reads once, and a header/cookie contract so edge decisions flow into WordPress.

Disabled by default. Enable via PerfLocale → Settings → Advanced → Edge Worker Integration, or programmatically with add_filter( 'perflocale/edge/enabled', '__return_true' ). When off, no REST route is registered and the edge_hint detection method is inert.

Config endpoint

URL: GET /wp-json/perflocale/v1/config
Auth: Public (no authentication). The payload contains only data already visible in the site’s rendered HTML - hreflang tags, switcher labels, etc.
Cache headers: Cache-Control: public, max-age=300, s-maxage=3600, stale-while-revalidate=86400 and an ETag so edges can revalidate with a cheap 304.

{
	"version": "1.0.0",
	"url_mode": "subdirectory",
	"url_prefix_type": "slug",
	"default_slug": "en",
	"hide_default_prefix": true,
	"excluded_paths": [ "/wp-json/", "/wp-admin/", "/wp-login.php" ],
	"detection_order": [ "url", "cookie", "browser", "default" ],
	"edge_hint_header": "X-PerfLocale-Lang",
	"edge_hint_cookie": "perflocale_edge_lang",
	"languages": [
		{
			"slug": "en",
			"locale": "en_US",
			"hreflang": "en-us",
			"prefix": "en",
			"domain": "",
			"text_direction": "ltr",
			"is_default": true
		}
	]
}

The payload is cached internally (3-layer cache, 15-minute TTL) and invalidated automatically whenever a language is added, updated, or removed, or when settings are saved.

Hint header + cookie

To have the edge’s decision honoured by PHP, add edge_hint to your detection order (Settings → URL & Routing → Language Detection Order) and send one of:

  • Header: X-PerfLocale-Lang: fr - header wins over cookie
  • Cookie: perflocale_edge_lang=fr - fallback

Both names are filterable:

add_filter( 'perflocale/edge/hint_header', fn() => 'X-Vercel-Lang' );
add_filter( 'perflocale/edge/hint_cookie', fn() => 'my_lang_cookie' );

Per-request veto:

add_filter( 'perflocale/edge/accept_hint', function ( bool $accept, string $slug ): bool {
	// Reject hints from probes that don't come through our CDN.
	return ! empty( $_SERVER['HTTP_CF_RAY'] ) ? $accept : false;
}, 10, 2 );

Trust model

The hint is trusted at the same level as a visitor-set cookie: at worst it lets a visitor preselect a language they could have chosen themselves. URL-based detection always wins when a prefix is present in the request path, so a spoofed hint can never override a canonical translated URL.

Reference Cloudflare Worker

A complete example ships with the plugin at assets/js/edge-helper.js. It demonstrates both deployment strategies:

  • URL rewrite (recommended) - edge adds the language prefix and forwards; rewritten URL becomes the CDN cache key
  • Header hint - edge forwards unchanged with X-PerfLocale-Lang set; WordPress detects via edge_hint
const CONFIG_URL   = 'https://example.com/wp-json/perflocale/v1/config';
const CACHE_TTL_MS = 10 * 60 * 1000;

let cachedConfig    = null;
let cachedConfigExp = 0;

async function loadConfig() {
	if ( cachedConfig && Date.now() < cachedConfigExp ) return cachedConfig;

	const res = await fetch( CONFIG_URL, {
		cf: { cacheEverything: true, cacheTtl: 600 }
	} );
	cachedConfig    = await res.json();
	cachedConfigExp = Date.now() + CACHE_TTL_MS;
	return cachedConfig;
}

addEventListener( 'fetch', event => event.respondWith( handle( event.request ) ) );

async function handle( request ) {
	const config  = await loadConfig();
	const country = ( request.cf && request.cf.country ) || '';
	const slug    = pickLanguage( country, config ); // your logic

	if ( slug && slug !== config.default_slug ) {
		const url = new URL( request.url );
		url.pathname = '/' + slug + url.pathname;
		return fetch( new Request( url.toString(), request ) );
	}

	return fetch( request );
}

See the plugin file for the full version with Accept-Language fallback, excluded-path handling, and the header-hint alternative strategy.