@chainingintention/pi-web-cn 1.202610.3 → 1.202610.4

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 (202) hide show
  1. package/README.md +1 -0
  2. package/dist/cli.js +129 -122
  3. package/dist/cli.js.map +1 -1
  4. package/dist/client/assets/PiWebApp-CN3g7SqA.js +4362 -0
  5. package/dist/client/assets/external-DUGCSDhZ.js +2 -0
  6. package/dist/client/assets/index-JduZlbIF.js +2 -0
  7. package/dist/client/index.html +4 -4
  8. package/dist/client/manifest.webmanifest +2 -1
  9. package/dist/localization.js +24 -0
  10. package/dist/localization.js.map +1 -0
  11. package/dist/nativeServices/serviceDoctor.js +45 -44
  12. package/dist/nativeServices/serviceDoctor.js.map +1 -1
  13. package/dist/pi-packages/captains-log/dist/browser/index.js +46 -45
  14. package/dist/pi-packages/captains-log/dist/browser/markdown.js +2 -1
  15. package/dist/pi-packages/captains-log/dist/browser/panel.js +56 -55
  16. package/dist/pi-packages/captains-log/i18n.js +7 -0
  17. package/dist/pi-packages/relays/i18n.js +7 -0
  18. package/dist/pi-packages/relays/markdownDocument.js +2 -1
  19. package/dist/pi-packages/relays/pi-web-plugin.js +8 -6
  20. package/dist/pi-packages/relays/relaysPanelElement.js +24 -23
  21. package/dist/pi-web-plugins/files/browser/pi-web-plugin.js +124 -124
  22. package/dist/pi-web-plugins/git/browser/git-contract.js +13 -12
  23. package/dist/pi-web-plugins/git/browser/git-panel.js +25 -24
  24. package/dist/pi-web-plugins/git/browser/i18n.js +7 -0
  25. package/dist/pi-web-plugins/git/browser/pi-web-plugin.js +7 -3
  26. package/dist/pi-web-plugins/git/git-backend.js +10 -9
  27. package/dist/pi-web-plugins/git/i18n.js +7 -0
  28. package/dist/pi-web-plugins/git/server-plugin.js +21 -19
  29. package/dist/pi-web-plugins/info/i18n.js +7 -0
  30. package/dist/pi-web-plugins/info/infoInternals.js +57 -62
  31. package/dist/pi-web-plugins/info/pi-web-plugin.js +34 -36
  32. package/dist/pi-web-plugins/mermaid/browser/pi-web-plugin.js +3 -3
  33. package/dist/pi-web-plugins/terminal/browser/pi-web-plugin.js +55 -52
  34. package/dist/pi-web-plugins/terminal/i18n.js +7 -0
  35. package/dist/pi-web-plugins/terminal/server-plugin.js +23 -21
  36. package/dist/pi-web-plugins/terminal/terminalService.js +22 -21
  37. package/dist/pi-web-plugins/updates/i18n.js +7 -0
  38. package/dist/pi-web-plugins/updates/pi-web-plugin.js +58 -54
  39. package/dist/pi-web-plugins/updates/updatesLogic.js +21 -20
  40. package/dist/pi-web-plugins/workspace-tasks/config.js +12 -11
  41. package/dist/pi-web-plugins/workspace-tasks/i18n.js +7 -0
  42. package/dist/pi-web-plugins/workspace-tasks/pi-web-plugin.js +8 -6
  43. package/dist/pi-web-plugins/workspace-tasks/tasksPanelElement.js +20 -19
  44. package/dist/pi-web-plugins/workspace-tasks/workspaceTasksClient.js +12 -11
  45. package/dist/pi-web-plugins/zh-cn/auth.json +9 -0
  46. package/dist/pi-web-plugins/zh-cn/bundled.json +176 -0
  47. package/dist/pi-web-plugins/zh-cn/cli.json +171 -0
  48. package/dist/pi-web-plugins/zh-cn/client.json +219 -0
  49. package/dist/pi-web-plugins/zh-cn/components.json +1002 -0
  50. package/dist/pi-web-plugins/zh-cn/config-errors.json +172 -0
  51. package/dist/pi-web-plugins/zh-cn/files.json +41 -0
  52. package/dist/pi-web-plugins/zh-cn/machines.json +28 -0
  53. package/dist/pi-web-plugins/zh-cn/main.json +459 -0
  54. package/dist/pi-web-plugins/zh-cn/management-errors.json +23 -0
  55. package/dist/pi-web-plugins/zh-cn/manifest.webmanifest +25 -0
  56. package/dist/pi-web-plugins/zh-cn/metadata.json +3 -0
  57. package/dist/pi-web-plugins/zh-cn/package.json +10 -0
  58. package/dist/pi-web-plugins/zh-cn/pi-web-plugin.js +16 -0
  59. package/dist/pi-web-plugins/zh-cn/projects.json +6 -0
  60. package/dist/pi-web-plugins/zh-cn/provider-auth.json +17 -0
  61. package/dist/pi-web-plugins/zh-cn/routing.json +68 -0
  62. package/dist/pi-web-plugins/zh-cn/server-main.json +99 -0
  63. package/dist/pi-web-plugins/zh-cn/server.json +174 -0
  64. package/dist/piWebVersionReport.js +17 -16
  65. package/dist/piWebVersionReport.js.map +1 -1
  66. package/dist/plugin-api.d.ts +4 -1
  67. package/dist/pluginRecoveryCli.js +25 -24
  68. package/dist/pluginRecoveryCli.js.map +1 -1
  69. package/dist/server/app.js +43 -28
  70. package/dist/server/app.js.map +1 -1
  71. package/dist/server/audit/normalToolAuditCli.js +45 -43
  72. package/dist/server/audit/normalToolAuditCli.js.map +1 -1
  73. package/dist/server/configRoutes.js +39 -30
  74. package/dist/server/configRoutes.js.map +1 -1
  75. package/dist/server/diagnostics/nodePtyNativeModule.js +7 -6
  76. package/dist/server/diagnostics/nodePtyNativeModule.js.map +1 -1
  77. package/dist/server/diagnostics/nodePtySpawnHelper.js +21 -20
  78. package/dist/server/diagnostics/nodePtySpawnHelper.js.map +1 -1
  79. package/dist/server/knownAutoInstallPiPackages.js +2 -2
  80. package/dist/server/knownAutoInstallPiPackages.js.map +1 -1
  81. package/dist/server/knownPiPackages.js +2 -2
  82. package/dist/server/knownPiPackages.js.map +1 -1
  83. package/dist/server/machines/machineClient.js +8 -6
  84. package/dist/server/machines/machineClient.js.map +1 -1
  85. package/dist/server/machines/machinePluginProxyRoutes.js +11 -10
  86. package/dist/server/machines/machinePluginProxyRoutes.js.map +1 -1
  87. package/dist/server/machines/machineProxyRoutes.js +27 -29
  88. package/dist/server/machines/machineProxyRoutes.js.map +1 -1
  89. package/dist/server/machines/machineRoutes.js +10 -12
  90. package/dist/server/machines/machineRoutes.js.map +1 -1
  91. package/dist/server/machines/machineService.js +17 -18
  92. package/dist/server/machines/machineService.js.map +1 -1
  93. package/dist/server/managementEmbed.js +26 -25
  94. package/dist/server/managementEmbed.js.map +1 -1
  95. package/dist/server/normalAuth.js +29 -26
  96. package/dist/server/normalAuth.js.map +1 -1
  97. package/dist/server/passwordVerifier.js +2 -1
  98. package/dist/server/passwordVerifier.js.map +1 -1
  99. package/dist/server/piPackageService.js +7 -5
  100. package/dist/server/piPackageService.js.map +1 -1
  101. package/dist/server/piWebPluginService.js +27 -11
  102. package/dist/server/piWebPluginService.js.map +1 -1
  103. package/dist/server/piWebStatus.js +16 -14
  104. package/dist/server/piWebStatus.js.map +1 -1
  105. package/dist/server/plugins/serverPluginRuntime.js +4 -2
  106. package/dist/server/plugins/serverPluginRuntime.js.map +1 -1
  107. package/dist/server/projects/projectService.js +4 -3
  108. package/dist/server/projects/projectService.js.map +1 -1
  109. package/dist/server/sessiond/projectMutationRoutes.js +5 -4
  110. package/dist/server/sessiond/projectMutationRoutes.js.map +1 -1
  111. package/dist/server/sessiond/sessionProxyRoutes.js +11 -8
  112. package/dist/server/sessiond/sessionProxyRoutes.js.map +1 -1
  113. package/dist/server/sessiond/workspaceCatalogRoutes.js +5 -3
  114. package/dist/server/sessiond/workspaceCatalogRoutes.js.map +1 -1
  115. package/dist/server/sessiond.js +8 -3
  116. package/dist/server/sessiond.js.map +1 -1
  117. package/dist/server/sessions/authRoutes.js +20 -19
  118. package/dist/server/sessions/authRoutes.js.map +1 -1
  119. package/dist/server/sessions/authService.js +13 -10
  120. package/dist/server/sessions/authService.js.map +1 -1
  121. package/dist/server/sessions/builtinCommands.js +28 -21
  122. package/dist/server/sessions/builtinCommands.js.map +1 -1
  123. package/dist/server/sessions/oauthLoginFlowService.js +17 -15
  124. package/dist/server/sessions/oauthLoginFlowService.js.map +1 -1
  125. package/dist/server/sessions/piSessionService.js +229 -208
  126. package/dist/server/sessions/piSessionService.js.map +1 -1
  127. package/dist/server/sessions/projectAuthService.js +5 -3
  128. package/dist/server/sessions/projectAuthService.js.map +1 -1
  129. package/dist/server/sessions/sessionArchiveMapping.js +8 -7
  130. package/dist/server/sessions/sessionArchiveMapping.js.map +1 -1
  131. package/dist/server/sessions/sessionCleanup.js +4 -3
  132. package/dist/server/sessions/sessionCleanup.js.map +1 -1
  133. package/dist/server/sessions/sessionCommandService.js +70 -67
  134. package/dist/server/sessions/sessionCommandService.js.map +1 -1
  135. package/dist/server/sessions/sessionNotificationStore.js +12 -11
  136. package/dist/server/sessions/sessionNotificationStore.js.map +1 -1
  137. package/dist/server/sessions/sessionRoutes.js +74 -72
  138. package/dist/server/sessions/sessionRoutes.js.map +1 -1
  139. package/dist/server/sessions/sessionTreeProjection.js +50 -49
  140. package/dist/server/sessions/sessionTreeProjection.js.map +1 -1
  141. package/dist/server/sessions/sessionUnreadStore.js +25 -2
  142. package/dist/server/sessions/sessionUnreadStore.js.map +1 -1
  143. package/dist/server/terminals/managementCommandRunService.js +13 -12
  144. package/dist/server/terminals/managementCommandRunService.js.map +1 -1
  145. package/dist/server/workbench/accessStateStore.js +9 -7
  146. package/dist/server/workbench/accessStateStore.js.map +1 -1
  147. package/dist/server/workbench/capabilitySearch.js +3 -2
  148. package/dist/server/workbench/capabilitySearch.js.map +1 -1
  149. package/dist/server/workbench/knowledgeSearch.js +8 -7
  150. package/dist/server/workbench/knowledgeSearch.js.map +1 -1
  151. package/dist/server/workbench/mcpClient.js +6 -5
  152. package/dist/server/workbench/mcpClient.js.map +1 -1
  153. package/dist/server/workbench/skillSync.js +4 -2
  154. package/dist/server/workbench/skillSync.js.map +1 -1
  155. package/dist/server/workbench/workbenchClient.js +8 -7
  156. package/dist/server/workbench/workbenchClient.js.map +1 -1
  157. package/dist/server/workbench/workbenchTools.js +8 -6
  158. package/dist/server/workbench/workbenchTools.js.map +1 -1
  159. package/dist/server/workingDirectory.js +3 -2
  160. package/dist/server/workingDirectory.js.map +1 -1
  161. package/dist/server/workspaceExplorerRoutes.js +16 -13
  162. package/dist/server/workspaceExplorerRoutes.js.map +1 -1
  163. package/dist/server/workspaces/fileContentService.js +11 -10
  164. package/dist/server/workspaces/fileContentService.js.map +1 -1
  165. package/dist/server/workspaces/fileOperationService.js +7 -6
  166. package/dist/server/workspaces/fileOperationService.js.map +1 -1
  167. package/dist/server/workspaces/filePreviewService.js +5 -4
  168. package/dist/server/workspaces/filePreviewService.js.map +1 -1
  169. package/dist/server/workspaces/fileSuggestions.js +2 -1
  170. package/dist/server/workspaces/fileSuggestions.js.map +1 -1
  171. package/dist/server/workspaces/pathAccessPolicy.js +24 -18
  172. package/dist/server/workspaces/pathAccessPolicy.js.map +1 -1
  173. package/dist/server/workspaces/pathSafety.js +6 -5
  174. package/dist/server/workspaces/pathSafety.js.map +1 -1
  175. package/dist/server/workspaces/projectPiWebConfig.js +3 -2
  176. package/dist/server/workspaces/projectPiWebConfig.js.map +1 -1
  177. package/dist/server/workspaces/workspaceRemovalService.js +4 -3
  178. package/dist/server/workspaces/workspaceRemovalService.js.map +1 -1
  179. package/dist/server/workspaces/workspaceRouteErrors.js +4 -2
  180. package/dist/server/workspaces/workspaceRouteErrors.js.map +1 -1
  181. package/dist/server/workspaces/workspaceUserError.js +18 -0
  182. package/dist/server/workspaces/workspaceUserError.js.map +1 -0
  183. package/dist/server-plugin-api.d.ts +3 -1
  184. package/dist/server-plugin-api.js.map +1 -1
  185. package/dist/serverPluginRecovery.js +3 -2
  186. package/dist/serverPluginRecovery.js.map +1 -1
  187. package/dist/shared/apiTypes.js.map +1 -1
  188. package/dist/shared/i18n.js +41 -0
  189. package/dist/shared/i18n.js.map +1 -0
  190. package/dist/shared/piWebConfigParsing.js +52 -49
  191. package/dist/shared/piWebConfigParsing.js.map +1 -1
  192. package/dist/shared/pluginApiTypes.d.ts +7 -0
  193. package/dist/shared/requiredTerminalPlugin.js +1 -1
  194. package/dist/shared/requiredTerminalPlugin.js.map +1 -1
  195. package/dist/shared/sessionDefaults.js +7 -6
  196. package/dist/shared/sessionDefaults.js.map +1 -1
  197. package/dist/shared/thinkingLevels.js +17 -16
  198. package/dist/shared/thinkingLevels.js.map +1 -1
  199. package/docs/config.md +10 -1
  200. package/docs/plugins.md +8 -0
  201. package/package.json +1 -1
  202. package/dist/client/assets/index-CFhaGb5m.js +0 -4357
@@ -1,8 +1,9 @@
1
1
  // Generated from pi-web-plugins/git/browser/git-contract.ts. Do not edit directly.
2
+ import { t } from "./i18n.js";
2
3
  export const GIT_STATUS_OPERATION = "status";
3
4
  export const GIT_DIFF_OPERATION = "diff";
4
5
  export function parseGitStatusResponse(value) {
5
- const record = requireRecord(value, "Git 状态响应");
6
+ const record = requireRecord(value, t("ui.main.7486c17f15ba", "Git status response"));
6
7
  const branch = optionalString(record, "branch");
7
8
  const upstream = optionalString(record, "upstream");
8
9
  const ahead = optionalNumber(record, "ahead");
@@ -21,7 +22,7 @@ export function parseGitStatusResponse(value) {
21
22
  };
22
23
  }
23
24
  export function parseGitDiffResponse(value) {
24
- const record = requireRecord(value, "Git 差异响应");
25
+ const record = requireRecord(value, t("ui.main.f5c4a5928162", "Git diff response"));
25
26
  const path = optionalString(record, "path");
26
27
  return {
27
28
  ...(path === undefined ? {} : { path }),
@@ -32,7 +33,7 @@ export function parseGitDiffResponse(value) {
32
33
  };
33
34
  }
34
35
  function parseGitStatusFile(value) {
35
- const record = requireRecord(value, "Git 状态文件");
36
+ const record = requireRecord(value, t("ui.main.c15d1c2fb1e7", "Git status file"));
36
37
  const oldPath = optionalString(record, "oldPath");
37
38
  const submoduleFromCommit = optionalString(record, "submoduleFromCommit");
38
39
  const submoduleToCommit = optionalString(record, "submoduleToCommit");
@@ -58,30 +59,30 @@ function parseGitFileState(value) {
58
59
  case "conflicted":
59
60
  return value;
60
61
  default:
61
- throw new Error("无效的 Git 文件状态");
62
+ throw new Error(t("ui.main.b9c6b8997acf", "Invalid Git file state"));
62
63
  }
63
64
  }
64
65
  function requireRecord(value, label) {
65
66
  if (!isRecord(value))
66
- throw new Error(`${label}必须是对象`);
67
+ throw new Error(t("ui.main.0068cdba7cb2", "{arg0} must be an object", { arg0: label }));
67
68
  return value;
68
69
  }
69
70
  function requireArray(record, key) {
70
71
  const value = record[key];
71
72
  if (!Array.isArray(value))
72
- throw new Error(`字段必须是数组:${key}`);
73
+ throw new Error(t("ui.main.7f27405e930e", "Field must be an array: {arg0}", { arg0: key }));
73
74
  return value;
74
75
  }
75
76
  function requireString(record, key) {
76
77
  const value = record[key];
77
78
  if (typeof value !== "string")
78
- throw new Error(`字段必须是字符串:${key}`);
79
+ throw new Error(t("ui.main.f6d0b37d664f", "Field must be a string: {arg0}", { arg0: key }));
79
80
  return value;
80
81
  }
81
82
  function requireBoolean(record, key) {
82
83
  const value = record[key];
83
84
  if (typeof value !== "boolean")
84
- throw new Error(`字段必须是布尔值:${key}`);
85
+ throw new Error(t("ui.main.7517a00e15b7", "Field must be a boolean: {arg0}", { arg0: key }));
85
86
  return value;
86
87
  }
87
88
  function optionalString(record, key) {
@@ -89,7 +90,7 @@ function optionalString(record, key) {
89
90
  if (value === undefined)
90
91
  return undefined;
91
92
  if (typeof value !== "string")
92
- throw new Error(`字段必须是字符串:${key}`);
93
+ throw new Error(t("ui.main.f6d0b37d664f", "Field must be a string: {arg0}", { arg0: key }));
93
94
  return value;
94
95
  }
95
96
  function optionalNumber(record, key) {
@@ -97,7 +98,7 @@ function optionalNumber(record, key) {
97
98
  if (value === undefined)
98
99
  return undefined;
99
100
  if (typeof value !== "number" || !Number.isFinite(value))
100
- throw new Error(`字段必须是有限数字:${key}`);
101
+ throw new Error(t("ui.main.d40fe7108098", "Field must be a finite number: {arg0}", { arg0: key }));
101
102
  return value;
102
103
  }
103
104
  function optionalBoolean(record, key) {
@@ -105,12 +106,12 @@ function optionalBoolean(record, key) {
105
106
  if (value === undefined)
106
107
  return undefined;
107
108
  if (typeof value !== "boolean")
108
- throw new Error(`字段必须是布尔值:${key}`);
109
+ throw new Error(t("ui.main.7517a00e15b7", "Field must be a boolean: {arg0}", { arg0: key }));
109
110
  return value;
110
111
  }
111
112
  function requireStringArray(value, key) {
112
113
  if (!Array.isArray(value) || !value.every((entry) => typeof entry === "string"))
113
- throw new Error(`字段必须是字符串数组:${key}`);
114
+ throw new Error(t("ui.main.141ce9c90033", "Field must be a string array: {arg0}", { arg0: key }));
114
115
  return value;
115
116
  }
116
117
  function isRecord(value) {
@@ -1,4 +1,5 @@
1
1
  // Generated from pi-web-plugins/git/browser/git-panel.ts. Do not edit directly.
2
+ import { t } from "./i18n.js";
2
3
  import { GIT_DIFF_OPERATION, GIT_STATUS_OPERATION, parseGitDiffResponse, parseGitStatusResponse, } from "./git-contract.js";
3
4
  import { buildGitFileList } from "./gitFileList.js";
4
5
  import { buildGitFileTree, collectGitFileTreeDirectoryPaths } from "./gitFileTree.js";
@@ -339,19 +340,19 @@ function createGitActions(panelId, controller) {
339
340
  return [
340
341
  {
341
342
  id: "view.git",
342
- title: "转到 Git",
343
+ title: t("client.actions.go.to.git.0d4886", "Go to Git"),
343
344
  shortcut: "mod+3",
344
345
  shortcutAliases: ["core:view.git"],
345
- group: "导航",
346
+ group: t("client.actions.navigation.e72622", "Navigation"),
346
347
  enabled: hasGitWorkspace,
347
348
  run: (context) => { context.selectWorkspaceTool(panelId); },
348
349
  },
349
350
  {
350
351
  id: "workspace.refresh-git",
351
- title: "刷新 Git",
352
+ title: t("client.actions.refresh.git.496f8a", "Refresh Git"),
352
353
  shortcut: "mod+shift+g",
353
354
  shortcutAliases: ["core:workspace.refresh-git"],
354
- group: "工作区",
355
+ group: t("bundled.workspace-tasks.workspace.379798", "Workspace"),
355
356
  enabled: hasGitWorkspace,
356
357
  run: (context) => context.refreshWorkspacePanels(panelId),
357
358
  },
@@ -381,7 +382,7 @@ function createGitPanel(html, svg, controller) {
381
382
  }
382
383
  function requestGitBackend(context, operation, input) {
383
384
  if (context.peer?.request === undefined) {
384
- return Promise.reject(new Error("Git 工作区后端不可用。请更新并重启此机器上的 PI WEB,然后重新加载浏览器。"));
385
+ return Promise.reject(new Error(t("ui.main.fc3b27465765", "Git workspace backend is unavailable. Update and restart PI WEB on this machine, then reload the browser.")));
385
386
  }
386
387
  return context.peer.request(operation, input);
387
388
  }
@@ -394,15 +395,15 @@ function renderGitPanel(html, controller, context) {
394
395
  <pi-web-git-panel-activity .controller=${controller} .context=${context}></pi-web-git-panel-activity>
395
396
  <section class="git-toolbar">
396
397
  <strong>Git</strong>
397
- ${state.stale ? html `<span class="git-stale">数据已过期</span>` : null}
398
+ ${state.stale ? html `<span class="git-stale">${t("ui.main.3468df3f1fe9", "stale")}</span>` : null}
398
399
  <div class="git-toolbar-actions">
399
400
  ${viewState.expandablePaths.length === 0 ? null : renderExpandCollapseAll(html, controller, context, state, viewState.expandablePaths)}
400
401
  ${renderViewToggle(html, controller, context)}
401
- <button type="button" ?disabled=${state.statusLoading} @click=${() => { void controller.refresh(context); }}>刷新</button>
402
+ <button type="button" ?disabled=${state.statusLoading} @click=${() => { void controller.refresh(context); }}>${t("bundled.relays.refresh.aee887", "Refresh")}</button>
402
403
  </div>
403
404
  </section>
404
405
  ${state.error === undefined ? null : html `<div class="git-error" role="alert">${state.error}</div>`}
405
- ${state.status?.truncated === true ? html `<div class="git-warning" role="status">Git 状态输出过大,文件列表已截断。</div>` : null}
406
+ ${state.status?.truncated === true ? html `<div class="git-warning" role="status">${t("ui.main.1634590c49b8", "Git status output was too large; the file list was truncated.")}</div>` : null}
406
407
  <section class="git-split">
407
408
  <div class="git-file-list">${renderFileList(html, controller, context, state, viewState)}</div>
408
409
  <div class="git-viewer">${renderDiffViewer(html, state)}</div>
@@ -412,9 +413,9 @@ function renderGitPanel(html, controller, context) {
412
413
  }
413
414
  function renderViewToggle(html, controller, context) {
414
415
  return html `
415
- <div class="git-view-toggle" role="group" aria-label="已更改文件视图">
416
- ${renderViewToggleButton(html, controller, context, "list", "列表")}
417
- ${renderViewToggleButton(html, controller, context, "tree", "树形")}
416
+ <div class="git-view-toggle" role="group" aria-label="${t("ui.main.898449210b9d", "Changed files view")}">
417
+ ${renderViewToggleButton(html, controller, context, "list", t("ui.workspaceGitPanel.list", "List"))}
418
+ ${renderViewToggleButton(html, controller, context, "tree", t("ui.main.7f32c63d2d35", "Tree"))}
418
419
  </div>
419
420
  `;
420
421
  }
@@ -424,17 +425,17 @@ function renderViewToggleButton(html, controller, context, view, label) {
424
425
  }
425
426
  function renderExpandCollapseAll(html, controller, context, state, expandablePaths) {
426
427
  const allExpanded = expandablePaths.every((path) => state.expandedDirectories.has(path));
427
- return html `<button type="button" @click=${() => { controller.toggleExpandAll(context, expandablePaths, allExpanded); }}>${allExpanded ? "全部折叠" : "全部展开"}</button>`;
428
+ return html `<button type="button" @click=${() => { controller.toggleExpandAll(context, expandablePaths, allExpanded); }}>${allExpanded ? t("ui.workspaceGitPanel.collapseAll", "Collapse all") : t("ui.workspaceGitPanel.expandAll", "Expand all")}</button>`;
428
429
  }
429
430
  function renderFileList(html, controller, context, state, viewState) {
430
431
  const status = state.status;
431
432
  if (status === undefined)
432
- return html `<p class="git-muted">${state.error === undefined ? "正在加载状态…" : "状态不可用。"}</p>`;
433
+ return html `<p class="git-muted">${state.error === undefined ? t("ui.main.f2cb84a98270", "Loading status…") : t("ui.main.d2302e08b20b", "Status unavailable.")}</p>`;
433
434
  if (!status.isGitRepo)
434
- return html `<p class="git-muted">当前工作区不是 Git 仓库。</p>`;
435
+ return html `<p class="git-muted">${t("ui.main.b4b1ea928fc3", "Not a git repository.")}</p>`;
435
436
  const summary = html `<p class="git-summary">${gitSummary(status)}</p>`;
436
437
  if (status.files.length === 0)
437
- return html `${summary}<p class="git-muted">没有更改。</p>`;
438
+ return html `${summary}<p class="git-muted">${t("ui.workspaceGitPanel.noChanges", "No changes.")}</p>`;
438
439
  state.remainingRows = state.visibleFileLimit;
439
440
  state.hasMoreRows = status.files.length > state.visibleFileLimit;
440
441
  const body = controller.currentView() === "tree"
@@ -442,7 +443,7 @@ function renderFileList(html, controller, context, state, viewState) {
442
443
  : renderListBody(html, controller, context, state, viewState.listModel);
443
444
  const rendered = Math.min(state.visibleFileLimit, status.files.length);
444
445
  const more = state.hasMoreRows || rendered < status.files.length
445
- ? html `<button type="button" class="git-load-more" @click=${() => { controller.showMore(context); }}>显示更多(${String(rendered)}/${String(status.files.length)})</button>`
446
+ ? html `<button type="button" class="git-load-more" @click=${() => { controller.showMore(context); }}>${t("ui.main.34f2d3bdae3d", "Show more (")}${String(rendered)}/${String(status.files.length)})</button>`
446
447
  : null;
447
448
  return html `${summary}${body}${more}`;
448
449
  }
@@ -501,14 +502,14 @@ function renderSelectableRow(html, controller, context, state, path, label, file
501
502
  }
502
503
  function renderDiffViewer(html, state) {
503
504
  if (state.selectedDiffPath === undefined)
504
- return html `<p class="git-muted">请选择一个已更改文件。</p>`;
505
+ return html `<p class="git-muted">${t("ui.main.77ed4aee3792", "Select a changed file.")}</p>`;
505
506
  const unstaged = state.selectedDiff;
506
507
  const staged = state.selectedStagedDiff;
507
508
  if (unstaged === undefined || staged === undefined)
508
- return html `<p class="git-muted">正在加载差异…</p>`;
509
+ return html `<p class="git-muted">${t("ui.workspaceGitPanel.loadingDiff", "Loading diff…")}</p>`;
509
510
  const diffs = [staged, unstaged].filter((diff) => diff.response.diff !== "");
510
511
  if (diffs.length === 0)
511
- return html `<p class="git-muted">没有已暂存或未暂存的差异。</p>`;
512
+ return html `<p class="git-muted">${t("ui.workspaceGitPanel.noStagedOrUnstagedDiff", "No staged or unstaged diff.")}</p>`;
512
513
  return html `<div class=${diffs.length === 1 ? "git-diffs is-single" : "git-diffs"}>${diffs.map((diff) => renderDiffSection(html, diff))}</div>`;
513
514
  }
514
515
  function consumeGitRow(state) {
@@ -524,10 +525,10 @@ function renderDiffSection(html, view) {
524
525
  const lines = view.lines ??= parseUnifiedDiff(diff.diff);
525
526
  return html `
526
527
  <section class="git-diff-section">
527
- <div class="git-viewer-header"><strong>${diff.path ?? "差异"}</strong><small>${diff.staged ? "已暂存" : "未暂存"}${diff.truncated ? " · 已截断" : ""}</small></div>
528
- ${lines.length === 0 ? html `<p class="git-muted">没有差异。</p>` : html `
528
+ <div class="git-viewer-header"><strong>${diff.path ?? t("ui.workspaceGitPanel.diff", "Diff")}</strong><small>${diff.staged ? t("ui.workspaceGitPanel.staged", "Staged") : t("ui.workspaceGitPanel.unstaged", "Unstaged")}${diff.truncated ? t("ui.workspaceGitPanel.truncated", " · Truncated") : ""}</small></div>
529
+ ${lines.length === 0 ? html `<p class="git-muted">${t("ui.unifiedDiffViewer.noDiff", "No diff.")}</p>` : html `
529
530
  <div class="git-diff-scroller">
530
- <div class="git-diff-grid" role="table" aria-label="统一差异">
531
+ <div class="git-diff-grid" role="table" aria-label="${t("ui.unifiedDiffViewer.unifiedDiff", "Unified diff")}">
531
532
  ${lines.map((line) => renderDiffLine(html, line))}
532
533
  </div>
533
534
  </div>
@@ -644,10 +645,10 @@ function defineGitPanelActivityElement() {
644
645
  customElements.define(activityElementTag, GitPanelActivityElement);
645
646
  }
646
647
  function submoduleBadge(html) {
647
- return html `<span class="submodule-badge">子模块</span>`;
648
+ return html `<span class="submodule-badge">${t("ui.workspaceGitPanel.submodule", "Submodule")}</span>`;
648
649
  }
649
650
  function gitSummary(status) {
650
- const branch = status.branch ?? "游离 HEAD";
651
+ const branch = status.branch ?? t("ui.workspaceGitPanel.detachedHead", "Detached HEAD");
651
652
  const ahead = status.ahead ?? 0;
652
653
  const behind = status.behind ?? 0;
653
654
  return ahead === 0 && behind === 0 ? branch : `${branch} · ↑${String(ahead)} ↓${String(behind)}`;
@@ -0,0 +1,7 @@
1
+ // Generated from pi-web-plugins/git/browser/i18n.ts. Do not edit directly.
2
+ let translate;
3
+ export function setTranslator(value) {
4
+ translate = value;
5
+ }
6
+ export const t = (key, fallback, params) => translate?.(key, fallback, params)
7
+ ?? fallback.replace(/\{([A-Za-z0-9_]+)\}/g, (match, name) => String(params?.[name] ?? match));
@@ -1,10 +1,14 @@
1
1
  // Generated from pi-web-plugins/git/browser/pi-web-plugin.ts. Do not edit directly.
2
+ import { setTranslator } from "./i18n.js";
2
3
  import { createGitBrowserContributions } from "./git-panel.js";
3
4
  const plugin = {
4
5
  apiVersion: 4,
5
6
  name: "Git",
6
- activate: ({ pluginId, runtimePluginId, html, svg }) => ({
7
- contributions: createGitBrowserContributions(pluginId, runtimePluginId, html, svg),
8
- }),
7
+ activate: ({ pluginId, runtimePluginId, html, svg, translate }) => {
8
+ setTranslator(translate);
9
+ return ({
10
+ contributions: createGitBrowserContributions(pluginId, runtimePluginId, html, svg),
11
+ });
12
+ },
9
13
  };
10
14
  export default plugin;
@@ -1,4 +1,5 @@
1
1
  // Generated from pi-web-plugins/git/git-backend.ts. Do not edit directly.
2
+ import { t } from "./i18n.js";
2
3
  import { createHash } from "node:crypto";
3
4
  import { realpath } from "node:fs/promises";
4
5
  import { GitStatusCache } from "./gitStatusCache.js";
@@ -147,11 +148,11 @@ async function gitDiffWithRunner(runGit, cwd, options) {
147
148
  args.push("--", path);
148
149
  const result = await runGit(cwd, args);
149
150
  if (result.code !== 0)
150
- throw new Error(result.stderr.trim() || "git diff 执行失败");
151
+ throw new Error(result.stderr.trim() || t("ui.main.0a7b52df3fee", "git diff failed"));
151
152
  if (!staged && path !== undefined && result.stdout === "" && await isUntracked(runGit, cwd, path)) {
152
153
  const untracked = await runGit(cwd, ["diff", "--no-ext-diff", "--color=never", "--no-index", "/dev/null", "--", path]);
153
154
  if (untracked.code !== 0 && untracked.code !== 1)
154
- throw new Error(untracked.stderr.trim() || "git diff 执行失败");
155
+ throw new Error(untracked.stderr.trim() || t("ui.main.0a7b52df3fee", "git diff failed"));
155
156
  return { path, staged, hash: hash(untracked.stdout), diff: untracked.stdout, truncated: untracked.truncated };
156
157
  }
157
158
  return { ...(path === undefined ? {} : { path }), staged, hash: hash(result.stdout), diff: result.stdout, truncated: result.truncated };
@@ -171,11 +172,11 @@ async function submoduleDiff(runGit, owner, path, staged) {
171
172
  args.push("--", rel);
172
173
  const result = await runGit(subCwd, args);
173
174
  if (result.code !== 0)
174
- throw new Error(result.stderr.trim() || "git diff 执行失败");
175
+ throw new Error(result.stderr.trim() || t("ui.main.0a7b52df3fee", "git diff failed"));
175
176
  if (!staged && result.stdout === "" && await isUntracked(runGit, subCwd, rel)) {
176
177
  const untracked = await runGit(subCwd, ["diff", "--no-ext-diff", "--color=never", "--no-index", "/dev/null", "--", rel]);
177
178
  if (untracked.code !== 0 && untracked.code !== 1)
178
- throw new Error(untracked.stderr.trim() || "git diff 执行失败");
179
+ throw new Error(untracked.stderr.trim() || t("ui.main.0a7b52df3fee", "git diff failed"));
179
180
  return { path, staged, hash: hash(untracked.stdout), diff: untracked.stdout, truncated: untracked.truncated };
180
181
  }
181
182
  return { path, staged, hash: hash(result.stdout), diff: result.stdout, truncated: result.truncated };
@@ -418,20 +419,20 @@ function commandResult(result, args) {
418
419
  }
419
420
  function requireStatusInput(input) {
420
421
  if (input !== null && !(isRecord(input) && input["refresh"] === true && Object.keys(input).length === 1))
421
- throw new Error("Git 状态输入必须为 null 或 refresh 对象");
422
+ throw new Error(t("ui.main.ec33070a9080", "Git status input must be null or a refresh object"));
422
423
  }
423
424
  function parseDiffInput(input) {
424
425
  if (!isRecord(input))
425
- throw new Error("Git 差异输入必须是对象");
426
+ throw new Error(t("ui.main.4ae7ff3e02c0", "Git diff input must be an object"));
426
427
  const unsupported = Object.keys(input).find((key) => key !== "path" && key !== "staged");
427
428
  if (unsupported !== undefined)
428
- throw new Error(`Git 差异输入包含不支持的字段:${unsupported}`);
429
+ throw new Error(t("ui.main.629f180b2bba", "Git diff input contains an unsupported field: {arg0}", { arg0: unsupported }));
429
430
  const path = input["path"];
430
431
  const staged = input["staged"];
431
432
  if (path !== undefined && typeof path !== "string")
432
- throw new Error("Git 差异输入的 path 必须是字符串");
433
+ throw new Error(t("ui.main.f1d20e0c6fa6", "Git diff input path must be a string"));
433
434
  if (staged !== undefined && typeof staged !== "boolean")
434
- throw new Error("Git 差异输入的 staged 必须是布尔值");
435
+ throw new Error(t("ui.main.bebd7c4f895a", "Git diff input staged must be a boolean"));
435
436
  return {
436
437
  ...(path === undefined ? {} : { path }),
437
438
  ...(staged === undefined ? {} : { staged }),
@@ -0,0 +1,7 @@
1
+ // Generated from pi-web-plugins/git/i18n.ts. Do not edit directly.
2
+ let translate;
3
+ export function setTranslator(value) {
4
+ translate = value;
5
+ }
6
+ export const t = (key, fallback, params) => translate?.(key, fallback, params)
7
+ ?? fallback.replace(/\{([A-Za-z0-9_]+)\}/g, (match, name) => String(params?.[name] ?? match));
@@ -1,4 +1,5 @@
1
1
  // Generated from pi-web-plugins/git/server-plugin.ts. Do not edit directly.
2
+ import { t, setTranslator } from "./i18n.js";
2
3
  import { basename, resolve } from "node:path";
3
4
  import { requestGitBackend } from "./git-backend.js";
4
5
  const GIT_LOCAL_ENV_VARS = Object.freeze([
@@ -15,6 +16,7 @@ const plugin = {
15
16
  apiVersion: 3,
16
17
  name: "Git",
17
18
  activate(context) {
19
+ setTranslator(context.translate);
18
20
  return {
19
21
  workspaceProvider: createGitWorkspaceProvider(context),
20
22
  peer: { request: (request) => requestGitBackend(context, request) },
@@ -28,23 +30,23 @@ export function createGitWorkspaceProvider(context) {
28
30
  async probe(project, signal) {
29
31
  const result = await runGit(context, project.path, ["rev-parse", "--is-inside-work-tree"], signal);
30
32
  if (result.signal !== null)
31
- throw new Error(`Git 仓库探测因信号 ${result.signal} 结束`);
33
+ throw new Error(t("ui.main.8919cbc9c0bd", "Git repository probe ended with signal {arg0}", { arg0: result.signal }));
32
34
  if (result.exitCode !== 0)
33
35
  return "pass";
34
36
  return result.stdout.trim() === "true" ? "claim" : "pass";
35
37
  },
36
38
  async list(project, signal) {
37
- const rootResult = await requireGit(runGit(context, project.path, ["rev-parse", "--show-toplevel"], signal), "解析 Git 工作树根目录");
39
+ const rootResult = await requireGit(runGit(context, project.path, ["rev-parse", "--show-toplevel"], signal), t("ui.main.49c35c822771", "resolve the Git worktree root"));
38
40
  const mainRootOutput = rootResult.stdout.trim();
39
41
  if (mainRootOutput === "")
40
- throw new Error("Git 返回了空的工作树根目录");
42
+ throw new Error(t("ui.main.f1639c9e2fd7", "Git returned an empty worktree root"));
41
43
  const mainRoot = resolve(mainRootOutput);
42
- const commonDirectoryResult = await requireGit(runGit(context, project.path, ["rev-parse", "--git-common-dir"], signal), "解析 Git 公共目录");
44
+ const commonDirectoryResult = await requireGit(runGit(context, project.path, ["rev-parse", "--git-common-dir"], signal), t("ui.main.d59fce8c03cf", "resolve the Git common directory"));
43
45
  const commonDirectoryOutput = commonDirectoryResult.stdout.trim();
44
46
  if (commonDirectoryOutput === "")
45
- throw new Error("Git 返回了空的公共目录");
47
+ throw new Error(t("ui.main.8d51c7fbda53", "Git returned an empty common directory"));
46
48
  const commonDirectory = resolve(project.path, commonDirectoryOutput);
47
- const listResult = await requireGit(runGit(context, project.path, ["worktree", "list", "--porcelain", "-z"], signal), "列出 Git 工作树");
49
+ const listResult = await requireGit(runGit(context, project.path, ["worktree", "list", "--porcelain", "-z"], signal), t("ui.main.09734cee0f68", "list Git worktrees"));
48
50
  const worktrees = parseGitWorktreeList(listResult.stdout)
49
51
  .filter((worktree) => worktree.bare !== true)
50
52
  .map((worktree) => {
@@ -63,7 +65,7 @@ export function createGitWorkspaceProvider(context) {
63
65
  if (selectable.length === 0)
64
66
  return [singleGitWorkspace(project)];
65
67
  return selectable.map(({ worktree, path, isMain }) => {
66
- const label = worktree.branch ?? (worktree.detached === true ? "游离 HEAD" : basename(worktree.path) || worktree.path);
68
+ const label = worktree.branch ?? (worktree.detached === true ? t("ui.workspaceGitPanel.detachedHead", "Detached HEAD") : basename(worktree.path) || worktree.path);
67
69
  return {
68
70
  key: path,
69
71
  path,
@@ -86,18 +88,18 @@ export function createGitWorkspaceProvider(context) {
86
88
  async prepareRemove({ project, workspace, signal }) {
87
89
  const privatePath = gitPrivateWorktreePath(workspace);
88
90
  if (resolve(privatePath) !== workspace.path) {
89
- throw new Error("Git 工作区删除数据与当前工作区路径不再匹配");
91
+ throw new Error(t("ui.main.ee323b371b28", "Git workspace removal data no longer matches the current workspace path"));
90
92
  }
91
- const listResult = await requireGit(runGit(context, project.path, ["worktree", "list", "--porcelain", "-z"], signal), "删除前验证 Git 工作树");
93
+ const listResult = await requireGit(runGit(context, project.path, ["worktree", "list", "--porcelain", "-z"], signal), t("ui.main.67b7774d37e3", "validate the Git worktree before removal"));
92
94
  const current = parseGitWorktreeList(listResult.stdout)
93
95
  .find((worktree) => resolve(worktree.path) === workspace.path);
94
96
  if (current === undefined || current.prunable === true) {
95
- throw new Error("Git 工作树已不可用于删除");
97
+ throw new Error(t("ui.main.2eaaec45ffc2", "Git worktree is no longer available for removal"));
96
98
  }
97
99
  if (current.bare === true)
98
- throw new Error("裸 Git 仓库不能作为链接工作树删除");
100
+ throw new Error(t("ui.main.e316bd0c1e32", "A bare Git workspace cannot be removed as a linked worktree"));
99
101
  return {
100
- title: `删除工作区:${workspace.label}`,
102
+ title: t("ui.shared.168f8f19045c", "Delete workspace: {workspace}", { workspace: workspace.label }),
101
103
  command: `git worktree remove ${shellQuote(workspace.path)}`,
102
104
  };
103
105
  },
@@ -139,18 +141,18 @@ function singleGitWorkspace(project) {
139
141
  }
140
142
  function gitRemovalPresentation(label, path) {
141
143
  return {
142
- actionLabel: "删除工作区",
143
- confirmation: `删除工作区 ${label}?\n\n此操作将运行 git worktree remove 并删除:\n${path}\n\n不会删除对应的 Git 分支。`,
144
+ actionLabel: t("client.actions.delete.workspace.1bca7e", "Delete workspace"),
145
+ confirmation: t("ui.main.8e2b2416adcd", "Delete workspace {arg0}?\n\nThis runs git worktree remove and deletes:\n{arg1}\n\nThe corresponding Git branch will not be deleted.", { arg0: label, arg1: path }),
144
146
  };
145
147
  }
146
148
  function gitPrivateWorktreePath(workspace) {
147
149
  const data = workspace.data;
148
150
  if (typeof data !== "object" || data === null || Array.isArray(data)) {
149
- throw new Error("Git 工作区删除数据不可用");
151
+ throw new Error(t("ui.main.b6c981521483", "Git workspace removal data is unavailable"));
150
152
  }
151
153
  const path = Reflect.get(data, "worktreePath");
152
154
  if (typeof path !== "string" || path === "")
153
- throw new Error("用于删除的 Git 工作树路径不可用");
155
+ throw new Error(t("ui.main.2f42169d50eb", "Git worktree path is unavailable for removal"));
154
156
  return path;
155
157
  }
156
158
  function shellQuote(value) {
@@ -164,7 +166,7 @@ async function runGit(context, cwd, args, signal) {
164
166
  signal,
165
167
  });
166
168
  if (result.stdoutTruncated || result.stderrTruncated) {
167
- throw new Error(`git ${args.join(" ")} 超出宿主输出限制`);
169
+ throw new Error(t("ui.main.f1dbb26bf138", "git {arg0} exceeded the host output limit", { arg0: args.join(" ") }));
168
170
  }
169
171
  return result;
170
172
  }
@@ -173,6 +175,6 @@ async function requireGit(resultPromise, action) {
173
175
  if (result.signal === null && result.exitCode === 0)
174
176
  return result;
175
177
  const detail = result.stderr.trim();
176
- const outcome = result.signal === null ? `退出码 ${String(result.exitCode)}` : `信号 ${result.signal}`;
177
- throw new Error(`无法${action}(${outcome})${detail === "" ? "" : `:${detail}`}`);
178
+ const outcome = result.signal === null ? t("client.shellMessages.exit.code.2beadf", "Exit code {value1}", { value1: String(result.exitCode) }) : t("ui.main.c008196ee907", "signal {arg0}", { arg0: result.signal });
179
+ throw new Error(t("ui.main.0def9a625382", "Could not {arg0} ({arg1}){arg2}", { arg0: action, arg1: outcome, arg2: detail === "" ? "" : `:${detail}` }));
178
180
  }
@@ -0,0 +1,7 @@
1
+ // Generated from pi-web-plugins/info/i18n.ts. Do not edit directly.
2
+ let translate;
3
+ export function setTranslator(value) {
4
+ translate = value;
5
+ }
6
+ export const t = (key, fallback, params) => translate?.(key, fallback, params)
7
+ ?? fallback.replace(/\{([A-Za-z0-9_]+)\}/g, (match, name) => String(params?.[name] ?? match));