GitLab CI
Keep your repository translation files in sync with Translatize straight from your GitLab pipelines. Wire it up with a CI/CD Catalog component you include:, or drop a copy-paste job into any .gitlab-ci.yml today – both run the Translatize CLI through npx, so there is nothing to vendor into your repo.
What the CLI does
The translatize CLI reads a config file (default translatize.config.json, committed to your repo) that points at your Translatize project and maps its label namespaces to files on disk.
| Command | Purpose |
|---|---|
pull | Download translations from Translatize into your repo locale files. |
push | Upload local source strings to Translatize. |
status | Compare local vs. remote and report drift. |
Useful flags: --config <path>, --api-url <url>, --json, --dry-run, and – for status – --fail-on-missing / --fail-on-diff (turn findings into a non-zero exit so a pipeline gate fails). The token is never passed on the command line: the CLI reads TRANSLATIZE_API_TOKEN from the environment, which you provide as a masked CI/CD variable.
Exit codes
| Code | Meaning | Job result |
|---|---|---|
0 | Success – nothing to report. | pass |
1 | A gate condition tripped (missing translations / drift) under --fail-on-missing / --fail-on-diff, or an API/network/auth error (bad or expired token, unreachable API). | fail |
2 | Usage or configuration error (unreadable/invalid config, missing token, bad flags). | fail |
Any non-zero code fails the job. Add allow_failure: true to a job to make it advisory instead of blocking.
Component usage
include:
- component: $CI_SERVER_FQDN/translatize/gitlab/translatize@0.1.0
inputs:
command: status
cli_version: latest
config: translatize.config.json
extra_args: "--fail-on-missing"That adds one job, translatize-sync, to your pipeline. Its inputs:
| Input | Default | Description |
|---|---|---|
stage | test | Stage the job runs in. |
command | status | One of pull, push, status. |
cli_version | latest | npm dist-tag or exact version of @translatize/cli. |
config | translatize.config.json | Path to the CLI config file. |
api_url | "" | Override the API base URL (empty = CLI default). |
extra_args | "" | Extra flags appended verbatim, e.g. --fail-on-missing --json. |
node_image | node:20-alpine | Image that provides Node.js and npx. |
include: component: line above resolves as printed. Prefer not to use the catalog? The copy-paste job below runs the identical npx invocation.Copy-paste job (no component needed)
Drop this into your project .gitlab-ci.yml. It runs the exact same npx invocation as the component defaults:
translatize-status:
stage: test
image: node:20-alpine
script:
- npx --yes @translatize/cli@latest status --config translatize.config.jsonSwap status for pull or push, pin @latest to an exact version for reproducible builds, and append flags such as --fail-on-missing or --json as needed.
CI/CD variable setup
- In Translatize, open your project and go to Project Settings → Integrations. Create an API token – it looks like
mcni_... - Tokens are branch-bound: each token is tied to one project and a base branch (default
main). A standard token acts only on that branch; acreate-own-scope token may also target branches it created (select one with--branchinextra_args). If you sync more than one branch with standard tokens, mint one token per branch and store them under distinct variable names. - In GitLab, go to Settings → CI/CD → Variables and add the token as a masked variable:
| Key | Value | Flags |
|---|---|---|
TRANSLATIZE_API_TOKEN | mcni_... | Masked |
The CLI reads this automatically – never echo it or pass it as a --flag.
TRANSLATIZE_API_TOKEN masked but not protected. A push token used only by branch or scheduled pipelines can be both masked and protected.Merge-request status gate
Fail the MR pipeline when translations are missing, so drift cannot merge to your default branch:
translatize-mr-gate:
stage: test
image: node:20-alpine
rules:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
script:
- npx --yes @translatize/cli@latest status --config translatize.config.json --fail-on-missing--fail-on-missing makes the CLI exit 1 when any target language is missing translations, which fails the job and blocks the merge. Add allow_failure: true to make it advisory instead.
Scheduled nightly pull that commits back
Pull the latest translations every night and commit them to the branch. Because a bot needs to write to the repo, this uses a GitLab project access token with the write_repository scope (Developer role or higher), stored as a masked and protected CI/CD variable TRANSLATIZE_GIT_TOKEN. This is a different token from TRANSLATIZE_API_TOKEN – the GitLab token authorizes the git push, the Translatize token authorizes the pull. Create the schedule under Settings → CI/CD → Pipeline schedules, targeting the branch your Translatize token is bound to.
translatize-nightly-pull:
stage: test
image: node:20-alpine
rules:
- if: '$CI_PIPELINE_SOURCE == "schedule"'
variables:
GIT_STRATEGY: clone
GIT_DEPTH: "0"
script:
- apk add --no-cache git
- npx --yes @translatize/cli@latest pull --config translatize.config.json
- |
if [ -z "$(git status --porcelain)" ]; then
echo "Translations already up to date."
exit 0
fi
git config user.email "bot@translatize.com"
git config user.name "Translatize Bot"
git add -A
git commit -m "chore(i18n): sync translations from Translatize [skip ci]"
git push "https://oauth2:${TRANSLATIZE_GIT_TOKEN}@${CI_SERVER_HOST}/${CI_PROJECT_PATH}.git" "HEAD:${CI_COMMIT_BRANCH}"[skip ci]in the commit message stops the push from triggering another pipeline.git status --porcelaindetects both edited and newly-created locale files, so a no-op night makes no empty commit.HEAD:${CI_COMMIT_BRANCH}pushes the detached CI checkout back onto the scheduled branch.
