@keith9681/dsh-sidebar 0.15.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (220) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +0 -0
  3. package/README_EN.md +0 -0
  4. package/cordis.patch.yml +49 -0
  5. package/lib/client-editor.js +34651 -0
  6. package/lib/client-mermaid.js +200629 -0
  7. package/lib/client-registry.js +13388 -0
  8. package/lib/client-terminal.js +8904 -0
  9. package/lib/client.js +13388 -0
  10. package/lib/index.js +3959 -0
  11. package/lib/invariant.js +22 -0
  12. package/lib/types/agent-pty.d.ts +226 -0
  13. package/lib/types/browser-probe.d.ts +15 -0
  14. package/lib/types/bundle-route.d.ts +12 -0
  15. package/lib/types/client/BrowserView.d.ts +22 -0
  16. package/lib/types/client/DiffTab.d.ts +6 -0
  17. package/lib/types/client/DiffView.d.ts +51 -0
  18. package/lib/types/client/EditorHost.d.ts +12 -0
  19. package/lib/types/client/FileTree.d.ts +36 -0
  20. package/lib/types/client/GitView.d.ts +8 -0
  21. package/lib/types/client/OrphanedTab.d.ts +11 -0
  22. package/lib/types/client/PdfView.d.ts +6 -0
  23. package/lib/types/client/RenderBoundary.d.ts +32 -0
  24. package/lib/types/client/SandboxStatusBar.d.ts +10 -0
  25. package/lib/types/client/SideCardSection.d.ts +74 -0
  26. package/lib/types/client/SideChatView.d.ts +16 -0
  27. package/lib/types/client/Sidebar.d.ts +6 -0
  28. package/lib/types/client/SubagentView.d.ts +16 -0
  29. package/lib/types/client/TabBar.d.ts +43 -0
  30. package/lib/types/client/TerminalView.d.ts +24 -0
  31. package/lib/types/client/TextEditor.d.ts +10 -0
  32. package/lib/types/client/TreePanel.d.ts +23 -0
  33. package/lib/types/client/UploadOverlay.d.ts +20 -0
  34. package/lib/types/client/add-plugin-modal.d.ts +15 -0
  35. package/lib/types/client/api.d.ts +268 -0
  36. package/lib/types/client/binary-download.d.ts +12 -0
  37. package/lib/types/client/breakpoints.d.ts +12 -0
  38. package/lib/types/client/browser.d.ts +50 -0
  39. package/lib/types/client/builtins/index.d.ts +18 -0
  40. package/lib/types/client/builtins/tabs.d.ts +11 -0
  41. package/lib/types/client/builtins/viewers.d.ts +3 -0
  42. package/lib/types/client/chunk-loader.d.ts +124 -0
  43. package/lib/types/client/chunks/editor.d.ts +9 -0
  44. package/lib/types/client/chunks/mermaid.d.ts +10 -0
  45. package/lib/types/client/chunks/terminal.d.ts +9 -0
  46. package/lib/types/client/cm-themes.d.ts +24 -0
  47. package/lib/types/client/conversation-draft.d.ts +14 -0
  48. package/lib/types/client/desktop-env.d.ts +35 -0
  49. package/lib/types/client/editable-state.d.ts +27 -0
  50. package/lib/types/client/editor-load.d.ts +66 -0
  51. package/lib/types/client/frame-batcher.d.ts +24 -0
  52. package/lib/types/client/icons.d.ts +57 -0
  53. package/lib/types/client/image-types.d.ts +3 -0
  54. package/lib/types/client/ime-guard.d.ts +36 -0
  55. package/lib/types/client/index.d.ts +19 -0
  56. package/lib/types/client/intercept.d.ts +33 -0
  57. package/lib/types/client/lang.d.ts +12 -0
  58. package/lib/types/client/lazy-chunk.d.ts +25 -0
  59. package/lib/types/client/link-intercept.d.ts +42 -0
  60. package/lib/types/client/locales.d.ts +366 -0
  61. package/lib/types/client/mermaid-blocks.d.ts +41 -0
  62. package/lib/types/client/mermaid-sanitize.d.ts +2 -0
  63. package/lib/types/client/mermaid.d.ts +12 -0
  64. package/lib/types/client/open-when-sized.d.ts +20 -0
  65. package/lib/types/client/open-with-settings.d.ts +4 -0
  66. package/lib/types/client/open-with.d.ts +87 -0
  67. package/lib/types/client/openpath-intercept.d.ts +41 -0
  68. package/lib/types/client/paths.d.ts +35 -0
  69. package/lib/types/client/pdf-types.d.ts +2 -0
  70. package/lib/types/client/plugin-settings.d.ts +8 -0
  71. package/lib/types/client/plugins-shared.d.ts +27 -0
  72. package/lib/types/client/plugins-tabs.d.ts +3 -0
  73. package/lib/types/client/plugins-viewers.d.ts +3 -0
  74. package/lib/types/client/prefs.d.ts +41 -0
  75. package/lib/types/client/produced-files.d.ts +23 -0
  76. package/lib/types/client/selection-payload.d.ts +27 -0
  77. package/lib/types/client/service.d.ts +440 -0
  78. package/lib/types/client/settings-nav-icon.d.ts +19 -0
  79. package/lib/types/client/shell-presets.d.ts +48 -0
  80. package/lib/types/client/sidechat-transcript.d.ts +103 -0
  81. package/lib/types/client/split-pane.d.ts +30 -0
  82. package/lib/types/client/state.d.ts +359 -0
  83. package/lib/types/client/subagent-detect.d.ts +54 -0
  84. package/lib/types/client/subagent-jobs.d.ts +63 -0
  85. package/lib/types/client/tab-content-memo.d.ts +33 -0
  86. package/lib/types/client/terminal-font.d.ts +20 -0
  87. package/lib/types/client/theme.d.ts +45 -0
  88. package/lib/types/client/titlebar-strip.d.ts +23 -0
  89. package/lib/types/client/upload.d.ts +69 -0
  90. package/lib/types/client/wco.d.ts +47 -0
  91. package/lib/types/config.d.ts +64 -0
  92. package/lib/types/context-types.d.ts +603 -0
  93. package/lib/types/fs-operations.d.ts +28 -0
  94. package/lib/types/fs-search.d.ts +24 -0
  95. package/lib/types/fs-tree.d.ts +51 -0
  96. package/lib/types/git.d.ts +82 -0
  97. package/lib/types/html-route.d.ts +59 -0
  98. package/lib/types/index.d.ts +47 -0
  99. package/lib/types/invariant.d.ts +15 -0
  100. package/lib/types/jobs-routes.d.ts +45 -0
  101. package/lib/types/open-external.d.ts +24 -0
  102. package/lib/types/prefs-shared.d.ts +225 -0
  103. package/lib/types/pty-deps.d.ts +78 -0
  104. package/lib/types/pty-manager.d.ts +168 -0
  105. package/lib/types/sidechat-core.d.ts +172 -0
  106. package/lib/types/sidechat-routes.d.ts +30 -0
  107. package/lib/types/subagent-activity.d.ts +44 -0
  108. package/lib/types/subagent-live-route.d.ts +44 -0
  109. package/lib/types/tools.d.ts +31 -0
  110. package/lib/types/trust-fence.d.ts +24 -0
  111. package/lib/types/wire.d.ts +38 -0
  112. package/package.json +173 -0
  113. package/scripts/install.ps1 +289 -0
  114. package/scripts/install.sh +287 -0
  115. package/src/agent-pty.ts +527 -0
  116. package/src/browser-probe.ts +26 -0
  117. package/src/bundle-route.ts +129 -0
  118. package/src/client/BrowserView.tsx +253 -0
  119. package/src/client/DiffTab.tsx +110 -0
  120. package/src/client/DiffView.tsx +305 -0
  121. package/src/client/EditorHost.tsx +525 -0
  122. package/src/client/FileTree.tsx +653 -0
  123. package/src/client/GitView.tsx +558 -0
  124. package/src/client/OrphanedTab.tsx +27 -0
  125. package/src/client/PdfView.tsx +110 -0
  126. package/src/client/RenderBoundary.tsx +49 -0
  127. package/src/client/SandboxStatusBar.tsx +60 -0
  128. package/src/client/SideCardSection.module.css +960 -0
  129. package/src/client/SideCardSection.tsx +1152 -0
  130. package/src/client/SideChatView.module.css +437 -0
  131. package/src/client/SideChatView.tsx +644 -0
  132. package/src/client/Sidebar.tsx +1148 -0
  133. package/src/client/SubagentView.module.css +547 -0
  134. package/src/client/SubagentView.tsx +883 -0
  135. package/src/client/TabBar.tsx +305 -0
  136. package/src/client/TerminalView.tsx +383 -0
  137. package/src/client/TextEditor.tsx +500 -0
  138. package/src/client/TreePanel.tsx +273 -0
  139. package/src/client/UploadOverlay.tsx +62 -0
  140. package/src/client/add-plugin-modal.tsx +199 -0
  141. package/src/client/api.ts +335 -0
  142. package/src/client/binary-download.tsx +23 -0
  143. package/src/client/breakpoints.ts +51 -0
  144. package/src/client/browser.ts +119 -0
  145. package/src/client/builtins/index.ts +37 -0
  146. package/src/client/builtins/tabs.tsx +331 -0
  147. package/src/client/builtins/viewers.tsx +125 -0
  148. package/src/client/chunk-loader.ts +351 -0
  149. package/src/client/chunks/editor.tsx +9 -0
  150. package/src/client/chunks/mermaid.tsx +10 -0
  151. package/src/client/chunks/terminal.tsx +9 -0
  152. package/src/client/cm-themes.ts +129 -0
  153. package/src/client/conversation-draft.ts +29 -0
  154. package/src/client/css-modules.d.ts +5 -0
  155. package/src/client/desktop-env.ts +72 -0
  156. package/src/client/editable-state.ts +70 -0
  157. package/src/client/editor-load.ts +92 -0
  158. package/src/client/frame-batcher.ts +56 -0
  159. package/src/client/icons.tsx +161 -0
  160. package/src/client/image-types.ts +8 -0
  161. package/src/client/ime-guard.ts +47 -0
  162. package/src/client/index.tsx +369 -0
  163. package/src/client/intercept.tsx +110 -0
  164. package/src/client/lang.ts +103 -0
  165. package/src/client/layout.css +94 -0
  166. package/src/client/lazy-chunk.tsx +89 -0
  167. package/src/client/link-intercept.ts +73 -0
  168. package/src/client/locales.ts +734 -0
  169. package/src/client/mermaid-blocks.ts +110 -0
  170. package/src/client/mermaid-sanitize.ts +93 -0
  171. package/src/client/mermaid.tsx +401 -0
  172. package/src/client/open-when-sized.ts +43 -0
  173. package/src/client/open-with-settings.tsx +135 -0
  174. package/src/client/open-with.ts +221 -0
  175. package/src/client/openpath-intercept.ts +62 -0
  176. package/src/client/paths.ts +47 -0
  177. package/src/client/pdf-types.ts +4 -0
  178. package/src/client/plugin-settings.ts +43 -0
  179. package/src/client/plugins-shared.ts +29 -0
  180. package/src/client/plugins-tabs.ts +87 -0
  181. package/src/client/plugins-viewers.ts +30 -0
  182. package/src/client/prefs.ts +207 -0
  183. package/src/client/produced-files.ts +91 -0
  184. package/src/client/selection-payload.ts +86 -0
  185. package/src/client/service.ts +838 -0
  186. package/src/client/settings-nav-icon.ts +45 -0
  187. package/src/client/shell-presets.ts +83 -0
  188. package/src/client/sidebar.module.css +2577 -0
  189. package/src/client/sidechat-transcript.ts +321 -0
  190. package/src/client/split-pane.tsx +322 -0
  191. package/src/client/state.ts +1175 -0
  192. package/src/client/subagent-detect.ts +137 -0
  193. package/src/client/subagent-jobs.ts +161 -0
  194. package/src/client/tab-content-memo.ts +46 -0
  195. package/src/client/terminal-font.ts +28 -0
  196. package/src/client/theme.ts +110 -0
  197. package/src/client/titlebar-strip.ts +37 -0
  198. package/src/client/upload.ts +187 -0
  199. package/src/client/wco.ts +120 -0
  200. package/src/config.ts +155 -0
  201. package/src/context-types.ts +610 -0
  202. package/src/fs-operations.ts +99 -0
  203. package/src/fs-search.ts +86 -0
  204. package/src/fs-tree.ts +158 -0
  205. package/src/git.ts +244 -0
  206. package/src/html-route.ts +106 -0
  207. package/src/index.ts +1132 -0
  208. package/src/invariant.ts +32 -0
  209. package/src/jobs-routes.ts +257 -0
  210. package/src/open-external.ts +90 -0
  211. package/src/prefs-shared.ts +268 -0
  212. package/src/pty-deps.ts +240 -0
  213. package/src/pty-manager.ts +376 -0
  214. package/src/sidechat-core.ts +468 -0
  215. package/src/sidechat-routes.ts +344 -0
  216. package/src/subagent-activity.ts +91 -0
  217. package/src/subagent-live-route.ts +93 -0
  218. package/src/tools.ts +479 -0
  219. package/src/trust-fence.ts +77 -0
  220. package/src/wire.ts +100 -0
@@ -0,0 +1,734 @@
1
+ /**
2
+ * Minimal zh/en copy for the sidebar. The copy follows the DSH i18n system:
3
+ * the client apply attaches the locale service (`ctx.locale`, provided by
4
+ * `@deepseek-ai/dsh-client-locale`) through {@link attachLocale}, and
5
+ * `t()`/`isZh()` resolve the active locale from it — the Host-backed
6
+ * `locale.preference` wins over the raw browser language and switches live.
7
+ * Without an attached service (standalone/test compositions) the browser
8
+ * language is used, matching the previous behavior. The dictionaries are
9
+ * also registered into the DSH locale registry under {@link LOCALE_NS}.
10
+ */
11
+
12
+ /** The zh dictionary (also registered into the DSH locale registry under {@link LOCALE_NS}). */
13
+ export const zh = {
14
+ files: '文件',
15
+ explorer: '资源管理器',
16
+ git: '源代码管理',
17
+ terminal: '终端',
18
+ editor: '编辑器',
19
+ editorExplorer: '文件打开方式',
20
+ editorExplorerDesc: '控制文件打开方式',
21
+ editorExplorerMerged: '合并',
22
+ editorExplorerMergedDesc: '文件在同一窗口内原地切换;新窗口默认展开文件树',
23
+ editorExplorerSplit: '独立',
24
+ editorExplorerSplitDesc: '无路径窗口即资源管理器(仅文件树);文件各自新开窗口(带文件树,默认收起)',
25
+ editorTreeToggle: '文件树面板',
26
+ editorPathPlaceholder: '输入文件路径(相对会话目录或绝对路径),Enter 打开',
27
+ editorSearchPlaceholder: '按文件名搜索…',
28
+ editorSearchNoResults: '无匹配文件',
29
+ editorSearchTruncated: '结果过多,仅显示部分匹配',
30
+ editorEmptyHint: '从右侧文件树或上方路径输入框选择文件开始预览',
31
+ openFileNewTab: '在新 Tab 中打开',
32
+ openFileSide: '在侧边打开',
33
+ openWithMenu: '在应用中打开',
34
+ openWithSshSuffix: ' (SSH)',
35
+ pinOpenWith: '固定到菜单',
36
+ unpinOpenWith: '取消固定',
37
+ openWithExplorer: '资源管理器',
38
+ openWithVscode: 'VS Code',
39
+ openWithCursor: 'Cursor',
40
+ openWithZed: 'Zed',
41
+ openWithSettingsSshTitle: 'SSH 远端主机',
42
+ openWithSettingsSshDesc: '留空为本地工作区;填入 user@host 或 SSH 别名后,VSCode 系打开方式将改用 vscode-remote/ssh-remote 协议,资源管理器 / Zed / 非 VSCode 系自定义编辑器将从菜单隐藏',
43
+ openWithSettingsSshPlaceholder: 'user@host 或 SSH 别名',
44
+ openWithSettingsCustomTitle: '自定义编辑器',
45
+ openWithSettingsCustomDesc: '名称 + URL 模板({path} 占位符)+ 是否 VSCode 系;SSH 模式下仅 VSCode 系可打开远端',
46
+ openWithSettingsAdd: '添加',
47
+ openWithSettingsName: '名称',
48
+ openWithSettingsTemplate: '如 cursor://file/{path}',
49
+ openWithSettingsFamily: 'VSCode 系',
50
+ openWithSettingsFamilyDesc: '该编辑器使用 VSCode 的 URL 协议(支持 SSH 远端打开)',
51
+ openWithSettingsRemove: '删除',
52
+ openWithSettingsInvalidHint: '名称或模板(需含 {path} 且以 scheme:// 开头)未填写的编辑器不会出现在菜单中',
53
+ newTab: '新建标签页',
54
+ openExplorer: '资源管理器',
55
+ brokenSymlink: '失效的软链接',
56
+ openGit: 'Git 面板',
57
+ newTerminal: '新终端',
58
+ terminalLimit: '终端数量已达上限 (3)',
59
+ close: '关闭',
60
+ closeOtherTabs: '关闭其他页签',
61
+ closeLeftTabs: '关闭左侧页签',
62
+ closeRightTabs: '关闭右侧页签',
63
+ collapse: '折叠侧边栏',
64
+ expand: '展开侧边栏',
65
+ terminalError: '终端连接失败',
66
+ terminalConnectFailed: '终端多次连接失败',
67
+ terminalRetry: '重试',
68
+ terminalDepsFailed: '终端依赖 node-pty 加载失败',
69
+ terminalDepsHint: '在 DSH 所在环境的终端或 cmd 中执行以下命令修复,然后点重试(node-pty 与 DSH 核心保持同一版本):',
70
+ terminalDepsProfile: '(检测到 profile:{profile})',
71
+ preview: '预览',
72
+ edit: '编辑',
73
+ mermaidError: 'Mermaid 渲染失败',
74
+ mermaidZoomIn: '放大',
75
+ mermaidZoomOut: '缩小',
76
+ mermaidZoomReset: '重置',
77
+ mermaidZoomHint: '滚轮缩放 · 拖拽平移 · Esc 关闭',
78
+ refresh: '刷新',
79
+ save: '保存',
80
+ saved: '已保存',
81
+ unsaved: '未保存',
82
+ saveFailed: '保存失败',
83
+ readOnlyMode: '只读',
84
+ editableMode: '可编辑',
85
+ switchReadOnlyTitle: '关闭写权限(只读)',
86
+ switchEditableTitle: '开启写权限(可编辑)',
87
+ truncation: '文件过大,仅显示前 512KB',
88
+ binary: '二进制文件,无法预览',
89
+ loading: '加载中…',
90
+ error: '加载失败',
91
+ retry: '重试',
92
+ splitLeft: '向左分栏',
93
+ splitRight: '向右分栏',
94
+ splitUp: '向上分栏',
95
+ splitDown: '向下分栏',
96
+ notRepo: '当前目录不是 git 仓库',
97
+ noChanges: '没有变更',
98
+ stage: '暂存',
99
+ unstage: '取消暂存',
100
+ stageAll: '全部暂存',
101
+ unstageAll: '全部取消暂存',
102
+ commitPlaceholder: '提交信息 (Ctrl+Enter)',
103
+ commit: '提交',
104
+ commitError: '提交失败',
105
+ branch: '分支',
106
+ checkoutError: '切换分支失败',
107
+ history: '历史',
108
+ changes: '变更',
109
+ staged: '已暂存',
110
+ unstaged: '未暂存',
111
+ cancel: '取消',
112
+ diffEmpty: '没有文本差异',
113
+ diffLoadError: '加载差异失败',
114
+ diffBinary: '二进制',
115
+ diffAdded: '新增',
116
+ diffDeleted: '删除',
117
+ diffRenamed: '重命名',
118
+ diffExpand: '展开其余 {count} 行',
119
+ diffCollapse: '收起',
120
+ discard: '放弃更改',
121
+ discardTitle: '放弃更改',
122
+ discardDesc: '将丢弃「{path}」的工作区修改(不可恢复)。',
123
+ viewCommitDiff: '查看提交差异',
124
+ copyShortHash: '复制短哈希',
125
+ copyFullHash: '复制完整哈希',
126
+ copySubject: '复制提交信息',
127
+ revertCommit: '还原此提交',
128
+ revertTitle: '还原此提交',
129
+ revertDesc: '将在当前分支创建一个反转「{subject}」的新提交。',
130
+ cherryPickCommit: '捡取此提交',
131
+ cherryPickTitle: '捡取此提交',
132
+ cherryPickDesc: '将「{subject}」的更改应用到当前分支。',
133
+ timeJustNow: '刚刚',
134
+ timeMinutesAgo: '{n} 分钟前',
135
+ timeHoursAgo: '{n} 小时前',
136
+ timeYesterday: '昨天',
137
+ loadMore: '加载更多',
138
+ historyLoadError: '加载更多历史失败',
139
+ produced: '本次产出',
140
+ producedOpen: '在侧边栏中打开',
141
+ disconnected: '终端连接断开,重连中…',
142
+ exited: '终端进程已退出',
143
+ noSession: '选择一个会话以使用侧边栏',
144
+ pluginNotLoaded: '插件未加载,标签页暂不可用:',
145
+ hiddenFiles: '隐藏文件',
146
+ parent: '上级目录',
147
+ copied: '已复制',
148
+ copy: '复制',
149
+ newFile: '新文件',
150
+ openEditor: '打开编辑器',
151
+ gitDetail: '查看变更详情',
152
+ referenceFile: '@文件',
153
+ addToConversation: '添加到对话',
154
+ copyRelative: '复制相对地址',
155
+ copyAbsolute: '复制绝对地址',
156
+ download: '下载',
157
+ uploadFiles: '上传文件',
158
+ uploadFolder: '上传文件夹',
159
+ uploadHere: '上传到此处',
160
+ uploadDropHint: '拖拽文件/文件夹到此处上传',
161
+ uploadDropChat: '拖放到聊天区:添加图片到对话',
162
+ uploadTo: '上传到 {dir}',
163
+ uploadingTo: '正在上传到 {dir}…',
164
+ uploadProgress: '正在上传 {done}/{total}: {name}',
165
+ uploadDone: '已上传 {count} 个文件',
166
+ uploadFailed: '上传失败:{error}',
167
+ uploadFailedUnknown: '未知错误',
168
+ uploadTooLarge: '文件过大,超出上传上限',
169
+ uploadCancelled: '上传已取消',
170
+ settingsNav: '侧边卡片',
171
+ settingsIntro: '管理侧边卡片的显示内容与默认行为',
172
+ settingsPopupDesc: '为「{feature}」配置相关选项',
173
+ settingsDone: '完成',
174
+ settingsOpenTitle: '新会话默认打开',
175
+ settingsOpenDesc: '新建会话时自动展开侧边卡片;已存在的会话保持各自布局',
176
+ settingsWidthTitle: '默认宽度占比',
177
+ settingsWidthDesc: '新建会话时侧边卡片占窗口宽度的百分比 (20–60)',
178
+ settingsWidthSuffix: '%',
179
+ settingsOpenPathTitle: '聊天区文件在侧边栏打开',
180
+ settingsOpenPathDesc: '在聊天里点击文件链接(工具行、产物列表、文件提及)时,在侧边栏编辑器中打开,不再调用系统默认应用',
181
+ settingsTitleBarTitle: '位置兼容模式',
182
+ settingsTitleBarDesc: '选择顶栏兼容方案:自动检测(默认,保守)/ DSH官方Web / 已知桌面壳 / 自定义方案(下移距离 + 自定义 CSS)',
183
+ settingsTitleBarStripTitle: '下移距离',
184
+ settingsTitleBarStripDesc: '标题栏条带高度:侧边栏按钮与内容下移的像素数(0–120,默认 40;自定义方案下生效)',
185
+ settingsSchemeAutoTitle: '自动检测',
186
+ settingsSchemeAutoDesc: '保守方案:仅在 Window Controls Overlay 标准 API 可用时按真实标题栏高度让位;网页环境下不做任何修改',
187
+ settingsSchemeWebTitle: 'DSH官方Web',
188
+ settingsSchemeWebDesc: '显式声明运行在官方网页版:不做任何适配(连标准 WCO 几何也不适用)',
189
+ settingsSchemeCustomTitle: '自定义方案',
190
+ settingsSchemeCustomDesc: '完全由你控制:注入自定义 CSS(可覆盖内置样式),并指定标题栏下移距离',
191
+ settingsSchemeDetectedSuffix: '已检测',
192
+ settingsCustomCssTitle: '自定义 CSS',
193
+ settingsCustomCssDesc: '追加到页面末尾的样式(同优先级下后写胜出;覆盖 JS 内联变量需用 !important)',
194
+ settingsCustomCssPlaceholder: '/* 例:为自绘标题栏的壳预留 36px */\nhtml[data-dsh-title-bar-height="36"] {\n --dsh-title-bar-strip: 36px !important;\n}',
195
+ settingsSaveFailed: '保存失败',
196
+ settingsConflict: '设置已被其他窗口修改,请重试',
197
+ binaryNoPreview: '此文件类型不支持预览',
198
+ downloadToView: '下载查看',
199
+ settingsSubagentTitle: '检测到子代理时自动展开任务管理页',
200
+ settingsSubagentDesc: '当前会话产生新的子代理时,自动展开侧边栏并打开任务管理页;关闭后需手动打开',
201
+ settingsJobsTitle: '有新后台任务时自动展开后台任务页',
202
+ settingsJobsDesc: '当前会话出现新的后台任务时,自动展开侧边栏并打开后台任务页(每个新任务都会触发);关闭后需手动打开',
203
+ settingsToolsTitle: '为模型注入终端工具',
204
+ settingsToolsDesc: '开启后,模型可通过 terminal_create 等 8 个工具创建并操作侧边栏终端(默认关闭)',
205
+ settingsFontFamilyTitle: '终端字体',
206
+ settingsFontFamilyDesc: '自定义终端字体族(CSS font-family,如 "JetBrains Mono", monospace;留空跟随主题等宽字体)',
207
+ settingsFontFamilyPlaceholder: '"JetBrains Mono", monospace',
208
+ settingsFontSizeTitle: '终端字号',
209
+ settingsFontSizeDesc: '终端字号(9–32,默认 13)',
210
+ settingsFontSizeSuffix: 'px',
211
+ settingsShellTitle: 'Shell 路径',
212
+ settingsShellDesc: 'UI 与模型终端启动的 shell(绝对路径或可执行名)。留空按既有顺序解析:yaml 的 config.shell → $SHELL / 登录 shell / Windows 的 powershell.exe。对之后打开的终端生效',
213
+ settingsShellPlaceholder: '如 /bin/zsh(留空自动解析)',
214
+ settingsShellArgsTitle: 'Shell 参数',
215
+ settingsShellArgsDesc: '显式 shell 启动参数,空格分隔;非空时完全替换默认参数(与 yaml 的 shellArgs 契约一致)',
216
+ settingsShellArgsPlaceholder: '如 -l(留空用默认参数)',
217
+ settingsTabsTitle: '侧边栏内容',
218
+ settingsViewersTitle: '文件预览',
219
+ settingsGeneralTitle: '常规',
220
+ settingsPopup: '功能设置',
221
+ settingsViewerCatchAll: '兜底:任意文件',
222
+ viewerImage: '图片',
223
+ viewerPdf: 'PDF',
224
+ viewerMarkdown: 'Markdown',
225
+ viewerCode: '代码',
226
+ viewerBinary: '二进制下载',
227
+ viewerHtml: 'HTML',
228
+ browser: '浏览器',
229
+ browserPlaceholder: '输入网址,例如 example.com',
230
+ browserGo: '前往',
231
+ browserBack: '后退',
232
+ browserForward: '前进',
233
+ browserStart: '输入网址开始浏览(沙箱模式)',
234
+ browserBlockedScheme: '已阻止:仅支持 http/https 链接',
235
+ browserBlockedLoopback: '已阻止:不允许在浏览器中访问本机或内部地址',
236
+ browserInvalid: '无效的网址',
237
+ browserNoSandboxWarning: '沙箱已关闭:当前页面与界面同源,拥有完整会话权限(可在设置中恢复)',
238
+ htmlNoSandboxWarning: '沙箱已关闭:此 HTML 与界面同源,可读取会话文件与内部接口(可在设置中恢复)',
239
+ sandboxStatusOn: '沙箱模式:已启用 · 页面无法访问界面数据与本地文件,登录态与第三方 Cookie 可能不可用',
240
+ sandboxUnlock: '临时解锁(不安全)',
241
+ sandboxRestore: '恢复沙箱',
242
+ settingsHtmlDefaultUnsafeTitle: 'HTML 预览默认以非沙箱模式打开(不安全)',
243
+ settingsHtmlDefaultUnsafeDesc: '开启后,每次打开 HTML 文件时预览默认处于非沙箱状态(与界面同源,可读取会话文件与内部接口);可在状态行临时恢复沙箱',
244
+ settingsHtmlSandboxTitle: '关闭 HTML 预览沙箱(不安全)',
245
+ settingsHtmlSandboxDesc: '关闭后,预览的 HTML 将与界面同源运行,可读取会话文件、本地存储并调用内部接口。仅对完全可信的文件开启',
246
+ settingsBrowserSandboxTitle: '关闭浏览器沙箱(不安全)',
247
+ settingsBrowserSandboxDesc: '关闭后,访问的任何网站都将与界面同源运行,可读取会话数据并冒充你的登录状态。仅对完全可信的站点开启',
248
+ settingsBrowserLinksTitle: '聊天区外链在侧边栏打开',
249
+ settingsBrowserLinksDesc: '开启后,点击聊天或界面中的外链时在侧边栏打开,不再弹出新窗口;HTTP 与 HTTPS 可分别通过下方开关控制;Ctrl/Cmd 点击可临时放行',
250
+ settingsBrowserHttpTitle: '侧边打开HTTP网页',
251
+ settingsBrowserHttpDesc: '开启后,点击聊天或界面中的 HTTP 外链时在侧边栏打开(声明了 urlTarget 的插件页面优先);Ctrl/Cmd 点击可临时放行',
252
+ settingsBrowserHttpsTitle: '侧边打开HTTPS网页',
253
+ settingsBrowserHttpsDesc: '开启后,点击聊天或界面中的 HTTPS 外链时在侧边栏打开。默认关闭:多数 HTTPS 站点拒绝被嵌入,走系统浏览器更顺畅',
254
+ browserOpenExternal: '在浏览器中打开',
255
+ browserEmbedBlocked: '{host} 拒绝了嵌入请求',
256
+ browserEmbedBlockedDesc: '该站点通过 X-Frame-Options / frame-ancestors 禁止在其它页面中显示,无法在侧边栏内加载。可在浏览器中直接打开',
257
+ browserEmbedAnyway: '仍然加载',
258
+ subagent: '任务管理',
259
+ openSubagent: '任务管理',
260
+ subagentMainAgent: '主代理',
261
+ subagentEmpty: '暂无子代理',
262
+ subagentEmptyDesc: '当前主代理派生的子代理将显示在这里',
263
+ subagentRunning: '运行中',
264
+ subagentInactive: '空闲',
265
+ subagentModeOneShot: '一次性',
266
+ subagentModeContinuable: '可续接',
267
+ subagentCount: '{count} 个子代理',
268
+ subagentCountRunning: '{count} 个子代理 · {running} 运行中',
269
+ subagentDiagCorrupt: '目录损坏',
270
+ subagentDiagUnsupported: '不支持的条目',
271
+ subagentDiagUnavailable: '不可用',
272
+ subagentThinking: '思考中…',
273
+ sideChat: '侧边对话(beta)',
274
+ sideChatNew: '新建对话',
275
+ sideChatUntitled: '新对话',
276
+ sideChatEmpty: '暂无侧边对话',
277
+ sideChatEmptyDesc: '每个侧边对话是标签栏里的独立 Tab,继承当前会话的上下文运行,不会进入主会话',
278
+ sideChatCreating: '正在创建侧边对话…',
279
+ sideChatRetry: '重试',
280
+ sideChatThreads: '切换线程 / 新建',
281
+ sideChatSave: '保存为新会话',
282
+ sideChatSaveTitle: '把该线程提升为顶层会话,出现在主会话列表中',
283
+ sideChatSaved: '已保存为新会话',
284
+ sideChatNoTurn: '至少完成一轮对话后才能保存',
285
+ sideChatPendingDrop: '最后一条未完成的追问不会包含在新会话中',
286
+ sideChatFirstPlaceholder: '输入第一个问题,已继承当前会话上下文…',
287
+ sideChatComposerPlaceholder: '追问…',
288
+ sideChatThinking: '正在深入…',
289
+ sideChatThink: '思考过程',
290
+ sideChatInjection: '已注入上下文',
291
+ sideChatSend: '发送',
292
+ sideChatCancel: '停止',
293
+ sideChatCancelTitle: '中止当前回合(保留队列)',
294
+ sideChatClose: '关闭线程',
295
+ sideChatCloseTitle: '释放线程的 agent(历史保留)',
296
+ sideChatError: '侧边对话出错:{message}',
297
+ jobs: '后台任务',
298
+ jobsCount: '{count} 个后台任务',
299
+ jobsCountRunning: '{count} 个后台任务 · {running} 运行中',
300
+ jobStatusRunning: '运行中',
301
+ jobStatusStopping: '终止中',
302
+ jobStatusCompleted: '已完成',
303
+ jobStatusKilled: '已终止',
304
+ jobStatusFailed: '失败',
305
+ jobDurationSeconds: '{seconds} 秒',
306
+ jobDurationMinutes: '{minutes} 分 {seconds} 秒',
307
+ jobDurationHours: '{hours} 小时 {minutes} 分',
308
+ jobViewOutput: '查看输出',
309
+ jobHideOutput: '收起输出',
310
+ jobNoOutput: '暂无输出',
311
+ jobNotReadYet: '等待模型读取该任务的输出(模型执行 job_output 后,输出会显示在这里)',
312
+ jobOutputTruncated: '输出过长,已截断显示',
313
+ jobOutputError: '输出读取失败',
314
+ jobKill: '终止',
315
+ jobKillConfirm: '再次点击确认终止',
316
+ jobKillError: '终止失败',
317
+ addPluginsTabCard: '添加 Tab 插件',
318
+ addPluginsTabCardDesc: '注册新的侧边栏页面',
319
+ addPluginsViewerCard: '添加预览插件',
320
+ addPluginsViewerCardDesc: '注册新的文件类型预览',
321
+ addPluginsTabDesc: '侧边栏页面(Tab)可以由插件扩展。插件通过 ctx.betterSidebar 服务注册;点击「安装」复制安装命令,粘贴到 DSH 所在环境的终端执行。',
322
+ addPluginsViewerDesc: '文件预览器可以由插件扩展。插件通过 ctx.betterSidebar 服务注册;点击「安装」复制安装命令,粘贴到 DSH 所在环境的终端执行。',
323
+ addPluginsBrowseMore: '在 GitHub 上浏览更多插件(topic: dsh-better-sidebar)',
324
+ addPluginsSearch: '搜索插件名称 / 描述…',
325
+ addPluginsNoMatch: '没有匹配的插件',
326
+ addPluginsRecommended: '推荐插件',
327
+ addPluginsEmpty: '暂未收录插件,欢迎在 GitHub topic 下发布你的插件',
328
+ openPlugin: '跳转',
329
+ copyInstall: '复制安装命令',
330
+ pluginOfficeDesc: '为 better-sidebar 编辑器提供 Office 三件套预览(.docx / .xlsx / .pptx),把重型 Office 渲染库拆出主包、按需安装',
331
+ pluginFlowglassDesc: '实时会话流程图:三列泳道展示用户、助手与工具调用,支持并行分组、子代理支线、逐层钻取和实时状态;安装 better-sidebar 后注册原生「流镜」Tab,未安装时保留独立抽屉',
332
+ pluginGitForgeDesc: 'better-sidebar「Git 凭据」Tab:GitHub/Gitea 等 Forge 账号库 + 按项目授权 + push 策略硬拦;token 仅存本地 secrets,不进模型上下文;提供只读 GitForge 工具与 agent HTTPS credential helper',
333
+ pluginGitRemotesDesc: 'better-sidebar Git 远程 Tab:看分支/上游/ahead-behind,fetch(可 prune)、ff-only pull、确认后才 push。不替换内置 Git 的暂存/提交,也不提供 force-push 或模型自动推送',
334
+ pluginSentinelDesc: '条件驱动的 agent 唤醒系统:文件/进程/端口/HTTP/命令/webhook 传感器,条件达成自动唤醒休眠会话;注册「哨兵」Tab 展示服务器全局监控表',
335
+ pluginSidebarQaDesc: '基于 better-sidebar 的划选提问tab分页: 对话划选 → 右侧面板提问 → 同工作区独立追问会话(❓追问·主题):快速无思考模型压缩主对话上下文后与引文一起注入,不打断主对话;追问可嵌套、可继续、可归档',
336
+ pluginSshTunnelDesc: 'better-sidebar「SSH 隧道」Tab:多机主机清单 + 按项目授权 + 密钥本地保管;模型工具 SSHManager(exec/SFTP/会话策略);中央交互终端与双栏 SFTP',
337
+ pluginTurnReviewDesc: '对「刚刚这一回合」的 diff 做 Approve / Request changes 的人闸门:只审上一回合,不 fork 会话;文件按主会话/子代理/未归因分组,按文件勾选打回 + 可选评语,点文件先看回合开始快照 vs 现在的 diff。不是 /rewind',
338
+ pluginVideoPreviewDesc: '在 better-sidebar 编辑器内联预览视频文件(.mp4/.webm/.mov/.mkv/.avi 等),自带支持 HTTP Range(206)的 /video 宿主路由,可拖动进度条、不受 20MB mediaLimit 限制',
339
+ pluginDocsPanelDesc: 'DSH 侧边栏里的「全局文档」:全局 Markdown 笔记,任何工作区随时可读——列表点选阅读、悬浮大纲跳转、Chrome / VS Code 外部打开、代码复制,目录可配置(默认 ~/.dsh/docs)',
340
+ }
341
+
342
+ /** The en dictionary (key-set-equal to zh, enforced by the type annotation). */
343
+ export const en: Record<keyof typeof zh, string> = {
344
+ files: 'Files',
345
+ explorer: 'Explorer',
346
+ git: 'Source Control',
347
+ terminal: 'Terminal',
348
+ editor: 'Editor',
349
+ editorExplorer: 'File open behavior',
350
+ editorExplorerDesc: 'Controls how files open',
351
+ editorExplorerMerged: 'Merged',
352
+ editorExplorerMergedDesc: 'Files switch in place in the same window; new windows start with the tree open',
353
+ editorExplorerSplit: 'Separate',
354
+ editorExplorerSplitDesc: 'Path-less windows are the standalone explorer (tree only); each file opens its own window (tree docked, closed by default)',
355
+ editorTreeToggle: 'File tree panel',
356
+ editorPathPlaceholder: 'File path (relative to the session directory or absolute), Enter to open',
357
+ editorSearchPlaceholder: 'Search files by name…',
358
+ editorSearchNoResults: 'No matching files',
359
+ editorSearchTruncated: 'Too many results — showing a partial list',
360
+ editorEmptyHint: 'Pick a file from the tree panel or the path input above to start previewing',
361
+ openFileNewTab: 'Open in New Tab',
362
+ openFileSide: 'Open to the Side',
363
+ openWithMenu: 'Open with',
364
+ openWithSshSuffix: ' (SSH)',
365
+ pinOpenWith: 'Pin to menu',
366
+ unpinOpenWith: 'Unpin',
367
+ openWithExplorer: 'File Manager',
368
+ openWithVscode: 'VS Code',
369
+ openWithCursor: 'Cursor',
370
+ openWithZed: 'Zed',
371
+ openWithSettingsSshTitle: 'SSH remote host',
372
+ openWithSettingsSshDesc: 'Empty = local workspace; with a user@host or SSH alias, VSCode-family openers switch to the vscode-remote/ssh-remote protocol and the File Manager / Zed / non-VSCode-family custom editors are hidden from the menu',
373
+ openWithSettingsSshPlaceholder: 'user@host or SSH alias',
374
+ openWithSettingsCustomTitle: 'Custom editors',
375
+ openWithSettingsCustomDesc: 'Name + URL template ({path} placeholder) + VSCode-family flag; in remote mode only VSCode-family editors can open a remote path',
376
+ openWithSettingsAdd: 'Add',
377
+ openWithSettingsName: 'Name',
378
+ openWithSettingsTemplate: 'e.g. cursor://file/{path}',
379
+ openWithSettingsFamily: 'VSCode-family',
380
+ openWithSettingsFamilyDesc: 'This editor speaks the VSCode URL dialect (supports SSH-remote opens)',
381
+ openWithSettingsRemove: 'Remove',
382
+ openWithSettingsInvalidHint: 'Editors with a missing name or a template without {path} / scheme:// are not shown in the menu',
383
+ newTab: 'New tab',
384
+ openExplorer: 'Explorer',
385
+ brokenSymlink: 'Broken symlink',
386
+ openGit: 'Git panel',
387
+ newTerminal: 'New terminal',
388
+ terminalLimit: 'Terminal limit reached (3)',
389
+ close: 'Close',
390
+ closeOtherTabs: 'Close Other Tabs',
391
+ closeLeftTabs: 'Close Tabs to the Left',
392
+ closeRightTabs: 'Close Tabs to the Right',
393
+ collapse: 'Collapse sidebar',
394
+ expand: 'Expand sidebar',
395
+ terminalError: 'Terminal connection failed',
396
+ terminalConnectFailed: 'Terminal failed to connect repeatedly',
397
+ terminalRetry: 'Retry',
398
+ terminalDepsFailed: 'Terminal dependency node-pty failed to load',
399
+ terminalDepsHint: 'Run the command below in a terminal or cmd on the DSH machine to repair it, then retry (node-pty stays in sync with the DSH core version):',
400
+ terminalDepsProfile: ' (detected profile: {profile})',
401
+ preview: 'Preview',
402
+ edit: 'Edit',
403
+ mermaidError: 'Mermaid render failed',
404
+ mermaidZoomIn: 'Zoom in',
405
+ mermaidZoomOut: 'Zoom out',
406
+ mermaidZoomReset: 'Reset',
407
+ mermaidZoomHint: 'Scroll to zoom · drag to pan · Esc to close',
408
+ refresh: 'Refresh',
409
+ save: 'Save',
410
+ saved: 'Saved',
411
+ unsaved: 'Unsaved',
412
+ saveFailed: 'Save failed',
413
+ readOnlyMode: 'Read-only',
414
+ editableMode: 'Editable',
415
+ switchReadOnlyTitle: 'Disable write permission (read-only)',
416
+ switchEditableTitle: 'Enable write permission (editable)',
417
+ truncation: 'File too large — showing the first 512KB',
418
+ binary: 'Binary file, preview unavailable',
419
+ loading: 'Loading…',
420
+ error: 'Failed to load',
421
+ retry: 'Retry',
422
+ splitLeft: 'Split left',
423
+ splitRight: 'Split right',
424
+ splitUp: 'Split up',
425
+ splitDown: 'Split down',
426
+ notRepo: 'This directory is not a git repository',
427
+ noChanges: 'No changes',
428
+ stage: 'Stage',
429
+ unstage: 'Unstage',
430
+ stageAll: 'Stage all',
431
+ unstageAll: 'Unstage all',
432
+ commitPlaceholder: 'Commit message (Ctrl+Enter)',
433
+ commit: 'Commit',
434
+ commitError: 'Commit failed',
435
+ branch: 'Branch',
436
+ checkoutError: 'Branch switch failed',
437
+ history: 'History',
438
+ changes: 'Changes',
439
+ staged: 'Staged',
440
+ unstaged: 'Unstaged',
441
+ cancel: 'Cancel',
442
+ diffEmpty: 'No text changes',
443
+ diffLoadError: 'Failed to load diff',
444
+ diffBinary: 'Binary',
445
+ diffAdded: 'Added',
446
+ diffDeleted: 'Deleted',
447
+ diffRenamed: 'Renamed',
448
+ diffExpand: 'Expand {count} more rows',
449
+ diffCollapse: 'Collapse',
450
+ discard: 'Discard changes',
451
+ discardTitle: 'Discard changes',
452
+ discardDesc: 'This discards the worktree changes of "{path}" (not recoverable).',
453
+ viewCommitDiff: 'View commit diff',
454
+ copyShortHash: 'Copy short hash',
455
+ copyFullHash: 'Copy full hash',
456
+ copySubject: 'Copy subject',
457
+ revertCommit: 'Revert commit',
458
+ revertTitle: 'Revert commit',
459
+ revertDesc: 'Create a new commit on the current branch that reverts "{subject}".',
460
+ cherryPickCommit: 'Cherry-pick commit',
461
+ cherryPickTitle: 'Cherry-pick commit',
462
+ cherryPickDesc: 'Apply the changes of "{subject}" to the current branch.',
463
+ timeJustNow: 'just now',
464
+ timeMinutesAgo: '{n} min ago',
465
+ timeHoursAgo: '{n} h ago',
466
+ timeYesterday: 'yesterday',
467
+ loadMore: 'Load more',
468
+ historyLoadError: 'Failed to load more history',
469
+ produced: 'Produced',
470
+ producedOpen: 'Open in sidebar',
471
+ disconnected: 'Terminal disconnected, reconnecting…',
472
+ exited: 'Terminal process exited',
473
+ noSession: 'Select a conversation to use the sidebar',
474
+ pluginNotLoaded: 'Plugin not loaded; tab unavailable:',
475
+ hiddenFiles: 'Hidden files',
476
+ parent: 'Parent directory',
477
+ copied: 'Copied',
478
+ copy: 'Copy',
479
+ newFile: 'New file',
480
+ openEditor: 'Open editor',
481
+ gitDetail: 'View change details',
482
+ referenceFile: '@file',
483
+ addToConversation: 'Add to conversation',
484
+ copyRelative: 'Copy relative path',
485
+ copyAbsolute: 'Copy absolute path',
486
+ download: 'Download',
487
+ uploadFiles: 'Upload files',
488
+ uploadFolder: 'Upload folder',
489
+ uploadHere: 'Upload here',
490
+ uploadDropHint: 'Drop files/folders here to upload',
491
+ uploadDropChat: 'Drop onto the chat to add images',
492
+ uploadTo: 'Upload into {dir}',
493
+ uploadingTo: 'Uploading into {dir}…',
494
+ uploadProgress: 'Uploading {done}/{total}: {name}',
495
+ uploadDone: 'Uploaded {count} file(s)',
496
+ uploadFailed: 'Upload failed: {error}',
497
+ uploadFailedUnknown: 'Unknown error',
498
+ uploadTooLarge: 'File too large (over the upload limit)',
499
+ uploadCancelled: 'Upload cancelled',
500
+ settingsNav: 'Side card',
501
+ settingsIntro: 'Manage what the side card shows and how it behaves',
502
+ settingsPopupDesc: 'Configure related options for {feature}',
503
+ settingsDone: 'Done',
504
+ settingsOpenTitle: 'Open by default for new conversations',
505
+ settingsOpenDesc: 'Expand the side card automatically for brand-new conversations; existing conversations keep their own layouts',
506
+ settingsWidthTitle: 'Default width share',
507
+ settingsWidthDesc: 'The side card\'s default share of the window width for new conversations (20–60)',
508
+ settingsWidthSuffix: '%',
509
+ settingsOpenPathTitle: 'Open chat files in the sidebar',
510
+ settingsOpenPathDesc: 'Open file links in the chat (tool rows, produced files, mentions) in the sidebar editor instead of the system default app',
511
+ settingsTitleBarTitle: 'Position compatibility mode',
512
+ settingsTitleBarDesc: 'Pick the title-bar compatibility scheme: auto-detect (default, conservative) / DSH official web / known desktop shells / custom (shift distance + custom CSS)',
513
+ settingsTitleBarStripTitle: 'Shift distance',
514
+ settingsTitleBarStripDesc: 'Title-bar strip height: how far the sidebar buttons and content move down in px (0–120, default 40; applies under the custom scheme)',
515
+ settingsSchemeAutoTitle: 'Auto-detect',
516
+ settingsSchemeAutoDesc: 'Conservative: only the standard Window Controls Overlay API contributes (real caption-overlay height); plain web environments get no modification',
517
+ settingsSchemeWebTitle: 'DSH official web',
518
+ settingsSchemeWebDesc: 'Explicitly declare the official web UI: no adaptation at all (not even standard WCO geometry)',
519
+ settingsSchemeCustomTitle: 'Custom',
520
+ settingsSchemeCustomDesc: 'Full control: inject custom CSS (can override built-in styles) and set the title-bar shift distance',
521
+ settingsSchemeDetectedSuffix: 'detected',
522
+ settingsCustomCssTitle: 'Custom CSS',
523
+ settingsCustomCssDesc: 'Styles appended at the end of the page (later in the cascade wins ties; use !important to override JS-written inline variables)',
524
+ settingsCustomCssPlaceholder: '/* e.g. reserve 36px for a shell with a custom-drawn title bar */\nhtml[data-dsh-title-bar-height="36"] {\n --dsh-title-bar-strip: 36px !important;\n}',
525
+ settingsSaveFailed: 'Failed to save',
526
+ settingsConflict: 'The setting changed in another window — please retry',
527
+ binaryNoPreview: 'This file type cannot be previewed',
528
+ downloadToView: 'Download to view',
529
+ settingsSubagentTitle: 'Auto-open the Tasks page when a subagent appears',
530
+ settingsSubagentDesc: 'Expand the side card and open the Tasks page when the current conversation spawns a new subagent; turn off to open it manually',
531
+ settingsJobsTitle: 'Auto-open the Jobs page on a new background job',
532
+ settingsJobsDesc: 'Expand the side card and open the Jobs page whenever a new background job appears for the current conversation (every new job triggers); turn off to open it manually',
533
+ settingsToolsTitle: 'Inject terminal tools for the model',
534
+ settingsToolsDesc: 'When enabled, the model can create and drive sidebar terminals through the 8 terminal_* tools (off by default)',
535
+ settingsFontFamilyTitle: 'Terminal font family',
536
+ settingsFontFamilyDesc: 'Custom terminal font family (a CSS font-family stack like "JetBrains Mono", monospace; leave empty to follow the theme\'s monospace font)',
537
+ settingsFontFamilyPlaceholder: '"JetBrains Mono", monospace',
538
+ settingsFontSizeTitle: 'Terminal font size',
539
+ settingsShellTitle: 'Shell path',
540
+ settingsShellDesc: 'Shell spawned for UI and model terminals (absolute path or bare executable). Empty keeps the legacy order: yaml config.shell → $SHELL / login shell / Windows powershell.exe. Applies to terminals opened afterwards',
541
+ settingsShellPlaceholder: 'e.g. /bin/zsh (empty = auto)',
542
+ settingsShellArgsTitle: 'Shell arguments',
543
+ settingsShellArgsDesc: 'Explicit shell arguments, space-separated; when non-empty they fully replace the defaults (same contract as the yaml shellArgs)',
544
+ settingsShellArgsPlaceholder: 'e.g. -l (empty = defaults)',
545
+ settingsFontSizeDesc: 'Terminal font size in px (9–32, default 13)',
546
+ settingsFontSizeSuffix: 'px',
547
+ settingsTabsTitle: 'Sidebar content',
548
+ settingsViewersTitle: 'File viewers',
549
+ settingsGeneralTitle: 'General',
550
+ settingsPopup: 'Feature settings',
551
+ settingsViewerCatchAll: 'Catch-all: any file',
552
+ viewerImage: 'Image',
553
+ viewerPdf: 'PDF',
554
+ viewerMarkdown: 'Markdown',
555
+ viewerCode: 'Code',
556
+ viewerBinary: 'Binary download',
557
+ viewerHtml: 'HTML',
558
+ browser: 'Browser',
559
+ browserPlaceholder: 'Enter a URL, e.g. example.com',
560
+ browserGo: 'Go',
561
+ browserBack: 'Back',
562
+ browserForward: 'Forward',
563
+ browserStart: 'Enter a URL to start browsing (sandbox mode)',
564
+ browserBlockedScheme: 'Blocked: only http/https URLs are allowed',
565
+ browserBlockedLoopback: 'Blocked: local and internal addresses cannot be browsed here',
566
+ browserInvalid: 'Invalid URL',
567
+ browserNoSandboxWarning: 'Sandbox off: the current page runs with full GUI privileges (re-enable in settings)',
568
+ htmlNoSandboxWarning: 'Sandbox off: this HTML runs with full GUI privileges (re-enable in settings)',
569
+ sandboxStatusOn: 'Sandbox mode: on · pages cannot access the GUI\'s data or local files; logins and third-party cookies may not work',
570
+ sandboxUnlock: 'Temporarily disable (unsafe)',
571
+ sandboxRestore: 'Restore sandbox',
572
+ settingsHtmlDefaultUnsafeTitle: 'Open HTML previews unsandboxed by default (unsafe)',
573
+ settingsHtmlDefaultUnsafeDesc: 'When on, every newly opened HTML preview starts in the unsandboxed state (same origin as the GUI — it can read session files and internal APIs); the status row still offers a one-tap restore',
574
+ settingsHtmlSandboxTitle: 'Disable HTML preview sandbox (unsafe)',
575
+ settingsHtmlSandboxDesc: 'With the sandbox off, previewed HTML runs with the same origin as the GUI: it can read session files, local storage and call internal APIs. Only enable for fully trusted files',
576
+ settingsBrowserSandboxTitle: 'Disable browser sandbox (unsafe)',
577
+ settingsBrowserSandboxDesc: 'With the sandbox off, any visited site runs with the same origin as the GUI: it can read session data and act as your logged-in session. Only enable for fully trusted sites',
578
+ settingsBrowserLinksTitle: 'Open chat external links in the sidebar',
579
+ settingsBrowserLinksDesc: 'When on, clicking an external link in the chat or GUI opens the sidebar instead of a new window; HTTP and HTTPS are controlled separately by the switches below; Ctrl/Cmd+click always bypasses',
580
+ settingsBrowserHttpTitle: 'Open HTTP pages in the sidebar',
581
+ settingsBrowserHttpDesc: 'When on, clicking an HTTP external link in the chat or GUI opens the sidebar (plugin pages declaring urlTarget win); Ctrl/Cmd+click always bypasses',
582
+ settingsBrowserHttpsTitle: 'Open HTTPS pages in the sidebar',
583
+ settingsBrowserHttpsDesc: 'When on, clicking an HTTPS external link in the chat or GUI opens the sidebar. Off by default: most HTTPS sites refuse to be embedded, so the system browser is the smoother default',
584
+ browserOpenExternal: 'Open in browser',
585
+ browserEmbedBlocked: '{host} refused to be embedded',
586
+ browserEmbedBlockedDesc: 'The site forbids being displayed inside other pages (X-Frame-Options / frame-ancestors), so it cannot load in the sidebar. Open it directly in your browser instead.',
587
+ browserEmbedAnyway: 'Load anyway',
588
+ subagent: 'Tasks',
589
+ openSubagent: 'Tasks',
590
+ subagentMainAgent: 'Main agent',
591
+ subagentEmpty: 'No subagents',
592
+ subagentEmptyDesc: 'Subagents spawned under the main agent will appear here',
593
+ subagentRunning: 'Running',
594
+ subagentInactive: 'Inactive',
595
+ subagentModeOneShot: 'One-shot',
596
+ subagentModeContinuable: 'Continuable',
597
+ subagentCount: '{count} subagents',
598
+ subagentCountRunning: '{count} subagents · {running} running',
599
+ subagentDiagCorrupt: 'Corrupt',
600
+ subagentDiagUnsupported: 'Unsupported',
601
+ subagentDiagUnavailable: 'Unavailable',
602
+ subagentThinking: 'Thinking…',
603
+ sideChat: 'Side Chat (beta)',
604
+ sideChatNew: 'New thread',
605
+ sideChatUntitled: 'New thread',
606
+ sideChatEmpty: 'No side conversations',
607
+ sideChatEmptyDesc: 'Every side conversation is its own tab in the tab strip — it inherits the current session\'s context and never enters the main conversation',
608
+ sideChatCreating: 'Creating side conversation…',
609
+ sideChatRetry: 'Retry',
610
+ sideChatThreads: 'Switch thread / new',
611
+ sideChatSave: 'Save as new session',
612
+ sideChatSaveTitle: 'Promote this thread to a top-level session in the main session list',
613
+ sideChatSaved: 'Saved as a new session',
614
+ sideChatNoTurn: 'Save is available after the first completed turn',
615
+ sideChatPendingDrop: 'The last unanswered follow-up will not be included in the saved session',
616
+ sideChatFirstPlaceholder: 'Ask the first question — context inherited…',
617
+ sideChatComposerPlaceholder: 'Ask a follow-up…',
618
+ sideChatThinking: 'Deep diving…',
619
+ sideChatThink: 'Thinking',
620
+ sideChatInjection: 'Context injected',
621
+ sideChatSend: 'Send',
622
+ sideChatCancel: 'Stop',
623
+ sideChatCancelTitle: 'Abort the running turn (queued work is kept)',
624
+ sideChatClose: 'Close thread',
625
+ sideChatCloseTitle: 'Release the thread\'s agent (history is kept)',
626
+ sideChatError: 'Side Chat error: {message}',
627
+ jobs: 'Background jobs',
628
+ jobsCount: '{count} background jobs',
629
+ jobsCountRunning: '{count} background jobs · {running} running',
630
+ jobStatusRunning: 'Running',
631
+ jobStatusStopping: 'Stopping',
632
+ jobStatusCompleted: 'Completed',
633
+ jobStatusKilled: 'Killed',
634
+ jobStatusFailed: 'Failed',
635
+ jobDurationSeconds: '{seconds}s',
636
+ jobDurationMinutes: '{minutes}m {seconds}s',
637
+ jobDurationHours: '{hours}h {minutes}m',
638
+ jobViewOutput: 'View output',
639
+ jobHideOutput: 'Hide output',
640
+ jobNoOutput: 'No output yet',
641
+ jobNotReadYet: 'Waiting for the model to read this job; its output appears here once the model runs job_output',
642
+ jobOutputTruncated: 'Output truncated',
643
+ jobOutputError: 'Failed to read output',
644
+ jobKill: 'Kill',
645
+ jobKillConfirm: 'Click again to confirm kill',
646
+ jobKillError: 'Kill failed',
647
+ addPluginsTabCard: 'Add tab plugins',
648
+ addPluginsTabCardDesc: 'Register a new sidebar page',
649
+ addPluginsViewerCard: 'Add preview plugins',
650
+ addPluginsViewerCardDesc: 'Register a file-type preview',
651
+ addPluginsTabDesc: 'Sidebar pages (tabs) can be extended by plugins. Plugins register through the ctx.betterSidebar service; clicking Install copies the install command — paste it into a terminal where your DSH profile lives and run it.',
652
+ addPluginsViewerDesc: 'File previewers can be extended by plugins. Plugins register through the ctx.betterSidebar service; clicking Install copies the install command — paste it into a terminal where your DSH profile lives and run it.',
653
+ addPluginsBrowseMore: 'Browse more plugins on GitHub (topic: dsh-better-sidebar)',
654
+ addPluginsSearch: 'Search by plugin name or description…',
655
+ addPluginsNoMatch: 'No plugins match',
656
+ addPluginsRecommended: 'Recommended plugins',
657
+ addPluginsEmpty: 'No plugins curated yet — publish yours under the GitHub topic',
658
+ openPlugin: 'Open',
659
+ copyInstall: 'Copy install command',
660
+ pluginOfficeDesc: 'Office-suite preview (.docx / .xlsx / .pptx) for the better-sidebar editor, keeping the heavy Office render libraries out of the core bundle',
661
+ pluginFlowglassDesc: 'Live session flowgraph with three lanes for user, assistant, and tool calls, plus parallel groups, sub-agent branches, drill-down, and live status; registers a native Flowglass tab when better-sidebar is installed and keeps its standalone drawer as a fallback',
662
+ pluginGitForgeDesc: 'Git Forge tab: GitHub/Gitea (and other forge) account library + per-project grants + hard push policy; tokens stay in local secrets (never in model context); read-only GitForge tool and agent HTTPS credential helper',
663
+ pluginGitRemotesDesc: 'Git Remotes tab: branch/upstream/ahead-behind, fetch (optional prune), ff-only pull, and push only after an in-tab confirm. Does not replace the built-in Git stage/commit tab, and does not offer force-push or a model auto-push tool',
664
+ pluginSentinelDesc: 'Condition-driven agent wakeup: file/process/port/http/command/webhook sensors wake dormant sessions when conditions fire; registers a "Sentinel" tab with the server-wide watch table',
665
+ pluginSidebarQaDesc: 'Select-and-ask: Select conversation text → ask in the right-side panel → a dedicated follow-up session (❓追问) in the same workspace; a fast no-thinking model compresses the main context and injects it with the quote, without interrupting the main conversation. Follow-ups nest, continue, and archive',
666
+ pluginSshTunnelDesc: 'SSH Tunnel tab: multi-host inventory + per-project grants + local secrets; SSHManager tool (exec/SFTP/session strategies); center interactive terminal and dual-pane SFTP',
667
+ pluginTurnReviewDesc: 'A human gate on the just-finished turn: Approve / Request changes per path with an optional comment; paths grouped by main session / subagent / unattributed; inline snapshot-vs-now diff before you decide. No fork, no /rewind',
668
+ pluginVideoPreviewDesc: 'Inline video preview (.mp4/.webm/.mov/.mkv/.avi etc.) for the better-sidebar editor, backed by a dedicated /video host route with HTTP Range (206) support — scrubbing works and files are not capped by the 20MB mediaLimit',
669
+ pluginDocsPanelDesc: 'Global docs in the DSH sidebar: read your own Markdown notes from any workspace — a file list, an outline, open in Chrome / VS Code, and copy buttons; the docs directory is configurable (default ~/.dsh/docs)',
670
+ }
671
+
672
+ /**
673
+ * The dictionary namespace this plugin owns in the DSH locale registry
674
+ * (`'sidebar'` is taken by DSH's own ui-sidebar, hence this distinct name).
675
+ */
676
+ export const LOCALE_NS = 'betterSidebar'
677
+
678
+ /** The DSH locale service attached by the client apply (absent → browser detection). */
679
+ let localeService: { getSnapshot(): { active: string } } | undefined
680
+
681
+ /**
682
+ * Attach (or detach, with undefined) the DSH locale service. The sidebar
683
+ * mounts its own React root outside the slot system's locale seat, so the
684
+ * service rides this module-level holder: components keep calling the plain
685
+ * `t()` function, and the Sidebar root's locale subscription re-renders the
686
+ * whole tree on switches.
687
+ */
688
+ export function attachLocale(service: { getSnapshot(): { active: string } } | undefined): void {
689
+ localeService = service
690
+ }
691
+
692
+ /**
693
+ * The active locale id ('zh' | 'en'): the DSH locale service's snapshot when
694
+ * attached, else the browser language.
695
+ */
696
+ function activeLocale(): string {
697
+ return localeService?.getSnapshot().active
698
+ ?? (typeof navigator !== 'undefined' ? navigator.language : '')
699
+ ?? 'en'
700
+ }
701
+
702
+ /** Translate a copy key in the active locale (zh → zh, else en). */
703
+ export type CopyKey = keyof typeof zh
704
+
705
+ /** Translate a copy key; `{name}` placeholders interpolate from `params`. */
706
+ export function t(key: CopyKey, params?: Record<string, string | number>): string {
707
+ const dict = activeLocale().toLowerCase().startsWith('zh') ? zh : en
708
+ let text = dict[key]
709
+ if (params !== undefined) {
710
+ for (const [name, value] of Object.entries(params)) {
711
+ text = text.replaceAll(`{${name}}`, String(value))
712
+ }
713
+ }
714
+ return text
715
+ }
716
+
717
+ /** Whether the active locale is Chinese (used for selectors). */
718
+ export function isZh(): boolean {
719
+ return activeLocale().toLowerCase().startsWith('zh')
720
+ }
721
+
722
+ /** Format an ISO 8601 author date relative to now (刚刚 / N 分钟前 / N 小时前 / 昨天 / date). */
723
+ export function relativeTime(iso: string): string {
724
+ const then = Date.parse(iso)
725
+ if (Number.isNaN(then)) return iso
726
+ const seconds = Math.floor((Date.now() - then) / 1000)
727
+ if (seconds < 60) return t('timeJustNow')
728
+ if (seconds < 3600) return t('timeMinutesAgo', { n: Math.floor(seconds / 60) })
729
+ if (seconds < 86400) return t('timeHoursAgo', { n: Math.floor(seconds / 3600) })
730
+ if (seconds < 172800) return t('timeYesterday')
731
+ const date = new Date(then)
732
+ const pad = (value: number): string => String(value).padStart(2, '0')
733
+ return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())}`
734
+ }