# Import & export

Move translations in and out of Comvi: supported formats, the import wizard and its conflict policy, export options, CLI sync, and a migration playbook.

Canonical: https://comvi.io/docs/platform/import-export

Import pulls translation files into Comvi; export downloads the current state as files, for
one-off migration, backups and hand-offs with external translators. For continuous sync with
a codebase, the [CLI](/docs/cli) wraps the same operations.

| Direction | Formats | Notes |
|---|---|---|
| **Import** | JSON files, ZIP archive of JSON | Flat or nested keys, auto-detected; i18next-shaped JSON converts to ICU on the way in |
| **Export** | JSON, i18next v4 | Flat or nested, pretty or minified |

XLIFF 1.2, XLIFF 2.0, CSV and PO (Gettext) are listed as coming soon in the export dialog
and cannot be imported or exported. Convert XLIFF to JSON before importing.

## Import

1. **Upload**

   Open **Import** in the sidebar and drop in JSON files or one ZIP of JSON files. Limits
   per batch: 50 files, 10 MB per file, 500 entries per ZIP, 100,000 keys. Comvi validates
   on upload and shows the file count and unique-key count. A session lives for one hour;
   after that, start over.

2. **Map files to language and namespace**

   Every file needs both. Comvi auto-assigns when the filenames make it obvious: `en.json`
   becomes English, `checkout/fr.json` becomes French in the `checkout` namespace, and
   `pt_BR.json` maps to `pt-BR`. Override any mapping, set all files at once with the bulk
   actions, or create a missing language or namespace from this screen.

3. **Resolve conflicts**

   A conflict is a key that already exists with a different value. Pick a winner per key or
   in bulk. Anything left untouched follows the **Unresolved Conflict Policy**:

   | Policy | Behaviour |
   |---|---|
   | **Resolve manually before import** | The import does not run until every conflict has a decision |
   | **Keep current project values** | The value in Comvi stays; the imported value is discarded |
   | **Prefer imported values** | The imported value overwrites the current one |

   The policy has no permission check: it writes whatever it says, regardless of the current
   value's status.

4. **Commit**

   Click **Import**. Comvi processes the batch in the background and shows per-file results:
   keys created, updated, skipped, failed. A file with broken JSON fails on its own without
   rolling back the rest, and you can retry the failing files.

Every non-empty imported value lands as **Translated**, stamped with the importer as its
reviewer, whatever the file's provenance. Empty values land as **Not Translated**. Import
needs the project import permission: Editor, Manager, Owner, or an API key with
`translations:write`.

> **Import is not a review gate**
>
> Machine output or vendor drafts arrive approved. Select the imported rows afterwards and
> use **Status → Mark as Needs Review**, and check the Content Deploy status filter before
> you import. See [Translation lifecycle](/docs/platform/translation-lifecycle).

## Export

1. **Pick a format**

   **JSON** keeps ICU MessageFormat values as they are. **i18next v4** converts ICU to
   i18next plural and context suffixes. Both take a key structure (`flat` with dot notation
   or `nested` objects) and a style (`pretty` or `minified`).

2. **Pick languages and namespaces**

   Tick any subset. A single namespace is the usual hand-off to an external translator.

3. **Filter by status (optional)**

   Include only `Translated`, `Needs Review` or `Not Translated`, and choose whether keys
   with empty values are included. `Translated` only is the safe hand-off to a build system
   that ships to users.

4. **Download**

   One language and one namespace gives a single file. Anything wider gives a ZIP laid out
   as `<namespace>/<language>.<ext>`, with the default namespace's files at the archive root.

## Sync with the CLI

`Terminal`

```bash
npx --package @comvi/cli comvi pull   # Comvi to local files
npx --package @comvi/cli comvi push   # local files to Comvi
```

The CLI reads a config file that maps the directory layout to namespaces, authenticates with
an [API key](/docs/platform/api-keys), and is built for CI. `push` asks about each conflict
by default, which fails outside an interactive terminal; in CI pass `--force-mode` with
`override`, `keep` or `abort`. See [CLI pull](/docs/cli/pull) and [CLI push](/docs/cli/push).

## Migrate from another TMS

1. **Check the key cap**

   The free plan holds 500 keys, early adopter 3,000. Count what you are bringing over; going
   over the cap puts the whole organization into read-only until usage is back under it.

2. **Export the old platform as JSON**

   Every major TMS exports flat JSON per language, and `i18next` and `vue-i18n` JSON import
   as-is.

3. **Create the project** with the source language and every target language. Do not create
   keys yet.

4. **Import the source language first**, in one batch. This creates every key with its
   source value.

5. **Import the target languages.** Every key already exists, so a file either fills an
   empty value or produces a conflict. **Prefer imported values** is usually right here.

6. **Spot-check ICU placeholders.** i18next plurals and `{{var}}` placeholders are converted
   on import (`{{var}}` becomes `{var}`); read a few plural strings to confirm.

7. **Set up namespaces** by bulk-moving keys once everything is in. See
   [Namespaces](/docs/platform/namespaces).

8. **Seed translation memory from TMX and glossaries from CSV.** See
   [Translation memory](/docs/platform/translation-memory) and
   [Glossaries](/docs/platform/glossaries).

Decide the conflict policy once and commit. Importing the same language twice with different
policies churns history and confuses reviewers.
[Migrating an existing project](/docs/platform/recipes/migrating-large-project) covers
pilots, reconciliation and cutover for large datasets.

## Troubleshooting

- **Files did not auto-map.** Filenames need a recognizable locale code (`en`, `fr-CA`,
`pt-BR`) or a namespace segment. Rename them or use the bulk mapping dropdown.
- **The import overwrote a value I wanted to keep.** The policy was **Prefer imported
values**. Restore the value from the editor's history and switch the policy next run.
- **Nothing is on the CDN after the import.** Import writes to the database, not the edge.
Enable **Settings → Content Deploy** or click **Deploy Now**. See
[Content Deploy / CDN](/docs/platform/cdn).

## Next steps

- [CLI pull](/docs/cli/pull): Automated download in CI/CD.
- [CLI push](/docs/cli/push): Automated upload from a codebase.
- [Namespaces](/docs/platform/namespaces): How imported files map to namespaces.
- [Translation lifecycle](/docs/platform/translation-lifecycle): Which status imported values end up in.
