# 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: ```text compact -> expanded -> translation -> translated expanded -> package ``` The standard commands are: ```shell 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: ```shell 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.md` - the upstream README preserved as `UPSTREAM-README.md` when present - `.transform/manifest.json` for 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 translation - Placeholders may be reordered for grammar. - raw `{{ ... }}` or `{% ... %}` Jinja is not allowed in translation text - broken 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: ```shell .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: ```shell 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.py` - `create_translation_migration_prs.py` - `validate_translation_config.py` - `download_clean_scaffold_artifacts.py` - `report_translation_consistency.py` - `resolve_migration_source.py` See [Public Template Repository Integration](downstream-integration.md) for the artifact contract between this repo and the public repository.