First release of the module as a Jahia community bundle.
It binds each language of a site to its own domain — something Jahia does not
support natively, because a hostname resolves to a site while the language
lives in the URL path. See
Why this module exists.
| Requires | Jahia 8.2 |
| Optional | site-settings-seo, for the hreflang and canonical rewriting |
| Licence | MIT |
| Configured in | Administration → Sites → Language URL mapping |
| Scope | live mode only — edit and preview are untouched by design |
What it does
- A droppable menu component (
lsm:domainSwitchLanguage) whose links each
carry the hostname registered for their language. Labels are endonyms,
langandhreflangare BCP 47, the current language getsaria-current
plus a non-colour indicator. - A per-language redirect: requesting a page in a language mapped to
another host answers 302 to the same path on the right host. It decides on
the resolved locale of the rendered resource, never on the shape of the
incoming URL, so vanity URLs are preserved rather than replaced by a
technical render path. - SEO head elements: the
hreflangalternates and the canonical link
produced bysite-settings-seoare rewritten to the host mapped to each
language, so a multi-domain multilingual site stops telling search engines
that every language lives on one host. - A site settings panel to enter one base URL per site language, guarded by
thesiteAdminLanguageUrlMappingpermission. UI texts ship in the six
standard Jahia UI languages.
The mapping does not have to be one domain per language: several languages can
share a host while others get a dedicated one.
Installing
Drop multi-domain-language-switch-1.0.0.jar into digital-factory-data/modules/,
then enable the module on the site. Every mapped hostname must be declared on
the site as its server name or in j:serverNameAliases, and must resolve to the
Jahia instance.
To use the component from your own module, or to restyle it, read
INTEGRATION.md.
Setup questions — which port to put in the mapping, behaviour behind a CDN,
testing several domains locally — are answered in
FAQ.md.
Security
The base URLs stored on the site node end up in the href of every menu link
and head element of a live page. They are parsed and rebuilt from their scheme,
host and optional port, which makes an attribute break-out unrepresentable
rather than filtered — and the check runs when reading as well as when saving,
because the property can also be written by an import, a migration or a script.
SECURITY.md describes the boundary; tests/cypress/e2e/09-mapping-injection.cy.ts
is the regression test.
Accessibility
Targets WCAG 2.2 AAA, with one boundary stated openly: the menu imposes no
colour and no font by design, so text and background contrast is the
integrator's to verify. Everything the module can guarantee without knowing
your palette — a focus indicator drawn in the inherited text colour, a 44px
target, non-colour state indicators, list semantics, BCP 47 language
attributes — it does. The split is tabulated in INTEGRATION.md.
Quality
- 100 unit tests, 97.3% coverage (98.4% by line)
- 64 Cypress integration tests against a real Jahia 8.2.3.2, over a network of
four hostnames, covering the menu, the redirect, vanity URLs, shared domains,
the SEO head elements, edit mode, the settings panel and the admin UI locale - SonarQube quality gate passing: 0 bugs, 0 vulnerabilities, 0 code smells,
ratings A/A/A, 0% duplication
Known limitations
- The mapping value is a scheme, a host and an optional port. A path is
dropped: both filters compare and rewrite on host and port only. - An internationalised domain must be given in punycode, and a hostname
containing an underscore is refused — both consequences of strict URI parsing. - The redirect answers 302, not 301, so it does not by itself declare a
canonical domain. The rewritten canonical link does that. - Behind a proxy or CDN that terminates TLS, the container must report the
client scheme and port, or the host/port comparison produces a redirect loop.
See the FAQ.