Skip to content

Add content internationalization#1553

Open
timmy-why wants to merge 1 commit into
Thinkmill:mainfrom
timmy-why:feat/content-i18n
Open

Add content internationalization#1553
timmy-why wants to merge 1 commit into
Thinkmill:mainfrom
timmy-why:feat/content-i18n

Conversation

@timmy-why

Copy link
Copy Markdown

Hey! 👋 This PR adds content internationalization to Keystatic — here's the gist.

Adds content i18n so you can author a collection or singleton in multiple languages.

Set i18n on the config, mark an entry localized, and drop a {locale} token into its path:

export default config({
  i18n: {
    locales: { en: 'English', pl: 'Polski', de: 'Deutsch' },
    defaultLocale: 'en',
  },
  collections: {
    posts: collection({
      label: 'Posts',
      localized: true,
      path: 'content/posts/{locale}/*',
      slugField: 'title',
      schema: { /* … */ },
    }),
  },
});

Each language gets its own file/folder on disk (content/posts/en/…, content/posts/pl/…), but the entry still shows up once in the navigation — a language switcher at the top of the sidebar decides which one you're editing. Entries without a {locale} token stay shared across all languages. Note this localizes your content, which is separate from the existing locale option that just sets the Admin UI language.

Since the token is just a folder in the path prefix, you can turn this on for an existing multi-language project without moving any files.

The Reader API reads one language at a time — createReader/createGitHubReader now take a { locale } option:

const reader = createReader(process.cwd(), config, { locale: 'en' });

Config is validated up front, so a localized entry without a {locale} token (or vice versa), a missing i18n, or a bad defaultLocale all fail with a clear error instead of breaking later.

Scoped to @keystatic/core. Docs are in the new Internationalization page, and there are tests for the path/token handling and locale-scoped reads.

Demo

Here's the flow end to end — opening a singleton and a collection while switching languages: for a singleton the form fields below swap to the selected locale's values automatically, and for a collection the list filters down to that language's entries:

i18n.showcase.mov

And the same language switcher above the navigation with GitHub mode, so you can see it isn't tied to local mode:

github mode i18n switch

@changeset-bot

changeset-bot Bot commented Jul 8, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 1d161f7

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@keystatic/core Patch

Not sure what this means? Click here to learn what changesets are.

Click here if you're a maintainer who wants to add another changeset to this PR

@eremannisto

Copy link
Copy Markdown
Contributor

This would be amazing! ⬆️

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants