All apps · 0 apps
book-translator-hub
Docker app from felixapel's Repository
Overview
Readme
View on GitHubBook Translator Hub
Universal, zero-wait bilingual reading overlay and translation engine for Calibre-Web, Kavita, and self-hosted ebook libraries powered by local or cloud LLMs.
✨ What it does
- Real-Time Token Streaming (SSE): Translates the first visible paragraph with Server-Sent Events (SSE), streaming words into the reader DOM in ~160ms as the LLM generates them.
- Instant Viewport Rush: Concurrently translates paragraphs 1, 2, and 3 in parallel micro-batches via Continuous Batching on local GPU (vLLM) or cloud providers.
- Zero-Wait Directional Lookahead: Intelligently pre-translates upcoming pages along the reader's directional trajectory for an instantaneous 0ms page-turn experience.
- High-Capacity IndexedDB Cache: Stores thousands of translated paragraphs offline directly in the browser (
BookTranslatorDB), bypassing standard 5MBlocalStoragelimitations. - High-Throughput SQLite WAL Engine: Server-side cache tuned with 256MB memory-mapping (
mmap_size) and 64MB RAM page cache for sub-millisecond (<0.5ms) lookups. - Dedicated E-Ink Mode: 1-bit high-contrast layout without animations, blurring, or drop shadows, perfectly optimized for e-readers (Kindle, Kobo, Onyx Boox).
- Universal Multi-Reader Support: Seamless native integration with stock Calibre-Web-Automated and pinned Kavita EPUB readers without altering either upstream image.
- Zero-Trust Privacy & Security: Keeps all LLM API tokens and server endpoints strictly isolated on the internal network; no client-side credential leakage.
🚀 Supported installation
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
git switch --detach v2.4.0
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 template defaults to Google's stable, low-latency Gemini model; add a server-side Google AI Studio or project API key and leave the local URL empty:
BT_ENABLE_CWA=true
BT_ENABLE_KAVITA=true
LLM_PROVIDER=gemini
LLM_MODEL=gemini-3.5-flash-lite
LLM_API_KEY=<Google AI Studio or project API key>
BT_LOCAL_URL=
BT_BATCH_SIZE=10
BT_BATCH_SOURCE_TOKEN_BUDGET=450
BT_BATCH_MAX_TOKENS=1200
BT_CLIENT_PREFETCH_GAP_MS=1000
BT_MAX_BATCH_PARAGRAPHS=50
Named providers use their fixed HTTPS API endpoints. Local and custom OpenAI-compatible backends are also supported through environment variables; they are optional, not required fallbacks. 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 is the current stable release target. The stock Kavita v0.9.0.2 EPUB connector is contract- and CI-certified in this checkout, but remains a candidate until physical Unraid and real-reader browser acceptance is recorded. Manga, PDF and library writeback are not supported.
⚡ High-Throughput Batching & Model Optimization
Empirical benchmarking across large language models has established optimal token economics for paragraph translation:
| Backend / Model | Avg Latency (20 paragraphs) | Parser Pass Rate | Recommended Batch Size |
|---|---|---|---|
Groq (openai/gpt-oss-120b) |
1.03s | 100% | 20 |
Local vLLM (gemma4-12b) |
2.34s | 100% | 20 |
Gemini (gemini-3.5-flash-lite) |
0.61s - 3.5s | 100% | 20 |
SQLite High-Concurrency WAL Engine
To eliminate database contention under concurrent batch reading, the SQLite cache runs in Write-Ahead Logging (WAL) mode:
PRAGMA journal_mode = WAL;
PRAGMA synchronous = NORMAL;
PRAGMA busy_timeout = 5000;
Response latency on cached paragraphs drops to < 0.5ms.
💖 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.
Install book-translator-hub on Unraid in a few clicks.
Find book-translator-hub in Community Apps on your Unraid server, review the template, and click Install. Unraid handles the Docker app or plugin setup from the published template.
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
- 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: api (pure API mode), proxy (reverse proxy overlay), all (combined API + proxy), hub (multi-reader)
- Target
- BT_ROLE
- Default
- api
- Value
- api
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. http://192.168.0.122:8383,https://books.example.com)
- Target
- BT_ALLOWED_ORIGINS
- Default
- *
- Value
- *
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
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