Languages (i18n)
Configure which locales your site supports, designate a default, and unlock translatable entries and settings.
Routes
| Route | Method | Purpose |
|---|---|---|
/admin/languages | GET | List languages |
/admin/languages/create | GET | New language |
/admin/languages | POST | Create |
/admin/languages/{language}/edit | GET | Edit |
/admin/languages/{language} | PUT | Update |
/admin/languages/{language} | DELETE | Delete (blocked if default) |
/admin/languages/{language}/set-default | PATCH | Set as default locale |
/admin/languages/{language}/toggle-active | PATCH | Activate / deactivate |
Language record
- code — IETF tag (
en,en-GB,es,hi,fr) - name — display name ("English")
- native_name — local script ("English", "हिन्दी")
- direction —
ltrorrtl - is_default — exactly one true
- is_active — when false, hidden from locale switchers and the API
- sort_order — display order in locale switchers
How localization is applied
Entries
If a content model has is_localized = true, each entry has a locale column. The unique constraint (content_model_id, slug, locale) lets the same slug exist across languages.
Settings
Settings marked is_translatable = true store their value as a JSON object keyed by locale code. The setting() helper resolves to the current locale, falling back to the default.
Slugs and URLs
Slugs are scoped per locale, so the same content can have language-appropriate URLs (e.g. /en/about vs /es/acerca-de).
Public locale endpoint
GET /api/v1/i18n/locales
Returns the list of active locales for use in frontend language switchers — no API key required. See API: Settings & Locales.
Deleting a languageBlocked while it is the default. Reassign default first. Existing entries in the deleted locale are kept; you can either re-enable the language or migrate them manually.