dsh-auto-translate
English | 中文
Full-pipeline Chinese translation for the DeepSeek Harness Web GUI. When the model is thinking (the Think disclosure), writing its final reply, or producing tool output, English content gets a Chinese rendering in place — translated live while the model is still streaming. Every translation is a standalone provider request that never enters the session transcript: no context window cost, no conversation-history pollution.
> Install (one command): > `` > dsh plugin add qwert702/dsh-auto-translate > ` > Restart the harness (dsh web`) and refresh the page.
Features
- Live reasoning translation — inside each Think disclosure row, the
expanded body shows the original thinking text followed by a Chinese translation; while the model is still reasoning the translation updates on a debounced cadence, and once the step settles the full text is translated once and cached.
- Inline reply translation — every English text block gets a small
Chinese line (with a 译 badge) directly beneath it. Chinese replies and code-dominated output are skipped heuristically.
- Tool-output summaries — for every settled tool call, a line
tool — 中文含义 plus a 译 summary renders at the end of the turn after the tool card sequence, summarizing the tool's text output in Chinese (a summary, not a line-by-line translation of raw output). The summary lives at the turn tail instead of inside the card because the chat view has no additive seat inside a tool card, and the tool-call renderer cannot be shadowed without losing the dedicated tool views (bash / web / read …) — see below.
- Zero context cost — translation and summary requests are standalone
provider /chat/completions calls made by the node half, fully outside the agent loop; the plugin adds no prompts, tools, or messages to any conversation and never rewrites a model request.
- Configurable model — defaults to the current conversation's model; an
override can be set in settings. When the conversation model id is unknown to the provider, the host retries once with deepseek-chat.
How it works (shadow rendering, no slot replacement)
The chat view has no additive seat inside a message, so the plugin uses the ecosystem's shadow registration technique: it registers the assistant-step renderer on conversation.chat.node at priority: -100, which shadows the harness's priority: 0 default and owns the in-place reasoning and reply translations. The renderer rebuilds the default presentation from public primitives (MarkdownText / DisclosureRow / JsonBlock from dsh-client-ui-primitives, ImageGallery from dsh-client-ui-attachment) — the same approach as the dsh-better-markdown plugin.
The tool-call node is deliberately NOT shadowed: its default renderer owns the sole declaration of the tool.call.toolview child slot (slot declarations are globally unique), so shadowing it either loses the dedicated tool views (bash / web / read …) or throws a duplicate-declaration error at startup. Tool summaries therefore ride the additive conversation.chat.turnTail chain seat, rendered after the turn's tool cards.
If a shadow renderer crashes it abdicates and the harness default takes over transparently.
Settings (optional)
Add a dsh-auto-translate namespace to ~/.dsh/settings.yaml:
dsh-auto-translate:
enabled: true # master switch
model: '' # '' = follow the current conversation's model; or e.g. deepseek-chat / deepseek-reasoner
apiKeyRef: DEEPSEEK_API_KEY # credential reference resolved by the harness credentials service
baseURL: https://api.deepseek.com
temperature: 0.3 # sampling temperature for translation requests
maxInputChars: 4000 # input truncation guardAll fields default as above. The API key stays server-side — it is resolved through the harness credentials service and never leaves the host.
Repo layout
lib/index.js— node half: settings namespace +POST /api/auto-translate/translateroute (standalone translate/summarize requests,mode: translate | summarize, with a model fallback).lib/client.js— browser half: theassistant-stepshadow registration (priority: -100, in-place reasoning/reply translations) plus the additiveconversation.chat.turnTailchain entry (tool-output summaries).test/smoke.cjs—node test/smoke.cjs: syntax checks, host route paths (disabled / bad-request / empty / no-key / ok / summarize / model-fallback), client registration assertions, and ReactDOMServer renders (thinking / text / streaming / tool summary).
Known limitations
- Conflicts with dsh-better-markdown — both shadow
assistant-stepat
priority: -100; installing both throws a duplicate-key error at startup. Install one; to coexist, change one side's priority.
- Tool summaries live at the turn tail, not inside cards — the chat view
has no additive seat inside a tool card and the tool-call renderer cannot be shadowed without losing the dedicated tool views, so summaries render after the turn's tool card sequence.
- Owns the default rendering — shadowing means the thinking/text block
presentation is maintained by this plugin; a dsh upgrade that changes the internal rendering may need an adaptation (a crash abdicates to the harness default, so nothing breaks silently).
- Streaming translations are provisional — while output is still
streaming, the translation reflects the text seen so far and updates on a debounced cadence; when output stops it is re-translated from the full text.
- Tool summaries cover text blocks only — images and binary output are
not translated; long outputs are truncated (maxInputChars) first.
- Heuristics — replies shorter than ~10 letters, CJK/latin mixed text,
and code-dominated output are not translated (isEnglishProse / isMostlyCode in lib/client.js).
- Cache — translations are cached in browser memory per node/call
identity; a page refresh re-requests the same content.
- Settings UI — configured through
settings.yaml; no settings panel yet.
License
MIT