


Localization as code: automate translations in your CI/CD with the API

transglot team
"Localization as code" is a simple idea: your translations should move through the same pipeline as everything else you ship — versioned, automated, and triggered by the same events that trigger your builds, not a manual export a human remembers to do before each release. Here is how to actually wire that up with the transglot REST API.
The three verbs that matter
The `/api/v1` surface is deliberately small. Everything you need for CI automation comes down to three operations: pull your latest translations, push new source strings, and trigger an AI translation batch — plus a way to check on that batch's status.
- `pull` — export the current state of a project (optionally scoped to a locale or format) so your build can bundle fresh translations.
- `push` — import new or changed source strings, with a choice between merging (add/update only) or syncing removals (mirror the source exactly, including deletions).
- `translate` — trigger an AI translation batch for missing or selected keys, so new strings get a first-pass translation without a human opening the editor first.
- `batches` — check the status of a triggered batch, or retry the ones that failed.
Authentication: scoped project tokens
Every API call authenticates with a bearer token scoped to a single project — not a personal account token. Tokens are prefixed `tgl_`, stored as a sha256 hash (so the raw value is shown to you exactly once, at creation), and carry explicit abilities: `push`, `pull`, and `manage`. A CI pipeline that only needs to pull translations should get a pull-only token; only your release-automation job needs push or manage. Tokens can also carry an optional expiry, and everything is rate-limited.
curl -s \
-H "Authorization: Bearer $TRANSGLOT_TOKEN" \
"https://app.transglot.ai/api/v1/projects/$PROJECT_ID/pull?format=json"A minimal CI pipeline: pull on build
The lowest-effort integration is a pull step that runs before your app builds, so every release ships with whatever has been translated up to that point — no one has to remember to export anything.
pull-translations:
script:
- >
curl -s -H "Authorization: Bearer $TRANSGLOT_TOKEN"
"https://app.transglot.ai/api/v1/projects/$PROJECT_ID/pull?format=json"
-o src/locales/en.json
artifacts:
paths:
- src/locales/This is deliberately provider-agnostic pseudo-YAML — the same `curl` calls (pull, and push if you also sync source strings from code) work whether your CI is GitHub-hosted, GitLab, CircleCI, or something self-managed. On GitHub you can skip the scripting entirely with the first-party transglot GitHub Action; anywhere else, the zero-dependency transglot CLI wraps the same calls. The REST API stays underneath for full control.
Pushing new source strings and auto-translating them
The more powerful pattern is pushing your source-language strings whenever they change in code (e.g. a merge to your main branch), then immediately triggering a translation batch so the other locales catch up automatically — no one has to notice that a new key was added and go translate it by hand.
# 1. Push updated source strings (merge mode: add/update only)
curl -s -X POST \
-H "Authorization: Bearer $TRANSGLOT_TOKEN" \
-H "Content-Type: application/json" \
-d @src/locales/en.json \
"https://app.transglot.ai/api/v1/projects/$PROJECT_ID/push?mode=merge"
# 2. Trigger AI translation for anything still missing
curl -s -X POST \
-H "Authorization: Bearer $TRANSGLOT_TOKEN" \
"https://app.transglot.ai/api/v1/projects/$PROJECT_ID/translate?scope=missing"This is worth calling out explicitly: even fully automated in CI, translation runs as a metered, batched AI job (about 30 keys per chunk) against your organization's quota, same as if you had clicked "translate missing" in the editor. Automating the trigger does not bypass the usage model — it just removes the manual step.
Reacting to completion with webhooks
Triggering a translation batch is asynchronous — you do not want your CI job blocking and polling until it finishes. Instead, register a webhook on `batch.completed` (and `batch.failed`) for the project, and let your automation react when the batch actually finishes, rather than guessing at a sleep duration.
Every webhook delivery is signed with HMAC-SHA256 so your receiving endpoint can verify the payload genuinely came from transglot before acting on it. Deliveries are logged (the last 50 per endpoint) with status and attempt count, and if an endpoint was down when a batch completed, you can manually redeliver the exact original payload rather than re-triggering the whole batch.
{
"event": "batch.completed",
"project_id": "prj_8k2m",
"batch_id": "btc_91fa",
"status": "completed",
"keys_translated": 27,
"locales": ["es", "fr", "de"]
}Putting it together
A reasonably complete "localization as code" setup looks like this: your CI pushes source strings on every merge to main, triggers a translation batch for anything new, and a webhook notifies a downstream job (or just posts to a Slack channel via your own relay) once translations are ready to pull for the next release build. None of this requires a human to remember a manual export/import step — the CLI (or the GitHub Action) plus webhooks carry the whole loop, all over the same small API surface.
If your team is choosing between managing translations by hand or wiring this up, the API surface here is intentionally small enough to integrate in an afternoon — pull, push, translate, and a webhook is usually all it takes.
Related articles
More guides on localization workflows, terminology, and translation QA.
