Most of your content can ship the moment the engine returns it. Some can't. A regulated disclosure, a medical instruction, a headline that carries the brand – for those, you want a person to read the translation and sign off before it goes live, not after a customer files a complaint.
The usual way to get a human into an automated flow is the painful way: hold the request open while someone reads, or build your own review queue, or hand-wire a translation vendor's API. This stage does it inside the job. When humanEdit is enabled, the async job runs the engine, then pauses on a person – your own team or an external professional – and resumes with their edit, carrying that output forward to any stages that follow.
It is the third stage of the localization pipeline and, like every stage, applies only to jobs created through the Async Localization API. New to the pipeline? Start with the overview.
On this page
How the pause works#
After the core translate step, the job hands the AI translation to a human for review. The reviewer reads it, then either approves it as-is or submits an edited version. Only then does the job continue. The human output – approved or edited – becomes the input to every later stage and, ultimately, the job's outputData.
The obvious objection to pausing a job for minutes, hours, or a day is cost: a request held open is a resource burning while nothing happens. This stage does not work that way.
The wait is event-driven, not a held-open connection
The workflow resumes on an event – a reviewer submitting in the dashboard (Internal Review) or a callback from the translation provider (External Review). It is not polling on a tight loop and it is not holding a connection open, so a long timeout consumes no compute in the background. A job can wait 48 hours for a human the same way it waits on a model: it is parked, not spinning.
Two review modes are available, picked per engine. They differ only in who does the reading – the pause, resume, and carry-forward behavior is identical.
Internal Review#
Your own team reviews translations directly in the Lingo.dev dashboard. Pending reviews land on the Human Reviewer page of your organization (/orgs/<org-id>/human-reviewer), and reviewers are notified when new items arrive. A reviewer claims an item, then approves the translation as-is or submits an edited version. The job resumes immediately with their output.
A second reviewer can't pick up an item someone is already working. Claims are exclusive – one reviewer holds an item at a time, so two people never edit the same translation and quietly overwrite each other. The string is locked to the claimant until they release it or submit.
Internal Review is the default mode for new engines. Reach for it when your team has the language expertise in-house and you want full control over the final wording, with no third party in the loop.
Permissions#
Internal review is not open to everyone in the organization – the Human Reviewer page is permission-gated, so a translation in review is visible only to the people you grant access. An organization admin assigns access through roles (Settings → Roles):
| Permission | What it unlocks |
|---|---|
Review translations (engine:review_translations) | See and work the review queue – claim a pending translation, edit it, approve it as-is, or submit the edited version |
Manage reviews (org:manage_reviews) | Review history and reviewer statistics for all internal reviews across the organization |
The two permissions are deliberately separate. A reviewer needs only Review translations – that single grant is the whole job: claim, edit, approve, submit. Manage reviews is for whoever oversees the operation; it adds the history and stats view across the org but does not include queue access on its own. Grant both to a lead who reviews and reports; grant only the first to someone who only works the queue.
External Review#
When you don't have in-house reviewers for a locale, the translation is submitted to a qualified professional translator through an external provider instead. The job pauses the same way; it resumes when the provider returns the edited translation. Nothing about your code changes – the difference is who reads the string, not how the job behaves.
External Review has two tiers, and the split is about how much accuracy the content demands:
| Tier | Best for |
|---|---|
| Standard | Accurate translation with a human voice – marketing copy, UI strings, help content |
| Pro | Professional use with an even higher accuracy bar – legal, medical, and regulated content |
This is the candor worth being explicit about: External Review is a real human translator on the other end, with the turnaround and cost that implies. It is not a faster model. Use it where a person's judgment is the point – regulated text, high-stakes copy – and lean on the AI-only path for the bulk of your content that doesn't need it.
Timeout#
A human stage introduces a risk the AI stages don't have: the human might never respond. A reviewer is on vacation, the provider is backed up, the item is forgotten. Left unbounded, the job would wait forever.
So the wait is bounded. You set how long the workflow waits for the human output – the same timeoutHours setting applies to both review modes. If the timeout expires with no response, the stage is marked skipped and the job continues with the AI translation as the final output. The default is 48 hours.
State the cost plainly: on timeout you ship the unreviewed AI translation. That is the correct fallback for most content – a translation that shipped beats a job stuck open indefinitely – but it is a real tradeoff. For content where a human must sign off no matter what, set a generous timeout and alert on the skip; for content where review is a nice-to-have, a short timeout keeps the pipeline moving.
Timeout is per stage, not per job
The timeout governs only how long this stage waits for a human. It is independent of how long the rest of the job takes. Because the wait is event-driven, a long timeout costs you latency-to-final-output if the reviewer is slow – never background compute.
Enabling the stage#
humanEdit is configured like every pipeline stage: an engine-level default in the engine's Pipeline tab, optionally overridden per request. The full two-layer model lives on Configure the pipeline; the shape specific to this stage is:
{
"humanEdit": {
"enabled": true,
"provider": "internal",
"tier": "standard",
"timeoutHours": 48
}
}provider selects the mode – internal for your own team, the external provider otherwise. tier (standard or pro) applies to External Review and is ignored for Internal. timeoutHours is the bound from the section above. To override for a single submission, pass this block inside pipelineConfig on the create call; omit it and the job inherits the engine's setting.
When the stage runs, it records itself on the job under stepId: "humanEdit" with a status of completed, failed, or skipped – the same step record every stage produces. Reading those records is covered in Observe pipeline runs.
A human edit can drift from your engine rules
A human translator may phrase something in a way that conflicts with your glossary, brand voice, or instructions – they're translating well, not memorizing your config. To reconcile the human's edit back to your engine rules automatically, enable the next stage, AI review. It runs only after a human stage that actually produced output.
