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.
|
> 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
|
Most community plugins ship hardcoded Chinese, and the interface language setting
|
||||||
strings never reach DSH's locale dictionaries, so they stay Chinese even when the
|
does not reach it. This plugin rewrites that text server-side, before any of it
|
||||||
interface language is English. This plugin translates them at the transport
|
reaches the browser.
|
||||||
layer, before any of that code runs.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## How it works
|
## How it works
|
||||||
|
|
||||||
Plugin bundles are served by DSH's `clientModules` service over `/plugins/...`.
|
The text arrives by two routes, so there are two seams.
|
||||||
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.
|
|
||||||
|
|
||||||
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
|
- **All-or-nothing literals.** Chinese has no word boundaries, so replacing known
|
||||||
words wherever they appear corrupts larger words (`当前工作区` would become
|
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
|
- **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
|
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.
|
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
|
The client half does one thing: it selects the `en` locale through
|
||||||
`ctx.locale.setLocale`, which persists the preference. It never touches the DOM.
|
`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
|
## What it does not cover
|
||||||
|
|
||||||
Translation works on string literals inside served bundles. Text that arrives
|
- Text rendered inside an `<img>`, canvas, or other non-text payload.
|
||||||
another way stays as it is:
|
- 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
|
The shipped dictionary holds roughly 1,570 entries. Coverage is concentrated on
|
||||||
listings, plugin titles).
|
strings that appear repeatedly; rare one-off sentences are usually left in
|
||||||
- **Server-side API prose** that is fetched as JSON at runtime.
|
Chinese, which is why the all-or-nothing rule matters.
|
||||||
- The long tail of one-off literals that the dictionary does not yet cover.
|
|
||||||
|
|
||||||
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/
|
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.
|
1. `dshmarket_dict.json` — harvested pairs.
|
||||||
2. `UI_TRANSLATIONS` in `patch-plugins.py` — 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
|
Add or fix translations in `src/dictionary.extra.json`, then run
|
||||||
`npm run dict && npm run build`.
|
`npm run dict && npm run build`.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue