book-translator-hub

book-translator-hub

Docker app from felixapel's Repository

Overview

Book Translator Hub is the universal, zero-wait bilingual reading overlay and real-time translation engine for Calibre-Web Automated (CWA), Kavita, and self-hosted ebook libraries. Powered by local LLMs (vLLM, Ollama, Bifrost) or leading cloud providers (Gemini, OpenAI, Claude, DeepSeek, Groq). Features literary-tuned chunking, instant SSE token streaming, context-aware translation, auto-detect source language, and SQLite WAL persistent caching.

Book Translator Hub

Book Translator Hub — bilingual EPUB reading, illustrated by an open book

Latest published release CI-gated License: GPL-3.0 Python 3.11 Docker GitHub Sponsors Ko-fi

Bilingual reading overlay and translation engine for stock Calibre-Web-Automated and Kavita EPUB readers, powered by local or cloud LLMs.


Concept illustration of aligned original and translated paragraphs beside an e-reader
Editorial illustration of bilingual reading, not a product screenshot.

✨ What it does

  • Streaming and visible-work priority: Streams eligible first-paragraph output and prioritizes visible paragraphs ahead of bounded background work. Actual latency depends on the reader, provider, model, network and cache state.
  • Bounded lookahead: Can pre-translate a limited forward window while keeping visible requests ahead of background work. It is not a page-turn latency guarantee.
  • Layered cache: Uses an in-memory reading cache and a private SQLite cache. Optional browser persistence is controlled by the server-owned reader configuration and may be unavailable when browser storage is constrained.
  • SQLite WAL configuration: Uses WAL, bounded busy timeouts, a memory-mapped I/O window and page cache settings. Operators should measure cache behavior on their own storage and workload.
  • Language and reading controls: Detects source language from reader metadata/HTML with a manual override, plus a target-language selector on the floating toolbar.
  • Manual activation: Each book entry and page reload starts with translation OFF, even if this browser previously translated the book. Book text is sent for translation only after the reader turns the mode on.
  • E-Ink display mode: Provides a high-contrast, low-motion presentation intended for compatible e-readers; verify it on the target browser and device.
  • Versioned reader connectors: Integrates with stock Calibre-Web-Automated and exact Kavita EPUB contracts without modifying upstream images. See the compatibility matrix for acceptance limits.
  • Server-side provider credentials: Managed configurations keep API keys in the private server environment. Browser configuration omits provider keys; operators must protect their environment files and proxy boundary.

🚀 Supported installation

Choose a tag from the published releases. VERSION identifies the checked-out source; changes on main may not yet be available in a published release. See the release process for the acceptance and publication requirements.

The production path is the universal btctl hub. It builds an immutable local image from an exact clean checkout and runs CWA, Kavita or both through one hardened container while keeping separate internal API processes, caches, keys and cookies:

git clone https://github.com/felixapel/book-translator-hub.git book-translator-hub
cd book-translator-hub
# Select an immutable published tag from the GitHub Releases page before installing.
git switch --detach vX.Y.Z

Copy the managed configuration outside the checkout and make it private:

install -d -m 0700 /absolute/private/path
cp .env.hub.example /absolute/private/path/book-translator-hub.env
chmod 0600 /absolute/private/path/book-translator-hub.env

Set each enabled reader's exact container, network, version, public origin and storage paths. The managed template defaults to a local OpenAI-compatible provider. Replace its placeholder endpoint and model in the private copy:

BT_ENABLE_CWA=true
BT_ENABLE_KAVITA=true
LLM_PROVIDER=local
LLM_MODEL=local-model
LLM_API_KEY=
BT_LOCAL_URL=http://local-llm:8000/v1/chat/completions
BT_BATCH_SIZE=5
BT_BATCH_SOURCE_TOKEN_BUDGET=0
BT_BATCH_MAX_TOKENS=8192
BT_MAX_BATCH_PARAGRAPHS=50

Named remote providers, including Gemini, use their fixed HTTPS API endpoints and a server-side API key. Local and custom OpenAI-compatible backends are also supported through environment variables; select a cloud provider only in the private environment after reviewing its privacy and quota implications. Then run:

./btctl plan --env /absolute/private/path/book-translator-hub.env
./btctl install --env /absolute/private/path/book-translator-hub.env --yes
./btctl doctor --env /absolute/private/path/book-translator-hub.env

plan validates and reports the intended resources without changing the reader or deployment state. install commits state only after live postconditions pass. doctor is read-only and every check must report ok.

Provider roles are selected entirely through the private environment, with shared defaults and optional per-reader overrides. The split profile retains its provider-only btctl reconfigure workflow. A hub provider change uses a reviewed uninstall with the old environment followed by install with the new one; translation data is retained, hub-owned session keys are regenerated, and all reader processes restart coherently, so tabs may require a fresh short-lived session. See the configuration reference. A ChatGPT, Codex, Gemini or Antigravity consumer subscription is not an API credential.

Stock Unraid requires root, Bash, Docker and a full checkout including .git. It does not require host Python, host Git or NerdTools to run ./btctl; the launcher uses a temporary containerized operator when needed. Linux hosts use BT_INSTALL_PROFILE=compose-existing. Operators who need independent container isolation or CWA Authentik-forwarded identity can retain the split profile.

Community Applications uses a separate CWA-only combined-image profile. Install it only from a searchable listing whose template pins an immutable image digest; if no listing is present, use btctl. See the Community Applications guide.

🛡️ Runtime boundary

Browser / reverse proxy -> injection proxy -> stock CWA or Kavita
                                  |
                                  +-> private translation API -> LLM
                                                     |
                                                     +-> SQLite cache

Managed native-reader profiles exchange existing CWA or Kavita proof for a short-lived, opaque translator session. Raw reader credentials are confined to the exact exchange endpoint; ordinary translation calls never receive them. CWA strong-session binding and Kavita native/OIDC login are supported within their documented boundaries. Do not publish the API, disable authentication, or add a route that bypasses the managed proxy. Advanced CWA Authentik deployments have a separate fail-closed profile and guide.

CWA 4.0.6 is the exact CWA contract reference; each deployed candidate still requires browser acceptance. Kavita has separate exact 0.9.0.2 and 0.9.1.4 contracts; the 0.9.1.4 native account/broker fixture does not establish browser or OIDC acceptance. See the compatibility matrix before choosing a reader version. Manga, PDF and library writeback are not supported.

💖 Sponsors & Community Support

Book Translator Hub is 100% free and open-source software built for the self-hosted and reading communities. Development, local GPU testing (vLLM/Ollama), and continuous integration are maintained independently.

If you find Book Translator Hub valuable for your daily reading, please consider supporting the project:

GitHub Sponsors    Support on Ko-fi

  • Bug Bounties & Hardware: Supports purchasing hardware for testing on physical E-Ink devices and running local GPU benchmarks.
  • Feature Requests: Backers can directly influence the roadmap for future reader integrations (Audiobookshelf, Komga, Readium).

📖 Documentation

🤝 Development and support

Read CONTRIBUTING.md and the development guide before changing the project. Use the issue templates for reproducible bugs and feature proposals. Report vulnerabilities through the private channel in SECURITY.md.

Book Translator Hub is GPL-3.0 software with no telemetry, ads or subscription. Support is optional through Ko-fi or GitHub Sponsors. The project is not affiliated with or endorsed by CWA, Kavita, Calibre, Google or any LLM provider.

See LICENSE for the license text.

Requirements

Local LLM (vLLM/Ollama/Bifrost) or Cloud LLM API Key (Gemini, OpenAI, Claude, Groq)

Related apps

Details

Repository
ghcr.io/felixapel/book-translator-hub:latest
Last Updated2026-10-05
First Seen2026-09-08

Runtime arguments

Web UI
http://[IP]:[PORT:8080]/
Network
bridge
Shell
sh
Privileged
false
Extra Params
--restart unless-stopped

Template configuration

Appdata (Database & Cache)Pathrw

Persistent storage for SQLite translations.db and persistent caching. Requires container appuser ownership (UID 101:GID 102, e.g. chown -R 101:102 /mnt/user/appdata/book-translator-hub/data; chmod 0700).

Target
/app/data
Default
/mnt/user/appdata/book-translator-hub/data
Value
/mnt/user/appdata/book-translator-hub/data
API PortPorttcp

Direct translation API port (REST + SSE streaming)

Target
8390
Default
8390
Value
8390
Proxy PortPorttcp

Reader proxy injection port (browse CWA or Kavita through this port to get the translation overlay)

Target
8080
Default
8385
Value
8385
Runtime RoleVariable

Runtime role: all (combined API + proxy overlay on :8385 - recommended for Unraid), api (pure API mode for SWAG/master proxy), proxy (reverse proxy overlay), hub (multi-reader)

Target
BT_ROLE
Default
all
Value
all
Calibre-Web (CWA) URLVariable

URL of your Calibre-Web / CWA container (e.g. http://192.168.0.122:8383 or http://calibre-web-automated:8083)

Target
CWA_URL
Kavita URLVariable

URL of your Kavita container (e.g. http://192.168.0.122:5547 or http://kavita:5000)

Target
KAVITA_URL
LLM ProviderVariable

LLM backend provider: local (vLLM / Ollama / Bifrost), gemini, openai, anthropic, groq, deepseek, openrouter

Target
LLM_PROVIDER
Default
local
Value
local
LLM ModelVariable

Model name (e.g. gemma4-12b, qwen2.5-14b, deepseek-chat, gpt-4o-mini)

Target
LLM_MODEL
Default
gemma4-12b
Value
gemma4-12b
Local LLM URLVariable

OpenAI-compatible endpoint of your local LLM (vLLM/Ollama/Bifrost). Use host IP or host.docker.internal, NOT localhost.

Target
BT_LOCAL_URL
Default
http://192.168.0.122:2819/v1/chat/completions
Value
http://192.168.0.122:2819/v1/chat/completions
LLM API KeyVariable

API key for cloud providers (leave blank when using local LLM)

Target
LLM_API_KEY
Allowed OriginsVariable

Comma-separated allowed web origins for CORS (e.g. https://books.example.com,https://translate.example.com)

Target
BT_ALLOWED_ORIGINS
Default
http://localhost:8083,http://localhost:8383
Value
http://localhost:8083,http://localhost:8383
Auth ModeVariable

Authentication: disabled (for private LAN), token (for reverse proxy), cwa_session, reader_session

Target
BT_AUTH_MODE
Default
disabled
Value
disabled
Allow Insecure AuthVariable

Set to true to allow BT_AUTH_MODE=disabled on private LAN

Target
BT_ALLOW_INSECURE_AUTH
Default
true
Value
true
Batch SizeVariable

Paragraphs per LLM call. Higher = faster throughput on GPU models.

Target
BT_BATCH_SIZE
Default
6
Value
6
Batch Source BudgetVariable

Max input source tokens per batch group. Paragraphs exceeding this are split or processed as singletons.

Target
BT_BATCH_SOURCE_TOKEN_BUDGET
Default
1500
Value
1500
Prefetch Pacing Delay (ms)Variable

Delay in milliseconds between background lookahead prefetch requests (0 to disable pacing)

Target
BT_CLIENT_PREFETCH_GAP_MS
Default
1000
Value
1000
Max Tokens (single)Variable

Maximum token ceiling for a single paragraph request

Target
BT_MAX_TOKENS
Default
4096
Value
4096
Max Tokens (batch)Variable

Maximum token ceiling for a batched request

Target
BT_BATCH_MAX_TOKENS
Default
8192
Value
8192
Max Upstream InflightVariable

Maximum simultaneous requests sent to LLM backend (e.g. 4-8 for GPU, 1-2 for CPU)

Target
BT_MAX_UPSTREAM_INFLIGHT
Default
8
Value
8
Max ConcurrentVariable

Maximum simultaneous batch requests processed by Hub

Target
BT_MAX_CONCURRENT
Default
8
Value
8
Request Timeout (s)Variable

Timeout in seconds before an LLM request is aborted

Target
BT_TIMEOUT
Default
90
Value
90
Context WindowVariable

Surrounding paragraphs given as [CONTEXT] to LLM for literary coherence

Target
BT_CONTEXT_WINDOW
Default
1
Value
1
TimezoneVariable

Container timezone

Target
TZ
Default
Europe/Berlin
Value
Europe/Berlin