前言¶
DSH 的會話界面裏,中文提問和中文回答都在同一屏顯示。做雙語閱讀練習的人常見的做法是把整段文本複製出去再翻譯,或者開另一個翻譯窗口逐句對照,過程中原文容易被覆蓋、也容易對錯行。實際翻譯時還有一個問題:整條消息一次性送翻譯,長回答不僅慢,還會把代碼塊一起改掉。
下面介紹的插件處理的正是這個問題。它由 SCUklr 維護,在社區目錄的「聯網工具」分類下,包名 @local/dsh-bilingual-helper,倉庫地址見文末。它的形態是 DSH bundle plugin:在每個提問和每個回答下方各加一個 EN 按鈕,點一下就在原消息下方展開該條消息的完整英文翻譯,再點一次收起,原文不動。
它解決什麼問題¶
定位一句話:給 DSH 會話加一層「按需展開」的中英對照面板,翻譯只針對當前這條消息,而不是整個會話或整篇導出。
目前已覈實的行爲:
- 中文提問下方、中文回答下方出現
EN 英文翻譯按鈕;已經是英文的消息不出現按鈕(沒有可翻譯內容)。 - 每行獨立展開、獨立緩存,摺疊後再展開是瞬時的,不會重複請求。
- 代碼塊(``` 圍起來的部分)原樣保留、不送翻譯,只翻正文。
- 長消息自動切塊,逐塊翻譯後再按原文順序拼回。
- 深色 / 淺色主題自動適配,只用主題 token。
- 網絡或服務錯誤時在面板內以紅色文案顯示,按鈕變爲「重試」,不會靜默失敗。
翻譯從哪來¶
點擊按鈕時,該消息正文發給 DSH 內置的翻譯服務(ctx.translator),返回純文本譯文。默認走 deepseek-official 付費路由:deepseek-flash 模型、thinking 關閉、單條文本、固定直譯提示詞(無對話歷史、無工具),按輸入 / 輸出 token 計費。README 給出的量級是約 0.5–1.5 分 / 條,具體見 DeepSeek 定價頁。
這個路由有兩個約束:
- 必須攜帶當前會話 id。瀏覽器半邊從 Chat 節點的標準 props 裏讀取
sessionId,隨請求一起發給 Host 半邊。 - 會話必須處於活躍狀態。歷史或已歸檔會話裏點擊會失敗,面板顯示
TRANSLATION_SESSION_INACTIVE之類的錯誤,需要回到活躍會話再點。
隱私方面:點擊按鈕等於把該消息正文發送給 DeepSeek;不點擊就不發送任何內容。
如果想回到不花錢的路線,把 cordis.patch.yml(以及 profile 裏 cordis.patch.yml 的覆蓋行)中兩處 provider: deepseek-official 改成 bing 或 google。匿名接口不消耗 token、不需要會話 id,但譯文質量是 NMT 直譯。
啓用與使用¶
插件的目錄目前在 ~/Agent&AI_dev/dsh-plugins/en-translation,profile 只保存一個 link: 依賴和一條 node_modules 軟鏈。README 未給出獨立的安裝命令,安裝路徑是 profile 裏的 link: 依賴註冊,包名爲 @local/dsh-bilingual-helper。
啓用步驟:
- 在 Settings → Plugins 中確認
@local/dsh-bilingual-helper已列出並啓用。 - 無需重啓,裝好後瀏覽器頁面會自動加載。目錄在含
&的路徑下(Agent&AI_dev),shell 裏操作記得加引號。 - 打開任意活躍會話,點提問或回答下方的
EN 英文翻譯;點「收起翻譯」摺疊;點「重試」重新請求。
配置項在 cordis.patch.yml 中本插件行的 config:
config:
targetLanguage: en # 目標語言,BCP 47,如 en、ja
provider: deepseek-official # 付費路由;也可改 bing / google 走匿名 NMT
換 provider 時兩處都要改(bundle 配置和 profile 覆蓋行),否則實際生效的可能仍是緩存的舊配置。
目錄結構與調用方式¶
倉庫很小,主要文件職責如下:
dsh-plugins/en-translation/
├── package.json bundle 清單:dsh.bundle.patch + dsh.client(web, immediately)
├── cordis.patch.yml 插入兩行:translator(內置翻譯服務)+ 本插件
├── index.js Host 半邊:在同源 Web 上註冊 /dsh-en-translation/* 路由
├── client.js 瀏覽器半邊:Chat 行定義 + 渲染器 + 按鈕 UI
├── locale/{zh,en}.json 插件面板裏的標題與說明
└── icon.svg 原創圖標
行從哪來:瀏覽器半邊註冊兩個 Conversation Definition(en-translation-question 匹配 user/message,en-translation-answer 匹配 assistant/message),各自發布 kind: "en-translation" 的 Chat Node,錨在該消息自己的 seq 上,因此行落在消息正下方。
橋接部分值得說幾句,因爲 bundle 的瀏覽器半邊不能直接調用 Host 服務,也沒有 host.call。Host 半邊改用 ctx.webServer 註冊同源 JSON 端點,瀏覽器只做 fetch:
GET /dsh-en-translation/health → 翻譯服務是否可用、可用 provider
POST /dsh-en-translation/translate {text, sessionId?} → {ok, translation, chunks, elapsedMs}
POST /dsh-en-translation/debug → 僅開發用,DEBUG=true 時把診斷寫進系統臨時目錄
譯文按會話持久化,同一會話內同一段文本重複展開不再請求;頁面內存裏另有一份緩存,最多 200 條。
已知限制¶
這些限制來自 README,先看再決定要不要開付費路由:
- 付費路由比匿名 NMT 慢:實測 270 字約 1.5 s、800 字約 3 s、接近 3000 字的單塊約 10–20 s。超長回答會被切成多塊串行翻譯,前端總超時 90 s,極長消息可能失敗,面板會提示原因。
- 付費路由綁定活躍會話,歷史 / 已歸檔會話裏點翻譯會失敗。
- 切到付費路由後每條新消息都會消耗 token(同一會話內重複展開命中緩存則免費),會話日誌裏會新增
plugin:translator/request|result記錄。 - 機器翻譯會改寫 Markdown 排版與專有名詞;原文始終保留在上方,可對照閱讀。
- 一條回覆如果分多個 assistant 消息(多步工具調用),中文的每一步都有自己的按鈕。
- 翻譯結果不落盤、不跨頁面持久化,刷新頁面後需重新點一次。
搬遷與重裝¶
兩條來自 README 的注意點:
- 目錄移動後必須重新安裝並更新鏈接,profile 只保存一個
link:依賴和一條node_modules軟鏈。 dsh-client-modules會把「Loader 行名 + 根目錄」對應的包元數據緩存到進程重啓爲止(sourceKey = baseUrl + '\0' + loaderName)。所以「刪掉同名包 → 原地改名或換路徑重裝」時,前端會靜默不加載,而 Host 半邊正常。解決辦法二選一:裝機時換一個新包名(當前做法是@local/dsh-bilingual-helper),或者重啓 DSH 應用。原地改文件內容、路徑不變則不受影響。
適合誰¶
適合在 DSH 會話裏做中英對照閱讀、需要按句子覈對譯文、又不想離開聊天界面的人。插件以當前 DSH 進程的權限運行,並在點擊時把消息正文發送給翻譯服務方,安裝前應先讀一遍源碼和許可證(MIT,© 2026 SCUklr),再決定是否信任這條數據通路。
倉庫:https://github.com/SCUklr/dsh-bilingual-helper
目錄頁:https://www.skillhub.cn/plugins/SCUklr/dsh-bilingual-helper