translation-management-cli
v0.1.1
Published
CLI for pulling translations from Translation Management into a repository.
Readme
translation-management-cli
Sync translations between Translation Management and your repository.
tm pull— download all translations of your project as one<lang>.jsonfile per languagetm push— upload local<lang>.jsonfiles into your project
The CLI talks to the production Translation Management API out of the box — no URL
configuration needed. The only thing you must provide is an API token via the
TM_TOKEN environment variable.
Quick start
1. Install
pnpm add -D translation-management-cli2. Get an API token
In the Translation Management web app, open your project → API Tokens → Nový token. Copy the plaintext token shown — it is displayed only once.
The token is bound to one project, so the CLI always knows which project to sync — no project ID needed.
3. Provide the token as TM_TOKEN
The CLI reads the token from the TM_TOKEN environment variable. It does not
load .env files by itself, so pick one of these:
One-off / local:
TM_TOKEN=tm_pat_xxx pnpm pull-localesShell profile (local dev): add
export TM_TOKEN=tm_pat_xxxto~/.zshrc..envfile: storeTM_TOKEN=tm_pat_xxxin.env.localand run through a loader, e.g.dotenv -e .env.local -- tm pull(dotenv-cli), ornode --env-file=.env.local node_modules/.bin/tm pull(Node 22+).CI: set
TM_TOKENas a secret in your pipeline.
Never commit the token.
4. Add a script and run it
Set --out to the folder your frontend reads translations from. The path is
relative to where you run the script (typically the repo root):
{
"scripts": {
"pull-locales": "tm pull --out src/locales"
}
}Examples per framework:
- Next.js (App Router with
next-intl):--out src/locales - Vite / CRA:
--out src/locales - React Native:
--out src/i18n/locales - Monorepo from root:
--out apps/web/src/locales
Then:
TM_TOKEN=tm_pat_xxx pnpm pull-locales✓ locales/cs.json
✓ locales/en.json
Pulled 2 language(s) into locales/Each file contains nested JSON (compatible with next-intl, react-i18next, formatjs, etc.):
{
"home": {
"hero": {
"title": "Vítejte"
}
},
"common": {
"save": "Uložit"
}
}Commands
tm pull
Downloads all translations for the project bound to TM_TOKEN and writes one
<lang>.json file per language defined in the project.
| Flag | Default | Description |
|---|---|---|
| --out <dir> | ./locales | Output directory (created if missing) |
tm push
Reads every <lang>.json file in a directory and uploads its keys into the
project. The language is taken from the filename (cs.json → cs); files for
languages not defined in the project are skipped and reported.
| Flag | Default | Description |
|---|---|---|
| --dir <dir> | ./locales | Directory containing <lang>.json files |
TM_TOKEN=tm_pat_xxx tm push --dir src/locales✓ cs: 42 key(s)
✓ en: 42 key(s)
Imported 84 key(s) across 2 language(s).Environment variables
| Variable | Required | Description |
|---|---|---|
| TM_TOKEN | yes | API token created in the web app (project-scoped) |
Exit codes
| Code | Meaning |
|---|---|
| 0 | Success |
| 1 | Configuration error (missing TM_TOKEN, unreadable directory, invalid JSON) |
| 2 | Token invalid or revoked (HTTP 401) |
| 3 | Other HTTP error |
| 4 | Unexpected error (non-JSON response, etc.) |
Troubleshooting
TM_TOKEN env var is required— the variable isn't visible to the process; see step 3 above (.envfiles are not loaded automatically).Unauthorized: token is invalid or has been deleted— the token was revoked in the web app or copied incorrectly; create a new one.HTTP 429— the API rate-limits import/export; wait a moment and retry.Skipped (not in project)after push — add the missing language to the project in the web app first, then push again.
