Skip to main content

Localisation

Two layouts, auto-detected, never configured. If a folder named defaultLocale exists at the content root the project is foldered; otherwise it is in root mode.

# Root mode — a single-language site pays no nesting cost
content/
_index.yml ← default locale
de/_index.yml

# Foldered mode — recommended for any multi-locale site
content/
en/_index.yml
de/_index.yml

Content at the root and a default-locale folder both existing is a build-time error (AMBIGUOUS_LOCALE_LAYOUT), not a silent preference.

Declaring locales

copy-ink.config.ts
defaultLocale: 'en',
locales: ['en', 'de', 'fr'],

defaultLocale must appear in locales. A locale not in the list is rejected wherever it is used — component prop, API option or route.

Resolving the current locale

The locale comes from the route: a pathname starting with a declared locale segment (/de/about) resolves to that locale, everything else to defaultLocale. Pass locale explicitly to any component or server function to override it.

copy-ink does not route for you. Use Next's own i18n routing (or your own segment) and copy-ink follows the resulting pathname.

Fallback

localeFallback decides what happens when a locale's file is missing a field:

ValueBehaviour
'default' (default)Fall back to the default locale's value
'empty'Render nothing

Falling back is usually right for a site being translated incrementally — a half-translated page beats an empty one. 'empty' is the honest choice when a missing translation should be visible rather than papered over.

Images fall back independently: see locale fallback for images.

Checking parity

npx copy-ink i18n

Compares locales key by key and reports what is missing where, including collection items whose slug exists in one locale but not another. It exits non-zero on errors, so it drops straight into CI.

The root-mode collision

Root mode has one collision it cannot avoid: a route segment whose name matches a declared locale. A /de page that is not the German translation is unresolvable — content/de/ is a locale folder by definition.

copy-ink check flags it as locale-collision and tells you to migrate:

npx copy-ink migrate --locale-folders --dry-run # preview
npx copy-ink migrate --locale-folders # do it

That is a pure file move — content is never rewritten — and it moves the public image mirror alongside. Afterwards the project is in foldered mode and the collision is gone.

If you know the site will be multi-locale, start foldered and skip the whole question.

The editor

The floating toolbar has a locale switcher. Switching changes which locale the client is editing; the page itself is not re-routed, so they see the same page with the other locale's content. Changes to different locales accumulate in the same changeset and publish in one commit.