Translator handoff
You have a translator (a freelancer, an agency, or an in-house specialist) and no hosted translation management platform. This guide covers the human side of the round trip: what to put in the handoff, how to brief the translator, how to handle their questions, and how to bring their work back into the project safely.
The technical surface (export, import, preview, apply) is documented in Export and import. This guide assumes you know that part and focuses on the workflow around it.
When to use this#
- You work with a translator directly instead of through a TMS like Lokalise, Crowdin, or Phrase.
- You want translators to work in a tool they already know (Excel, Google Sheets, Numbers, or even just a text editor) without learning Git.
- You want pull request review, lint, tests, and the catalog to stay the source of truth.
- You want a repeatable process so every translator pass looks the same to the rest of the team.
If you have a hosted TMS, the round trip looks similar but the platform handles file delivery and translator access. See the export and import reference for the underlying commands.
What a good handoff looks like#
A handoff is a small bundle of files and information that a translator can act on without asking you a question. At a minimum:
- The CSV. Exported with the source and target locales side by side.
- A brief. A short document explaining the product, tone, and rules.
- A glossary. A list of terms that must stay in the source language or have a fixed translation.
- Context. Screenshots, links to the staging UI, or a published catalog URL so the translator can see where each string appears.
- Editing rules. A short list of what they can change and what they must leave alone.
A motivated freelancer can produce good work with less, but skipping any of these tends to produce questions, blockers, or wrong-context translations that you have to throw away.
Step 1: Decide what to send#
Scope the export to what actually needs work. Sending the entire project usually produces noise (the translator wonders if archived messages are still in use, why an inherited value is filled in, etc.).
For a brand-new target locale:
$ npx messagevisor export \ --locale=en \ --locale=de \ --target=web \ --onlyUntranslated \ --output=handoff/2026-05-de-web.csvFor an existing locale where only new keys need translation:
$ npx messagevisor export \ --locale=en \ --locale=de \ --target=web \ --onlyUntranslated \ --output=handoff/2026-05-de-web-delta.csvFor a regional locale (en-GB, pt-BR, nl-BE) where direct review is needed even though inheritance fills the gaps:
$ npx messagevisor export \ --locale=en \ --locale=en-GB \ --target=web \ --onlyDirectlyUntranslated \ --output=handoff/2026-05-en-GB-web.csvA few rules of thumb:
- always include the source locale next to the target locale; translators need context to translate well
- date the file name so multiple rounds do not collide
- keep status columns; translators use them to decide what to touch
For translators using Excel on Windows:
$ npx messagevisor export \ --locale=en --locale=de --target=web \ --bom --lineEnding=crlf \ --output=handoff/2026-05-de-web.csvThe --bom and --lineEnding=crlf flags avoid "characters look broken" surprises in Excel.
Step 2: Write a short brief#
A one-page brief is usually enough. Include:
- Product context. One paragraph about what the product is and who uses it.
- Tone. Formal vs casual, second person vs third person, conventions around capitalization. A few example sentences in the target language help more than abstract rules.
- Variants. Any audience or platform variants the translator should be aware of. Override rows in the CSV look like
auth.signin:pro; explain what the override key means. - Numbers, dates, currencies. Whether the project formats those itself (it does, via formats), so the translator should leave format strings like
{amount, number, money}alone. - Links to live UI. Staging URLs, design files, or a published catalog build that the translator can browse.
Keep the brief in the handoff folder next to the CSV. Re-use it across translators and rounds. Update it once a quarter, not once a handoff.
Step 3: Write a glossary#
A glossary is a flat list of terms with a fixed translation (or an explicit "do not translate"). Even a 20-row spreadsheet is enough to keep brand names and product terms consistent.
Example:
| Source term | Target (de) | Notes |
|---|---|---|
| Workspace | Workspace | Brand term, do not translate |
| Pro plan | Pro plan | Brand term, do not translate |
| Pipeline | Pipeline | Product feature, do not translate |
| Sign in | Anmelden | Use this exact translation |
| Sign out | Abmelden | Use this exact translation |
If you maintain a glossary in a shared sheet, link to it from the brief. If the translator works in Excel, paste the glossary into a second tab of the handoff file.
Step 4: Write editing rules#
Translators benefit from a short, blunt list of what they can change. Something like:
- Only edit cells under the target locale column (
de). Do not touchen,messageKey,messageDescription,enStatus, ordeStatus. - Do not change
messageKeyvalues. They are how the code looks up each string. - Leave override rows (
messageKey:overrideKey) in place. Translate their target cells the same way as a normal row. - Inside translation values, anything in curly braces is a placeholder the code fills at runtime. Examples:
{name},{count},{amount, number, money}. Keep these exactly as written, including the inner words likeplural,select,number,money. - If you cannot translate a row (because the source is ambiguous, the placeholder is unclear, or the source has a typo), leave the cell empty and add a note in a
notescolumn or in a follow-up email. - Where the source uses ICU plural or select blocks like
{count, plural, one {# item} other {# items}}, translate only the strings inside the inner braces (# item,# items). Keep the surrounding structure intact.
Pasting these rules into the brief works fine. Most translators will read them once.
Step 5: Hand over the files#
Bundle everything in one folder or zip:
2026-05-de-web/├── 2026-05-de-web.csv├── brief.md├── glossary.csv└── screenshots/ ├── dashboard.png └── checkout.pngSend by email, shared drive, or whatever channel you already use with the translator. Agree on a deadline and a return format (usually "the same CSV with the de column filled").
Step 6: Bring the file back#
When the translator returns the file, save it next to the original so the diff is reviewable:
2026-05-de-web/├── 2026-05-de-web.csv # original├── 2026-05-de-web.returned.csv # translated└── ...Validate the shape with a preview import:
$ npx messagevisor import 2026-05-de-web/2026-05-de-web.returned.csv --locale=deRead the preview summary carefully. Common things to look for:
- Skipped rows. Usually means the CSV was damaged (delimiter changed, columns shifted, quoting broken). Open the file in a text editor.
- Warnings on specific rows. Often means a placeholder was altered or a quote was unescaped. Fix in the CSV before applying.
- A much larger or smaller change count than expected. Means the translator edited more or fewer cells than agreed.
If the translator used Excel with European regional settings, the file may come back with ; as the delimiter. Match it on import:
$ npx messagevisor import 2026-05-de-web/2026-05-de-web.returned.csv --locale=de --delimiter=";"Step 7: Apply and validate#
When the preview looks right:
$ npx messagevisor import 2026-05-de-web/2026-05-de-web.returned.csv --locale=de --apply$ npx messagevisor lint$ npx messagevisor test$ npx messagevisor catalogOpen the catalog and skim the new translations. ICU placeholder damage and wrong-tone copy show up much faster in a rendered preview than in a CSV diff.
Step 8: Open a pull request#
A safe handoff pull request usually includes:
- The returned CSV checked in under
handoff/as a record of the input. - The changed
messages/files (the actual translation updates). - The preview summary pasted into the PR description.
- A link to the catalog build for the changed namespaces.
- Lint and test results from CI.
Review focuses on the translations themselves, not on whether the CSV-to-YAML transform behaved.
Handling questions during translation#
Translators will have questions. The most common are:
- "What does
{name}refer to here?" Answer with the variable's runtime meaning (user's first name, workspace name, etc.). Consider adding a description on the message file so the next handoff has the answer. - "Where does this string appear?" A screenshot or a live URL is faster than a written description. Catalog deep links work well too.
- "Should this be formal or casual?" Answer once in the brief, not per-string.
- "This English string is grammatically ambiguous." Often a real bug in the source. Fix the source string, re-export, and re-send.
Track recurring questions and roll them into the brief for the next round.
Tips and variations#
Use the catalog as the translator's read-only UI#
The catalog can be built and deployed alongside your app's staging environment. A translator with a URL can browse messages, see examples, and inspect override variants without needing Git access. This often reduces the size of each handoff because the translator no longer needs screenshots inline.
Combine machine translation with human review#
Pre-fill the de column with DeepL, Google Sheets, or an AI agent before sending to the translator. The translator becomes a reviewer, which is usually faster and cheaper than translating from scratch. Be upfront with the translator that the draft is machine output.
Keep handoff folders in the repository#
Some teams check the handoff CSV into the repo under handoff/ or translations/handoff/. It gives you an audit trail and lets you re-run an import if a messages/ change accidentally clobbers a translation. Other teams treat handoff files as ephemeral and only commit the resulting messages/ changes. Pick one and stay consistent.
Build a small handoff script#
If you do handoffs often, wrap the export step in a small shell script that takes a locale and a date and produces the standard folder layout (CSV, brief copy, glossary copy). It removes the friction of "did I remember to include --bom?".

