Files
rustycms/docs/multilingual.md

2.0 KiB

Multilingual (i18n)

Content per language in separate folders:

content/
  de/
    page/
      home.json5
      about.json5
    post/
      example-post.json5
  en/
    page/
      home.json5
      about.json5
    post/
      example-post.json5
  • Same slug per language (e.g. home in DE and EN).
  • API: ?_locale=de or ?_locale=en. If parameter is missing, default locale is used.
  • Configuration: RUSTYCMS_LOCALES=de,en enables the mode; first locale = default (e.g. de).
  • Without RUSTYCMS_LOCALES: Previous behavior (single language). Content remains under content/{collection}/ (no locale folder).

Activation

# .env or export
RUSTYCMS_LOCALES=de,en

On startup you'll see e.g.: Multilingual: locales ["de", "en"] (default: de).

API usage

# Default locale (first in RUSTYCMS_LOCALES, e.g. de)
GET /api/content/page/home

# Explicit locale
GET /api/content/page/home?_locale=en
GET /api/content/page?_page=1&_per_page=50&_locale=en

Response still has the same structure; only the content is locale-dependent. For POST/PUT/DELETE, _locale can be passed as a query parameter so the entry is created/updated/deleted in the correct locale.

Optional extensions

  • page_config per locale: e.g. content/de/page_config/default.json5 and content/en/page_config/default.json5 for locale-specific SEO, footer text, etc.
  • Available locales in API: e.g. GET /api/locales["de","en"] (from config).
  • hreflang / languageAlternates: derive in frontend from page config or known locales (e.g. already considered in @types/SeoProps.ts).

Alternatives (not implemented)

  • Locale as field in entry: Entry with locale: "de", slug unique per language (e.g. home-de, home-en). Works without store changes, but same logical content has different slugs.
  • Translations in one entry: File with translations: { de: {...}, en: {...} }. No extra folders, but schema and API (filter, resolve) become more complex.