Atlas CMS

Localization

Read content in multiple languages — request a specific locale via the Public API and understand the fallback behaviour.

Localization

Atlas is multi-locale by design. A single entry (or page) can hold values for several languages at once: one base value for the default locale plus any number of per-locale translations. The Public API returns the right values for the language you request, falling back to the base when a translation is missing.

How it fits together

ConceptWhere it livesPurpose
Workspace localesDashboard → Settings → LocalesThe set of languages a workspace supports, with one marked as default.
Localizable fieldContent type field (localizable: true)Marks which fields can carry per-locale values.
dataEntry payloadField values for the default locale — all fields appear here.
translationsEntry payloadPer-locale overrides — only localizable fields, keyed by locale code.

Locale codes are short language tags such as en, id, or fr (2–10 characters).

Setting up locales and translations

Configuring workspace locales, marking fields as localizable, and providing translated values are all done through the Atlas dashboard or via the Admin API (documented in a later phase).

Reading a specific locale

Request a language by adding ?locale= to any Public API list or detail endpoint.

cURL
curl "https://api.atlas.latellu.com/api/v1/public/entries/getting-started-with-headless-cms?locale=id" \
  -H "X-API-Key: atlas_live_abc123xyz"

?locale= is available on both entry endpoints:

EndpointDescription
GET /public/entries?type={slug}&locale={code}List published entries of a content type in a locale.
GET /public/entries/{entrySlug}?locale={code}Fetch a single published entry in a locale.

Understanding the response

The entry's data object always contains default-locale values for every field. The translations.<locale>.data object contains values that override data for localizable fields only. Your frontend should merge these: use the translation value when present, otherwise fall back to data.

Response — GET /public/entries/getting-started-with-headless-cms?locale=id
{
  "success": true,
  "data": {
    "slug": "getting-started-with-headless-cms",
    "status": "published",
    "data": {
      "title": "Getting Started with Headless CMS",
      "summary": "A beginner-friendly introduction to decoupled content management.",
      "cover_image": {
        "url": "https://cdn.atlas.latellu.com/blog/covers/headless-cms-intro.webp",
        "width": 1200,
        "height": 630
      },
      "published_at": "2026-05-10T08:00:00Z"
    },
    "translations": {
      "id": {
        "data": {
          "title": "Memulai dengan Headless CMS",
          "summary": "Pengenalan ramah pemula untuk manajemen konten terpisah."
        }
      }
    }
  }
}

In this example cover_image and published_at are not localizable — they have no per-locale override, so you always read them from the top-level data. title and summary are localizable and appear in translations.id.data for Indonesian.

Fallback behaviour

If you request a locale that the entry has no translation for, Atlas returns the default-locale values rather than an empty result. The single-entry endpoint flags this with is_fallback: true, so your frontend can show a "translation unavailable" hint when needed.

Response — locale not available (fallback to default)
{
  "success": true,
  "data": {
    "slug": "getting-started-with-headless-cms",
    "status": "published",
    "is_fallback": true,
    "data": {
      "title": "Getting Started with Headless CMS",
      "summary": "A beginner-friendly introduction to decoupled content management."
    },
    "translations": {}
  }
}

Pages are localizable too

Pages support the same model: SEO metadata and individual content blocks can each carry per-locale translations. Each block's data/translations shape comes from its block type (a content type with is_block: true) — use the Schema Explorer to look up a block type's fields the same way you would for an entry.

Next Steps

On this page