Auto-localize a template into per-locale carrier-approved variants
One source template, many languages: Orbit translates a template into up to 25 target locales in a single call, keeps your{{token}} placeholders intact, and (for WhatsApp and RCS) submits each translated variant for carrier approval exactly as if you had authored it by hand. This guide walks both halves of the feature, the dashboard and API flows, the limits and failure codes, and what happens at send time when a recipient’s language is matched against your variants.
Auto-localization rewrites copy only. It never chooses a route or sends anything by itself; every variant still goes through your normal template, campaign, and approval flows.
1. The two halves: generate vs commit
The feature is two endpoints that solve different problems. Know which half you need before you call either.
Generate is for drafting: you hand it copy, it hands back translations for you to review, edit, and then commit onto a campaign or template through the regular write endpoints. The campaign composer’s translate-locales dialog is a client of this endpoint.
Commit is for the template library: it reads one canonical template (its body and, for rich WhatsApp templates, its button labels), translates it, and bulk-creates one real template row per locale. Each created row is indistinguishable from a hand-authored variant. It shares the source template’s
channel and name, carries its own language, and is submitted to the carrier for approval on creation.
A useful rule of thumb: campaign copy that you review before a specific send → generate; a canonical WhatsApp/RCS template you want available in every market → commit.
2. Dashboard walkthrough: the translate-locales dialog
In the campaign composer (Campaigns → Create), the Translate locales dialog runs the generate half against your campaign’s current message:- Open the dialog from the message step of the composer. It reads the body (and subject, for email) you have drafted so far as the source, with its locale as the source locale.
- Pick your target locales (BCP-47 tags such as
fr,de,pt-BR). Up to 25 per run. - Run the translation. The dialog shows one editable variant per locale, plus the source locale as the default variant. Edit any variant’s body or subject in place if a translation needs a brand-specific tweak. The response also names any locale the model failed to return (
missingLocales), so you author that one manually instead of silently shipping fewer variants. - Commit the variant set to the campaign. From then on, each recipient receives the variant matching their stored
language(section 6).
3. API walkthrough
All calls are authenticated the same way as the rest of the API; the commit endpoint requires thetemplates:write scope and accepts an Idempotency-Key header.
3.1 Generate: translate a body for review
subject, each variant carries a translated subject too. missingLocales lists any requested locale the model did not return, so you can re-run just those or author them by hand.
The same call from JavaScript:
3.2 Commit: bulk-create per-locale template rows
Give the commit endpoint a stored template id and the locales you want. It translates the template’s body (and button labels for rich WhatsApp templates) and creates one row per locale:sourceLocale is optional; when omitted, the source template row’s own language is used. The response reports one outcome per locale, each with its own status:
skipped with model_returned_no_variant, a locale whose row already exists is skipped with variant_already_exists (re-running localize is safe), and a per-row create failure is failed with create_failed while the rest still land. templateStatus is the status at insert time; the carrier-approval state settles afterwards and is authoritative via the tracker endpoint in section 5.
4. Limits and behavior
- 1–25 target locales per call, on both endpoints. For more markets, call again with the next batch; the commit endpoint’s skip-if-exists behavior makes repeat runs harmless.
- Source locale handling. Generate always includes the source locale as the default variant and drops it from the translation targets; commit never re-translates the source row.
- 30 s translation ceiling. The whole translation round-trip is capped at 30 seconds. If it expires you get
504witherror.code: LLM_TIMEOUT. - Upstream failure of the translation provider returns
502withLLM_UPSTREAM_ERROR; both are retryable. - Unparseable model output returns
422withAI_PARSE_FAILED. Retry, or retry with a smaller locale batch. - No AI provider configured for your organization returns
503(LOCALIZATION_UNAVAILABLEon commit). Author per-locale variants manually instead. - Validation errors (empty body, more than 25 locales, malformed tags) return
400. - Billing. Translation runs on your organization’s AI tier; usage is attributed to your organization, not to individual users.
- Placeholder preservation. The translation contract requires the model to copy every placeholder through exactly as written: named tags (
{{first_name}},{{company}}) and WhatsApp positional tokens ({{1}},{{2}}) are never translated, their braces are never reordered, and no spaces are inserted inside them. URLs, email addresses, and phone numbers are likewise copied verbatim into every variant. - Channel length norms. The model is instructed per channel: SMS bodies stay within 160 characters, push within 120, and WhatsApp/RCS bodies within the carrier body limit (1024 characters) with button labels within 25.
5. Per-locale carrier approval
Every WhatsApp/RCS row the commit endpoint creates goes through the same carrier-approval path as a hand-authored template: same submission, same queue, same status lifecycle on the row. There is no separate “localized” approval state; per-locale approval is just each row’sstatus.
Poll all locales of one template with the tracker endpoint. The id may be any variant’s id; it resolves the shared (channel, name) and returns every sibling variant with its approval status, carrier external id, and any submission error:
fr approved while pt-BR is still pending or comes back rejected.
When one locale is rejected and the others are approved: treat the rejected row exactly like any rejected template. Edit and resubmit that one variant, or delete it; the approved siblings are unaffected and keep sending. Until the rejected locale is approved, recipients whose language points at it are served by the send-time fallback chain below rather than by an unapproved template. Re-running localize for that locale only recreates the row if you deleted it; an existing row reports skipped / variant_already_exists.
Approval authoring norms per channel live in Create and approve WhatsApp templates and the RCS templates tab.
6. How a recipient’s language picks a variant at send time
The input is the contact’slanguage attribute: a BCP-47-ish tag (en, fr, pt-BR) stored on the contact, set through contact imports and the contacts API, defaulting to en.
At send time the resolver (the resolveLocaleVariant fallback chain in the template-localization module) picks a variant per recipient in this order, first hit wins:
- Exact tag — a variant whose tag equals the recipient’s, case-insensitively (
pt-brmatchesPT_br). - Primary subtag — a variant sharing the language part. A bare-primary variant (
pt) is preferred over a regional one (pt-BR), so apt-PTrecipient lands on neutralptbefore an unrelated region. - Your fallback chain — the optional
fallback_languagesorder you set on the template (for example["es", "en"]), consulted after the recipient’s own language fails to match and before the default. This lets a multi-market sender say “no variant for this language? prefer Spanish, then English.” - The default locale — the variant matching the set’s declared source locale.
- First variant — last resort, and a sign the default-locale variant was dropped from the set.
_ and - as equivalent, so messy CRM values like " PT_br " still resolve. A recipient with no stored language falls through to the default locale.
For variable interpolation inside the chosen variant, see the personalization walkthrough; for reading translation quality back out of your traffic, see the language quality guide.
7. Troubleshooting
8. See also
- Campaign template + variable personalization walkthrough — per-channel authoring norms and variable slots that apply to every variant.
- Create and approve WhatsApp templates — the approval path each localized WhatsApp variant joins.
- RCS templates tab — managing RCS template variants in the dashboard.
- Language quality guide — measuring how your localized traffic actually reads.
- Outbound templates — the template library these variants live in.