npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

translato-cli

v1.1.7

Published

Translato CLI — push & pull translation keys from CI/CD pipelines

Readme

translato-cli

CLI for Translato — push and pull translation keys between your local i18n files and the Translato TMS.

Install

npm install -g translato-cli

Quick Start

# 1. Log in via your browser
translato login

# 2. Create config files interactively
translato init

# 3. Push source keys AND values to the TMS
translato push

# 4. Pull all translations (including source language) to local files
translato pull

# 5. Or do both in one step
translato sync

Commands

| Command | Description | |---------|-------------| | translato init | Interactive setup — creates .translato.yml config and .env for credentials | | translato login | Authenticate with Translato via browser (device authorization flow) | | translato logout | Remove stored credentials from .env | | translato push | Upload source language keys and values to the TMS | | translato pull | Download translations for all languages (including source) to local files | | translato sync | Two-way sync: push keys then pull translations | | translato status | Show project info and per-language translation progress bars | | translato validate | Check files for missing keys, extra keys, empty values, and placeholder mismatches | | translato diff | Compare local translation files with remote TMS translations | | translato watch | Watch source files for changes and auto-push on save |

Login

translato login

Authenticates using a device authorization flow. The CLI displays a one-time code and opens your browser. Log in to Translato in the browser, enter the code, and the CLI receives an API token automatically. The token is saved to .env for future use.

🔑 Logging in to Translato...

  Your authorization code: ABCD-EFGH

  A browser window will open. Log in to Translato and enter the code above.
  If the browser doesn't open, visit:

    http://translato.app/auth/cli?code=ABCD-EFGH

  Waiting for authorization... (expires in 10 minutes)

  ✅ Login successful!

  Your API key has been saved to .env.
  Run translato status to verify your connection.

Logout

translato logout

Removes TRANSLATO_API_KEY, TRANSLATO_PROJECT, and TRANSLATO_HOST from your .env file. If .env becomes empty after removal, the file is deleted. Other environment variables in .env are preserved.

Init

translato init

Interactive setup wizard that creates a .translato.yml config file and optionally saves credentials to .env. The command:

  1. Auto-detects your locales directory — scans for src/locales, src/i18n, src/lang, locales, i18n, lang, translations, public/locales, public/i18n, assets/locales, assets/i18n, and resources/lang.
  2. Auto-detects languages — reads filenames (en.json, de.yml) and subdirectories (en/, fr/) from the locales directory.
  3. Auto-detects namespaces — finds namespace files like common.json, auth.json in the source language directory.
  4. Prompts for configuration — project name, locales directory, source language, target languages (if not detected), API key, and project ID.
  5. Verifies credentials — if both API key and project ID are provided, calls the API to confirm they work before writing config.
  6. Writes .translato.yml — safe to commit (no secrets).
  7. Writes credentials to .env — with 0600 permissions on Unix (owner-only).
  8. Updates .gitignore — adds .env, .env.lock, .translato.state, and .translato.lock if missing.
🚀 Initializing Translato project...

  📁 Detected locales directory: ./src/locales
  🌐 Detected languages: en, de, fr, es

  Project name (my-app):
  Locales directory (src/locales):
  Source language (en):
  ✓ Languages detected from files: en, de, fr, es

  API key (or press Enter to set later in .env):
  Project ID (or press Enter to set later in .env):

  ✅ Created .translato.yml (safe to commit)
  ✅ Added .env, .env.lock, .translato.state, .translato.lock to .gitignore

   Then run: translato push

In non-interactive environments (CI, piped input), the command skips prompts and uses auto-detected values or defaults.

Tip: If you already ran translato login, your API key is already in .envinit will pick it up automatically.

Push

translato push reads your source language files, extracts all keys, and uploads them to the Translato API:

  1. Terms — every key in the source files is registered as a term in the project.
  2. Source translations — the actual values (e.g. "Hello", "Active API Access Tokens") are stored as translations for the source language. This ensures the TMS shows the real text instead of "click to translate".

The CLI tracks file hashes locally (.translato.state) and skips the push when nothing has changed since the last push. Use --force to push anyway.

Pushing keys to Translato...

  📄 ./src/i18n/en.json — 5 keys

  Total unique keys: 5

  Terms — parsed: 5, added: 2
  Translations (en) — parsed: 5, added: 2, updated: 3

✅ Push complete.

Before pushing, the CLI performs two safety checks:

  1. Pull-before-push guard — if the remote project has translations you haven't pulled yet (or you've never pulled), the push is blocked. Run translato pull first, or use --force to skip.
  2. Orphan key detection — remote keys that no longer exist in your local source files are flagged. The push is aborted unless --force is used.

Pull

translato pull downloads translations for every language in the project (including the source language) and writes them to local files. On success, it records a pull timestamp in .translato.state so the push guard knows your workspace is current. If any language fails to pull, the timestamp is not updated.

Pulling translations from Translato...

  Languages: en, fr, es, de

  ✅ en — 5 ungrouped keys → ./src/i18n/en.json
  ✅ fr — 5 ungrouped keys → ./src/i18n/fr.json
  ✅ es — 5 ungrouped keys → ./src/i18n/es.json
  ⏭  de — no translations, skipping

✅ Pull complete.

Languages are downloaded in parallel (up to --concurrency at a time, default: 5). Per-language errors are handled gracefully — one failed language won't stop the rest from being pulled.

Sync

translato sync

Two-way sync: runs push followed by pull in a single command. Useful as a one-liner for CI or when you want to upload new keys and download the latest translations in one step.

Status

translato status

Shows project information and per-language translation progress:

📊 Translato Project Status

  Project:   My App
  ID:        cmnee05bm0001fw1uv7jo5f6k
  Terms:     248
  Created:   2026-03-31

  Languages:
    en     ████████████████████ 100%
    de     ██████████████░░░░░░  71%
    fr     ████████████░░░░░░░░  60%
    es     ████░░░░░░░░░░░░░░░░  20%

Validate

translato validate
translato validate --lang es,fr

Checks all translation files against the source language for:

  • Missing keys — keys present in source but absent in a target language
  • Extra keys — keys in a target file that don't exist in source
  • Empty values — keys that exist but have no translation text
  • Placeholder mismatches{name}, {{count}}, %{user}, %s, %d patterns that differ between source and target

Exit code is non-zero when issues are found — useful as a CI gate.

Diff

translato diff
translato diff --lang de,fr

Compares your local translation files against what is stored in the remote TMS. Shows keys that exist only locally, keys only in remote, and keys with different values. Languages are compared in parallel (up to --concurrency).

🔄 Comparing local files with remote translations...

  Languages: en, fr, de

  ✅ en — in sync
  ⚠️  fr — 3 difference(s):
    + 1 key(s) only in local files
      + nav.settings: Settings
    ~ 2 key(s) with different values
      ~ greeting:
        local:  Bonjour le monde
        remote: Bonjour
  ✅ de — in sync

──────────────────────────────────────────────────
⚠️  3 total difference(s) found.

Watch

translato watch

Watches source language files for changes and auto-pushes when a file is saved. Changes to target language files are ignored. Useful during active development. The CLI debounces rapid saves (500ms) and prevents overlapping pushes.

Configuration

.translato.yml

Running translato init creates this file in your project root. It is safe to commit — no secrets are stored here.

# Translato CLI Configuration
project: my-app
paths:
  locales: ./src/locales
  source: en
  format: json           # json | yaml | po | properties
languages:
  - en
  - de
  - fr
  - es
namespaces:
  - name: common
    file: common.json
hooks:
  pre-push: npm run lint:translations
  post-pull: npm run format:translations
  timeout: 30            # seconds (default: 60, minimum: 5)

.env (secrets)

Credentials are stored in .envnever commit this file.

TRANSLATO_API_KEY=your-api-key
TRANSLATO_PROJECT=your-project-id

The CLI loads .env automatically on startup. You can also set these as real environment variables (e.g. in CI).

Environment Variable References

Use ${VAR_NAME} syntax inside .translato.yml to reference environment variables. They are resolved at load time. The CLI warns when a referenced variable is not set.

paths:
  locales: ${MY_LOCALES_DIR}

Config Priority

CLI flags are saved to .env and take effect immediately. Priority:

CLI flags  >  environment variables  >  .env file  >  .translato.yml values

You can set credentials with any command — they are saved for future use:

translato status --api-key sk-my-key --project proj-123

Global Options

These can be passed to any command:

| Option | Env Variable | Description | |--------|-------------|-------------| | --api-key <key> | TRANSLATO_API_KEY | API key — saved to .env for future use | | --project <id> | TRANSLATO_PROJECT | Project ID — saved to .env for future use | | --host <url> | TRANSLATO_HOST | API server URL (optional — only for self-hosted instances) | | --files <glob> | — | File glob pattern (default: from config or src/locales/*.json) | | --format <fmt> | — | File format: json / yaml / po / properties | | --out-dir <path> | — | Output directory for pulled translations | | --concurrency <n> | — | Max parallel language operations (default: 5, max: 20) | | --force | — | Skip orphan key warnings and change detection on push | | --lang <codes> | — | Only process these languages (comma-separated, e.g. de,fr) | | --exclude-lang <codes> | — | Skip these languages (comma-separated, e.g. en,ja) | | --skip-existing | — | Skip files that already exist locally (pull only) | | --json | — | Output results as JSON (for CI pipelines) | | --dry-run | — | Preview changes without API calls or file writes | | --verbose | — | Show detailed output including HTTP requests | | -v, --version | — | Print CLI version |

File Formats

| Format | Extensions | Notes | |--------|-----------|-------| | JSON | .json | Nested objects flattened to dot notation on push, unflattened on pull | | YAML | .yml, .yaml | Full YAML support via js-yaml | | PO/Gettext | .po, .pot | msgid/msgstr, multiline, msgctxt, plural forms | | Properties | .properties | key=value pairs, \uXXXX Unicode escapes, line continuation |

JSON nesting

Nested JSON objects are flattened to dot-separated keys for the TMS:

{ "common": { "hello": "Hello" } }

Becomes the term key common.hello with value Hello. On pull, it is unflattened back to the original nested structure.

Namespaces

When namespaces are configured in .translato.yml, the CLI groups keys by namespace:

  • Push: Keys from files matching a namespace (e.g. auth.json) are prefixed as auth:login.title when uploaded.
  • Pull: Keys with a namespace prefix (e.g. auth:) are split back into the correct namespace file.
  • The CLI auto-detects directory-based (en/common.json) vs flat (en.json) locale structures.

Files that don't match any namespace entry are handled as ungrouped keys.

Hooks

| Hook | Runs | Triggered By | |------|------|-------------| | pre-push | Before uploading keys | push, sync, watch | | post-pull | After downloading translations | pull, sync |

Hooks run in a shell and abort the command if they exit with a non-zero code. The timeout is configurable (default: 60 seconds, minimum: 5 seconds):

hooks:
  pre-push: npm run lint:translations
  post-pull: npm run format:translations
  timeout: 30  # seconds

Security: Dangerous patterns (eval, backtick subshells, curl | sh, source, xargs, find -exec, etc.) are blocked. Commands starting with known-safe prefixes (npm, npx, yarn, pnpm, bun, node, prettier, eslint, biome, echo, true) bypass the blocklist check. Commands longer than 500 characters are rejected.

Note: Hooks execute shell commands. Always audit hook commands in .translato.yml before running the CLI in a new project, especially from untrusted sources.

Language Filtering

Use --lang and --exclude-lang to limit which languages are processed. These flags work with pull, validate, and diff.

# Only pull German and French
translato pull --lang de,fr

# Pull everything except English and Japanese
translato pull --exclude-lang en,ja

# Validate only Spanish translations
translato validate --lang es

# Compare only specific languages with remote
translato diff --lang de,fr

When both flags are used together, --lang is applied first (allowlist), then --exclude-lang removes from the result.

Dry Run

Preview what would happen without making changes:

translato push --dry-run
translato pull --dry-run

JSON Output

Use --json to get structured JSON output on stdout (human-readable output goes to stderr). Useful for CI pipelines and scripting:

translato status --json
translato validate --json
translato diff --json

Update Notifications

The CLI checks npm for newer versions once every 24 hours and displays a warning if an update is available. To disable (e.g. in CI), set:

TRANSLATO_NO_UPDATE_CHECK=1

The check is also automatically skipped when CI=true.

Proxy Support

The CLI respects HTTP_PROXY, HTTPS_PROXY, and NO_PROXY environment variables for corporate environments. Requires undici to be available (built-in with Node 18.7+).

HTTPS_PROXY=http://proxy.corp:8080 translato pull

Files to .gitignore

Add these to your .gitignore (automatically added by translato init):

.env
.env.lock
.translato.state
.translato.lock

CI/CD

GitHub Actions

name: Translation Sync
on:
  push:
    paths: ['src/locales/en.json']

jobs:
  sync:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with: { node-version: '20' }
      - run: npx translato-cli push
        env:
          TRANSLATO_API_KEY: ${{ secrets.TRANSLATO_API_KEY }}
          TRANSLATO_PROJECT: ${{ secrets.TRANSLATO_PROJECT }}

GitLab CI

translate:
  script:
    - npx translato-cli push
  variables:
    TRANSLATO_API_KEY: $TRANSLATO_API_KEY
    TRANSLATO_PROJECT: $TRANSLATO_PROJECT

PR Validation

Add a validation step to catch translation issues before merge:

- run: npx translato-cli validate --json

Troubleshooting

Output path fallback

When pulling translations, if the CLI cannot determine an output path from a {lang} placeholder, wildcard, or source language directory in your file glob, it falls back to inserting the language code before the file extension. For example, messages.json becomes messages.de.json. To avoid this fallback, use a {lang} placeholder in your glob (e.g. locales/{lang}.json) or structure files with a source language directory (e.g. locales/en/messages.json). Run with --verbose to see when the fallback is used.

"click to translate" after push

If the TMS web UI shows "click to translate" instead of your source text, run translato push again. The CLI pushes both terms and source language translations. Check the output for the Translations (en) line — added or updated should be non-zero.

Pull skips a language

If pull shows ⏭ xx — no translations, skipping, it means no translation records exist on the server for that language. Push first (translato push), then translate in the TMS, then pull.

Missing API key or project ID

❌ Missing API key. Use --api-key or set TRANSLATO_API_KEY.

Set credentials with translato login (recommended), or pass --api-key and --project flags (saved to .env automatically), or add them manually to .env in your project root.

"No changes since last push"

The CLI tracks a SHA-256 hash of your source translations. If nothing changed, push is skipped to avoid unnecessary API calls. Use --force to push anyway.

Another process is running

If you see a warning about another translato process, it means a .translato.lock file exists from a previous run. The CLI checks if the PID is still alive — stale locks from crashed processes are cleaned up automatically.

Development

# Run in dev mode (without building)
npm run dev -- push

# Run tests
npm test

# Build for distribution
npm run build

License

MIT