Skip to content
Skip to Content

Docs / Guides

Hand off with Excel or CSV

Export untranslated strings to an Excel workbook or CSV files for a translator, then import the result with the same safety checks as an automated run.

Use this when a person should translate some strings: marketing copy, legal text, or the languages that matter most. You export the strings that need translating, a translator fills them in, and you import the file back into your locale files.

Export picks exactly the keys an automated run would translate (the new and changed ones), and import runs the same integrity checks as translate, so a hand-typed value that breaks a placeholder is withheld and reported instead of written. Neither command calls a provider or needs an API key.

You need a verbatra project with at least one target locale.

The round-trip

# 1. Export the strings that need translating
verbatra export

# 2. A translator fills the Translation column and sends the file back

# 3. Import the filled workbook
verbatra import verbatra-translations.xlsx

Export writes verbatra-translations.xlsx in the working directory. Import validates every filled row, writes the values that pass, and advances the lock file for exactly the keys it accepted, as a translate run would.

What lands in the workbook

The workbook opens with an Instructions sheet, then one sheet per target locale, named for its locale (de, fr, ...). Every locale sheet has the same columns:

ColumnEditablePurpose
Keynothe key path; the only thing that maps a row back to a string
Sourcenothe source-locale value
Current translationnothe existing target value, if any
Statusnonew, changed (the source changed since it was translated), or unchanged (only with --include-unchanged)
Translationyesthe only cell the translator fills
Source hashnohidden; detects a source that changed after export
Contextnothe key's description, when the source format carries one; never imported
Review statusnook, or review when a review flag suggests a second look
Review reasonsnothe review reasons behind a review status

Every column except Translation is locked by sheet protection, and Translation uses Excel's text format, so a value like 007 or one starting with = stays literal text. The review columns are advisory: import never reads them.

Handing off

Tell the translator these rules (the Instructions sheet repeats them):

  • Fill the Translation column, nothing else.
  • Do not rename, delete or reorder the language tabs. Each tab is matched to a locale by its exact name, so a renamed or missing tab fails that locale.
  • Sorting and filtering rows is fine, because rows are matched by Key. Columns must stay where they are.
  • Leave a cell empty for "not translated yet". A half-filled workbook can come back now and the rest later.
  • To clear an existing value on purpose, type exactly [[CLEAR]].

What import accepts

Every filled row is judged against the live project before anything is written:

  • Source drift: if the source string changed after export, the row is withheld, so a translation of an old source never lands.
  • Integrity: placeholders, inline markup and ICU structure must match the source, as in every run. See the integrity gate.
  • Degenerate values: a repetition loop, a runaway length or an empty value for a non-empty source is withheld.
  • Unknown keys: a filled row whose key exists in neither the source nor the target fails that locale's sheet. A key that exists only in the target is left unwritten.
  • Unchanged rows (from 0.13.0): in a CSV, TSV or xlsx handoff, a filled row equal to the value an up-to-date key already holds is left alone and reported unchanged, once it passes the same gate.

A withheld or blank row keeps its lock baseline, so the key is exported again until it is resolved; a blank row whose source drifted also raises BLANK_ROW_BASELINE_RETAINED. An unreadable row or a repeated key is reported without failing the sheet. Each sheet is one locale in the run summary, and import uses the same exit codes as translate, so a handoff fits the same CI checks as an automated run. verbatra import has the details.

Dry-run first

Preview what a returned workbook would write, without touching a file:

verbatra import verbatra-translations.xlsx --dry-run

CSV and TSV instead of a workbook

If a vendor or a pipeline wants plain text, --format csv or --format tsv writes the same columns as one file per locale:

# write handoff/de.csv and handoff/fr.csv
verbatra export --format csv --out handoff

# import every locale file in the directory back
verbatra import handoff --format csv

The locale comes from the file name, so keep the files named as they were exported. Compared with the workbook:

  • Nothing is protected. Every column is editable and Source hash is visible. An edited hash is never trusted: the row is compared with the live source and withheld as drift.
  • There is no Instructions sheet. Pass the rules above to the translator yourself.
  • Formulas are defused. A value starting with =, +, -, @, a tab or a carriage return is written with a leading apostrophe, so a spreadsheet keeps it as text; import strips the apostrophe again. Still treat a returned file as untrusted input.
  • A narrower re-export retires older files. A file left over from an earlier, wider export is refused on import instead of applied. Nothing is deleted.

XLIFF for a CAT tool

If an agency works in a CAT tool such as Trados, memoQ or OmegaT, export XLIFF instead: see Hand off to an agency.

TMX is a different path

A handoff carries the pending strings of each locale to a person. verbatra tmx moves the whole translation memory between tools as one multilingual file, so it is not an export --format value.

Selecting what to export

By default, export includes only the missing and changed strings:

# Only the German and French sheets
verbatra export --locales de,fr

# Also include strings that are already up to date
verbatra export --include-unchanged

# Write to a specific path
verbatra export --out handoff/round-2.xlsx

Use --include-unchanged when a translator wants a whole locale for context. --out must stay inside the project and must not name a file the project depends on. See verbatra export for every flag and rule.

The review columns

Both columns are computed at export from the source and current values, so a row without a translation is always ok. Review reasons spells each reason in lower case with hyphens (length-ratio-outlier), except the two only a run can see (provider-degraded, fuzzy-cache-reuse), which never appear. It adds icu-arms with the missing or extra arms when a value's ICU arms do not fit the target language; the integrity gate refuses that value, so fix it before the row comes back. To clear a flag, fix the translation.

From the SDK

The two commands wrap exportWorkbook and importWorkbook:

import { exportWorkbook, importWorkbook, loadConfig } from "@verbatra/sdk";

const config = await loadConfig();

await exportWorkbook({ config, format: "csv", out: "handoff" });

const summary = await importWorkbook({ config, workbook: "handoff", format: "csv" });

importWorkbook returns the same RunSummary as translate.

Edit on GitHub

On this page