Wenyi: whole-book translation for EPUB novels from the command line
将被语言阻隔的作品,带到读者的语言中。Bringing literature into your language.
At a glance
- What is it?
- Wenyi is a Python tool that parses an EPUB, prescans the whole book, translates chapter by chapter with a live glossary, and writes the result back into the original XHTML. It is built for novels and long-form nonfiction, not for one-off strings.
- Who is it for?
- Wenyi is worth adopting if you translate books rather than strings: the CLI installs with uv sync, the pipeline checkpoints every batch, and the glossary is extracted from the text as it goes. Skip it if you need PDF input without an external MinerU key, or if you want a hosted service that hides the model calls.
- Can I use it commercially?
- Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
- Is it still maintained?
- Yes. The repository last received commits 1 day ago.
- What is it written in?
- Mainly Python, according to GitHub's language statistics.
Answers come from the project's GitHub data, last synced on September 18, 2026, and from our analysis. They are not legal advice.
DEEP OPEN-SOURCE ANALYSIS
The problem Wenyi targets: segment-level translation of a whole book
Most translation tooling works on strings. You send a paragraph, you get a paragraph back. That model breaks down on a 300-page novel, where a character's name must be rendered the same way in chapter two and chapter twenty-two, and where a pronoun's referent may sit three pages earlier. Wenyi's README frames the contrast directly: the typical approach translates segments in isolation, unaware of surrounding content, while Wenyi runs a whole-book prescan with chapter digests and rolling context.
The intended user is someone translating long-form text: novels, social-science monographs, narrative nonfiction. That is a narrower audience than a general API wrapper serves. If your job is a marketing page or a support macro, the prescan and glossary machinery is overhead you will pay for and never use. If your job is a book, the machinery is the point.
How the pipeline works: prescan, glossary, batches, review
The documented flow has four stages. Prepare parses the book, detects the source language, and prescans it, producing per-chapter digests and a book-level synopsis. Translate then works through the chapters in batches, and the synopsis is injected into every batch so each request carries book-level context rather than only the current chunk. While translating, Wenyi extracts proper names, terms and recurring expressions into a glossary, detects conflicting translations of the same term, and feeds the glossary back into subsequent batches. Review is a separate pass over the finished work, checked against the completed glossary.
The state model is what makes this practical. The README describes batch-level checkpoints, chapter status tracking and atomic state writes, so an interrupted run resumes with the same command. Multilingual targets keep separate state and output names, which means a zh to en run and an en to ja run of the same file do not overwrite each other's progress.
Output is not a fresh document. Wenyi writes translated text back into the original XHTML templates and attempts to preserve styles, images, TOC and anchors. An optional bilingual edition places translation alongside visually subdued source text. The word "attempts" is the README's own, and it is the honest word: template preservation is the part of any EPUB pipeline most likely to meet a file it did not anticipate.
Installing Wenyi and translating a first book
Wenyi requires Python 3.10+ and uv. Clone the repository and sync the workspace, which resolves the wenyi-core, wenyi-cli and wenyi-api members declared in pyproject.toml.
git clone https://github.com/BigDawnGhost/wenyi.git
cd wenyi
uv syncSet a provider key. The quick start uses DeepSeek, and .env.example lists the other accepted variables: OPENAI_API_KEY, OPENROUTER_API_KEY, GEMINI_API_KEY and ORCAROUTER_API_KEY. Only the providers you actually select in config need credentials.
export DEEPSEEK_API_KEY=sk-...Then translate. One command parses the book, detects the source language, prescans, translates every chapter and assembles the output; the monolingual Chinese EPUB lands at output/book.zh.epub by default.
uv run wenyi translate book.epubIf you want to inspect the prescan before spending tokens on body text, run the stages separately. Prepare does the parsing and analysis without translating any body text, translate resumes from that state, review runs the final pass, and status reports progress.
uv run wenyi prepare book.epub
uv run wenyi translate book.epub
uv run wenyi review book.epub
uv run wenyi status book.epubFlags on translate adjust the run: --polish and --review enable the optional stages, --no-polish and --no-review disable them, --bilingual produces both editions, and --chapter 0 limits the run to a single chapter. Polishing is described as using a stronger model, so it changes both cost and output.
Interface, providers and the routing configuration
There are two ways in. The CLI above covers the whole pipeline. A web workspace adds a live progress view, paragraph proofreading with revision history, and the whole-book review with evidence and publication results. The interface ships in English and Chinese, switchable in Settings; screenshots in the README show the Chinese layout. The workspace is a separate deployment: package.json exposes dev:api as uvicorn wenyi_api.main:app on port 8000, dev:worker as an arq worker, and dev:web through pnpm in apps/web. Compose files and a deploy directory exist for the stack, with DATABASE_URL and REDIS_URL defaulting to local Postgres and Redis and WENYI_CONFIG pointing at config.yaml.
Provider support is broad by design: DeepSeek, OpenAI, OpenRouter, OrcaRouter, Google Gemini, Ollama, vLLM, and generic OpenAI-compatible endpoints. The configuration documentation describes keeping three convenient tiers or selecting models per operation, mixing connections and sharing request limits. That matters for cost control on a long book, because the polish stage can be pointed at a stronger model than the main translation without rewriting the pipeline. It also means the configuration surface is the part most likely to trip up a first run: .env.example notes that custom providers need the variable named by llm.providers.<name>.api_key_env, so a provider added under a custom name will not pick up a key from a differently named variable.
Where Wenyi is the wrong tool
The README has a Limitations section, and the constraints that surface in the rest of the documentation are worth stating plainly. The web workspace is a server deployment, not a desktop app: it needs Postgres, Redis and a worker process, which is a lot of infrastructure if you only ever translate one book from a terminal. The multilingual path is marked experimental in the documentation, and the quick start's own example is Chinese output from an unspecified source language, so a zh to en or en to ja run is the less-travelled branch.
PDF input is conditional. .env.example states that MinerU is used only for PDF input with pipeline.pdf_backend: mineru, and MINERU_API_KEY is a separate credential. Without it, PDF is not a supported input path, and the optional pdf-output and pdf-output-lite dependency groups cover generating PDFs, not reading them.
Finally, the quality story rests on model calls you pay for. Prescan, translation, optional polish and review are four passes over the same book, and the review pass is described as evidence-driven rather than a guarantee. Wenyi gives you structure and resumability; it does not remove the need to read the output.
How Wenyi differs from a document translation service
The obvious alternative is a hosted document translation service, or a general LLM API wrapper that accepts an EPUB and returns a translated one. The difference is where context lives. A wrapper typically chunks the document and sends each chunk with instructions; whatever consistency you get comes from the prompt. Wenyi builds the context first, as per-chapter digests and a book-level synopsis, and maintains a glossary that is extracted from the text as translation proceeds and fed back into later batches, with conflict detection when the same term is rendered two ways.
The second difference is state. A wrapper that fails at chapter fourteen usually restarts from the beginning. Wenyi persists every completed batch and tracks chapter status, so the same command resumes. For a book-length job that is not a convenience feature; it is the difference between a run that survives an API outage and one that does not.
The trade-off is that you own the deployment. A hosted service hides the model choice, the retries and the storage. Wenyi exposes all of it in config.yaml and .env.example, and expects you to have the credentials and the database to run it.
Editorial conclusion
Wenyi is worth adopting if you translate books rather than strings: the CLI installs with uv sync, the pipeline checkpoints every batch, and the glossary is extracted from the text as it goes. Skip it if you need PDF input without an external MinerU key, or if you want a hosted service that hides the model calls. Before committing a real book, run uv run wenyi prepare on one volume and read the generated chapter digests and glossary to check that the prescan understood your text.
Frequently asked questions
What is the meaning of the name Wenyi?
The repository does not explain the name. Its tagline is "Carry stories across languages", and the project is described as a workspace for multilingual long-form translation, so the name is presented as a brand rather than with a stated meaning.
What Python version does Wenyi need?
The README lists Python 3.10+ and uv as prerequisites, and pyproject.toml sets requires-python to >=3.10. Installation is a git clone followed by uv sync.
Does Wenyi translate PDFs as well as EPUBs?
PDF input is conditional. The .env.example file states that MinerU is used only for PDF input with pipeline.pdf_backend: mineru, and MINERU_API_KEY is a separate credential. The documented quick start uses an EPUB file.
Can a Wenyi translation run be resumed after an interruption?
Yes. The README says every completed batch is persisted immediately and that an interrupted run resumes by executing the same command again. It also lists batch checkpoints, chapter status tracking and atomic state writes among the core features.
Community notes