CLI Generate

Generate translation files from source JSON

The tstlai generate command creates translation files from a source JSON file. This is perfect for:

  • Static sites - Generate all translations at build time
  • Mobile apps - Create language bundles for iOS/Android
  • CI/CD pipelines - Automate translation updates
  • Cost optimization - Translate once, use everywhere

Quick Start#

# Set your API key
export OPENAI_API_KEY=sk-...

# Generate Spanish and French translations
npx tstlai generate -i locales/en.json -o locales/ -l es,fr

This creates:

  • locales/es_ES.json
  • locales/fr_FR.json

Command Reference#

npx tstlai generate [options]

OPTIONS:
  -i, --input <file>       Source JSON file (required)
  -o, --output <dir>       Output directory (default: same as input)
  -l, --languages <list>   Target languages, comma-separated (required)
  -c, --context <text>     Translation context for better results
  -e, --exclude <terms>    Terms to keep untranslated
  --flat                   Output flat JSON structure
  --dry-run                Preview without API calls
  -v, --verbose            Show detailed output
  -h, --help               Show help

Examples#

Basic Usage

# Single language
npx tstlai generate -i messages/en.json -l es

# Multiple languages
npx tstlai generate -i messages/en.json -l es,fr,de,ja,zh

Providing context dramatically improves translation quality:

# E-commerce site
npx tstlai generate -i en.json -l es,fr \
  -c "E-commerce website selling outdoor gear"

# Developer documentation
npx tstlai generate -i en.json -l de,ja \
  -c "Technical documentation for a REST API"

# Mobile game
npx tstlai generate -i en.json -l ko,zh \
  -c "Casual puzzle game for mobile devices"

Excluding Terms

Keep brand names, technical terms, or variables untranslated:

npx tstlai generate -i en.json -l es \
  -e "Acme Corp,ProductName,API,SDK"

Preview Mode (Dry Run)

See what would be translated without making API calls:

npx tstlai generate -i en.json -l es,fr,de --dry-run

Output:

๐Ÿ“„ Source: /path/to/en.json
๐Ÿ“Š Found 45 translatable strings
๐ŸŒ Target languages: es, fr, de

๐Ÿ” DRY RUN - No API calls will be made

Would generate: /path/to/es_ES.json
  Language: Spanish (Spain)
  Strings: 45
Would generate: /path/to/fr_FR.json
  Language: French (France)
  Strings: 45
Would generate: /path/to/de_DE.json
  Language: German (Germany)
  Strings: 45

๐Ÿ“ˆ Estimated API usage:
  Input tokens per language: ~1,250
  Total tokens (all languages): ~7,500

Flat Output

Convert nested JSON to flat key-value pairs:

npx tstlai generate -i en.json -l es --flat

Input (en.json):

{
  "common": {
    "welcome": "Welcome",
    "login": "Log in"
  }
}

Output (es_ES.json):

{
  "common.welcome": "Bienvenido",
  "common.login": "Iniciar sesiรณn"
}

Contextual Strings (Disambiguation)#

Single words can translate differently based on context. Use the $t / $ctx format to provide hints:

{
  "actions": {
    "save": { "$t": "Save", "$ctx": "button: save file to disk" },
    "post": { "$t": "Post", "$ctx": "verb: publish content" },
    "file": { "$t": "File", "$ctx": "noun: menu item" },
    "match": { "$t": "Match", "$ctx": "noun: sports game" }
  }
}

How It Works

SourceContextSpanishWithout Context
Savebutton: save fileGuardarAhorrar? Salvar?
Postverb: publishPublicarCorreo? Poste?
Filenoun: menu itemArchivoFila? Lima?
Matchnoun: sports gamePartidoCerilla? Coincidencia?

Output Format

Contextual strings become plain strings in the output:

Input (en.json):

{
  "save": { "$t": "Save", "$ctx": "button: save file" }
}

Output (es_ES.json):

{
  "save": "Guardar"
}

Best Practices

  1. Be specific - "verb: publish content" is better than just "verb"
  2. Include UI context - "button", "menu item", "page title", "error message"
  3. Mention domain - "sports", "finance", "medical" when relevant
  4. Only when needed - Don't add context to unambiguous phrases

Input Format#

The CLI accepts any valid JSON structure:

Nested Objects

{
  "pages": {
    "home": {
      "title": "Welcome Home",
      "description": "Your personal dashboard"
    }
  }
}

Arrays

{
  "features": ["Fast performance", "Easy to use", "Secure by default"]
}

Mixed Content

{
  "app": {
    "name": "MyApp",
    "taglines": ["Simple", "Powerful", "Free"],
    "stats": {
      "users": "Over 1 million users"
    }
  }
}

Language Codes#

You can use either short codes or full locale codes:

ShortFullLanguage
eses_ESSpanish (Spain)
frfr_FRFrench (France)
dede_DEGerman (Germany)
jaja_JPJapanese
zhzh_CNChinese (Simplified)
ptpt_BRPortuguese (Brazil)

See Supported Languages for the full list.

CI/CD Integration#

GitHub Actions

name: Generate Translations

on:
  push:
    paths:
      - 'locales/en.json'

jobs:
  translate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - uses: actions/setup-node@v4
        with:
          node-version: '20'

      - name: Generate translations
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          npx tstlai generate \
            -i locales/en.json \
            -o locales/ \
            -l es,fr,de,ja \
            -c "SaaS application for project management"

      - name: Commit translations
        run: |
          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add locales/
          git commit -m "chore: update translations" || exit 0
          git push

GitLab CI

translate:
  stage: build
  image: node:20
  script:
    - npx tstlai generate -i locales/en.json -o locales/ -l es,fr,de
  only:
    changes:
      - locales/en.json
  artifacts:
    paths:
      - locales/

Cost Estimation#

The CLI shows estimated token usage in dry-run mode. Actual costs depend on your OpenAI model:

ModelInput (1M tokens)Output (1M tokens)
gpt-4o-mini$0.15$0.60
gpt-4o$2.50$10.00
gpt-3.5-turbo$0.50$1.50

Example: 100 strings (~2,500 tokens) ร— 5 languages = ~25,000 total tokens

  • gpt-4o-mini: ~$0.02
  • gpt-4o: ~$0.31

Environment Variables#

VariableDescriptionDefault
OPENAI_API_KEYYour OpenAI API keyRequired
OPENAI_MODELModel to usegpt-4o-mini
OPENAI_BASE_URLCustom API endpointhttps://api.openai.com/v1

Tips#

  1. Start with dry-run - Always preview before translating
  2. Use context - Better context = better translations
  3. Exclude brands - Keep product names consistent
  4. Review Tier 3 languages - Functional languages may need human review
  5. Version control - Commit translations alongside source