docs: describe both translation seams and the merged dictionary order
This commit is contained in:
parent
68a7fc608d
commit
b865825c51
1 changed files with 35 additions and 22 deletions
57
README.md
57
README.md
|
|
@ -2,23 +2,29 @@
|
|||
|
||||
> Renders Chinese UI text in [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) third-party plugins as English.
|
||||
|
||||
Most community plugins ship hardcoded Chinese inside their client bundles. Those
|
||||
strings never reach DSH's locale dictionaries, so they stay Chinese even when the
|
||||
interface language is English. This plugin translates them at the transport
|
||||
layer, before any of that code runs.
|
||||
Most community plugins ship hardcoded Chinese, and the interface language setting
|
||||
does not reach it. This plugin rewrites that text server-side, before any of it
|
||||
reaches the browser.
|
||||
|
||||
---
|
||||
|
||||
## How it works
|
||||
|
||||
Plugin bundles are served by DSH's `clientModules` service over `/plugins/...`.
|
||||
This plugin wraps `clientModules.bundleResource`, decodes each JavaScript
|
||||
response, rewrites the Chinese string literals it can translate, and returns the
|
||||
result. Because interception happens server-side, it covers every plugin at once,
|
||||
including combination bundles that carry dozens of them, and it runs before any
|
||||
plugin code is evaluated.
|
||||
The text arrives by two routes, so there are two seams.
|
||||
|
||||
Two deliberate choices:
|
||||
**Plugin bundles.** `clientModules` serves every plugin bundle over
|
||||
`/plugins/...`. Wrapping `clientModules.bundleResource` decodes each JavaScript
|
||||
response, rewrites the Chinese string literals it can translate, and returns the
|
||||
result. One interception covers every plugin, including combination bundles that
|
||||
carry dozens, and it runs before any plugin code is evaluated.
|
||||
|
||||
**API copy.** Plugin descriptors, model and provider names, and settings
|
||||
descriptions never appear in bundles at all: they reach the browser as JSON over
|
||||
`/api`. The gateway resolves its own `dispatchRpc` per request, so overriding
|
||||
that instance method intercepts those responses without claiming the interceptor
|
||||
slot the gateway already owns.
|
||||
|
||||
Three deliberate choices:
|
||||
|
||||
- **All-or-nothing literals.** Chinese has no word boundaries, so replacing known
|
||||
words wherever they appear corrupts larger words (`当前工作区` would become
|
||||
|
|
@ -28,6 +34,13 @@ Two deliberate choices:
|
|||
- **A compile gate.** Each rewritten bundle is parsed with `new Function` before
|
||||
it is served. If a rewrite ever produced invalid JavaScript, the original bytes
|
||||
are served instead, so a bad dictionary entry cannot break the UI.
|
||||
- **An endpoint allowlist.** Only endpoints returning server-authored copy are
|
||||
rewritten. `/api/session/list`, for example, returns your own prompts and
|
||||
transcripts, and is left untouched.
|
||||
|
||||
Where an author already wrote English, that English is used rather than the
|
||||
dictionary: locale maps (`{ zh, en }`) resolve to the English sibling, and
|
||||
bilingual descriptors joined by ` · ` keep their English half.
|
||||
|
||||
The client half does one thing: it selects the `en` locale through
|
||||
`ctx.locale.setLocale`, which persists the preference. It never touches the DOM.
|
||||
|
|
@ -36,17 +49,15 @@ The client half does one thing: it selects the `en` locale through
|
|||
|
||||
## What it does not cover
|
||||
|
||||
Translation works on string literals inside served bundles. Text that arrives
|
||||
another way stays as it is:
|
||||
- Text rendered inside an `<img>`, canvas, or other non-text payload.
|
||||
- Content fetched from a third-party server at runtime (announcements, remote
|
||||
catalogs) rather than from DSH itself.
|
||||
- The long tail of one-off strings the dictionary does not yet cover.
|
||||
|
||||
- Plugin **descriptors** in `package.json` and `README.md` files (marketplace
|
||||
listings, plugin titles).
|
||||
- **Server-side API prose** that is fetched as JSON at runtime.
|
||||
- The long tail of one-off literals that the dictionary does not yet cover.
|
||||
The shipped dictionary holds roughly 1,570 entries. Coverage is concentrated on
|
||||
strings that appear repeatedly; rare one-off sentences are usually left in
|
||||
Chinese, which is why the all-or-nothing rule matters.
|
||||
|
||||
The shipped dictionary holds roughly 1,200 entries and covers about 45% of the
|
||||
Chinese literals in a typical plugin set. Coverage is concentrated on strings
|
||||
that appear repeatedly; rare one-off sentences are usually left in Chinese.
|
||||
|
||||
---
|
||||
|
||||
|
|
@ -70,11 +81,13 @@ npm run dict # rebuild src/dictionary.json from its sources
|
|||
npm run build # bundle the server and client halves into lib/
|
||||
```
|
||||
|
||||
Dictionary sources, merged in this order:
|
||||
Dictionary sources, merged in this order (later wins):
|
||||
|
||||
1. `dshmarket_dict.json` — harvested pairs.
|
||||
2. `UI_TRANSLATIONS` in `patch-plugins.py` — harvested pairs.
|
||||
3. `src/dictionary.extra.json` — curated entries, merged last so they win.
|
||||
3. `src/dictionary.extra.json` — curated entries.
|
||||
4. `locale-pairs.json` — author-written `{ zh, en }` pairs lifted from plugin
|
||||
locale maps; highest quality, so it overrides everything above.
|
||||
|
||||
Add or fix translations in `src/dictionary.extra.json`, then run
|
||||
`npm run dict && npm run build`.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue