Usage guide
August 9, 2026 · View on GitHub
Installation and first run
Running from source requires Python 3.10+ and uv.
uv sync
export DEEPSEEK_API_KEY=sk-...
uv run trans-novel --version
uv run trans-novel translate book.epub
The displayed version is generated from the repository's Git tags. Tagged builds show the release version; development builds include their commit distance and hash.
Whenever the program starts, it checks for config.yaml in the current directory and creates a documented default file when it is missing. Review the model settings before starting a real translation.
Windows
Windows releases provide wenyi-windows-x64.zip. Verify the archive against
SHA256SUMS.txt before running it.
When using a packaged wenyi.exe, set the API key in PowerShell:
# Current PowerShell session only
$env:DEEPSEEK_API_KEY = "sk-..."
.\wenyi.exe translate .\book.epub
To save the environment variable permanently, run the following command and then open a new PowerShell window:
setx DEEPSEEK_API_KEY "sk-..."
You may also set language.source to a known ISO language code to avoid an additional model call for language detection.
Linux
Releases provide wenyi-linux-x64.tar.gz and wenyi-linux-arm64.tar.gz. Download
the archive matching your processor, verify it against SHA256SUMS.txt, and run:
tar -xzf wenyi-linux-arm64.tar.gz # use wenyi-linux-x64.tar.gz on x64 systems
chmod +x wenyi
export DEEPSEEK_API_KEY=sk-...
./wenyi translate book.epub
macOS
Releases provide separate terminal executables for Apple Silicon (wenyi-macos-arm64.tar.gz)
and Intel (wenyi-macos-x64.tar.gz) Macs. Download the archive matching your processor,
verify it against SHA256SUMS.txt, and run:
tar -xzf wenyi-macos-arm64.tar.gz # use wenyi-macos-x64.tar.gz on Intel Macs
chmod +x wenyi
export DEEPSEEK_API_KEY=sk-...
./wenyi translate book.epub
These command-line executables are ad-hoc signed by PyInstaller but are not notarized with an Apple Developer certificate. macOS may quarantine a downloaded build; after verifying the checksum, approve it in System Settings → Privacy & Security if prompted.
Input and output
- Input formats: EPUB, FB2, TXT, Markdown, HTML, and PDF.
- Default output: a monolingual
<book-name>.zh.epubunder the source file'soutput/directory. The bilingual<book-name>.zh-bi.epubis optional. --format txt|html|markdown|pdf: export the selected format. Every input format still produces EPUB by default.- For EPUB input, Wenyi attempts to write translated text back into the original XHTML templates while preserving styles, images, the table of contents, and anchors.
- The bilingual edition displays the translation and source text together. The source is visually subdued by default; set
output.bilingual_preserve_source_style: trueto inherit the book's normal text style. Their order is controlled byoutput.bilingual_order. - EPUB output includes an “About this translation” page by default. Set
output.about_page: falseto disable it. - Runtime data is stored under
state/, including chapter intermediates, the SQLite glossary, usage data, and reports.
Experimental PDF support
PDF input and PDF output are both experimental.
PDF input
The first PDF import requires MINERU_API_KEY:
export MINERU_API_KEY=...
uv run trans-novel translate book.pdf
MinerU's converted HTML is saved at
state/<book>/source/<source-sha256>/converted.html. The content-addressed
directory prevents an interrupted run from reusing another PDF's conversion.
Later runs reuse this file, and you may correct it manually before resuming.
PDF output
WeasyPrint is the default PDF engine. Install its optional dependency and omit
--pdf-engine:
uv sync --extra pdf-output
uv run trans-novel assemble book.html --format pdf
For a lightweight cross-platform engine without system rendering libraries,
use fpdf2:
uv sync --extra pdf-output-lite
uv run trans-novel assemble book.html --format pdf --pdf-engine fpdf2
fpdf2 supports basic layout and images, but only a limited HTML/CSS subset.
Images mixed with text are placed as separate blocks. It uses a discoverable
CJK system font; if none is found, set TRANS_NOVEL_PDF_FONT to a TTF, OTF, or
TTC font file. This option also works on Windows.
Per-run metrics
state/<book>/usage.json remains the cumulative token total for the book.
translate, prepare, review, assemble, and report each write an independent
state/<book>/run_metrics/<run-id>.json record with:
- the input SHA-256, configuration, package, and Git revision fingerprints;
- invocation options such as a selected chapter, output format, and PDF engine;
- requested stages, completion or failure status, and per-stage wall time;
- only the LLM calls and tokens added by that invocation; and
- ending chapter and segment completion counts.
Every resume creates a new record, so clean runs from different branches can be compared without mixing their costs. Records omit the full source path and book text, redact sensitive option values, and store only an exception type on failure.
New manifests store source_sha256 instead of an absolute source path. Wenyi
rejects a same-title state directory when its recorded hash does not match the
current input. Manifests created by older versions must be rebuilt.
Common commands
# Run the complete workflow, translate one chapter, or prepare without translating
uv run trans-novel translate book.epub
uv run trans-novel translate book.epub --chapter 3
uv run trans-novel translate book.epub --format txt
uv run trans-novel prepare book.epub
uv run trans-novel translate book.pdf
# Override polishing and final review settings
uv run trans-novel translate book.epub --polish --review
uv run trans-novel translate book.epub --no-polish --no-review
# Produce both editions, or only the bilingual edition
uv run trans-novel translate book.epub --bilingual
uv run trans-novel translate book.epub --no-mono --bilingual
prepare parses the book, detects its language, generates the style guide and initial glossary, and completes the configured whole-book prescan without translating any body text. Run translate with the same source file to continue from the saved state.
Interrupting and resuming
Every completed batch is written to the state directory. To resume after an interruption, run the same source file again:
uv run trans-novel translate book.epub
uv run trans-novel status book.epub
Changing polishing settings does not automatically rerun translation batches that
are already complete. Review is different: every review invocation rechecks the
complete translated book and creates a new timestamped read-only review run.
Use a new state directory or remove the corresponding state only when you
intentionally want a fresh translation.
Independent stages and glossary management
uv run trans-novel review book.epub
uv run trans-novel glossary list book.epub
uv run trans-novel glossary conflicts book.epub
uv run trans-novel glossary resolve book.epub "source term" "chosen translation"
uv run trans-novel report book.epub
uv run trans-novel assemble book.epub
review checks the complete translated book using the final glossary. Its
unchanged initial Reviewer runs over contiguous chunks concurrently; candidates
can then enter a bounded evidence loop, and contradictory cross-chunk consistency
suggestions can receive a final recommendation. Confirmed issues may generate
provisional full-segment replacements in a run-local shadow translation. Every
Fixer in a round reads the same immutable snapshot; the next whole-book pass
blindly reviews the resulting shadow text without receiving prior issue
explanations. Review never writes these replacements to the manifest, chapter
JSON, or glossary. Each run writes one user-facing result.json, its model-usage
delta, an event stream, and internal round traces to
state/<book>/reviews/review-<timestamp>/. The same usage delta is also added once
to the book's cumulative usage.json; report.json contains only a compact
read-only review summary.
report summarizes the current translation and read-only Review result without
modifying translated text. assemble rebuilds output from existing state without
calling the model again. If another terminal is still translating, export uses a
consistent snapshot of the batches already persisted when the command starts; run
it again to include batches completed afterward.