Translatize CLI
The command-line client for Translatize. It downloads a branch into per-language JSON files with pull, sends local source keys back with push, and reports drift with status – so a pull request can be gated on translation completeness.
Install
Add the CLI as a dev dependency. The binary is named translatize – run it with npx translatize <command> or from an npm script. It is built on @translatize/core and requires Node.js 18.17 or newer.
npm install -D @translatize/cli@translatize scope, so the install above and npx @translatize/cli@latest resolve from the public registry.Quickstart
# 1. Scaffold translatize.config.json (records your project + file layout)
npx translatize init
# 2. Provide a branch-bound API token
export TRANSLATIZE_API_TOKEN=mcni_xxx
# 3. Download translations into locales/<lang>.json
npx translatize pullinit writes a translatize.config.json you commit to your repo. The token is never written to that file – it is read from the environment or the --token flag at run time.
Authentication
The CLI authenticates with an API token – a string beginning with mcni_, not your login. Create one under Project Settings → Integrations in the app. A token is bound to a single project and a base branch, and by default translatize acts on that bound branch.
A token whose scope is create-own – an agent token – may also target branches it created: pass --branch <name> (or set branch in the config) to operate on one of them. Naming a branch the token cannot touch fails with a branch_not_allowed error that lists the branches the token may target.
The token is resolved in this order:
- the
--token <mcni_...>flag, then - the
TRANSLATIZE_API_TOKENenvironment variable.
translatize.config.json or any file. In CI, store it as a secret and expose it as the TRANSLATIZE_API_TOKEN environment variable.Configuration
translatize.config.json lives at the root of your project, or wherever you point --config. File patterns are resolved relative to the directory that holds the config file.
{
"apiUrl": "https://api.translatize.com/v1",
"projectId": "your-project-id",
"format": "json-nested",
"files": "locales/{lang}.json",
"namespace": "app",
"branch": "feature-x"
}| Field | Required | Description |
|---|---|---|
apiUrl | no | API base URL including the /v1 segment. Defaults to https://api.translatize.com/v1. |
projectId | no | The project id. May be left empty – the CLI derives it from the token at run time. Set it to pin the project, and a mismatch with the token is reported. |
format | yes | On-disk shape: json-nested (dotted keys become nested objects) or json-flat (dotted keys stay flat). |
files | yes | Path pattern for each language file. Must contain the {lang} placeholder, e.g. locales/{lang}.json. |
namespace | no | Restrict every operation to keys beginning with that namespace prefix. |
branch | no | Default branch for pull/push/status. Must be in the token allowed set and is overridden by --branch. When omitted, commands use the bound branch. |
The flat, dotted keys stored by the API can be written to disk two ways: json-nested turns app.nav.home into nested objects, while json-flat keeps the dotted key as-is. Both round-trip losslessly, and files are written with keys sorted and a trailing newline so re-running pull stays diff-friendly.
Commands
Every command accepts these global flags:
| Flag | Description |
|---|---|
-c, --config <path> | Path to the config file. Default translatize.config.json. |
--token <token> | API token, overriding TRANSLATIZE_API_TOKEN. |
--api-url <url> | API base URL, overriding the config value. |
translatize --version and translatize <command> --help are available at any level.
translatize init
Create translatize.config.json. Refuses to overwrite an existing file unless --force is passed. If a token is available it validates it via the API and prints the project name, bound branch, role, and configured languages.
| Flag | Description |
|---|---|
--project-id <id> | Project id to record in the config. |
--files <pattern> | File pattern with a {lang} placeholder. Default locales/{lang}.json. |
--format <format> | json-nested (default) or json-flat. |
--force | Overwrite an existing config file. |
translatize pull
Download the branch and write one file per project language at the files pattern, creating parent directories as needed. A key whose value is empty or missing for a language is omitted from that file. When namespace is set, only keys under it are pulled.
| Flag | Description |
|---|---|
--branch <name> | Branch to operate on. Overrides the config branch field and the token bound branch. Must be in the token allowed set. |
--dry-run | Report the per-file changes (new file / keys added / changed / removed locally) without writing anything. |
--json | Emit machine-readable JSON. |
translatize push
Read each language file, compare it with the branch, and upload only new and changed keys. Values are assembled per key across all language files, and requests are chunked automatically to stay within the server batch limit. Translatize never deletes keys via push: keys that exist on the branch but not locally are reported and left untouched. It exits 1 if the server rejects any key.
| Flag | Description |
|---|---|
--branch <name> | Branch to operate on. Overrides the config branch field and the token bound branch. Must be in the token allowed set. |
--dry-run | Print the pending create/update list without sending anything. |
--json | Emit machine-readable JSON. |
translatize status
Compare local files against the branch without changing either side – this is the CI gate. It prints per-language completeness (non-empty translations over total branch keys) and the counts of keys that are only local, only remote, or whose values differ, with up to 10 example keys each. Without a --fail-* flag it reports differences but still exits 0.
| Flag | Description |
|---|---|
--branch <name> | Branch to operate on. Overrides the config branch field and the token bound branch. Must be in the token allowed set. |
--fail-on-missing | Exit 1 if any language has missing translations. |
--fail-on-diff | Exit 1 if local differs from the branch in any way. |
--json | Emit machine-readable JSON. |
Selecting a branch
pull, push, and status all accept --branch <name>. The branch is resolved in this order:
- the
--branch <name>flag, then - the
branchfield intranslatize.config.json, then - the token bound (base) branch.
A standard token can only ever act on its bound branch, so --branch must name that same branch. A create-own agent token may additionally target any branch it created. Targeting a branch outside the token allowed set fails with a branch_not_allowed error listing the branches the token may use.
create-own scope lets an AI agent open and manage its own translation branches – it can act on the branches it creates but can never reach one it did not. See the MCP Server and Integration API docs for the full agent workflow.Exit codes
| Code | Meaning |
|---|---|
0 | Success (including status differences when no --fail-* gate is set). |
1 | A gate tripped, a push had server-side failures, or an API request failed. |
2 | Usage or configuration error (bad flags, missing/invalid config, no token). |
Use in CI
status is designed to fail a build when translations fall behind. This GitHub Actions job blocks merges when any language is missing translations:
name: translations
on: [pull_request]
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx translatize status --fail-on-missing
env:
TRANSLATIZE_API_TOKEN: ${{ secrets.TRANSLATIZE_API_TOKEN }}To push newly added source keys after a merge to main, run npx translatize push in a job with a token bound to that branch. Rather than script npx by hand, prefer the ready-made GitHub Action or GitLab CI component.
