Skip to main content

Stateless web-novel translation service with switchable engines

Project description

🌐 lncrawl-translator

Translate entire web novels through one small, stateless API — tuned for Chinese · Korean · Japanese → English.

PyPI Python Docker CI License

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.

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

lncrawl_translator-0.2.2.tar.gz (157.9 kB view details)

Uploaded Source

Built Distribution

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

lncrawl_translator-0.2.2-py3-none-any.whl (190.6 kB view details)

Uploaded Python 3

File details

Details for the file lncrawl_translator-0.2.2.tar.gz.

File metadata

  • Download URL: lncrawl_translator-0.2.2.tar.gz
  • Upload date:
  • Size: 157.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/7.0.0 CPython/3.13.14

File hashes

Hashes for lncrawl_translator-0.2.2.tar.gz
Algorithm Hash digest
SHA256 f5298a6b311baa00bd49029a5eb803731445f34f40aa70b7d55174a91b89684b
MD5 b9effe048ce4b5de16bdca155d1d1b7c
BLAKE2b-256 59f2440f5afe89eaa4307ece94067d12074a6965b816830586929c48516e9b67

See more details on using hashes here.

Provenance

The following attestation bundles were made for lncrawl_translator-0.2.2.tar.gz:

Publisher: publish.yml on lncrawl/translator

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

File details

Details for the file lncrawl_translator-0.2.2-py3-none-any.whl.

File metadata

File hashes

Hashes for lncrawl_translator-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 bc69c31a29485a0d6d7beca144da50136bffa73218935cb9b40c3b6fb65d9897
MD5 fcf354fa59fa19b596b1d0e0d39a6a20
BLAKE2b-256 a1c4d2594fc7bf99e4eb05b444fffc4a9cf680cac36be43b20f3be6f6d04f33b

See more details on using hashes here.

Provenance

The following attestation bundles were made for lncrawl_translator-0.2.2-py3-none-any.whl:

Publisher: publish.yml on lncrawl/translator

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