# Entry Localization

The `locale` query parameter controls how localized field values are read and written through the API.

## Endpoints that support locale

| Endpoint | Locale support |
|---|---|
| `GET /api/v1/{workspace}/entries?contentBucket=X&contentType=Y` | `?locale=en-US`, `?locale=is-IS`, `?locale=*` |
| `GET /api/v1/{workspace}/entries/{entry}` | `?locale=en-US`, `?locale=is-IS`, `?locale=*` |
| `POST /api/v1/{workspace}/entries?contentBucket=X&contentType=Y` | `?locale=en-US`, `?locale=is-IS`, `?locale=*` |
| `PATCH /api/v1/{workspace}/entries/{entry}` | `?locale=en-US`, `?locale=is-IS`, `?locale=*` |
| `DELETE /api/v1/{workspace}/entries/{entry}` | Does not use locale |

## Locale parameter values

| Value | Read behavior | Write behavior |
|---|---|---|
| `en-US` (default) | Fields returned as flat values for `en-US` | Writes values for `en-US` |
| Any locale code | Fields returned as flat values for that locale | Writes values for that locale |
| `*` | Fields returned as objects keyed by locale code (`{"title": {"en-US": "...", "is-IS": "..."}}`) | Expects locale-keyed field objects. Writes to currently enabled locales. |

## Setting the default locale

The default locale is `en-US`. When no `locale` parameter is provided, the API defaults to `en-US`:

```shell
curl "https://app.example.com/api/v1/acme/entries?contentBucket=content&contentType=pages" \
  -H "Authorization: Bearer $VIRESSO_API_KEY"
```

This is equivalent to `?locale=en-US`.

## Locale validation

The API validates the `locale` parameter against the configured locale codes. If an invalid locale is provided:

```json
{
  "message": "No locale found for [xx-XX]."
}
```

Returns `400 Bad Request`. Read endpoints include the invalid locale in the message as shown above; create/update validation may return the generic `Bad Request`.

## Controlling which locales an entry supports

The `locales` array in the request body controls which locales the entry is enabled for:

```json
{
  "locales": ["en-US", "is-IS", "fr-FR"]
}
```

- On **create**, this sets which locales the entry supports.
- On **update**, this replaces the existing locale list. Locales removed from the list have their translations permanently deleted.
- `en-US` is always enforced and cannot be removed from the list.

## Limitations

- **No selected-locale subset request.** You cannot request specific locales as a subset (e.g. `?locale[]=en-US&locale[]=is-IS`). Use `locale=*` and filter on the client side, or make separate requests per locale.
- **No locale fallback.** Requesting a locale that has no translation returns `null` for field values. The API does not fall back to `en-US` or any other locale.

## Related pages

- [Localization](/docs/content/localization) — Full guide with examples for creating, reading, and updating localized entries.
- [Entries API](/docs/api/entries) — Entry CRUD reference.
- [Entries](/docs/content/entries) — Entry lifecycle and management.
