Assume I have the following setup:
Two sites with both english and french content pages
/content/siteAAA/language-masters/en
/content/siteAAA/language-masters/fr
/content/siteBBB/language-masters/en
/content/siteBBB/language-masters/fr
Site AAA was created first and all my page templates are defined in its conf folder. E.g.
/conf/siteAAA/settings/wcm/templates/best-product
Now I also want to use the exact same page templates for Site BBB
First challenge: how to make the variation language-aware
In my "best-product" page template, I have configured two experience fragments, one for the header and one for the footer. The path to include this from the page template is pointing to the english version
/content/experience-fragments/siteAAA/language_masters/en/site/header/master
Now, both english and french pages using this best-product page template show only the english header XF
/content/siteAAA/language-masters/en/buy-this
/content/siteAAA/language-masters/fr/buy-this
But maybe I want a different header on my french pages, so I want the page template and experience fragment to be language-context-aware, and use the FR sibling in the experience-fragments folder.
How can this be achieved? Obviously I do not want to create a copy of all page templates for every language, to point to their own hardcoded experience fragment path.
Second challenge: how to also make the variation site-aware
Now since I have another site also using the same page templates, I want the path to include the experience fragment variation to be site-aware as well as language aware
In other words, I only have ONE generic page template with only ONE header experience fragment configured, and
Page /content/siteAAA/language-masters/en/buy-this
Uses XF /content/experience-fragments/siteAAA/language_masters/en/site/header/master
Page /content/siteAAA/language-masters/fr/buy-this
Uses XF /content/experience-fragments/siteAAA/language_masters/fr/site/header/master
Page /content/siteBBB/language-masters/en/buy-this
Uses XF /content/experience-fragments/siteBBB/language_masters/en/site/header/master
Page /content/siteBBB/language-masters/fr/buy-this
Uses XF /content/experience-fragments/siteBBB/language_masters/fr/site/header/master
How can this be achieved?
Topics help categorize Community content and increase your ability to discover relevant content.
Views
Replies
Total Likes
hi @MeasurableBusinessResults,
One possible approach is to resolve the Experience Fragment path at render time by utilizing Sling Context-Aware Configuration (CAC) for site- and language-specific base paths. This can be combined with a simple Sling Model that determines the current page's site and language root, allowing it to dynamically build the correct XF variation path.
While using CAC is recommended, it is not mandatory. If you can establish a single pattern that you are confident will not change, you could also set this pattern as a field in an OSGI configuration.
Implementation steps:
In the Sling Model bound to the header/footer component, you will resolve both site and language page (with getAbsoluteParent) to derive their node names, finally you will replace the placeholders from above-mentioned pattern
Do not forget to provide a robust fallback sequence: localized XF → site default XF → global default XF, so missing locales don’t break page rendering.
Hi @MeasurableBusinessResults,
I think, for your case you don’t really need to duplicate page templates - you can solve it in two main ways:
Use Context-Aware Config (CAC):
Put a config at the site/language root that says where the header/footer XF should live. Then, when the page renders, the component looks up CAC and automatically pulls the right localized XF. This way, your French page will get the FR header without you hardcoding paths.
Or (IMO simpler if your folder structure is strict):
Don’t even store configs. Just calculate the XF path dynamically based on the current page. From the page path you already know the site (siteAAA vs siteBBB) and the language (en vs fr). Your Sling Model can take those values and build the path pattern like:
That way the same template works for all sites and languages.
In practice, I’d probably go with CAC if you expect flexibility (paths may change, not always consistent). If your sites follow a fixed pattern, then the runtime calculation is lighter and easier.
Either way you only keep one generic page template, and the header/footer XF will always resolve to the right variation.
Views
Replies
Total Likes
Got it — you want to avoid duplicating your page templates per language/site and instead have them dynamically resolve the correct Experience Fragment (XF) based on the page context (site + language). This is a very common AEM multi-site / multi-language setup challenge.
Let’s break this down step by step.
🧩 Problem Summary
You have one template (/conf/siteAAA/.../best-product) used across multiple sites (siteAAA, siteBBB) and multiple languages (en, fr).
Template includes XFs for header/footer, currently hardcoded to /content/experience-fragments/siteAAA/language_masters/en/...
You want:
Language-aware resolution: French pages use FR XF, English pages use EN XF.
Site-aware resolution: SiteBBB pages use SiteBBB XF (not SiteAAA’s XF).
Single template maintenance: No duplicate templates per site or language.
✅ Recommended Approach: Dynamic XF Path Resolution
1. Use Context-Aware Configuration or Dynamic Path Resolution in the Component
Instead of hardcoding /content/experience-fragments/siteAAA/... in your template, configure the relative path or a property that can be resolved dynamically at runtime.
You have two main strategies:
Option A: Context-Aware Config (Caconfig) + Sling Model
Store the XF root path in Caconfig
Define a context-aware configuration under /conf/siteAAA and /conf/siteBBB:
/conf/siteAAA/settings/cloudconfigs/xf-config
+ headerXFRoot = /content/experience-fragments/siteAAA/language_masters
+ footerXFRoot = /content/experience-fragments/siteAAA/language_masters
/conf/siteBBB/settings/cloudconfigs/xf-config
+ headerXFRoot = /content/experience-fragments/siteBBB/language_masters
+ footerXFRoot = /content/experience-fragments/siteBBB/language_masters
Resolve language dynamically
From the page’s cq:language or from the page path (between language-masters/ and next /), extract the language code (en / fr).
Construct full XF path:
String xfPath = headerXFRoot + "/" + currentLanguage + "/site/header/master";
Render XF dynamically
Use <cq:include path="${xfPath}" resourceType="cq/experience-fragments/components/xfpage" />
Or if using a custom Sling Model for your header/footer component, compute this path there and expose it as a model property.
This approach allows site-aware and language-aware resolution with one config per site, no template duplication.
Option B: Use Relative XF Paths
If you prefer no caconfig, you can:
Use a relative path pattern in the template like:
/content/experience-fragments/${siteName}/language_masters/${language}/site/header/master
Resolve siteName and language dynamically from the current page path in a Sling Model backing your component:
Resource page = currentPage.adaptTo(Resource.class);
String pagePath = page.getPath();
String siteName = pagePath.split("/")[2]; // siteAAA / siteBBB
String language = pagePath.split("/")[4]; // en / fr
String xfPath = "/content/experience-fragments/" + siteName + "/language_masters/" + language + "/site/header/master";
This keeps your template fully generic — just compute and include the right XF at runtime.
2. (Optional) Use XF Variations for Localization
If your header/footer only changes text but keeps the same structure, you can:
Create one XF master and translate it (AEM XF translation projects support i18n).
That way, you don’t need separate XF per language — but per your question, it sounds like you want separate XFs anyway.
3. Example Template Usage
Instead of this in your template:
<cq:include path="/content/experience-fragments/siteAAA/language_masters/en/site/header/master"
resourceType="cq/experience-fragments/components/xfpage"/>
Use something like:
<sly data-sly-use.header="com.myproject.core.models.DynamicXFModel"
data-sly-test="${header.xfPath}">
<cq:include path="${header.xfPath}" resourceType="cq/experience-fragments/components/xfpage"/>
</sly>
Where DynamicXFModel builds xfPath based on page context (site + language + configured root).
🏁 Benefits of This Setup
✅ Single template for all sites/languages
✅ Automatic resolution — no manual updates when you add a new language
✅ Clean separation of concerns — template stays generic, logic lives in Sling Model or configuration
✅ Reusability — easily extend to more sites or locales
Views
Replies
Total Likes
Views
Likes
Replies
Views
Likes
Replies