---
title: Languages
status: current
order: 12
---

# Languages

A site has one **default language**: the one its content is written in. Add more and every field marked **Localized** gets one value per language, while the rest (prices, photos, dates) keep a single value for all of them. Your site asks for a language with `?locale=en`.

## The default language

It's what your content is written in, and what the API returns when nobody asks for a language. Pluma guesses it when you create the site, from your browser's language, and again from the content itself when it first reads your site for [Visibility](ai-answers.md), as long as nobody picked one and the site has a single language.

To change it: **Settings → General → Content language**. By API, `PATCH /api/v1/spaces/:space_id` with `{"default_locale": "es"}`; by MCP, `update_site` with `default_locale`.

Changing it **relabels** the content, it doesn't translate it: every value stored under the old language moves to the new one, in every entry and every version (published ones too), and the language keeps its place. Use it when the content was stored under the wrong language, like a Spanish site that started as `en`.

- If an entry already has values in **both** languages, nothing changes and you get [`validation_failed`](../errors/validation_failed.md) with the entries that clash: moving would overwrite one of them. Remove the other language first, or empty those values.
- Your deploy hooks get `content_type.changed`, so the site rebuilds.

## Add or remove languages

**Settings → Languages.** Each language has:

| | What it is | Example |
| --- | --- | --- |
| Code | Two letters, or two plus a region | `es`, `en`, `pt`, `fr`, `en-US` |
| Name | What the dashboard shows. By default, the language's own name | English |
| Fallback | What to show when a value is missing in this language. By default, the default language. It can be none | `es` |

**Removing a language deletes its values** from every entry and every version, published ones too. The dashboard asks first and says how many entries have values in it. The default language can't be removed: make another one the default first.

By API:

```json
POST /api/v1/spaces/:space_id/locales
{ "code": "en", "name": "English", "fallback_code": "es" }
```

`PATCH /api/v1/spaces/:space_id/locales/:code` changes `name` or `fallback_code`. `DELETE /api/v1/spaces/:space_id/locales/:code` removes it; if it has values, it refuses unless you send `?delete_values=true`. All three need `manage_model`. By MCP: `add_locale`, `update_locale`, `remove_locale`. See [Management API](../api/management.md#languages).

## In the dashboard

With more than one language, each entry has a tab per language, like **Español | English**:

- The default tab has every field, as always.
- The other tabs have only the localized fields. Empty ones show the fallback's value as a placeholder, which is what your site gets until someone writes them.
- Each tab says how many fields are **not translated** yet: localized fields with a value in the default language and none in that one.
- Fields that aren't localized show once, in the default tab.

One **Save** keeps every tab, as one new version. Turn **Localized** on or off for a field in **Model**.

## Translate with AI

In a language's tab, **Translate with AI** fills the fields still missing in that language from the default one, and saves them as a **new draft version**. It never publishes: read it, fix what you'd say differently, then publish.

- **Text, long text and tags** are translated.
- **Rich text** keeps its structure: the same headings, lists, links and images. If the translation comes back with a different structure, that field is left as it was and Pluma says so.
- **Slugs** get a translated slug (`menu-del-dia` → `daily-menu`), made unique among the type's entries in that language.
- **Lists** get their text translated; numbers and dates in them stay.
- **References, files, numbers, dates and yes/no** stay as they are: they show the default language's value.

When every field is translated, the button becomes **Translate again**, which replaces what's there (as a new version: the old one stays in Versions).

By API, `POST /api/v1/spaces/:space_id/entries/:id/translate` with `{"to": "en"}` (and `"overwrite": true` to translate every field again). By MCP, `translate_entry`. If the AI provider is down you get [`translation_unavailable`](../errors/translation_unavailable.md) and nothing is saved.

## By API

Reading, with any key:

- Without `locale`, fields come in the default language.
- `?locale=en`: in English. A missing value falls back to the language's fallback; fields that aren't localized always come in the default language's value.
- `?locale=*`: every language, as `{ "title": { "es": "Menú del día", "en": "Daily menu" } }`.
- Filters and sorting (`fields.slug=daily-menu`, `order=fields.title`) use the language you asked for, so a site finds an entry by its English slug.

Writing, with a management key or an agent token, the same `locale`:

```json
PATCH /api/v1/spaces/:space_id/entries/12?locale=en
{ "fields": { "title": "Daily menu", "slug": "daily-menu" } }
```

```json
PATCH /api/v1/spaces/:space_id/entries/12?locale=*
{ "fields": { "title": { "es": "Menú del día", "en": "Daily menu" } } }
```

- Only the fields and languages you send change. `null` empties that field in that language, and the others keep theirs.
- A field that isn't localized only takes the default language: sending it in another one gives `validation_failed`.
- Saving checks the types in every language. **Publishing requires the required fields in the default language only**; a missing translation falls back. Slugs have to be unique within the type in each language.
- With `locale=*`, errors for a language other than the default come as `title.en`.
- In a [batch](../api/management.md#batch), `create_entry` and `update_entry` take `"locale"` the same way. The MCP's `create_entry`, `update_entry`, `get_entry` and `list_entries` too.

## URLs

In a type's URL path, `{locale}` becomes the language: with `/{locale}/menu/{slug}`, the English version of an entry links to `/en/menu/daily-menu`, and `sys.url` and `sys.preview_url` come in the language you asked for, with its slug.

The default language goes **without prefix** by default: `/menu/menu-del-dia`. To have it too (`/es/menu/menu-del-dia`), turn on **Put the default language in URLs too** in **Settings → Languages**, or send `"prefix_default_locale": true` to `PATCH /api/v1/spaces/:space_id` or `update_site`. A URL path without `{locale}` is the same for every language, with each language's slug.
