All apps · 0 apps
book-translator-hub
Docker app from felixapel's Repository
Overview
Readme
View on GitHubBook Translator Hub
Bilingual reading overlay and translation engine for stock Calibre-Web-Automated and Kavita EPUB readers, powered by local or cloud LLMs.
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:
- 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
- Documentation map
- Universal CWA and Kavita hub
- Managed
btctlinstall - Kavita managed install
- Community Applications
- Authentik integration
- Lifecycle and recovery
- Troubleshooting
- Compatibility
- Configuration
- Architecture
🤝 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
Related apps
Explore more like this
Explore allDetails
ghcr.io/felixapel/book-translator-hub:latestRuntime arguments
- Web UI
http://[IP]:[PORT:8080]/- Network
bridge- Shell
sh- Privileged
- false
- Extra Params
--restart unless-stopped
Template configuration
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
Direct translation API port (REST + SSE streaming)
- Target
- 8390
- Default
- 8390
- Value
- 8390
Reader proxy injection port (browse CWA or Kavita through this port to get the translation overlay)
- Target
- 8080
- Default
- 8385
- Value
- 8385
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
URL of your Calibre-Web / CWA container (e.g. http://192.168.0.122:8383 or http://calibre-web-automated:8083)
- Target
- CWA_URL
URL of your Kavita container (e.g. http://192.168.0.122:5547 or http://kavita:5000)
- Target
- KAVITA_URL
LLM backend provider: local (vLLM / Ollama / Bifrost), gemini, openai, anthropic, groq, deepseek, openrouter
- Target
- LLM_PROVIDER
- Default
- local
- Value
- local
Model name (e.g. gemma4-12b, qwen2.5-14b, deepseek-chat, gpt-4o-mini)
- Target
- LLM_MODEL
- Default
- gemma4-12b
- Value
- gemma4-12b
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
API key for cloud providers (leave blank when using local LLM)
- Target
- LLM_API_KEY
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
Authentication: disabled (for private LAN), token (for reverse proxy), cwa_session, reader_session
- Target
- BT_AUTH_MODE
- Default
- disabled
- Value
- disabled
Set to true to allow BT_AUTH_MODE=disabled on private LAN
- Target
- BT_ALLOW_INSECURE_AUTH
- Default
- true
- Value
- true
Paragraphs per LLM call. Higher = faster throughput on GPU models.
- Target
- BT_BATCH_SIZE
- Default
- 6
- Value
- 6
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
Delay in milliseconds between background lookahead prefetch requests (0 to disable pacing)
- Target
- BT_CLIENT_PREFETCH_GAP_MS
- Default
- 1000
- Value
- 1000
Maximum token ceiling for a single paragraph request
- Target
- BT_MAX_TOKENS
- Default
- 4096
- Value
- 4096
Maximum token ceiling for a batched request
- Target
- BT_BATCH_MAX_TOKENS
- Default
- 8192
- Value
- 8192
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
Maximum simultaneous batch requests processed by Hub
- Target
- BT_MAX_CONCURRENT
- Default
- 8
- Value
- 8
Timeout in seconds before an LLM request is aborted
- Target
- BT_TIMEOUT
- Default
- 90
- Value
- 90
Surrounding paragraphs given as [CONTEXT] to LLM for literary coherence
- Target
- BT_CONTEXT_WINDOW
- Default
- 1
- Value
- 1
Container timezone
- Target
- TZ
- Default
- Europe/Berlin
- Value
- Europe/Berlin