Document the translator WebSocket API and reference client

This commit is contained in:
2026-09-02 03:30:36 +00:00
parent 2f78877f15
commit f6eef1c75f
3 changed files with 42 additions and 14 deletions
+30 -6
View File
@@ -210,14 +210,38 @@ def get_translation(path, lang, data) -> Translation | None:
updates `Data.chunks` / `node.chunks` — only genuinely new text lands in
the kanta change diff (see docs/migrate.md).
### Translator service API
An external machine-translation service connects over WebSocket at
`/_translate/{key}` — deliberately **not** under `/_api`: the SSO
forward-auth does not cover that route, and the key in the path is the
access control. The key is `Data.translate_key`, generated once at startup
and surfaced to the admin in `GET /_api/settings` as `translate_key`. A
wrong or empty key rejects the handshake (close-before-accept → HTTP 403).
Frames are JSON-encoded tagged msgspec structs (`pagerite/translate.py`;
`bytes` fields ride as base64):
- `{"type": "hello", "langs": [...]}` — client greeting: the target
languages it handles (normalized to base subtags; `en`/empty dropped).
- `{"type": "job", "lang", "items": [{key, text, path, kind}]}` — server
push: pending fragments (article titles and chunks), deduped by key.
- `{"type": "result", "lang", "items": [{key, text}]}` — client reply:
translated fragments, matched to content by chunk key alone.
The model is **push**, not polling: on `hello` the server sends everything
pending per announced language; afterwards `_invalidate_pages()` (called by
every content/translation write) schedules a delta push of newly pending
items. Outstanding-item tracking is per connection, so a reconnecting client
simply re-receives everything still pending. Results are stored into `trans`
in one transaction and set `node.langs[lang]` on every article they touch
(shared chunks make several pages gain a language from one fragment).
### Explicitly out of scope for phase 2
- The machine translation itself: chunking output goes in, translated chunks
come back. The **service API exists**`GET /_api/translate/{lang}` lists
pending items (`{"key", "text", "path", "kind"}`, key = base64 chunk hash),
`POST /_api/translate/{lang}` stores a batch (`{"items": [{key, text}]}`)
into `trans` and maintains `node.langs`; an external service does the
actual translating (gated by the /_api forward-auth like everything else).
- The machine translation itself: the API above moves fragments in and out;
the translating is external. `scripts/translator.py` is the reference
client (Seed-X-PPO-7B only — its 28 languages are the ceiling).
- Garbage collection of orphaned chunks/translations (see docs/migrate.md).
- sitemap.xml per-language entries; translated UI chrome; per-language
typographer options; multi-locale date/number formatting.