Advanced Usage /

Configure Different Default Languages for Different Domains

Creght supports binding multiple domains to the same site and assigning different default languages to different domains. This is useful for multi-country or multi-region websites where the same site and CMS data should use natural URLs for each market.

For example, example.com/about can serve English, while example.fr/about can serve French without requiring example.fr/fr/about.

Prerequisites

  • Multilingual routing is enabled for the site.
  • All related domains are bound to the same site.
  • Each language is included in the locales list.

Note: i18n.domains only controls locale routing. Each domain must still be bound in Settings → Domains. Otherwise the request will not resolve to this site and its i18n config will not be used.

Configuration Example

Add i18n.domains in talizen.config.ts:

export default {
  i18n: {
    defaultLocale: "en",
    locales: ["en", "fr"],
    localeDetection: true,
    domains: [
      { domain: "example.com", defaultLocale: "en" },
      { domain: "example.fr", defaultLocale: "fr" },
    ],
  },
}

After this configuration:

  • example.com/about serves English.
  • example.fr/about serves French.
  • /fr/about can still be used as an explicit locale path.
  • If locale detection or an explicit locale prefix resolves to a language handled by another configured domain, the renderer can redirect to that domain.

Field Reference

defaultLocale is the site's base default language. It is usually also the base layer for CMS fields.

locales is the full list of languages supported by the site.

domains declares which domain maps to which default language. In each item, domain is the hostname to match, and defaultLocale is the language served on unprefixed paths for that domain. Each item can also include locales to declare which additional languages that domain serves beyond its default (see the next section).

The locales Field in domains: Serving Multiple Languages on One Domain

By default, each domain only serves its own defaultLocale (on unprefixed paths). domains[].locales declares which additional languages that domain also serves — those languages are reached via prefixed paths on this domain and are not redirected elsewhere.

What happens if you omit locales?

Omitting locales is not an error, but the domain becomes single-language: it only recognizes its own defaultLocale. If a user requests another language on this domain (via a locale prefix or locale detection), the renderer issues a 307 redirect to the domain that owns that language (matched by each domain's defaultLocale). If no domain owns the language, it is served on the current domain with a prefixed path instead, without redirecting.

Example — a bilingual site whose base default language is Chinese:

export default {
  i18n: {
    defaultLocale: "zh-CN",
    locales: ["zh-CN", "en"],
    domains: [
      { domain: "www.example.cn", defaultLocale: "zh-CN", locales: ["zh-CN", "en"] },
      { domain: "www.example.com", defaultLocale: "en" },
    ],
  },
}

Results:

www.example.cn/about        → Chinese (unprefixed default)
www.example.cn/en/about     → English (.cn also serves en, shown as-is, no redirect)
www.example.com/about       → English (unprefixed default)

If you drop locales from .cn, it serves Chinese only: www.example.cn/en/about then 307-redirects to www.example.com/about — English is pushed to .com. So to serve multiple languages on one domain, list them all in that domain's locales (including its own defaultLocale for clarity).

In short: locales is the switch that makes a domain multilingual. Omit it when a domain serves a single language; set it when you need two or more. This matches Next.js i18n.domains[].locales semantics — "other locales, besides defaultLocale, that should be routed to this domain".

Routing Rules

Without domain routing, Creght uses path prefixes for non-default languages:

/about     → default language
/fr/about  → French
/zh/about  → Chinese

With domain routing, each domain can have its own unprefixed default language:

example.com/about  → English
example.fr/about   → French

This keeps regional domains clean and avoids redundant locale prefixes.

FAQ

Why does example.fr not need /fr?

Because example.fr declares French as its default locale:

{ domain: "example.fr", defaultLocale: "fr" }

So example.fr/about is treated as French directly.

Is i18n.domains enough?

No. The domain must also be bound to the same site in Settings → Domains. If example.fr is not bound to this site, the platform cannot route the request to this site's i18n config.

Can one domain support multiple languages?

Yes. The domain's defaultLocale is used for unprefixed paths. Additional locales on the same domain still use path prefixes.

export default {
  i18n: {
    defaultLocale: "en",
    locales: ["en", "nl-NL", "nl-BE"],
    domains: [
      {
        domain: "example.nl",
        defaultLocale: "nl-NL",
        locales: ["nl-BE"],
      },
    ],
  },
}

Result:

example.nl/about        → nl-NL
example.nl/nl-BE/about  → nl-BE

That is correct behavior. Under domain routing, <Link> and localizedPath() use the current domain's unprefixed default language: when the target language is that domain's default, the link has no prefix. For example, on www.example.com (default en), localizedPath("/about", "en") returns /about, not /en/about; a prefix appears only when switching to a non-default language of that domain. This is why you should not concatenate locale paths by hand.

Use one domain for each primary market:

example.com  → en
example.fr   → fr
example.de   → de

For internal links, use Creght/Talizen locale-aware navigation such as <Link> or localizedPath(). Avoid manually concatenating locale paths so links stay correct when domain or default-language rules change.

Render diagnostics