Skip to content

comvi push

The comvi push command uploads local translation files to the Comvi platform. Use it to sync translations that developers add in code back to the platform where translators can review and translate them into other languages.

You need a .comvirc.json file in your project root and an API key. Prefer COMVI_API_KEY for the key:

.comvirc.json
{
"apiBaseUrl": "https://api.comvi.io",
"translationsPath": "./src/locales",
"fileTemplate": "{languageTag}/{namespace}.json",
"format": "json"
}
Terminal window
comvi push

This reads all translation files from the configured translationsPath and uploads them to your Comvi project. Conflict handling is controlled by --force-mode.

Terminal window
comvi push [options]
OptionAliasDefaultDescription
--config-c.comvirc.jsonPath to the Comvi config file
--lang-lAll detected languagesComma-separated list of language tags to upload
--ns-nAll detected namespacesComma-separated list of namespaces to upload
--path-p.comvirc.jsontranslationsPathSource directory containing translation files
--dry-runfalsePreview changes without uploading anything
--force-mode.comvirc.jsonpush.forceMode or 'ask'Conflict resolution: override, keep, ask, or abort

The CLI expects files organized by language and namespace, matching the structure comvi pull produces:

src/locales/
├── en/
│ ├── common.json
│ ├── auth.json
│ └── dashboard.json
├── de/
│ ├── common.json
│ └── auth.json
└── fr/
└── common.json

Each JSON file contains flat or nested key-value pairs:

src/locales/en/common.json
{
"greeting": "Hello, {name}!",
"nav.home": "Home",
"nav.settings": "Settings"
}

The CLI detects the language from the directory name and the namespace from the filename.

Always preview what will change before pushing to the platform. The --dry-run flag shows a summary of additions, updates, and deletions without making any changes:

Terminal window
comvi push --dry-run

Example output:

Dry run — no changes will be made.
en/common.json:
+ nav.profile (new key)
~ greeting (value changed)
= nav.home (unchanged, skipped)
en/auth.json:
+ reset.title (new key)
+ reset.description (new key)
Summary: 3 keys to add, 1 key to update, 1 key unchanged

By default, comvi push does not overwrite existing translations on the platform:

  • New keys are always created.
  • Existing keys are skipped unless --overwrite is set.
  • Missing keys on the local side are left untouched on the platform unless --delete-missing is set.

This protects translator work. If a translator has already translated a key, pushing from your codebase does not erase their work.

To update values for keys that already exist on the platform:

Terminal window
comvi push --overwrite

To delete keys from the platform that no longer exist in your local files:

Terminal window
comvi push --delete-missing

This is useful for keeping the platform clean after you remove deprecated keys from your codebase. Combine with --dry-run first to review what will be deleted:

Terminal window
comvi push --delete-missing --dry-run

Upload only certain languages:

Terminal window
# Push only the source language
comvi push --lang en
# Push English and German
comvi push -l en,de

Upload only certain namespaces:

Terminal window
# Push only the common namespace
comvi push --ns common
# Push common and auth namespaces
comvi push -n common,auth

Push translations from your main branch after a merge so that new keys are immediately available to translators:

.github/workflows/push-translations.yml
name: Push Translations
on:
push:
branches: [main]
paths:
- 'src/locales/en/**'
jobs:
push:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npx comvi push --lang en
env:
COMVI_API_KEY: ${{ secrets.COMVI_API_KEY }}

This workflow triggers only when the source language files change on main, pushing new and updated keys to the platform for translators.

All push options can be set in .comvirc.json:

.comvirc.json
{
"apiBaseUrl": "https://api.comvi.io",
"translationsPath": "./src/locales",
"fileTemplate": "{languageTag}/{namespace}.json",
"format": "json",
"push": {
"forceMode": "ask"
}
}

Command-line flags override config file values.