Skip to main content

Create dual-language EPUB books with OpenRouter translations.

Project description

EPUB Dual Language

A Python CLI that turns an EPUB into a dual-language EPUB using OpenRouter.

The default output is paragraph aligned:

Original paragraph
Translated paragraph

This tends to work well for novels and essays because both languages stay close together without interrupting every sentence.

Features

  • Translates EPUB books with OpenRouter chat models.
  • Preserves the original EPUB container and stylesheet links.
  • Produces a separate dual-language edition with updated title and EPUB identifiers.
  • Supports paragraph or sentence interleaving.
  • Supports chapter-based or token-budget chunking.
  • Can translate only the beginning of a book for quick tests.
  • Can add rare bracketed translator notes for important cultural or archaic references.

Example of a generated dual-language EPUB (left) vs. original (right) opened in Calibre:

example

Installation

Install from PyPI:

pip install epub-dual-language

Python 3.10 or newer is required.

For development, clone the repository and install it into a Python environment:

pip install -e ".[dev]"

OpenRouter API Key

The CLI reads OPENROUTER_API_KEY from the environment. You can pass it directly when you run the command.

macOS/Linux:

OPENROUTER_API_KEY=your_openrouter_key epub-dual-language "path/to/book.epub" "English"

PowerShell:

$env:OPENROUTER_API_KEY="your_openrouter_key"; epub-dual-language "path/to/book.epub" "English"

Windows cmd:

set OPENROUTER_API_KEY=your_openrouter_key && epub-dual-language "path/to/book.epub" "English"

You can also create a .env file in the directory where you run the command:

OPENROUTER_API_KEY=your_openrouter_key

When you call epub-dual-language, it loads .env from the current working directory. An environment variable already set in your shell takes priority over the .env value. The repository's own .env is ignored by git.

Basic Usage

epub-dual-language "path/to/book.epub" "English"

Write to a specific output path:

epub-dual-language "path/to/book.epub" "English" --output "output/book.dual.epub"

Translate only a small beginning sample:

epub-dual-language "path/to/book.epub" "English" --limit-units 30 --output "output/sample.dual.epub"

Run without calling OpenRouter:

epub-dual-language "path/to/book.epub" "English" --dry-run --limit-units 20

Options

epub-dual-language INPUT_EPUB TARGET_LANGUAGE \
  --source-language German \
  --model google/gemini-3-flash-preview \
  --chunking tokens \
  --max-tokens 6000 \
  --layout paragraph \
  --translation-style italic-muted \
  --translator-notes \
  --limit-units 40 \
  --output output/sample.dual.epub

Metadata

The generated EPUB is marked as a separate dual-language edition.

For example, an input title like:

Original Title

becomes:

Original Title (Dual English)

The OPF unique identifier is also replaced with a new deterministic dual-edition UUID. This reduces the chance that Calibre or an e-reader treats the translated edition as the same book as the source.

Chunking

--chunking tokens is the default. It walks the EPUB in reading order and packs paragraphs or sentences into model requests until the estimated --max-tokens budget is reached. Small samples can therefore fit into a single API call even if they cross EPUB file boundaries.

--chunking chapters sends one EPUB spine document at a time. Many EPUBs store chapters as separate XHTML files, so this often approximates chapter-by-chapter translation. It is simple, but very long chapters can create large requests.

Token counts are estimates based on text-like tokens, not provider billing tokens.

Layouts

--layout paragraph is the default and recommended mode for reading:

Original paragraph
Translated paragraph

--layout sentence alternates original and translated sentences inside each paragraph. It can be useful for language study, but it is less pleasant for uninterrupted reading.

Translation Styling

Translated text is italic by default so it is easy to distinguish from the original without changing the book too aggressively.

epub-dual-language "path/to/book.epub" "English" --translation-style italic

Available styles:

  • italic
  • muted
  • italic-muted
  • plain

Translator Notes

Use --translator-notes to let the model add rare, short notes in square brackets for genuinely important archaic, historical, or culturally specific references:

epub-dual-language "path/to/book.epub" "English" --translator-notes

The prompt explicitly asks the model not to explain ordinary lines or add notes everywhere.

Development

Run tests:

pytest

Run the CLI module directly:

python -m epub_dual_language.cli "path/to/book.epub" "English" --dry-run --limit-units 10

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

epub_dual_language-0.1.2.tar.gz (13.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

epub_dual_language-0.1.2-py3-none-any.whl (12.1 kB view details)

Uploaded Python 3

File details

Details for the file epub_dual_language-0.1.2.tar.gz.

File metadata

  • Download URL: epub_dual_language-0.1.2.tar.gz
  • Upload date:
  • Size: 13.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for epub_dual_language-0.1.2.tar.gz
Algorithm Hash digest
SHA256 2c2b3b214fbcd5a2a5a62e8655dde6d746440276c799cfe92b88b09bb029b117
MD5 4e541dfa9858e2d647b5aef999f06f67
BLAKE2b-256 8974e50295157c768aeca7b383033d6078e7351e2c0b88e33cbc5f16d523bd82

See more details on using hashes here.

Provenance

The following attestation bundles were made for epub_dual_language-0.1.2.tar.gz:

Publisher: release.yml on OscarPellicer/epub-dual-language

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file epub_dual_language-0.1.2-py3-none-any.whl.

File metadata

File hashes

Hashes for epub_dual_language-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 d0537cd89aaf1ccccde7a1ebc00deb454cc63cd31590ae61d092cec4b54657db
MD5 98db4d1abfe43603cd6821fe88453b79
BLAKE2b-256 cb98ed3dbb076c59548017cbafebba9cf6bc16ac0c7b797e90849a8fa413a2f8

See more details on using hashes here.

Provenance

The following attestation bundles were made for epub_dual_language-0.1.2-py3-none-any.whl:

Publisher: release.yml on OscarPellicer/epub-dual-language

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page