# Implement domain-based locale routing | Creght API for AI

> A machine-oriented guide to i18n.domains, default locales, cross-domain redirects, locale-aware links, and multilingual CMS behavior in Creght.

[![Creght](https://ugc.talizen.com/_assets/site/2061660904709165056/1780797461299__creght_logo.png)API for AI](/)

[View llms.txt](/llms.txt)

Overview

- [Creght API for AI](/api)

Discoverability

- [How to optimize llms.txt](/api/optimize-llms-txt)

Site configuration

- [Implement domain-based locale routing](/api/domain-locale-routing)

On this page

- [Required inputs](#required-inputs)
- [Canonical configuration](#canonical-configuration)
- [Routing decision algorithm](#routing-decision-algorithm)
- [Domain locale ownership](#domain-locale-ownership)
- [Single-language domain](#single-language-domain)
- [Multilingual domain](#multilingual-domain)
- [Unprefixed path](#unprefixed-path)
- [Explicit locale path](#explicit-locale-path)
- [Generate links with Talizen APIs](#generate-links-with-talizen-apis)
- [Language switcher](#language-switcher)
- [Read locale and CMS content correctly](#read-locale-and-cms-content-correctly)
- [Acceptance matrix](#acceptance-matrix)
- [Implementation checklist](#implementation-checklist)
- [Forbidden implementations](#forbidden-implementations)

Site configuration/Implement domain-based locale routing

# Implement domain-based locale routing

An agent-oriented specification for configuring locale ownership, domain redirects, locale-aware links, and multilingual CMS behavior in Creght.

Copy Markdown link

Use this specification when an AI coding agent must configure one Creght site to serve different default languages on different domains. Treat the rules below as an implementation contract, not as optional UI guidance.

**Agent objective**

Produce a valid `talizen.config.ts`, preserve locale-aware navigation, and verify the expected host + path + locale matrix without manually parsing or concatenating locale URLs.

## Required inputs

Collect these values before editing code:

- The site-wide base `defaultLocale`. This is also the fallback layer for multilingual CMS fields.
- The complete site-wide `locales` list.
- Every hostname that is already bound to this same Creght site.
- The unprefixed default locale owned by each hostname.
- Any additional prefixed locales that each hostname must serve locally.
- Whether automatic locale detection should be enabled.

> **Hard requirement:** `i18n.domains` does not bind DNS or attach domains to a site. Every configured hostname MUST already be bound in Settings → Domains. If it is not bound, the request never reaches this site's locale router.

## Canonical configuration

Write `i18n` as a plain object in `talizen.config.ts`. Do not import a configuration helper.

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

Keep every domain locale inside the top-level `locales` array. Including a domain's own `defaultLocale` in `domains[].locales` is not required for routing, but SHOULD be done for an explicit, auditable configuration.

## Routing decision algorithm

1. Match the request hostname against `i18n.domains[].domain`.
2. Use that entry's `defaultLocale` as the routing default for unprefixed paths on that hostname.
3. If the URL contains an explicit locale prefix, verify that locale is supported site-wide.
4. If the current domain serves the requested locale—through its `defaultLocale` or `locales`—serve it on the current domain.
5. Otherwise, find the configured domain whose `defaultLocale` owns the requested locale and issue a temporary 307 redirect to that domain.
6. If no configured domain owns the locale, keep the request on the current domain and serve it with its explicit locale prefix.

> **Do not confuse defaults:** top-level `i18n.defaultLocale` remains the site's base content locale. A domain entry's `defaultLocale` controls only the unprefixed routing default for requests on that hostname.

## Domain locale ownership

### Single-language domain

Omit additional locales when the domain should serve only its own `defaultLocale`. Requests for a locale owned by another domain redirect there.

### Multilingual domain

List every additional locally served locale in `domains[].locales`. These locales remain on this host and use explicit path prefixes.

### Unprefixed path

`example.fr/about` resolves to French when that domain declares `defaultLocale: 'fr'`. Do not add a redundant `/fr` prefix.

### Explicit locale path

`example.cn/en/about` stays on `example.cn` only when that domain also serves `en`; otherwise it can redirect to the domain that owns English.

## Generate links with Talizen APIs

Internal links MUST use Talizen locale-aware navigation. Never concatenate `/${locale}` manually and never infer locale from `window.location.pathname`.

```
import { Link, localizedPath } from 'talizen'

// Preferred for rendered internal navigation.
<Link href='/about'>About</Link>

// Use when a component requires a raw URL string.
const href = localizedPath('/about', locale)
```

When the target locale is the current domain's unprefixed default, `Link` and `localizedPath()` correctly omit the locale prefix. A missing prefix in that case is expected behavior, not a bug.

### Language switcher

A language switcher SHOULD preserve the current locale-less route instead of sending every user to the home page.

```
import { Link } from 'talizen'
import { getLocalePath } from 'talizen/router'

<Link href={getLocalePath()} locale='en'>English</Link>
```

## Read locale and CMS content correctly

On the server, read the resolved locale from `context.locale` or `getLocale()`. In React components, use `useLocale()`. Do not parse the URL because the router can strip locale prefixes before page code runs.

```
import { getLocale } from 'talizen'
import { getContent } from 'talizen/cms'

export async function getServerSideProps() {
  const { locale } = getLocale()
  const page = await getContent('pages', 'about', {})
  return { props: { locale, page } }
}
```

`talizen/cms` returns fields already decoded for the current locale. Read the normal fields directly. Do not manually merge `_i18n` inside page code.

## Acceptance matrix

For the canonical configuration above, verify this exact behavior:

```
www.example.cn/about       → zh-CN, 200, no locale prefix
www.example.cn/en/about    → en, 200, remains on .cn
www.example.com/about      → en, 200, no locale prefix
www.example.com/zh-CN/about → redirect or prefixed output according to domain ownership
```

If `en` is removed from `www.example.cn.locales`, then `www.example.cn/en/about` SHOULD return a 307 redirect to `www.example.com/about`.

## Implementation checklist

- Confirm every domain is bound to the same site before changing `talizen.config.ts`.
- Confirm all domain defaults and additional domain locales exist in top-level `i18n.locales`.
- Keep the config as a plain object; do not introduce Next.js configuration helpers.
- Use Talizen `Link` or `localizedPath()` for internal links.
- Use `getLocale()`, `context.locale`, or `useLocale()` instead of parsing URLs.
- Test unprefixed and prefixed routes on every configured hostname.
- Verify redirect status, destination hostname, path preservation, query preservation, and absence of redirect loops.
- Verify CMS content resolves to the same locale selected by routing.

## Forbidden implementations

- Do not add `react-router-dom`, Next.js routing packages, or custom locale routers.
- Do not hardcode `/en`, `/fr`, or another prefix into shared navigation components.
- Do not treat top-level `defaultLocale` as if it changes per domain.
- Do not assume that adding `i18n.domains` also binds or verifies a hostname.
- Do not duplicate CMS entries per locale; use field-level translations in one stable content item.
- Do not convert expected 307 locale redirects into permanent redirects unless the product's routing contract explicitly changes.

![Creght](https://ugc.talizen.com/_assets/site/2061660904709165056/1780797461299__creght_logo.png)

This website is built with [Creght](/)

[Discord](https://discord.gg/Qvq2nmZNnb)

## Links

- [Pricing](/price)
- [Help Center](/help)
- [Contact Us](/contact)
- [Blog](/blogs)
- [Refund Policy](/tuikuan)

## Resources

- [All Resources](/resources)
- [Templates](/templates)
- [Components](https://creghtlib.site.creght.com)
- [Animations](/effects)
- [Figma to Creght](/figma2creght)
- [API for AI](/api)

## Terms

- [Terms of Service](/legal/terms)
- [Privacy Policy](/legal/privacy)
- [Acceptable Use Policy](/legal/acceptable-use)

## Social Media

- [Twitter](https://twitter.com)
- [Facebook](https://www.facebook.com)
- [LinkedIn](https://www.linkedin.com)

[蜀ICP备2023038192号-2](https://beian.miit.gov.cn)
