Ask your question and get a summary of the document by referencing this page and the AI provider of your choice
Version History
- "Add domain-based locale routing via routing.domains configuration."v8.7.04/3/2026
If you have an idea for improving this documentation, please feel free to contribute by submitting a pull request on GitHub.
GitHub link to the documentationCopy doc Markdown to clipboard
Custom Domains
Intlayer supports domain-based locale routing, allowing you to serve specific locales from dedicated hostnames. For example, Chinese visitors can be directed to intlayer.zh instead of intlayer.org/zh.
How It Works
The domains map in routing associates each locale with a hostname. Intlayer uses this map in two places:
- URL generation (
getLocalizedUrl): when the target locale lives on a different domain than the current page, an absolute URL is returned (e.g.https://intlayer.zh/about). When both domains match, a relative URL is returned (e.g./fr/about). - Server proxy (Next.js & Vite): incoming requests are redirected or rewritten based on the domain they arrive on.
Exclusive vs. shared domains
The key distinction is exclusivity:
- Exclusive domain - only one locale maps to that hostname (e.g.
zh → intlayer.zh). The domain itself identifies the locale, so no locale prefix is added to the path.https://intlayer.zh/aboutserves Chinese content. - Shared domain - multiple locales map to the same hostname (e.g.
enandfrboth map tointlayer.org). Normal prefix-based routing applies.intlayer.org/fr/aboutserves French content.
Configuration
Locales that are not listed in domains continue to use the standard prefix routing without any domain override.
URL Generation
getLocalizedUrl automatically produces the correct URL type based on the calling context.
Same-domain locale (relative URL)
Cross-domain locale (absolute URL)
Serving from the locale's own domain
Current domain auto-detection
currentDomain is optional. When omitted, getLocalizedUrl resolves it in this order:
- The hostname of an absolute input URL (e.g.
https://intlayer.org/about→intlayer.org). window.location.hostnamein browser environments.- If neither is available (SSR without explicit option), a relative URL is returned for same-domain locales and no absolute URL is produced - this is the safe fallback.
getMultilingualUrls with domains
getMultilingualUrls calls getLocalizedUrl for every locale, so it produces a mix of relative and absolute URLs depending on the caller's domain:
These absolute URLs are ready to use in <link rel="alternate" hreflang="..."> tags for SEO.
Proxy Behaviour
Next.js
The intlayerProxy middleware handles domain routing automatically. Add it to your middleware.ts:
Redirect - request arrives on the wrong domain for a given locale prefix:
Rewrite - request arrives on the locale's exclusive domain without a prefix:
Vite
The intlayerProxy Vite plugin applies the same logic during development:
Note: in local development you are typically onlocalhost, so cross-domain redirects will point to the live domains rather than another local port. Use a hosts-file override (e.g.127.0.0.1 intlayer.zh) or a reverse proxy if you need to test multi-domain routing locally.
Locale Switcher
The useLocale hook from next-intlayer handles domain-aware navigation automatically. When a user switches to a locale on a different domain the hook performs a full-page navigation (window.location.href) instead of a client-side router push, because the Next.js router cannot cross origins.
No extra configuration is required - useLocale detects window.location.hostname internally and decides between router.replace (same domain) and window.location.href (cross-domain).
SEO: hreflang Alternate Links
Domain-based routing is commonly used together with hreflang to tell search engines which URL to index for each language. Use getMultilingualUrls to generate the full set of alternate URLs:
This produces:
Core Utilities
Open the table in a modal to view all data content clearly
| Utility | Description |
|---|---|
getLocalizedUrl(url, locale, { currentDomain }) | Returns relative or absolute URL depending on whether the target locale is on the current domain. |
getMultilingualUrls(url, { currentDomain }) | Returns a locale-keyed map of localized URLs, mixing relative and absolute as needed. |
getPrefix(locale, { domains }) | Returns an empty prefix for exclusive-domain locales, normal prefix otherwise. |