Translation contract
booktx now keeps translation state per profile.
Primary profile-local state
translations/<profile>/translation-store.jsontranslations/<profile>/translation-version-ledger.jsontranslations/<profile>/tasks/translations/<profile>/ingest/translations/<profile>/translated/translations/<profile>/todos/
Todo files
translations/<profile>/todos/<todo-id>.{json,md} are run-control artifacts
written by booktx translate todo-next. They describe a bounded multi-chapter
agent run (chapters to complete, per-task word budget, stop conditions).
Todo files are NOT translation submissions. The agent reads the markdown loop
instructions, fills ingest files, and runs translate insert for each batch.
Do not submit todo JSON files through translate insert.
Task metadata
booktx translate next persists tasks with:
profiletarget_languagetarget_localetranslation_versioncontext_sha256source_sha256source/profile config hashes
booktx translate insert rejects:
task/profile mismatches
submission/profile mismatches
stale task version metadata
Compatibility exports
Compatibility translated chunk files remain JSON objects with chunk_id and
ordered record targets, but they are profile-local:
translations/<profile>/translated/NNNN.json
Comparison rules
booktx translation compareis profile-local.Cross-profile comparison is explicit under
booktx profile compare.
Block submission schema
booktx translate next --format block writes a durable ingest file under
translations/<profile>/ingest/<task>.block.txt. Edit only that file and
submit it back. Example:
# booktx block submission
# profile: PROFILE_A
# task: bt-task-20260101T000000Z-ch01-0001r0001-a1b2c3d4
# translation_version: 1.2
>>> 0001-000001
Translated text here.
>>> 0001-000002
Second translated record.
Rules:
Keep every
>>> RECORD_IDheader unchanged.Write only the target translation under each header.
Preserve required placeholder tokens (for example
__NAME_001__) exactly.Preserve enclosing quotation marks when the source record is fully quoted. German targets may use either
„...“or»...«, but both opening and closing quotation marks must be present as a valid pair. Do not mix quote styles within one outer pair.Do not add commentary outside target text.
Do not edit
tasks/<task>.source.block.txtas the submission.
JSON submission schema
Submissions may also be supplied as JSON (schema_version 2). Example:
{
"schema_version": 2,
"profile": "PROFILE_A",
"task_id": "bt-task-...",
"translation_version": "1.2",
"records": [{ "id": "0001-000001", "target": "Translated text here." }]
}
The profile and translation_version fields must match the target profile
and the durable task metadata, or booktx translate insert rejects the
submission.
EPUB inline XHTML fragments
EPUB source records may contain constrained inline XHTML fragments. Targets must preserve equivalent inline XHTML semantics. A target that drops <em>, <strong>, link, span-class, code, superscript/subscript, or other source inline semantics is invalid unless the user explicitly approves a semantic change.
Translate only human-readable text nodes. Preserve tag names and attributes around the equivalent target-language phrase. Do not replace XHTML with Markdown markers. Do not invent block markup, comments, scripts, styles, or new attributes. Opaque inline elements such as <code>...</code> must stay unchanged.
Review candidates
Review candidates are quality-improved targets stored separately from
translation versions. They live under a separate reviews[] array in
StoredTranslationRecordV2 and use a separate ref namespace – R<pass>.<run> (e.g. R1.1, R2.1) – so they are visibly different from dotted version refs.
Translation versions answer: which source/context/model produced the initial target?
Review candidates answer: which quality pass improved or approved that target?
Final output resolves as: active_review (if valid) -> active_version -> missing.
A stale or invalid active review is reported as an error during validation.
Review candidates are stored under translations/<profile>/reviews/.
Revision provenance
translation revise-record and translation revise-block preserve provenance for revised candidates. The commands resolve the current translation version and baseline once, create chapter-scoped context-view snapshots for affected records, and write baseline_ref, baseline_sha256, context_view_sha256, context_view_path, and context-note scope metadata to the candidate. Revising an existing candidate at the same version amends that candidate; immutable correction-history references are not part of this contract.
Glossary phrase collisions
When a shorter source term is contained inside a longer configured source phrase, enforcement uses only the longest non-shadowed source span. A separate standalone occurrence of the shorter term remains active. Do not distort the target sentence merely to satisfy the shorter literal target token. Prefer one of:
natural apposition or rephrasing that contains the approved target naturally;
a longer source phrase glossary entry, which shadows the shorter entry;
an explicit forbidden target for the bad correction pattern.
Example: a binding Mole Cricket-kinden -> Maulwurfsgrillenart entry shadows
Cricket-kinden -> Grillenart for that contained occurrence, allowing the
natural German compound. Create the longer decision with context mandate-term.
Apposition is only a fallback when no longer phrase decision exists.