Multi-language
Configuring languages
site.config.json languages is an array of BCP-47 language codes. The first entry is the default language. The default language is never included in the URL.
{ "languages": ["en", "nb", "de"] }The translation model
Two patterns, mutually exclusive:
- Per-language root — set
translatable: trueon a list field. The full array lives in.<lang>.json. Use when items differ per language (e.g. localized FAQs). - Shared list with translated sub-fields — leave
translatable: falseon the list, mark sub-fields astranslatable: true. The base file has the full structure; the per-language overlay is{ "<itemId>": { "<field>": "<value>" } }. Use when structure is shared but copy differs (e.g. team grid).
loadPage(), loadCollectionEntry(), loadGlobal() all merge the overlay automatically — block .astro files do not need to know about translations.
Anti-patterns
- Don't mark both the list and its sub-fields as translatable. The list flag wins, and the sub-field flags become dead code.
- Don't read
.<lang>.jsondirectly from blocks. UseloadXxx()helpers. - Don't hardcode language. Always use
Astro.currentLocale ?? siteConfig.languages[0].