LingoSeal CLI

Command-line tool for pushing and pulling translations between your project and LingoSeal.

Installation

The CLI is distributed as a tarball (.tgz file). Download the latest build below.

Download lingoseal-cli-latest.tgz

bash
# Install globally
npm install -g ./lingoseal-cli-latest.tgz

# Or install as a dev dependency in your project
npm install --save-dev ./lingoseal-cli-latest.tgz

After installing, the lingoseal command is available globally, or via npx lingoseal if installed locally.

Quick Start

bash
# 1. Initialize a config file in your project root
lingoseal init --url https://app.lingoseal.com --project <project-id> --token <api-token>

# 2. Review and edit lingoseal.config.js if needed

# 3. Download translations (pull)
lingoseal download

# 4. Push local translation files to the server
lingoseal push --include-base

Getting Your API Token

  1. Open your project in LingoSeal
  2. Go to the Settings tab
  3. Under Public API Token, click Generate Token
  4. Copy the token into lingoseal.config.js or pass it via --token

Commands

All commands read from lingoseal.config.js by default. CLI flags override config values.

lingoseal init

Creates a lingoseal.config.js configuration file in the current directory.

bash
lingoseal init
lingoseal init --url https://app.lingoseal.com --project abc-123 --token my-secret-token
OptionDescription
--url <url>Base URL of the LingoSeal server
--project <id>Project ID (find it in your project URL)
--token <token>API token from project settings

lingoseal download

Downloads translations from the server and writes them as JSON files.

bash
# Using config file (default: lingoseal.config.js)
lingoseal download

# Override config values via CLI
lingoseal download \
  --url https://app.lingoseal.com \
  --project abc-123 \
  --token my-secret-token \
  --output ./src/locales \
  --format nested-json

# Download specific languages only
lingoseal download --languages en,de,fr

# Use short language codes (en instead of en-US)
lingoseal download --short-codes --include-base
OptionDescriptionDefault
-c, --config <path>Path to config filelingoseal.config.js
-u, --url <url>Base URL of translation server-
-p, --project <id>Project ID-
-t, --token <token>API token-
-o, --output <path>Output directory./locales
-f, --format <format>Output formatflat-json
-l, --languages <langs>Comma-separated languagesall
--include-baseInclude base languagefalse
--short-codesUse short language codes (en instead of en-US)false

lingoseal push

Pushes local translation files to the server. Reads files from your output directory, parses them based on the configured format, and uploads them via the public API.

bash
# Push all translation files (excluding base language by default)
lingoseal push

# Preview what would change without applying
lingoseal push --dry-run

# Push including the base (source) language
lingoseal push --include-base

# Push specific languages only
lingoseal push --languages de,fr

# Overwrite existing translations on the server
lingoseal push --conflict-strategy overwrite

# Only fill in empty translations
lingoseal push --conflict-strategy overwrite-empty
OptionDescriptionDefault
-c, --config <path>Path to config filelingoseal.config.js
-u, --url <url>Base URL of translation server-
-p, --project <id>Project ID-
-t, --token <token>API token-
-i, --input <path>Input directory (overrides outputPath)./locales
-f, --format <format>File format: flat-json, nested-json, i18nextflat-json
-l, --languages <langs>Comma-separated languages to pushall found
--conflict-strategy <s>How to handle existing keys (see below)sync
--dry-runPreview changes without writing to the serverfalse
--include-baseInclude the base languagefalse
--short-codesMap short codes in filenames to full codesfalse

Conflict Strategies

StrategyBehavior
syncDefault. Add new keys, update existing, and delete keys missing from any language file.
overwriteCreate new keys and update all existing translations. No deletions.
skipOnly create new keys. Don’t touch existing translations.
overwrite-emptyCreate new keys. Only update translations that are currently empty on the server.

Dry Run Output

When using --dry-run, the CLI shows what would change without applying anything:

text
📤 LingoSeal Translation Push

✓ Project: My App
  Base language: en
  Supported languages: en, de, fr, cs-CZ
  Conflict strategy: overwrite
  Mode: DRY RUN (no changes will be made)

Pushing 2 language(s)...

  Pushing de... ✓ 150 keys (+3 new, ~12 updated, 135 unchanged)
    + settings.notifications: "Benachrichtigungen"
    + settings.theme: "Design"
    ~ home.title: "Startseite" → "Willkommen"
    ~ nav.login: "Anmelden" → "Einloggen"
    ... and 10 more changed keys
  Pushing fr... ✓ 150 keys (+3 new, ~8 updated, 139 unchanged)

✓ Dry run complete (no changes applied)

Summary:
  New keys created:  6
  Keys updated:      20
  Keys skipped:      0
  Keys unchanged:    274

Configuration File

Create a lingoseal.config.js in your project root (or use lingoseal init):

javascript
/** @type {import('lingoseal-cli').LingoSealConfig} */
module.exports = {
  // Required
  url: "https://app.lingoseal.com",
  projectId: "your-project-id",
  token: "your-api-token",

  // Optional
  outputPath: "./src/locales",    // Where to read/write translation files
  format: "flat-json",            // flat-json | nested-json | i18next
  filePattern: "{lang}.json",     // File naming pattern
  languages: [],                  // Empty = all project languages
  includeBase: true,              // Include the base (source) language
  namespace: "translation",       // Namespace for i18next format
  shortCodes: false,              // Use en instead of en-US
};

File Patterns

PlaceholderDescriptionExample
{lang}Language codeen, cs-CZ
{ns}Namespacetranslation
PatternOutput
{lang}.jsonen.json, cs-CZ.json
{lang}/{ns}.jsonen/translation.json
locales/{lang}/translation.jsonlocales/en/translation.json

The same file pattern is used by both download (to write files) and push (to discover files to upload).

Output Formats

flat-json (default)

Flat key-value pairs:

json
{
  "home.title": "Welcome",
  "home.description": "This is the homepage",
  "nav.login": "Login"
}

nested-json

Nested objects from dot-separated keys:

json
{
  "home": {
    "title": "Welcome",
    "description": "This is the homepage"
  },
  "nav": {
    "login": "Login"
  }
}

i18next

Wrapped in a namespace for i18next:

json
{
  "translation": {
    "home.title": "Welcome",
    "home.description": "This is the homepage"
  }
}

CI/CD Integration

The recommended CI/CD setup uses two workflows: push source strings when they change, and pull the latest translations on a schedule.

Push on Merge

When source strings change on main, push them to LingoSeal so translators can start working immediately.

yaml
# .github/workflows/translations-push.yml
name: Push source translations

on:
  push:
    branches: [main]
    paths:
      - 'src/locales/en.json'   # adjust to your base language file

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

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

      - name: Install LingoSeal CLI
        run: npm install -g ./lingoseal-cli-latest.tgz

      - name: Push base language to LingoSeal
        run: >
          lingoseal push
          --include-base
          --languages en
          --conflict-strategy overwrite
          --token ${{ secrets.LINGOSEAL_TOKEN }}

Pull on Schedule

Periodically pull the latest translations and open a PR for review.

yaml
# .github/workflows/translations-pull.yml
name: Pull translations

on:
  schedule:
    - cron: '0 6 * * 1-5'  # Weekdays at 6am UTC
  workflow_dispatch:          # Allow manual trigger

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

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

      - name: Install LingoSeal CLI
        run: npm install -g ./lingoseal-cli-latest.tgz

      - name: Download translations
        run: lingoseal download --token ${{ secrets.LINGOSEAL_TOKEN }}

      - name: Create PR with updates
        uses: peter-evans/create-pull-request@v6
        with:
          token: ${{ secrets.GITHUB_TOKEN }}
          commit-message: 'chore: update translations from LingoSeal'
          title: 'chore: update translations from LingoSeal'
          body: Automated translation update from LingoSeal.
          branch: translations/update
          delete-branch: true

Preview in PRs

Add a CI check that previews what a push would do, without applying changes:

yaml
# .github/workflows/translations-preview.yml
name: Preview translation changes

on:
  pull_request:
    paths:
      - 'src/locales/**'

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

      - name: Install LingoSeal CLI
        run: npm install -g ./lingoseal-cli-latest.tgz

      - name: Preview changes
        run: >
          lingoseal push --dry-run
          --include-base
          --conflict-strategy overwrite
          --token ${{ secrets.LINGOSEAL_TOKEN }}

Package Scripts

json
// package.json
{
  "scripts": {
    "translations:pull": "lingoseal download",
    "translations:push": "lingoseal push --include-base --conflict-strategy overwrite",
    "translations:preview": "lingoseal push --dry-run --include-base --conflict-strategy overwrite",
    "prebuild": "npm run translations:pull"
  }
}

Framework Examples

Example configurations for popular i18n libraries.

react-i18next

javascript
// lingoseal.config.js
module.exports = {
  url: "https://app.lingoseal.com",
  projectId: "your-project-id",
  token: "your-api-token",
  outputPath: "./src/locales",
  format: "flat-json",
  filePattern: "{lang}/translation.json",
  includeBase: true,
  shortCodes: true,
};
typescript
// i18n.ts
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import en from './locales/en/translation.json';
import de from './locales/de/translation.json';

i18n.use(initReactI18next).init({
  resources: {
    en: { translation: en },
    de: { translation: de },
  },
  lng: 'en',
  fallbackLng: 'en',
});

next-intl

javascript
// lingoseal.config.js
module.exports = {
  url: "https://app.lingoseal.com",
  projectId: "your-project-id",
  token: "your-api-token",
  outputPath: "./messages",
  format: "nested-json",
  filePattern: "{lang}.json",
  includeBase: true,
};

Building & Distributing

For maintainers who need to build and distribute the CLI:

bash
cd cli

# Install dependencies & build & create tarball
npm install
npm run pack:dist
# Output: lingoseal-cli-latest.tgz

Share the .tgz file with team members via Slack, shared drive, or your internal file sharing tool. Recipients install with:

bash
npm install -g lingoseal-cli-latest.tgz

Requirements

  • Node.js >= 18.0.0