🌐 lncrawl-translator
Translate entire web novels through one small, stateless API — tuned for Chinese · Korean · Japanese → English.
A translation service for web-novel metadata (titles, author, synopsis, tags) and HTML chapter content — markup preserved, only human-readable text translated. Run it as a standalone container or embed it as a Python library inside your own app.
Built as the stateless translation engine behind lightnovel-crawler, with switchable engines (free-tier hosted APIs and CPU-friendly local models). Every request can carry a per-novel glossary that gets injected into translations and returned with any new terms — so the caller keeps names and terms consistent across thousands of chapters.
✨ Highlights
| 🈶 CJK → English first | Purpose-tuned for Chinese/Korean/Japanese source text; other directions work best-effort. |
| 🧾 Text and HTML | Batch short strings, or translate a whole chapter's HTML with tags kept intact. |
| 📖 Glossary-aware | Pass a glossary in, get new terms out — consistent character/place names at book scale. |
| 🔀 Switchable engines | OpenAI-compatible LLMs, DeepL, Baidu, and a keyless Bing lane behind one router. |
| ♻️ Resilient routing | Client-side rate limiting, retries, cooldowns, and quota-aware failover across lanes. |
| 🎛️ Live config | Browser dashboard + CRUD API; edits apply atomically and persist to a sparse YAML overlay. |
| 🧭 Offline detection | Unicode-script heuristics + langdetect — no network, no engine quota. |
| 🧩 Standalone or embedded | Docker/uvicorn service, or a thread-safe synchronous Python facade. |
🚀 Quick start
No config file needed — a curated set of free providers is pre-wired, and the keyless Bing lane is the default, so translation works even with zero keys:
docker compose up -d
curl http://localhost:8184/health # shows which engines came up
Then open http://localhost:8184/ and paste your provider API keys — the matching engines enable instantly, no restart needed.
📚 See the deployment guide for engine keys, the keyless Bing lane, and API examples · design doc for API & architecture · engine research.
🔌 API
| Endpoint | What it does |
|---|---|
GET / |
Browser demo & config UI — try translations, watch engine status, manage config in place. |
GET /health |
Liveness / readiness. |
GET /engines |
Configured engines with live status (quota, cooldowns). |
POST /detect |
Local language detection (no engine quota). |
POST /translate/text |
Batched short strings (titles, tags, synopsis). |
POST /translate/html |
One chapter per call — glossary in, new terms out. |
GET /config + CRUD on /providers, /engines, /routing |
Runtime config; changes apply atomically and persist to config.yml. |
⚠️ The API is unauthenticated by design — run it on localhost or a private network only (see the deployment guide).
📦 Use as a library
pip install lncrawl-translator # Python 3.9+
The embedded service is a thread-safe, synchronous facade that runs the same engine router on its own event loop:
from translator import TranslatorService
service = TranslatorService(config_path="translator.yml")
service.detect(["どこから来ましたか"]) # local, no quota
response = service.translate_text({
"texts": ["少年は勇者になった"],
"target_lang": "en",
"glossary": {"勇者": "Hero"},
})
print(response.translations, response.engine, response.new_terms)
service.close() # on shutdown
translate_text / translate_html accept an optional signal (threading.Event) for
cooperative cancellation and a timeout in seconds.
Error handling. Failures share a common TranslatorError base, re-exported from the
top-level namespace — map them without importing pydantic or reaching into internals:
from translator import TranslatorError, ApiError, AbortedError, InvalidRequestError
Invalid dict payloads raise InvalidRequestError (not pydantic's ValidationError). Need
only a language code? from translator import detect_code returns the bare ISO 639-1 code
(or None) without ever constructing a service; detect_language is also available.
Mount the dashboard into a host app
app.mount("/translator", service.create_app())
The mounted app shares the service's live config — edits in the dashboard apply to the embedded service immediately. It carries no authentication of its own; the host gates access.
When the host authenticates the mount, pass create_app(auth=True): the OpenAPI then
declares HTTPBasic and HTTPBearer schemes (so the docs' Authorize button works), and
the dashboard reads an admin token from the page's URL fragment (#token=…) and sends it
as a Bearer header. The schemes are only declared here — the host still verifies the
credential.
🛠️ Development
uv sync
uv run poe check # ruff + mypy + pytest
uv run poe dev # dev server with auto-reload
uv run poe start # production-style server (uvicorn on :8184)
uv run poe live-test # smoke-test real engines from config.yml (opt-in)
See AGENTS.md for project decisions and conventions, and CHANGELOG.md for release notes.
📜 License
Licensed under the Apache License 2.0.
Release files for lncrawl-translator 0.2.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| lncrawl_translator-0.2.2.tar.gz | 157.9 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| lncrawl_translator-0.2.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 348.5 kB
Release files / lncrawl_translator-0.2.2.tar.gz
| Download URL | lncrawl_translator-0.2.2.tar.gz |
|---|---|
| Size | 157.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f5298a6b311baa00bd49029a5eb803731445f34f40aa70b7d55174a91b89684b
|
|
BLAKE2b-256 checksum How to use checksums |
59f2440f5afe89eaa4307ece94067d12074a6965b816830586929c48516e9b67
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.
Transparency logRelease files / lncrawl_translator-0.2.2-py3-none-any.whl
| Download URL | lncrawl_translator-0.2.2-py3-none-any.whl |
|---|---|
| Size | 190.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
bc69c31a29485a0d6d7beca144da50136bffa73218935cb9b40c3b6fb65d9897
|
|
BLAKE2b-256 checksum How to use checksums |
a1c4d2594fc7bf99e4eb05b444fffc4a9cf680cac36be43b20f3be6f6d04f33b
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Jul 31, 2026.
Transparency log