Translation contract

booktx now keeps translation state per profile.

Primary profile-local state

  • translations/<profile>/translation-store.json

  • translations/<profile>/translation-version-ledger.json

  • translations/<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:

  • profile

  • target_language

  • target_locale

  • translation_version

  • context_sha256

  • source_sha256

  • source/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 compare is 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_ID header 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.txt as 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:

  1. natural apposition or rephrasing that contains the approved target naturally;

  2. a longer source phrase glossary entry, which shadows the shorter entry;

  3. 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.