Segment editor & AI translation
Translating with AI
From a file's target language, estimateTranslation reports how many
segments are still untranslated and an up-front credit estimate; translateFile
(the whole file) or translateSelected (a chosen set of segments) then reserve
credits and enqueue one or more translation jobs.
Models are restricted to an allowlist — only a model with a pricing entry
in src/config/model-pricing.config.ts can be selected, both when enqueuing
and again inside the worker, so a tampered job payload can never drive an
unpriced (and unbillable) model into a live API call.
A large file is split into chunks of at most
TRANSLATION_MAX_SEGMENTS_PER_JOB segments, each its own job with its own
credit reservation — so no single job, or its payload, is ever unbounded.
Credits are reserved at enqueue and settled with the real token usage
once the worker finishes each chunk (see Credits for the
reserve → settle primitive); a job that fails after partial progress still
gets paid for what it delivered, with the rest refunded.
The segment editor
Opening a file (/translations/[projectId]/[fileId]) shows a paginated table
of segments for the selected target language, with search and status filters
(pending / translated / reviewed / approved). Selecting a row opens an
editing panel:
- Placeholders (
{1}...{/1}) render as literal text in the editor and are re-validated on save — a translation that drops or duplicates a placeholder is flagged, never silently exported broken. - QA checks run live as you type (
src/lib/qa/index.ts): empty translation, placeholder mismatch, number mismatch, unusual length ratio, double spaces, stray whitespace, and glossary terms that should have been used but weren't. - Translation memory suggests an exact match from prior approved
translations in the same organization (
tm.lookup), one click to apply. Approving a segment also saves it back to memory (tm.save) for future reuse. - Comments thread per segment/target — any member can comment; resolving or deleting requires being the author or holding a reviewing/managing project role.
Bulk actions
Selecting multiple rows exposes translate-selected, mark-reviewed, approve, and restore-AI-translation actions. Each item in a bulk action is applied independently — one failure doesn't abort the batch silently; the UI reports how many succeeded and how many didn't, and always refreshes the list afterwards.
Notifications
When a translation job or export finishes (or fails after its retries are
exhausted), the job's creator gets an in-app notification and, unless they've
opted out under the "translation" category in their notification preferences,
an email — reused from the same notify() delivery path as every other
kit notification.