Translations everywhere: one capability, every surface

Embed
Preview of the card
<a href="https://forumulate.com/guides/translations-everywhere"><img src="https://forumulate.com/guides/_api/public/orgs/046a9bc0-d530-43ae-9bae-af7945008cda/spaces/36aa4df0-1e95-4cef-8ae9-795169441345/pages/b7cdb7d1-d369-4d4a-adcd-5f5a8f6bca46/social-card.svg?v=3e7ae33eec8b" alt="Translations everywhere: one capability, every surface" width="600" height="315"></a>

Everything you can do with translations in Forumulate, and where you do it: the REST API, the JavaScript SDK (client.translations), the CLI (forumulate translations, alias forumulate i18n), the agent (MCP) server and the console. Every row works on every surface. A test enforces this, so a capability can't ship on one surface and skip another.

All machine translation uses your organization's own provider: your DeepL key, or your connected AI provider for content-library entries. There is no platform key. Until you connect one, every machine-translate call answers 409 ai.unavailable. forumulate translations auto on a space checks for a key before it translates anything, so you get that answer once rather than once per piece.

The four states

Every translatable piece is reported in the same four states, whatever kind of piece it is:

State

Meaning

missing

No translation exists in that language yet.

draft

A translation exists, but readers aren't served it.

published

Readers are served it, and it was made from the current original.

outdated

Readers are served it, but the original changed after it was made.

Where the translation lives depends on the kind of piece:

  • Docs page (also legal, FAQ and other page-backed spaces): a language twin, which is a page of its own. Declaring a language seeds an unpublished twin of every page. The twin's id is the id in its cell, and you read and write its text through …/items/{id}. A legal edition's translation is its twin too, and it keeps the original's edition and acceptance record.

  • Blog post, forum topic, changelog release: stored under the original's id at …/{blog|forum|changelog}/{id}/translations/{locale}.

  • Status incident: stored at …/status/incidents/{id}/translations/{locale}. Incident translations have no draft state. One is either published or outdated.

  • Content-library entry: a locale twin holding the entry's localized fields.

The SDK, the CLI and the MCP tools work out the kind from the space's type, so you address the original piece and the language, and never the door.

The matrix

SP is /orgs/{orgId}/spaces/{spaceId} and LIB is /orgs/{orgId}/content/libraries/{libraryId}.

Capability

REST (canonical)

SDK client.translations.

CLI forumulate translations

MCP tool

Console

Declare, rename and remove languages (space or library)

GET/POST SP/docs/locales, PATCH/DELETE SP/docs/locales/{code}, the same under LIB/locales

locales.list/add/relabel/remove/set

locales list/add/relabel/remove/set

list_translation_locales, set_translation_locales

Studio → Settings → Translations; Content → library → Languages

Coverage (piece × language → state)

GET SP/translations; per piece GET SP/pages/{pageId}/translations, GET SP/{kind}/{id}/translations

status, list

status [--fail-on missing,outdated]

translation_status

Studio → Settings → Translations

Read one translation

page: its twin via GET SP/items/{itemId}; GET SP/{kind}/{id}/translations/{locale} (has markdown)

get

pull

get_translation

The piece's editor → Translations

Write or correct one by hand

page: PUT SP/items/{itemId}/content; PUT SP/{kind}/{id}/translations/{locale} (takes markdown)

put

push

put_translation

The piece's editor → Translations

Remove one

page: DELETE SP/items/{itemId}; DELETE SP/{kind}/{id}/translations/{locale}

remove

remove

remove_translation

The piece's editor → Translations

Machine-translate (your key)

POST …/translations/{locale}/auto for every kind (below)

auto, autoEntry

auto

auto_translate

Studio → Settings → Translations → Translate (one piece, or every missing or outdated one)

Correct a piece's declared language

PATCH SP/items/{itemId} { "locale": "es" }

setItemLocale

item-locale

set_item_locale

The piece's inspector

A library entry's locale twin

GET LIB/entries/{entryId}/locales, PUT LIB/entries/{entryId}/locales/{locale}, POST LIB/entries/{entryId}/translations

entryLocale.get/put

entry

translate_entry

Content → entry → Languages

Space and collection names

PATCH SP / PATCH SP/collections/{collectionId} translations

names.get/set

name

set_name_translation

Studio inspector / Collection settings

Chrome words (labels, strings, per-locale href)

GET …/i18n/strings, PUT/PATCH …/i18n/labels on a site or a space

labels.strings/replace/merge

labels pull, labels push (JSON or XLIFF)

call_api

Studio → Settings → Translations; Sites

Interface string overrides and the public catalog

GET/PUT/DELETE /orgs/{orgId}/translation-overrides, GET /public/orgs/{orgId}/i18n/catalog

overrides.*

overrides pull, overrides push

call_api

Organization settings → Text customization

Reader language switcher

GET/PUT /orgs/{orgId}/language-switcher; per space theme.i18n.switcher

switcher.get/set

switcher

call_api

Organization settings; a space's Look

Your translation provider key

GET/PUT/DELETE /orgs/{orgId}/deepl

deepl.status/connect/disconnect

provider

call_api

A docs space's studio → Settings → For developers and agents

The agent server has a named tool for all the translation work. For the settings rows it uses call_api: the agent server doesn't mirror every settings route as its own tool, and call_api reaches each of them with the same permissions.

Two reader-side features aren't authoring capabilities, so they aren't rows here. A forum reader can translate a topic or post on the fly with POST /public/orgs/{orgId}/spaces/{spaceId}/forum/t/{slug}/translate, using the organization's provider. The docs editor's helper, POST /orgs/{orgId}/spaces/{spaceId}/pages/{pageId}/ai/translate, translates a document you send it and writes nothing.

Every route by name

  • Coverage: GET /orgs/{orgId}/spaces/{spaceId}/translations

  • Languages: GET /orgs/{orgId}/spaces/{spaceId}/docs/locales, POST /orgs/{orgId}/spaces/{spaceId}/docs/locales, GET /orgs/{orgId}/content/libraries/{libraryId}/locales

  • A page: GET /orgs/{orgId}/spaces/{spaceId}/pages/{pageId}/translations

  • A post, topic or release: GET /orgs/{orgId}/spaces/{spaceId}/blog/{topicId}/translations, PUT /orgs/{orgId}/spaces/{spaceId}/blog/{topicId}/translations/{locale} (and the same under forum/{topicId} and changelog/{releaseId})

  • An incident: GET /orgs/{orgId}/spaces/{spaceId}/status/incidents/{incidentId}/translations

  • A piece's own text and language: GET /orgs/{orgId}/spaces/{spaceId}/items/{itemId}, PATCH /orgs/{orgId}/spaces/{spaceId}/items/{itemId}

  • An entry's twin: GET /orgs/{orgId}/content/libraries/{libraryId}/entries/{entryId}/locales

  • Names: GET /orgs/{orgId}/spaces/{spaceId}

  • Chrome: GET /orgs/{orgId}/sites/{siteId}/i18n/strings

  • Overrides: GET /orgs/{orgId}/translation-overrides

  • Switcher: GET /orgs/{orgId}/language-switcher

  • Provider: GET /orgs/{orgId}/deepl

Machine translation: one address

Machine translation used to have three names: …/auto on posts and releases, …/machine on incidents, and …/ai/translate on content entries. Pages had no machine-translate route at all. The canonical address is now the same for every kind:

Kind

Canonical

Older address, kept as an alias

Docs page

POST /orgs/{orgId}/spaces/{spaceId}/pages/{pageId}/translations/{locale}/auto

none (this route is new)

Blog post

POST /orgs/{orgId}/spaces/{spaceId}/blog/{topicId}/translations/{locale}/auto

none (already canonical)

Forum topic

POST /orgs/{orgId}/spaces/{spaceId}/forum/{topicId}/translations/{locale}/auto

none

Changelog release

POST /orgs/{orgId}/spaces/{spaceId}/changelog/{releaseId}/translations/{locale}/auto

none

Status incident

POST /orgs/{orgId}/spaces/{spaceId}/status/incidents/{incidentId}/translations/{locale}/auto

POST /orgs/{orgId}/spaces/{spaceId}/status/incidents/{incidentId}/translations/{locale}/machine

Library entry

POST /orgs/{orgId}/content/libraries/{libraryId}/entries/{entryId}/translations/{locale}/auto

POST /orgs/{orgId}/content/libraries/{libraryId}/ai/translate (batch of up to 25)

Every canonical route takes the same body:

  • force: true replaces a translation a person wrote. Without it, that request is refused with a 409.

  • published: true publishes the result at once. By default the result is a draft that a person reads first.

There are two exceptions. An incident has no draft state, so its route does not take published: sending it is a 422. A library entry's machine translation is always a draft, so published: true is a 422 there too, and force changes nothing: the result is written into the entry's draft twin either way. The aliases keep their own bodies (replace on …/machine), and the incident's canonical route accepts replace too. Nothing that worked before has stopped working.

From the CLI

forumulate login
# Declare exactly these languages (add, rename; --prune also removes)
forumulate translations locales set es=Español fr --space docs
forumulate translations locales add de --library site      # labelled "Deutsch"
forumulate translations locales relabel es "Español (LatAm)" --space docs
forumulate translations locales remove de --library site --yes
forumulate translations locales list --space docs

# Coverage, and a CI gate: exit 1 if anything Spanish is missing or outdated
forumulate translations status --space docs
forumulate translations status --space docs --locale es --fail-on missing,outdated

# Round trip through files (one Markdown file per piece per language)
forumulate translations pull --space docs --out translations --include-missing
forumulate translations push translations --space docs --dry-run   # the diff
forumulate translations push translations --space docs             # idempotent

# Machine-translate what is missing or outdated, with your own DeepL key
DEEPL_API_KEY=… forumulate translations provider connect
forumulate translations auto --space docs --locale es,fr --state missing,outdated
forumulate translations auto --library site --locale de --entry <entryId>

# Chrome words and interface overrides, as JSON or XLIFF for your TMS
forumulate translations labels pull --space docs --format xliff --out labels.xlf
forumulate translations labels push labels.xlf --space docs
forumulate translations overrides pull --format xliff
forumulate translations overrides push overrides.xlf --prune

# The rest
forumulate translations remove <pieceId> es --space docs --yes
forumulate translations item-locale <itemId> es --space docs
forumulate translations entry <entryId> es --library site --fields es.json
forumulate translations name es "Guías" --space docs
forumulate translations switcher get
forumulate translations provider status

Every command takes --json and --org, and the defaults come from FORUMULATE_ORG, FORUMULATE_SPACE and FORUMULATE_LIBRARY.

A pulled file's front matter says which space, piece and language it is, so a file your TMS renames still lands on the right piece. A file pulled with --include-missing holds the original's words. push skips such a file until someone has changed it, so English is never published under a Spanish address.

From the SDK

import { ForumulateClient } from '@forumulate/sdk';
const client = ForumulateClient.fromEnv();

const cov = await client.translations.status(orgId, spaceId);
for (const item of cov.items)
  if (item.locales.es?.state === 'missing')
    await client.translations.auto(orgId, spaceId, item.id, 'es');

const es = await client.translations.get(orgId, spaceId, pageId, 'es'); // { title, markdown, state }
await client.translations.put(orgId, spaceId, pageId, 'es', { markdown: es.markdown + '\n\nActualizado.' });

The Python and Go SDKs are generated from the same OpenAPI document and already carry these operations, the canonical /auto routes included.

From an agent (MCP)

Connect to the authenticated agent server with a token. Then:

  • translation_status finds what needs work.

  • get_translation and put_translation read and write one piece in one language, as Markdown. An agent that writes a translation counts as a person, so automatic translation never overwrites it.

  • auto_translate machine-translates with the organization's own provider. If no provider is connected, it answers ai.unavailable, and the agent should ask the user to connect one.

  • list_translation_locales and set_translation_locales read and declare the languages.

  • remove_translation, set_item_locale and set_name_translation cover the rest of the translation work.

  • translate_entry writes a content-library entry's localized fields.

What readers and search engines see

The language is in the address, on every type

A translation is read at its own address: the language code is a path segment after the space's mount, the same way on every type with reader pages.

Type

Original

Spanish

Docs, FAQ, careers, custom

/docs/getting-started

/docs/es/getting-started

Blog

/blog/launch-week

/blog/es/launch-week

Community spaces

/community/welcome

/community/es/welcome

Status

/status

/status/es

Legal

/legal/terms

/legal/es/terms

Any type's root

/changelog

/changelog/es

(The mounts above are examples; yours are whatever you mounted each space at.)

  • Only a declared language is a segment. /docs/es/… is read as Spanish only when the space declares es; otherwise es is an ordinary slug, so a page called "es" can never be taken over by a language nobody declared. The original language never has a segment.

  • A status page's languages come from its incidents. The languages it translates into automatically, and every language an incident has a translation in — including one written by hand with no automatic translation — each get a path (/status/es). You do not have to declare them a second time.

  • theme.i18n.urlStyle: "query" keeps the older ?locale=es form for a space that relied on it. Unset is path, the form search engines index as a separate page. The space's value wins over its site's.

  • <html lang> is the language the page actually served.

  • The reader never picks a language from the browser. Reader pages are cached at the edge by address, so a language chosen from a request header would be served to the next reader who asked for that address. The reader's language comes from the address alone; the language switcher (and its remember suggestion) links to the other addresses.

Canonical and hreflang

Every type's index, item and hub pages name their canonical and alternates the same way:

  • A translation that is published canonicalises to its own address (/blog/es/launch-week), never to the original, so a search engine indexes it as the Spanish page rather than dropping it as a duplicate.

  • An address in a language the piece has not been published in shows the original as a fallback, and names the original as its canonical.

  • The hreflang alternates list only the languages that hold the piece (an index or hub lists every declared language), plus the original under both its own language and x-default.

  • Page 2 and later of a list keep their own canonical and name no alternates, because each language's page 2 holds different items.

Sitemaps

A space's sitemap submits each translation at its own address: the root and the hubs (archive, tags, /c/<slug> collections) in every declared language, each translated post, topic and legal document, and every translated docs page, each entry naming its twins. Status incidents are submitted as items.

Events and courses have no translated content (their interface words translate, their text does not), so their language addresses are not submitted: they would be the original text claiming to be another language. Spaces created from a template preview are never in a sitemap.

updates.xml: what changed, as RSS

Every space, of any type, has /<mount>/updates.xml: its 30 most recently changed pieces — pages, posts, topics, releases, incidents, events, legal documents by kind, the contact page — each linked at the address readers use. /<mount>/<lang>/updates.xml is the same feed in a declared language: each piece's published translation at its language address, and an untranslated piece under its original title and address.

curl -sS https://docs.acme.com/docs/es/updates.xml
# the same feed from the API
curl -sS 'https://forumulate.com/api/public/orgs/'$ORG'/spaces/'$SPACE'/updates.xml?locale=es'

The API route is in the public reference. A language the space does not declare gets the original feed rather than an error. A docs-family root (docs, FAQ, careers, custom) names the feed as its RSS alternate, so a feed reader finds it from the page.

The header search, per type

The search box in a space's header asks that type's own search, and every hit links to the address the type really reads it at (an incident at incidents/<id>, a policy at its kind, a contact topic at ?topic=):

Type

Search route under /public/orgs/{orgId}/spaces/{spaceId}/

Reference

Docs, FAQ, careers, custom, courses

search

Public

Blog

blog/search

Public blog

Community spaces

forum/search

Public forum search

Roadmap

roadmap/search

Public roadmap

Changelog

changelog/search

Public changelog

Events

events/search

Events (public)

Status, legal, contact

status/search, legal/search, contact/search

Public

Each answers { hits: [{ title, snippet?, path }] }, where path is the hit's address under the space's mount.

In the API

Every operation below is also reachable from the other surfaces without a dedicated command. forumulate api <Operation> calls it from the CLI, the JavaScript SDK has a typed method for each one (the last column names it; the Python and Go clients are generated from the same spec), and an agent reaches the organization-scoped ones through the MCP call_api tool. Where a CLI command or MCP tool exists too, the last column names it. Operation names link to the API reference.

Blog Post Translation

Operation

Request

What it does

Shortcuts

BlogPostTranslation_list

GET /orgs/{orgId}/spaces/{spaceId}/blog/{topicId}/translations

List translations in a space (blog)

forumulate blog translations list<br>client.blog.postTranslation.list()<br>MCP list_translations

BlogPostTranslation_get

GET /orgs/{orgId}/spaces/{spaceId}/blog/{topicId}/translations/{locale}

Get the translation (spaces blog translations)

forumulate blog translations get<br>client.blog.postTranslation.get()<br>MCP get_translation

BlogPostTranslation_put

PUT /orgs/{orgId}/spaces/{spaceId}/blog/{topicId}/translations/{locale}

Replace the translation (blog)

forumulate blog translations put<br>client.blog.postTranslation.put()<br>MCP put_translation

BlogPostTranslation_remove

DELETE /orgs/{orgId}/spaces/{spaceId}/blog/{topicId}/translations/{locale}

Delete the translation (blog)

forumulate blog translations remove<br>client.blog.postTranslation.remove()<br>MCP remove_translation

BlogPostTranslation_auto

POST /orgs/{orgId}/spaces/{spaceId}/blog/{topicId}/translations/{locale}/auto

Create the auto in a space (blog)

forumulate blog translations auto<br>client.blog.postTranslation.auto()<br>MCP auto_translate

Content Ai

Operation

Request

What it does

Shortcuts

ContentAi_status

GET /orgs/{orgId}/content/libraries/{libraryId}/ai/status

Whether AI for content is available

client.content.ai.status()

ContentAi_translate

POST /orgs/{orgId}/content/libraries/{libraryId}/ai/translate

Translate entries with the organization’s AI provider

client.content.ai.translate()

ContentAi_auto

POST /orgs/{orgId}/content/libraries/{libraryId}/entries/{entryId}/translations/{locale}/auto

Machine-translate an entry

client.content.ai.auto()<br>MCP auto_translate

ContentAi_seo

POST /orgs/{orgId}/content/libraries/{libraryId}/entries/{entryId}/ai/seo

Suggest an SEO title and description

client.content.ai.seo()

ContentAi_draft

POST /orgs/{orgId}/content/libraries/{libraryId}/entries/{entryId}/ai/draft

Draft a blocks field from a brief

client.content.ai.draft()

Content Entry Locales

Operation

Request

What it does

Shortcuts

ContentEntryLocales_read

GET /orgs/{orgId}/content/libraries/{libraryId}/entries/{entryId}/locales

Read an entry's fields in a locale

forumulate entries locale get<br>client.content.entryLocales.read()<br>MCP get_translation

ContentEntryLocales_write

PUT /orgs/{orgId}/content/libraries/{libraryId}/entries/{entryId}/locales/{locale}

Write an entry's localized fields in a locale

forumulate entries locale set<br>client.content.entryLocales.write()<br>client.content.entries.writeLocale()<br>MCP translate_entry

Content Locales

Operation

Request

What it does

Shortcuts

ContentLocales_list

GET /orgs/{orgId}/content/libraries/{libraryId}/locales

List locales in an organization

forumulate libraries locales list<br>client.content.locales.list()<br>MCP list_translation_locales<br>MCP set_translation_locales

ContentLocales_add

POST /orgs/{orgId}/content/libraries/{libraryId}/locales

Create a locale in an organization

forumulate libraries locales add<br>client.content.locales.add()<br>MCP set_translation_locales

ContentLocales_settings

PATCH /orgs/{orgId}/content/libraries/{libraryId}/locales

Update locales in an organization

forumulate libraries locales settings<br>client.content.locales.settings()<br>MCP set_translation_locales

ContentLocales_relabel

PATCH /orgs/{orgId}/content/libraries/{libraryId}/locales/{code}

Update the locale (content libraries)

forumulate libraries locales relabel<br>client.content.locales.relabel()<br>MCP set_translation_locales

ContentLocales_remove

DELETE /orgs/{orgId}/content/libraries/{libraryId}/locales/{code}

Delete the locale (content libraries)

forumulate libraries locales remove<br>client.content.locales.remove()<br>MCP set_translation_locales

Deepl

Operation

Request

What it does

Shortcuts

Deepl_status

GET /orgs/{orgId}/deepl

Get the deepl in an organization

forumulate orgs deepl status<br>client.integrations.deepl.status()<br>MCP translation_provider

Deepl_setKey

PUT /orgs/{orgId}/deepl

Replace the deepl in an organization

forumulate orgs deepl set<br>client.integrations.deepl.setKey()<br>MCP set_translation_provider

Deepl_clear

DELETE /orgs/{orgId}/deepl

Delete the deepl in an organization

forumulate orgs deepl clear<br>client.integrations.deepl.clear()<br>MCP set_translation_provider

Forum Topic Translation

Operation

Request

What it does

Shortcuts

ForumTopicTranslation_list

GET /orgs/{orgId}/spaces/{spaceId}/forum/{topicId}/translations

List translations in a space (forum)

forumulate forum translations list<br>client.forum.topicTranslation.list()<br>MCP list_translations

ForumTopicTranslation_get

GET /orgs/{orgId}/spaces/{spaceId}/forum/{topicId}/translations/{locale}

Get the translation (spaces forum translations)

forumulate forum translations get<br>client.forum.topicTranslation.get()<br>MCP get_translation

ForumTopicTranslation_put

PUT /orgs/{orgId}/spaces/{spaceId}/forum/{topicId}/translations/{locale}

Replace the translation (forum)

forumulate forum translations put<br>client.forum.topicTranslation.put()<br>MCP put_translation

ForumTopicTranslation_remove

DELETE /orgs/{orgId}/spaces/{spaceId}/forum/{topicId}/translations/{locale}

Delete the translation (forum)

forumulate forum translations remove<br>client.forum.topicTranslation.remove()<br>MCP remove_translation

ForumTopicTranslation_auto

POST /orgs/{orgId}/spaces/{spaceId}/forum/{topicId}/translations/{locale}/auto

Create the auto in a space (forum)

forumulate forum translations auto<br>client.forum.topicTranslation.auto()<br>MCP auto_translate

Forum Translate

Operation

Request

What it does

Shortcuts

ForumTranslate_translateTopic

POST /public/orgs/{orgId}/spaces/{spaceId}/forum/t/{slug}/translate

Create the translate in a space (public reader forum t)

client.forum.translate.translateTopic()

ForumTranslate_translatePost

POST /public/orgs/{orgId}/spaces/{spaceId}/forum/t/{slug}/posts/{postId}/translate

Create the translate in a space (public reader forum t posts)

client.forum.translate.translatePost()

Org Language Switcher

Operation

Request

What it does

Shortcuts

OrgLanguageSwitcher_get

GET /orgs/{orgId}/language-switcher

Get the language switcher in an organization

client.orgs.languageSwitcher.get()

OrgLanguageSwitcher_set

PUT /orgs/{orgId}/language-switcher

Replace the language switcher in an organization

client.orgs.languageSwitcher.set()

Page Translation

Operation

Request

What it does

Shortcuts

PageTranslation_list

GET /orgs/{orgId}/spaces/{spaceId}/pages/{pageId}/translations

List a page’s translations

client.pages.translation.list()<br>MCP get_translation<br>MCP list_translations<br>MCP put_translation<br>MCP remove_translation

PageTranslation_auto

POST /orgs/{orgId}/spaces/{spaceId}/pages/{pageId}/translations/{locale}/auto

Machine-translate a page

client.pages.translation.auto()<br>MCP auto_translate

Release Translation

Operation

Request

What it does

Shortcuts

ReleaseTranslation_list

GET /orgs/{orgId}/spaces/{spaceId}/changelog/{releaseId}/translations

List translations in a space (changelog)

forumulate changelog translations list<br>client.changelog.translation.list()<br>MCP list_translations

ReleaseTranslation_get

GET /orgs/{orgId}/spaces/{spaceId}/changelog/{releaseId}/translations/{locale}

Get the translation (spaces changelog translations)

forumulate changelog translations get<br>client.changelog.translation.get()<br>MCP get_translation

ReleaseTranslation_put

PUT /orgs/{orgId}/spaces/{spaceId}/changelog/{releaseId}/translations/{locale}

Replace the translation (changelog)

forumulate changelog translations put<br>client.changelog.translation.put()<br>MCP put_translation

ReleaseTranslation_remove

DELETE /orgs/{orgId}/spaces/{spaceId}/changelog/{releaseId}/translations/{locale}

Delete the translation (changelog)

forumulate changelog translations remove<br>client.changelog.translation.remove()<br>MCP remove_translation

ReleaseTranslation_auto

POST /orgs/{orgId}/spaces/{spaceId}/changelog/{releaseId}/translations/{locale}/auto

Create the auto in a space (changelog)

forumulate changelog translations auto<br>client.changelog.translation.auto()<br>MCP auto_translate

Status Translations

Operation

Request

What it does

Shortcuts

StatusTranslations_list

GET /orgs/{orgId}/spaces/{spaceId}/status/incidents/{incidentId}/translations

List an incident’s translations

forumulate status translations list<br>client.status.translations.list()<br>MCP get_translation<br>MCP list_translations

StatusTranslations_put

PUT /orgs/{orgId}/spaces/{spaceId}/status/incidents/{incidentId}/translations/{locale}

Write an incident’s translation

forumulate status translations put<br>client.status.translations.put()<br>MCP put_translation

StatusTranslations_remove

DELETE /orgs/{orgId}/spaces/{spaceId}/status/incidents/{incidentId}/translations/{locale}

Remove an incident’s translation

forumulate status translations remove<br>client.status.translations.remove()<br>MCP remove_translation

StatusTranslations_machine

POST /orgs/{orgId}/spaces/{spaceId}/status/incidents/{incidentId}/translations/{locale}/machine

Machine-translate an incident

forumulate status translations machine<br>client.status.translations.machine()<br>MCP auto_translate (alias of StatusTranslations_auto)

StatusTranslations_auto

POST /orgs/{orgId}/spaces/{spaceId}/status/incidents/{incidentId}/translations/{locale}/auto

Machine-translate an incident (canonical)

forumulate status translations auto<br>client.status.translations.auto()<br>MCP auto_translate

Translation Coverage

Operation

Request

What it does

Shortcuts

TranslationCoverage_coverage

GET /orgs/{orgId}/spaces/{spaceId}/translations

Get a space’s translation coverage

client.docs.translationsCoverage.coverage()<br>MCP translation_status

Translation Override

Operation

Request

What it does

Shortcuts

TranslationOverride_list

GET /orgs/{orgId}/translation-overrides

List translation overrides in an organization

forumulate orgs strings list<br>client.i18n.overrides.list()<br>MCP list_ui_string_overrides

TranslationOverride_set

PUT /orgs/{orgId}/translation-overrides

Replace translation overrides in an organization

forumulate orgs strings set<br>client.i18n.overrides.set()<br>MCP set_ui_string_override

TranslationOverride_remove

DELETE /orgs/{orgId}/translation-overrides

Delete translation overrides in an organization

forumulate orgs strings remove<br>client.i18n.overrides.remove()<br>MCP set_ui_string_override

The Forumulate teamUpdated