Export and import
Export and import let you hand translation work to another tool or translator as CSV, or bring existing JSON translation maps into Messagevisor definitions.
This workflow is useful when translators work outside Git, but you still want Git review, linting, tests, catalog review, and build artifacts to remain the source of truth.
Typical workflow#
$ npx messagevisor export --locale=en --locale=nl-NL --target=web --output=exports/nl-NL-web.csv$ npx messagevisor import exports/nl-NL-web.csv$ npx messagevisor import exports/nl-NL-web.csv --locale=nl-NL --apply$ npx messagevisor lint$ npx messagevisor test$ npx messagevisor catalogFor sets-based projects, include a set:
$ npx messagevisor export --set=staging --locale=nl-NL --target=web$ npx messagevisor import exports/staging-nl.csv --set=staging$ npx messagevisor import exports/staging-nl.csv --set=staging --applyExporting CSV#
$ npx messagevisor export$ npx messagevisor export --locale=nl-NL --target=web$ npx messagevisor export --locale=en --locale=nl-NL --target=web$ npx messagevisor export --includeMessages="checkout*"$ npx messagevisor export --excludeOverridesWithout --locale, export includes all available locales. Pass --locale once to export one locale, or repeat it to include multiple locale columns in the same CSV. A common translator handoff is to include a source/reference locale next to the target locale, for example --locale=en --locale=nl-NL.
Useful output options:
| Option | Use |
|---|---|
--output=<path> | Write to a specific CSV file |
--print | Print CSV to stdout instead of writing a file |
--force | Overwrite an existing output file |
--delimiter=";" | Use a custom one-character delimiter |
--withoutStatus | Omit locale status columns |
--withoutDescription | Omit message description column |
--bom | Include a UTF-8 BOM for spreadsheet tools |
--lineEnding=crlf | Use CRLF line endings |
CSV columns#
A standard export includes:
| Column | Meaning |
|---|---|
set | Present only for sets-aware exports |
messageKey | Message key, or messageKey:overrideKey for override rows |
messageDescription | Message summary or description when included |
<locale> | Translation value for that locale |
<locale>Status | Whether the value is direct, inherited, or missing |
Example:
messageKey,messageDescription,en,enStatus,nl-NL,nl-NLStatusauth.signin,Sign in button label,Sign in,direct,Aanmelden,directdashboard.welcome,Dashboard welcome heading,Welcome {name},direct,,missingcheckout.cta:pro,Pro checkout variant,Complete Pro checkout,direct,Pro checkout afronden,directOverride rows use the configured exportOverrideKeySeparator, which defaults to :.
Multiline and CSV validity#
Messagevisor exports multiline translations as standard quoted CSV fields. Values containing line breaks, the selected delimiter, or " are wrapped in quotes, and quotes inside the value are doubled.
Imports expect the same valid CSV shape. Multiline translations must stay inside quoted fields, and quotes inside translations must be escaped as doubled quotes. Malformed spreadsheet or vendor exports with stray quotes, characters after a closing quote, or shifted extra columns fail validation instead of silently dropping translated cells.
Messagevisor does not escape spreadsheet formulas by default because doing so would change the translation text. Treat CSV files as exchange artifacts, preview every import before --apply, and review the generated message changes in Git.
Status values#
| Status | Meaning |
|---|---|
direct | The locale has an authored translation on the message or override |
inherited | The value comes from inheritTranslationsFrom |
missing | No direct or inherited translation exists |
Status columns are especially important when using locale inheritance. A translator may decide to leave inherited copy alone, or provide direct regional copy when local nuance matters.
Untranslated filters#
Use these filters to prepare focused translator handoff files:
$ npx messagevisor export --locale=nl-NL --onlyUntranslated$ npx messagevisor export --locale=en-GB --onlyDirectlyUntranslated--onlyUntranslated includes rows where the resolved translation is missing. Inherited values count as translated.
--onlyDirectlyUntranslated includes rows without a direct translation, even if inheritance currently provides a value. This is useful when a regional locale must be explicitly reviewed.
Importing CSV#
Preview first:
$ npx messagevisor import exports/nl-NL-web.csv$ npx messagevisor import exports/nl-NL-web.csv --locale=nl-NLApply when the summary looks right:
$ npx messagevisor import exports/nl-NL-web.csv --locale=nl-NL --apply$ npx messagevisor import exports/en-US-web.csv --locale=en-US --prune --applyWith --apply, import updates authored message files. It reports changed messages, changed overrides, created messages, created overrides, changed translations, pruned translations, skipped rows, skipped cells, and warnings in both preview and apply mode.
Without --locale, import reads all known locale columns in the CSV. Pass --locale to import only that locale column, or repeat it to import only those selected locale columns. Known locale columns outside the requested set are ignored without warnings.
Use --prune when importing regional or child locales that inherit from a parent locale. If an imported non-empty value matches the inherited value from inheritTranslationsFrom, Messagevisor does not write a direct translation for that cell. If a matching direct translation already exists, --prune removes it so inheritance takes over. Preview mode shows the Pruned translations count before you apply.
Importing JSON#
Use JSON import when translations are already available as a flat object of message keys to translated strings:
{ "common.welcome": "Welkom", "common.goodbye": "Tot ziens"}Preview and apply it with --from-json and exactly one --locale:
$ npx messagevisor import ./translations.json --from-json --locale=nl-NL$ npx messagevisor import ./translations.json --from-json --locale=nl-NL --applyThe input can also be an HTTP(S) URL:
$ npx messagevisor import https://example.com/translations/nl-NL.json --from-json --locale=nl-NL --applyIf the translation object is nested inside a larger JSON payload, pass a simple dot path:
{ "data": { "translations": { "common.welcome": "Welkom" } }}$ npx messagevisor import payload.json --from-json --json-path=data.translations --locale=nl-NLJSON keys can also target overrides using the configured override separator, for example common.welcome:pro. JSON import supports --createMissing, --prune, preview mode, and --apply. CSV-only options such as --delimiter and --bom are not valid with --from-json.
Creating missing rows#
By default, import skips unknown messages and unknown overrides with warnings. Use --createMissing only when the CSV is meant to create new message or override entries:
$ npx messagevisor import vendor/new-copy.csv --createMissingWhen creating override rows, the base message must already exist or be created by another row in the same import.
Sets behavior#
For sets projects, CSV export can include a set column. Import behavior depends on the file shape:
- CSV with a
setcolumn can update multiple sets. - CSV without a
setcolumn requires exactly one--set=<set>. - JSON import has no set column, so
--from-jsonrequires exactly one--set=<set>. --setis only valid whensets: trueis configured.
$ npx messagevisor export --set=staging --locale=nl-NL$ npx messagevisor import translations.csv --set=staging$ npx messagevisor import translations.json --from-json --locale=nl-NL --set=stagingTranslator handoff advice#
For external translation work:
- export only the target and locales that need work; include a source/reference locale when it helps translators
- keep status columns unless the translator tool cannot handle them
- keep
messageKeyunchanged - preserve override rows because they are real runtime variants
- ask translators to edit only the target locale columns, leaving source/reference locale columns alone
- run
importto preview before applying anything
After importing, run lint, tests, examples, and catalog review before building datafiles.
Review flow#
A safe import pull request usually includes:
- the returned CSV as a review artifact if your workflow keeps vendor files
- the changed
messages/files npx messagevisor import ...preview summary copied into the PR- catalog links for changed namespaces
- lint and test results

