How to Localize Fragments with AEM Edge Delivery Services
This demo showcases how AEM Edge Delivery Services serves locale-specific shared content — navigation, footers, promotional banners — by automatically resolving fragment paths against the current URL locale prefix.
Using the fragment localization pattern, a fragment authored at /fragments/nav is automatically served from /de/fragments/nav when a visitor is on a German locale page. If no localized version exists, the site transparently falls back to the default fragment — no broken pages, no authoring overhead.
Why This Matters
The challenge: Your site serves visitors in multiple languages under locale URL prefixes like /de/, /fr/, and /es/. Shared page elements — the navigation, footer, and promotional banners — are authored as fragments and reused across pages. But those fragments need to show locale-appropriate content: translated labels, region-specific links, or market-specific offers.
The solution: Fragment localization automatically prepends the current locale prefix to every fragment path before fetching. Authors create locale-specific fragments only where content must differ. Everything else inherits the root default — no code changes, no per-locale block configuration.
Why use fragment localization:
- Automatic resolution — Fragments resolve to the locale-specific version without any author intervention on the page
- Graceful fallback — If a localized fragment doesn't exist, the default loads seamlessly; no 404s or blank sections
- Author-friendly — Create only the fragments that differ per locale; everything else inherits from root
- Correct HTML lang attribute — The
<html lang>attribute is set automatically from the detected locale on every page load - Opt-out control — Append
#_dntto any fragment URL to pin it to the root version regardless of locale
Real-world use cases:
- Global navigation with locale-specific labels and links for each market
- Regional promotional banners that vary by country or language
- Footer content with locale-appropriate legal text, phone numbers, or addresses
- Cookie consent or privacy notices that differ by jurisdiction
How it Works
When a visitor is on /de/products and the page includes a link to /fragments/nav, the fragment block:
- Calls
getLocale()to detect the current locale prefix (/de) from the URL pathname - Constructs the localized path:
/de/fragments/nav - Fetches
/de/fragments/nav.plain.htmlfirst - If that returns a 404, falls back to
/fragments/nav.plain.html - Renders whichever response was successful; media paths are resolved relative to the actual path that loaded
The same logic applies to all fragment loading paths — both fragments auto-blocked from inline links and those loaded explicitly via the Fragment block.
Key insight: The locale detection is purely URL-based. There is no session state, cookie, or user preference involved — the locale is always derived from the pathname. This makes pages fully cacheable on the CDN per locale path.
Authoring Localized Fragments
Mirror the fragment folder structure under each locale prefix. You only need to create a localized version when the content actually needs to differ from the root default.
/fragments/nav— Global default navigation, always required/de/fragments/nav— German-specific nav; created only when it differs from the default/fr/fragments/promo— French-only promotional banner; no root equivalent needed/fragments/footer— Shared footer used by all locales that don't have an override
To pin a specific fragment to the root version and skip localization entirely, append #_dnt (do not translate) to the fragment URL:
/fragments/global-legal-notice#_dnt
This is useful for globally shared content like legal disclaimers or brand assets that must not be inadvertently localized.
Configuration
Supported locales are declared in scripts/shared.js as the LOCALES map. Add or remove entries to match the site's language support:
export const LOCALES = {
'': { lang: 'en' },
'/de': { lang: 'de' },
'/es': { lang: 'es' },
'/fr': { lang: 'fr' },
'/ja': { lang: 'ja' },
'/zh': { lang: 'zh' },
'/hi': { lang: 'hi' },
};
The empty string key ('') is the root/English locale and is always required. Each additional entry maps a URL path prefix to a BCP 47 language code used for the lang attribute.
No other configuration is needed. The getLocale() function is called once in loadEager and sets the page language automatically. All fragment loading — both auto-blocked inline links and explicit Fragment blocks — uses the same locale prefix transparently.