2.0 KiB
2.0 KiB
Multilingual (i18n)
Recommended approach: Locale as folder (implemented)
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.
homein DE and EN). - API:
?_locale=deor?_locale=en. If parameter is missing, default locale is used. - Configuration:
RUSTYCMS_LOCALES=de,enenables the mode; first locale = default (e.g.de). - Without
RUSTYCMS_LOCALES: Previous behavior (single language). Content remains undercontent/{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.json5andcontent/en/page_config/default.json5for 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.