Translation Workflow¶
This document explains how the tooling turns an upstream DSW document template into a translator-facing tree, then syncs that tree back into a packageable template. Translator day-to-day instructions belong in the public translated-template repository.
Workspace Shapes¶
The translation pipeline has three workspace shapes:
compact: the upstream DSW document template source.expanded: the same template with sentence-preserving marker comments around translatable units.translation: one Markdown file per translation unit, optimized for human review and editing.
The reversible path is:
compact -> expanded -> translation -> translated expanded -> package
The standard commands are:
make transform
make export-translation-tree
make sync-translation-tree
When the upstream template or parser changes, regenerate a fresh tree and merge existing translations conservatively:
make export-fresh-translation-tree
make merge-translation-tree
Expanded Workspace¶
make transform generates an expanded template workspace from a compact DSW
template. The original .j2 files stay in place, but translatable regions are
wrapped with generated comments such as __tr_block_####.
The markers are comments, not {% set %} captures. They preserve larger units
such as headings, paragraphs, list items, and branch-complete sentence groups
without changing Jinja scope.
The generated expanded workspace includes:
original template files under their normal paths
generated translation markers
a generated
README.mdthe upstream README preserved as
UPSTREAM-README.mdwhen present.transform/manifest.jsonfor machine checks
The generated README.md in the expanded workspace is internal. During
translated output sync, the tool copies the public repository’s configured
public README into the package when that file exists. If it is
missing, the tool writes a short fallback README so the DSW package still has a
displayable description. The translated package intentionally excludes
internal-only files such as .transform/ and UPSTREAM-README.md; public
README text should link to the upstream GitHub README instead of copying it into
the public repository.
Translator-Facing Tree¶
make export-translation-tree writes one translation.md file per translation
unit. Each file shows the source sentence first and the editable target block
second. Machine metadata is kept in a collapsed details section so translators
can inspect it when needed without having it dominate the page.
Translator-facing tree rules enforced by this tooling:
every editable file has a stable source block and target translation block
every placeholder that appears in the source sentence, such as
{name}, must remain present after translationPlaceholders may be reordered for grammar.
raw
{{ ... }}or{% ... %}Jinja is not allowed in translation textbroken or deleted translation block skeletons can be regenerated
The generated outline.md gives reviewers a compact progress view of all
translation units. It is committed, but it is not edited by hand: export, merge,
and CI refreshes recalculate it from the current translation.md blocks so a
filled translation block automatically becomes a checked item.
Optional XLIFF Exchange¶
The canonical translation source is still the Markdown translation tree. External translation platforms should be treated as editing interfaces, not as the source of truth.
Use XLIFF as the exchange boundary:
.venv/bin/dsw-template-tree export-xliff --tree translation --output xliff/messages.xlf
.venv/bin/dsw-template-tree import-xliff --tree translation --xliff xliff/messages.xlf
export-xliff reads the current translation tree and writes a standard XLIFF
1.2 file. An external platform can edit that file without understanding the
custom translation.md format.
import-xliff writes XLIFF targets back into the editable translation blocks.
Import checks that every XLIFF unit still belongs to the current tree and that
the source hash matches. Placeholder, Jinja, and HTML safety checks remain the
responsibility of make audit-translation-tree and make sync-translation-tree,
so the validation rules stay centralized.
Do not point an external platform at generated compact, expanded, or translated output. It should only edit an explicit XLIFF exchange file. This tool ships import/export helpers, not a hosted translation service or branch-based review workflow.
Sync and Audit¶
make sync-translation-tree applies translator edits into a generated translated
expanded workspace and packages it. During sync, the tooling checks that
placeholders, Jinja structure, HTML wiring, links, assets, and static files stay
structurally safe.
Blank translation blocks intentionally fall back to the English source text. That allows scaffold artifacts to be generated before translation is complete, but such artifacts are not finished translations.
Useful checks:
make audit-translation-tree
make sync-translation-tree
make audit-translated-template
Public version workflows add two runtime checks after packaging. The demo PDF
uses the maintained sample project for human wording and layout review. The
translated-package regression imports the actual package ZIP and renders the
complete selected fixture set with render_success; this is the executable
release gate and must have complete generated-fixture branch coverage.
Cross-Version Translation Sync¶
The public translated-template repository commonly uses one sync/v* branch
per upstream template version. This repo provides helpers for that model, but
the branch policy itself belongs in the public repository.
Clean scaffold discovery can record every compatible upstream tag in
template.supported_versions. That does not mean every tag must be translated.
The public repository opts versions into translator-facing branches with
version_policy.refresh; omitted policy defaults to scaffold-only so new tags
do not silently become translation work.
Versions with migrate_into: auto form the automatic synchronization group and
may act as both source and target. After a translated sync/v* branch passes
CI, its exact-source translations fan out to the other group members. Blank
target units are filled and existing target translations are updated; the
source branch is authoritative for that run. Versions set to manual
participate only in an operator-dispatched run, while false versions do not
participate.
Synchronization remains structural rather than fuzzy. It applies only when the source hash and executable placeholders match. If the source sentence, Jinja shape, or HTML structure changed, the target unit keeps its current state and requires version-specific translation. Normal artifact refresh is separate and always preserves that branch’s translator edits before cross-version sync runs.
The operations workflow also produces a read-only cross-version consistency
report. It groups identical visible source sentences from active and
maintenance branches, then reports blank/nonblank translation gaps and
different nonblank wording. exact-source findings share the executable source
hash; visible-source-only findings may have different Jinja or HTML and are
terminology hints only. Findings never weaken exact-source migration, change a
translation, or fail CI by themselves. Malformed or missing configured trees
still fail because the report could not be trusted.
Each synchronization PR commits only matching translation.md files and, when
its checkbox state changes, the generated outline.md. The merge report is kept
in the PR body and Actions job summary rather than committed to a version branch.
After such a PR merges, version validation still refreshes the package, preview,
and release assets, but it does not start another migration fan-out. A normal
translator PR merge remains the source of a new fan-out. The controlled
chore(sync): carry commit prefix is the protocol between the migration script
and version workflow; update both together if that prefix ever changes.
The helper scripts live under scripts/ci/:
sync_translation_version_branches.pycreate_translation_migration_prs.pyvalidate_translation_config.pydownload_clean_scaffold_artifacts.pyreport_translation_consistency.pyresolve_migration_source.py
See Public Template Repository Integration for the artifact contract between this repo and the public repository.