Translations
Most text that guests and staff read in SuiteOp, such as manual titles, department names and upsell copy, isn’t stored on the record itself. The record holds a translation ID (a field such as titleId or nameId), and the text lives in that translation, once per language. This guide covers reading that text, repairing it after a rename and filling in a language. Every field is listed on the operation’s page in the API Reference.
| Operation | Request | Permission |
|---|---|---|
getTranslationEntries | GET /translations/{translationId}/entries | Any permission, then per domain (see below) |
getTranslationEntriesBatch | GET /translations/entries | Any permission, then per domain (see below) |
retranslateGuideText | POST /translations/{translationId}/retranslate | modify_guides |
initializeLanguageTranslations | POST /translations/initialize-language | manage_organization |
getLanguageCoverage | GET /translations/language-coverage | manage_organization |
createTranslation | POST /translations | modify_tasks |
Paths are relative to your region’s base URL, for example https://api-us.suiteop.com/api/v1. See Authentication for permissions.
How translations work
Section titled “How translations work”- A translation is one piece of text, identified by a translation ID. Pass that ID, never the ID of the manual or task that holds it.
- An entry is the text of that translation in one language:
language,textandmethod.methodrecords how the entry got there:manual(written or edited by a person),automatic(machine-translated),recursive, ornull(older rows; treated as hand-written). - Machine translation runs in the background. Operations that translate return as soon as the work is queued. Languages appear in the entries as the jobs finish.
- Hand-written text is protected when you rename a manual category.
updatePortalManualCategoryre-translates the other languages only when every one of them is machine output (an entry whosemethodisnullcounts as hand-written). If anyone wrote or reviewed a translation by hand, only English changes.retranslateGuideTextis how you push the new wording to the other languages anyway. Other updates are not protected this way: changing an upsell’stitleordescriptionwithupdateUpsellre-translates every other language, overwriting hand-written translations.
The languages are en, es, fr, nl, de, zh, ar, it, bg, ja, pt, el, cs, he, uk, ru, id and ka. Machine translation targets the languages enabled for your organization, plus English.
Reading translated text
Section titled “Reading translated text”curl "https://api-us.suiteop.com/api/v1/translations/3f1c9a2e-…/entries" \ -H "Authorization: Bearer sk_live_your_key_here"{ "data": [ { "language": "en", "text": "Kitchen appliances", "method": "manual" }, { "language": "fr", "text": "Appareils de cuisine", "method": "automatic" } ], "meta": { "requestId": "…" }}To read many at once, repeat translationIds (up to 50):
curl "https://api-us.suiteop.com/api/v1/translations/entries?translationIds=3f1c9a2e-…&translationIds=8b0d4f71-…" \ -H "Authorization: Bearer sk_live_your_key_here"data is an object keyed by each ID you asked for, and each value is the same array of entries.
Who can read what:
- The operations only need the credential to hold at least one permission. Each translation is then checked against the domain it belongs to: you need that domain’s view permission or its write permission. For example, manual and upsell copy needs
view_guidesormodify_guides, task copy needsview_tasksormodify_tasks, and property copy needsview_propertiesormodify_properties. Pre-arrival step, guest portal and upsell text is also readable withview_propertiesormodify_properties, because the operations that return those IDs need them. - Without the right permission,
getTranslationEntriesreturns403withMissing permission: one of …, naming the permissions that would work. A translation that can’t be attributed to any domain returns403This translation is not readable through the public API. - An ID from another organization, or one tied to properties an OAuth token can’t reach, returns an empty array rather than an error.
- The batch form never refuses an individual ID: an ID you can’t read comes back as an empty array, the same as a translation with no entries yet.
Re-translating guide text after a rename
Section titled “Re-translating guide text after a rename”When you rename guide text in English and an operator had hand-written any other language, those languages keep the old wording. Re-translate them from the new English:
- Rename the text. For example,
PATCH /portal-manual-categories/{id}with{"title": "Kitchen appliances"}(needsmodify_guides). The response includestitleId. - Re-translate that
titleId:
curl -X POST https://api-us.suiteop.com/api/v1/translations/3f1c9a2e-…/retranslate \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Idempotency-Key: 550e8400-e29b-41d4-a716-446655440000" \ -H "Content-Type: application/json" \ -d '{"sourceLanguage": "en", "overrideExisting": true}'{ "data": { "translationId": "3f1c9a2e-…" }, "meta": { "requestId": "…" }}- The response is
200and only echoes the ID. The translations run in the background, so read the result withGET /translations/{translationId}/entries.
Field notes:
- Both fields are required. A request without
sourceLanguageoroverrideExistingis refused with400. overrideExisting: trueoverwrites every other language, hand-written and reviewed translations included.falseonly fills languages that have no entry yet.sourceLanguageis a preference. Hand-written text wins: if your language holds machine output and another language holds hand-written text, that text is used as the source.- Only guide text is accepted: the text of guide items and lists, manuals, manual categories, events, upsells and fee products. Any other translation ID, including one from another organization, returns
404.
Filling in a language
Section titled “Filling in a language”POST /translations/initialize-language machine-translates existing organization content into one language, filling only the gaps. Text that already exists in that language is skipped, so nothing hand-written is overwritten.
curl -X POST https://api-us.suiteop.com/api/v1/translations/initialize-language \ -H "Authorization: Bearer sk_live_your_key_here" \ -H "Idempotency-Key: 7c9e6679-7425-40de-944b-e07fc1f90ae7" \ -H "Content-Type: application/json" \ -d '{"language": "fr"}'The response is 200 with counters for the work that was started, not finished: enqueued, deduplicated, hydrationSkipped and enqueueFailed. This call doesn’t enable the language for your organization; enable it in settings first, or nothing displays the new entries.
GET /translations/language-coverage shows where the gaps are: total translatable records, byLanguage with translated and missing counts per language (English first), and inFlight, the records still being translated. The counts aren’t taken at a single instant, so a gap that just closed can still show as open.
Creating question text
Section titled “Creating question text”POST /translations creates a translation for pre-arrival question copy, the titleMlTextId of a question or the nameMlTextId of an option used by createPrecheckStep. It accepts only the sourceTable values precheck_question, precheck_option and precheck_step_detail. sourceTable, contentTag, inputType and text are required, and language defaults to en. The response is 201 with data.translationId. The text is stored in that one language and isn’t machine-translated.