dsh-switchman 1.5.0 → 1.7.0

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.
package/client.js CHANGED
@@ -53,10 +53,55 @@ window.__ModuleLoader__.load({
53
53
  { value: 'ko', label: '한국어' },
54
54
  { value: 'es', label: 'Español' },
55
55
  { value: 'fr', label: 'Français' },
56
+ { value: 'it', label: 'Italiano' },
57
+ { value: 'pt', label: 'Português' },
56
58
  { value: 'de', label: 'Deutsch' },
57
59
  { value: 'ru', label: 'Русский' },
58
60
  ];
59
61
 
62
+ /** Interface-language choices for this plugin's own UI: "auto"
63
+ * follows the DSH app language; any other value forces the plugin
64
+ * UI into that locale (extra locales resolve from the inline
65
+ * EXTRA_UI_DICTS table, falling back to English). Labels are
66
+ * endonyms, identical in every UI language. */
67
+ const UI_LOCALE_OPTIONS = [
68
+ { value: 'auto', label: 'Auto' },
69
+ { value: 'en', label: 'English' },
70
+ { value: 'zh', label: '简体中文' },
71
+ { value: 'zh-TW', label: '繁體中文' },
72
+ { value: 'ja', label: '日本語' },
73
+ { value: 'ko', label: '한국어' },
74
+ { value: 'de', label: 'Deutsch' },
75
+ { value: 'es', label: 'Español' },
76
+ { value: 'fr', label: 'Français' },
77
+ { value: 'it', label: 'Italiano' },
78
+ { value: 'pt', label: 'Português' },
79
+ { value: 'ru', label: 'Русский' },
80
+ ];
81
+
82
+ /** Repaint signal for the manual interface-locale override: t()
83
+ * reads an apply()-scope closure variable, so every component that
84
+ * renders plugin strings subscribes to this tiny store to
85
+ * re-render when the override changes (the DSH locale store only
86
+ * fires on app-language changes). Snapshot is a monotonic version
87
+ * counter; notify never lets one bad listener block the rest. */
88
+ const uiLocaleListeners = new Set();
89
+ let uiLocaleVersion = 0;
90
+ const subscribeUiLocale = (listener) => {
91
+ uiLocaleListeners.add(listener);
92
+ return () => uiLocaleListeners.delete(listener);
93
+ };
94
+ const notifyUiLocale = () => {
95
+ uiLocaleVersion += 1;
96
+ for (const listener of uiLocaleListeners) {
97
+ try {
98
+ listener();
99
+ } catch {
100
+ /* one bad listener never blocks the rest */
101
+ }
102
+ }
103
+ };
104
+
60
105
  /** Sentinel select value standing for a hand-typed language. */
61
106
  const CUSTOM = '__custom__';
62
107
 
@@ -145,6 +190,7 @@ window.__ModuleLoader__.load({
145
190
 
146
191
  /** Every settings field this page edits, in mutate order. */
147
192
  const ALL_FIELDS = [
193
+ 'uiLocale',
148
194
  ...LANG_FIELDS,
149
195
  ...POOL_FIELDS.map(({ field }) => field),
150
196
  ...POOL_FIELDS.map(({ manualField }) => manualField),
@@ -180,11 +226,12 @@ window.__ModuleLoader__.load({
180
226
  : route;
181
227
  }
182
228
 
183
- /** 思考强度 fallback 档位(模型拿不到 wire 元数据时用);
184
- * 真实列表以 wire reasoning.efforts 为准。 */
229
+ /** Reasoning-effort fallback tiers (used when wire metadata is
230
+ * unavailable for a model); the real list follows wire
231
+ * reasoning.efforts. */
185
232
  const EFFORTS = ['low', 'medium', 'high'];
186
233
 
187
- /** 一条格式良好的 effort 条目({provider, model, effort}),或 null。 */
234
+ /** One well-formed effort entry ({provider, model, effort}), or null. */
188
235
  function sanitizeEffortEntry(entry) {
189
236
  const route = sanitizeRoute(entry);
190
237
  if (route === null) return null;
@@ -239,9 +286,14 @@ window.__ModuleLoader__.load({
239
286
  const bool = (field, def) =>
240
287
  typeof value?.[field] === 'boolean' ? value[field] : def;
241
288
  return {
242
- // 作用域枚举(host 快照缺失/非法值一律按 global 呈现);
243
- // 放在首位,与 save() 组装的 desired 键序一致,保持
244
- // sameValues 的无改动早退路径可用。
289
+ // Interface-locale enum (a missing/invalid host snapshot
290
+ // always presents as "auto"), then the scope enum (same
291
+ // fallback to "global"). Both sit first to mirror save()'s
292
+ // desired object; equality itself is canonical()-based, so
293
+ // key order is not load-bearing.
294
+ uiLocale: UI_LOCALE_OPTIONS.some((option) => option.value === value?.uiLocale)
295
+ ? value.uiLocale
296
+ : 'auto',
245
297
  langScope: value?.langScope === 'project' ? 'project' : 'global',
246
298
  langConversation: string('langConversation'),
247
299
  langComments: string('langComments'),
@@ -289,6 +341,7 @@ window.__ModuleLoader__.load({
289
341
  langConversation: values.langConversation,
290
342
  langComments: values.langComments,
291
343
  langDocs: values.langDocs,
344
+ uiLocale: values.uiLocale,
292
345
  ...Object.fromEntries(
293
346
  POOL_FIELDS.map(({ field, manualField }) => [
294
347
  field,
@@ -594,6 +647,11 @@ window.__ModuleLoader__.load({
594
647
  whitelistSyncError: '同步失败:{error}',
595
648
  whitelistSyncPending: '等待同步…',
596
649
  whitelistSyncNote: '白名单变更仅对之后新建的会话生效。',
650
+ uiSectionTitle: '界面',
651
+ uiSectionDescription: '本插件自身界面(徽标、面板、本设置页)的显示语言。',
652
+ uiLocaleLabel: '界面语言',
653
+ uiLocaleHelp: '「自动」跟随 DeepSeek Harness 应用语言;选择具体语言后,本插件界面将固定为该语言。',
654
+ uiLocaleAuto: '自动(跟随 DSH)',
597
655
  },
598
656
  en: {
599
657
  badge: 'Team autonomy',
@@ -747,6 +805,1256 @@ window.__ModuleLoader__.load({
747
805
  whitelistSyncError: 'Sync failed: {error}',
748
806
  whitelistSyncPending: 'Waiting to sync…',
749
807
  whitelistSyncNote: 'Whitelist changes only affect sessions created afterwards.',
808
+ uiSectionTitle: 'Interface',
809
+ uiSectionDescription: "Display language for this plugin's own UI (badge, panel, this settings page).",
810
+ uiLocaleLabel: 'Interface language',
811
+ uiLocaleHelp: "Auto follows the DeepSeek Harness app language; picking a language forces this plugin's UI into it.",
812
+ uiLocaleAuto: 'Auto (follow DSH)',
813
+ },
814
+ };
815
+
816
+ /** Inline dictionaries for the extra interface locales (every
817
+ * UI_LOCALE_OPTIONS tag beyond zh/en). Inlined on purpose: the
818
+ * harness loads plugin client bundles as classic scripts, where
819
+ * ESM-only syntax (module meta context, dynamic module
820
+ * loading) is a parse-time SyntaxError there, and
821
+ * the plugin asset route serves only client*.js chunks — so an
822
+ * on-demand module fetch could never work. Key set mirrors the
823
+ * DICTS en table (verified by script at generation time). Keep in
824
+ * sync with UI_LOCALE_OPTIONS and the host ENUM_FIELDS. */
825
+ const EXTRA_UI_DICTS = {
826
+ 'zh-TW': {
827
+ badge: '自主團隊',
828
+ badgeTip: 'dsh-switchman:四個內建預設(standard / ptc / minimal / cordis)已注入自主智能體團隊調度規程',
829
+ handoverActive: '交接進行中',
830
+ handoverPhaseBackup: '備份會話',
831
+ handoverPhaseCompacting: '壓縮上下文',
832
+ handoverPhaseContinuation: '喚醒續接',
833
+ handoverActiveTip: 'Switchman 正在背景交接:fork 備份會話並壓縮上下文,完成後自動繼續任務;期間會話靜止屬正常現象。',
834
+ visionHintNeedsPool: '目前模型不支援讀圖:請在 dsh-switchman 設定中配置多模態池模型,之後用 /vision 傳送圖片。',
835
+ visionHintUseVision: '目前模型不支援讀圖:圖片請用 /vision 傳送(將自動派發多模態池讀取)。',
836
+ visionAutoConverted: '圖片直傳被拒:已自動改用 /vision 重送(由多模態池讀取)。',
837
+ settingsTitle: 'dsh-switchman',
838
+ panelLabel: 'Switchman 調度中心',
839
+ settingsDescription: '設定 dsh-switchman 的各項偏好。',
840
+ langSectionTitle: '語言偏好',
841
+ langSectionDescription: '控制智能體的對話、程式碼註解與文件撰寫語言。',
842
+ langScopeLabel: '語言作用範圍',
843
+ langScopeHelp: '選擇這三項語言偏好的存放位置。',
844
+ langScopeGlobal: '全域(本 profile)',
845
+ langScopeProject: '按專案(.switchman/lang.json)',
846
+ langProjectNote: '按專案模式:各專案讀取自身的 .switchman/lang.json;首次詢問的答案會寫入該檔案,檔案不存在時每個會話都會詢問。以下三項僅在全域模式生效。',
847
+ langConversationLabel: '對話語言',
848
+ langConversationHelp: '智能體回覆與討論使用的語言;未設定時會在首次使用時詢問一次並記住。',
849
+ langCommentsLabel: '程式碼註解語言',
850
+ langCommentsHelp: '智能體撰寫程式碼註解使用的語言。',
851
+ langDocsLabel: '文件語言',
852
+ langDocsHelp: '智能體撰寫文件使用的語言。',
853
+ followConversation: '跟隨對話語言',
854
+ notSetAsk: '未設定(首次使用時詢問)',
855
+ customLanguage: '自訂…',
856
+ customLanguagePlaceholder: '語言名稱或 BCP 標籤',
857
+ customLanguageRequired: '請輸入自訂語言(1–48 個字元)。',
858
+ currentValue: '目前:{value}',
859
+ currentValueUnset: '目前:未設定',
860
+ suggestedValue: '建議:{value}',
861
+ save: '儲存',
862
+ saving: '儲存中…',
863
+ discard: '放棄修改',
864
+ saveFailed: '本部署沒有接受這些值,已保留供你修改。',
865
+ saveConflict: '設定已在其他位置更新。請放棄修改後重試。',
866
+ formLoading: '正在載入設定…',
867
+ formUnavailable: '該外掛目前未載入,暫時無法設定。',
868
+ formReadOnly: '本部署的設定為唯讀。',
869
+ dispatchSectionTitle: '派發池與模型排序',
870
+ dispatchSectionDescription: '按任務複雜度把模型分組進六個派發池,並維護能力排序;僅影響 dsh-switchman 的委派調度。',
871
+ dispatchProgress: '已設定 {pools}/6 池 · 已排名 {ranked} 項 · 模式 {mode}',
872
+ poolEconomyTitle: '輕量池 · economy',
873
+ poolEconomyDesc: '輕量批次與低複雜度任務',
874
+ poolMechanicalTitle: '機械池 · mechanical',
875
+ poolMechanicalDesc: '機械改寫與模板化操作',
876
+ poolMainTitle: '主力池 · main',
877
+ poolMainDesc: '常規編碼與日常任務',
878
+ poolHardTitle: '高難池 · hard',
879
+ poolHardDesc: '高難推理與大規模重構',
880
+ poolVisionTitle: '多模態池 · vision',
881
+ poolVisionDesc: '影像等多模態輸入任務',
882
+ poolReviewTitle: '複審池 · review',
883
+ poolReviewDesc: '唯讀複審與獨立驗證',
884
+ poolSelectAll: '全選',
885
+ poolClear: '清空',
886
+ poolEmpty: '暫無候選模型',
887
+ poolManualLabel: '手動序',
888
+ poolManualHelp: '開啟後按清單順序派發(首個即首選);未開啟按能力排序自動排。',
889
+ poolManualSelected: '已選 · 派發優先序',
890
+ poolManualAddable: '可新增',
891
+ poolMoveUp: '上移',
892
+ poolMoveDown: '下移',
893
+ poolRemoveOne: '移除',
894
+ poolEffortFollow: '跟隨泳道',
895
+ poolEffortLabel: '思考強度',
896
+ poolEffortHelp: '手動指定該模型的思考強度,派發時優先於泳道預設',
897
+ catalogLoading: '正在載入模型目錄…',
898
+ catalogLoadFailed: '無法載入模型目錄。',
899
+ catalogRetry: '重試',
900
+ catalogPartial: '部分模型提供者暫時無法載入;已儲存的選擇仍可移除。',
901
+ catalogEmpty: '目前沒有模型提供者公布模型。',
902
+ catalogUnavailableGroup: '已儲存但目前不可用',
903
+ catalogUnavailable: '目前不可用',
904
+ unauthorizedBadge: '未在 DSH 設定的子智能體模型選擇授權清單中',
905
+ unauthorizedHint: '標有 ⚠ 的模型未在 DSH 設定 → 子智能體 → 模型選擇 中授權,Agent 明確指定它們會被拒絕;去 DSH 設定授權,或讓 Agent 走隱式派發。',
906
+ rankTitle: '能力排序',
907
+ rankDescription: '序號即能力序(最強在前),可為每項錨定 S/A/B/C 檔。清單為六池選中 ∪ 已有排序;任意編輯都會固化目前顯示順序。',
908
+ rankEmpty: '先在上方池中勾選模型,排序清單會自動出現。',
909
+ rankTier: '檔位',
910
+ rankTierNone: '—',
911
+ rankMoveUp: '上移',
912
+ rankMoveDown: '下移',
913
+ rankRemove: '移出排序',
914
+ enforceLabel: '執行模式',
915
+ enforceOff: '關閉',
916
+ enforceAdvice: '建議',
917
+ enforceEnforce: '強制',
918
+ enforceHelpOff: '不向委派注入任何池子指引。',
919
+ enforceHelpAdvice: '池子指引作為建議注入,模型可自行偏離。',
920
+ enforceHelpEnforce: '池子指引作為硬性約束注入,偏離會被拒絕。',
921
+ wmSectionTitle: '上下文水位',
922
+ wmSectionDescription: '按 token 用量分級收緊行為:建議、限讀與收尾、自動交接。',
923
+ wmSoftLabel: '建議水位(soft)',
924
+ wmSoftHelp: '達到後出現橫幅提示,並建議委派與整理上下文。',
925
+ wmHardLabel: '硬水位(hard)',
926
+ wmHardHelp: '達到後讀取預算收緊,並建議收尾目前工作。',
927
+ wmForceLabel: '強制水位(force)',
928
+ wmForceHelp: '達到後建議備份並移交壓縮(可設為自動)。',
929
+ wmReadBudgetLabel: '單次讀取預算',
930
+ wmReadBudgetHelp: '每次讀取的 token 預算;每輪上限為其兩倍。',
931
+ wmNumberInvalid: '請輸入不小於 {min} 的整數。',
932
+ wmOrderInvalid: '三檔水位需嚴格遞增:soft < hard < force。',
933
+ wmDenyModeLabel: '硬檔行為',
934
+ wmDenyModeCap: '限流放行',
935
+ wmDenyModeDeny: '直接拒絕',
936
+ wmDenyModeHelpCap: '超出讀取預算的呼叫放行,但記錄警示。',
937
+ wmDenyModeHelpDeny: '超出讀取預算的呼叫直接拒絕。',
938
+ wmAutoHandoverLabel: '自動交接',
939
+ wmAutoHandoverHelp: '達到強制水位時自動備份並移交壓縮,無需手動確認。',
940
+ wmSubagentTitle: '子智能體',
941
+ wmSubagentCapLabel: '子智能體上下文上限',
942
+ wmSubagentCapHelp: '開啟後子智能體可用下方獨立強制閾值;關閉則完全跟隨上方三檔水位。',
943
+ wmSubagentForceLabel: '子智能體強制閾值',
944
+ wmSubagentForceHelp: '僅覆蓋子智能體的 force 檔(soft/hard 與主會話共用);0 = 跟隨上方強制水位。',
945
+ wmSubagentFollowForce: '跟隨 force 檔(0)',
946
+ wmCommands: '命令:/ctx-pause 暫停水位干預 · /ctx-resume 恢復干預 · /ctx-handover 立即備份並交接壓縮。',
947
+ teamsSectionTitle: '智能體團隊',
948
+ teamsSectionDescription: '切換派發形態:關閉為純 subagent 派發(DSH 出廠保守團隊策略接管);開啟後注入自主團隊規程並啟用 Agent Teams。',
949
+ teamsModeLabel: '智能體團隊模式',
950
+ teamsModeHelp: '開啟後注入團隊規程(預設委派 + 分級驗證 + 任務板紀律),並自動啟用 DSH 的 Agent Teams bundle;派發池的 ⚠ 授權徽標僅在開啟時顯示。',
951
+ syncWhitelistLabel: '同步子智能體模型白名單',
952
+ syncWhitelistHelp: '獨立開關(不依賴智能體團隊模式):把六池選中模型的聯集整體寫入 DSH「設定 → 子智能體 → 模型選擇」的授權清單;dsh-switchman 成為唯一事實來源。',
953
+ whitelistSyncOk: '已同步 {count} 條({time})。',
954
+ whitelistSyncError: '同步失敗:{error}',
955
+ whitelistSyncPending: '等待同步…',
956
+ whitelistSyncNote: '白名單變更僅對之後新建的會話生效。',
957
+ uiSectionTitle: '介面',
958
+ uiSectionDescription: '本外掛自身 UI(徽章、面板、此設定頁)的顯示語言。',
959
+ uiLocaleLabel: '介面語言',
960
+ uiLocaleHelp: '「自動」跟隨 DeepSeek Harness 應用程式語言;指定語言後,本外掛的 UI 固定使用該語言。',
961
+ uiLocaleAuto: '自動(跟隨 DSH)',
962
+ },
963
+ ja: {
964
+ badge: '自律チーム',
965
+ badgeTip: 'dsh-switchman:内蔵の 4 プリセット(standard / ptc / minimal / cordis)には自律エージェントチームのディスパッチ規律が注入済み',
966
+ handoverActive: 'ハンドオーバー進行中',
967
+ handoverPhaseBackup: 'バックアップ作成中',
968
+ handoverPhaseCompacting: 'コンテキスト圧縮中',
969
+ handoverPhaseContinuation: '継続セッション起動中',
970
+ handoverActiveTip: 'Switchman がバックグラウンドでハンドオーバー中です:セッションを fork してバックアップし、コンテキストを圧縮します。完了するとタスクは自動的に再開します。この間セッションが静止するのは正常です。',
971
+ visionHintNeedsPool: 'このモデルは画像を読めません:dsh-switchman の設定でマルチモーダルプールのモデルを追加し、画像は /vision で送信してください。',
972
+ visionHintUseVision: 'このモデルは画像を読めません:画像は /vision で送ってください(自動的にマルチモーダルプールへルーティングされます)。',
973
+ visionAutoConverted: '画像の直接送信は拒否されました:自動的に /vision で再送信します(マルチモーダルプールが読み取ります)。',
974
+ settingsTitle: 'dsh-switchman',
975
+ panelLabel: 'Switchman ディスパッチセンター',
976
+ settingsDescription: 'dsh-switchman の各種設定を行います。',
977
+ langSectionTitle: '言語設定',
978
+ langSectionDescription: 'エージェントの返信・コードコメント・ドキュメントの言語を制御します。',
979
+ langScopeLabel: '言語スコープ',
980
+ langScopeHelp: 'これらの言語設定の保存先です。',
981
+ langScopeGlobal: 'グローバル(このプロファイル)',
982
+ langScopeProject: 'プロジェクト単位(.switchman/lang.json)',
983
+ langProjectNote: 'プロジェクトモード:各プロジェクトは自身の .switchman/lang.json を読み取ります。初回の回答はそこに保存され、ファイルが存在するまで毎セッション尋ねます。下の 3 項目はグローバルモードでのみ有効です。',
984
+ langConversationLabel: '会話言語',
985
+ langConversationHelp: 'エージェントが返信や議論に使う言語です。未設定の場合、最初の使用時に一度だけ尋ねて記憶されます。',
986
+ langCommentsLabel: 'コードコメント言語',
987
+ langCommentsHelp: 'エージェントがコードコメントを書く言語です。',
988
+ langDocsLabel: 'ドキュメント言語',
989
+ langDocsHelp: 'エージェントがドキュメントを書く言語です。',
990
+ followConversation: '会話言語に従う',
991
+ notSetAsk: '未設定(初回使用時に尋ねる)',
992
+ customLanguage: 'カスタム…',
993
+ customLanguagePlaceholder: '言語名または BCP タグ',
994
+ customLanguageRequired: 'カスタム言語を入力してください(1–48 文字)。',
995
+ currentValue: '現在:{value}',
996
+ currentValueUnset: '現在:未設定',
997
+ suggestedValue: '推奨:{value}',
998
+ save: '保存',
999
+ saving: '保存中…',
1000
+ discard: '変更を破棄',
1001
+ saveFailed: 'このデプロイメントはこれらの値を受け付けませんでした。修正できるよう残してあります。',
1002
+ saveConflict: '設定が別の場所で変更されました。下書きを破棄してもう一度お試しください。',
1003
+ formLoading: '設定を読み込み中…',
1004
+ formUnavailable: 'このプラグインは現在ロードされていないため、設定できません。',
1005
+ formReadOnly: 'このデプロイメントの設定は読み取り専用です。',
1006
+ dispatchSectionTitle: 'ディスパッチプールとモデル順位',
1007
+ dispatchSectionDescription: 'タスクの複雑さに応じてモデルを 6 つのディスパッチプールに分け、能力順位を管理します。dsh-switchman の委譲にのみ影響します。',
1008
+ dispatchProgress: '{pools}/6 プール設定 · {ranked} 件ランク済み · モード {mode}',
1009
+ poolEconomyTitle: '軽量 · economy',
1010
+ poolEconomyDesc: '小口のバッチと低複雑度タスク',
1011
+ poolMechanicalTitle: '機械的 · mechanical',
1012
+ poolMechanicalDesc: '機械的な書き換えとテンプレート操作',
1013
+ poolMainTitle: '主力 · main',
1014
+ poolMainDesc: '日常的なコーディングと定常タスク',
1015
+ poolHardTitle: '高難度 · hard',
1016
+ poolHardDesc: '難しい推論と大規模リファクタリング',
1017
+ poolVisionTitle: 'マルチモーダル · vision',
1018
+ poolVisionDesc: '画像などのマルチモーダル作業',
1019
+ poolReviewTitle: 'レビュー · review',
1020
+ poolReviewDesc: '読み取り専用レビューと独立検証',
1021
+ poolSelectAll: 'すべて選択',
1022
+ poolClear: 'クリア',
1023
+ poolEmpty: '候補モデルなし',
1024
+ poolManualLabel: '手動順序',
1025
+ poolManualHelp: 'オンにするとリストの順序でディスパッチします(先頭=第一候補)。オフなら能力順で自動的に並びます。',
1026
+ poolManualSelected: '選択済み · ディスパッチ優先順',
1027
+ poolManualAddable: 'モデルを追加',
1028
+ poolMoveUp: '上へ',
1029
+ poolMoveDown: '下へ',
1030
+ poolRemoveOne: '削除',
1031
+ poolEffortFollow: 'レーンに従う',
1032
+ poolEffortLabel: '思考強度',
1033
+ poolEffortHelp: 'このモデルの思考強度を固定します。ディスパッチ時にレーンのデフォルトより優先されます',
1034
+ catalogLoading: 'モデルカタログを読み込み中…',
1035
+ catalogLoadFailed: 'モデルカタログを読み込めませんでした。',
1036
+ catalogRetry: '再試行',
1037
+ catalogPartial: '一部のモデルプロバイダーを読み込めませんでした。保存済みの選択は引き続き削除できます。',
1038
+ catalogEmpty: '現在モデルを公開しているプロバイダーはありません。',
1039
+ catalogUnavailableGroup: '保存済みだが現在利用不可',
1040
+ catalogUnavailable: '現在利用不可',
1041
+ unauthorizedBadge: 'DSH 設定のサブエージェント・モデル選択の許可リストに含まれていません',
1042
+ unauthorizedHint: '⚠ マークのモデルは DSH 設定 → サブエージェント → モデル選択 で許可されていません。エージェントが明示的に指定すると拒否されます。DSH 設定で許可するか、暗黙のディスパッチを利用してください。',
1043
+ rankTitle: '能力順位',
1044
+ rankDescription: '番号は能力順(最強が先頭)で、各項目に S/A/B/C ティアを設定できます。リストはプール選択 ∪ 保存済み順位です。編集すると表示中の順序がそのまま保存されます。',
1045
+ rankEmpty: '上のプールでモデルを選択すると、順位リストが自動的に表示されます。',
1046
+ rankTier: 'ティア',
1047
+ rankTierNone: '—',
1048
+ rankMoveUp: '上へ',
1049
+ rankMoveDown: '下へ',
1050
+ rankRemove: '順位から削除',
1051
+ enforceLabel: '強制モード',
1052
+ enforceOff: 'オフ',
1053
+ enforceAdvice: 'アドバイス',
1054
+ enforceEnforce: '強制',
1055
+ enforceHelpOff: '委譲にプールのガイダンスを注入しません。',
1056
+ enforceHelpAdvice: 'プールのガイダンスをアドバイスとして注入します。モデルは外れることができます。',
1057
+ enforceHelpEnforce: 'プールのガイダンスを厳格な制約として注入します。外れた場合は拒否されます。',
1058
+ wmSectionTitle: 'コンテキスト水位',
1059
+ wmSectionDescription: 'token 使用量に応じた段階的な引き締め:アドバイス、読み取り制限と締めくくり、自動ハンドオーバー。',
1060
+ wmSoftLabel: 'ソフト水位(soft)',
1061
+ wmSoftHelp: '超えるとバナーが表示され、委譲やコンテキスト整理が推奨されます。',
1062
+ wmHardLabel: 'ハード水位(hard)',
1063
+ wmHardHelp: '超えると読み取り予算が引き締められ、仕事の締めくくりが推奨されます。',
1064
+ wmForceLabel: '強制水位(force)',
1065
+ wmForceHelp: '超えるとバックアップと圧縮へのハンドオーバーが推奨されます(自動化可能)。',
1066
+ wmReadBudgetLabel: '読み取り予算',
1067
+ wmReadBudgetHelp: '1 回の読み取りあたりの token 予算です。各ラウンドの上限はその 2 倍です。',
1068
+ wmNumberInvalid: '{min} 以上の整数を入力してください。',
1069
+ wmOrderInvalid: '3 段階の水位は厳密に昇順にしてください:soft < hard < force。',
1070
+ wmDenyModeLabel: 'ハード段階の動作',
1071
+ wmDenyModeCap: '制限して警告',
1072
+ wmDenyModeDeny: '即時拒否',
1073
+ wmDenyModeHelpCap: '予算超過の呼び出しは通しますが、警告を記録します。',
1074
+ wmDenyModeHelpDeny: '予算超過の呼び出しは即座に拒否します。',
1075
+ wmAutoHandoverLabel: '自動ハンドオーバー',
1076
+ wmAutoHandoverHelp: '強制水位に達したら、確認なしでバックアップして圧縮へハンドオーバーします。',
1077
+ wmSubagentTitle: 'サブエージェント',
1078
+ wmSubagentCapLabel: 'サブエージェントのコンテキスト上限',
1079
+ wmSubagentCapHelp: 'オンにすると、下の専用強制しきい値を使えます。オフなら上の 3 段階の水位に完全に従います。',
1080
+ wmSubagentForceLabel: 'サブエージェント強制しきい値',
1081
+ wmSubagentForceHelp: 'サブエージェントの force 段階のみを上書きします(soft/hard はメインセッションと共通)。0 なら上の強制水位に従います。',
1082
+ wmSubagentFollowForce: 'force 段階に従う(0)',
1083
+ wmCommands: 'コマンド:/ctx-pause で水位アクションを一時停止 · /ctx-resume で再開 · /ctx-handover で今すぐバックアップしてハンドオーバー。',
1084
+ teamsSectionTitle: 'エージェントチーム',
1085
+ teamsSectionDescription: 'ディスパッチ形態の切り替え:オフは通常の subagent ディスパッチ(DSH 出荷時の保守的なチームポリシーが引き継ぎ)。オンにすると自律チーム規律を注入し、Agent Teams を有効にします。',
1086
+ teamsModeLabel: 'エージェントチームモード',
1087
+ teamsModeHelp: 'オンにするとチーム規律(デフォルト委譲 + 段階的検証 + タスクボードの規律)を注入し、DSH の Agent Teams バンドルを有効にします。ディスパッチプールの ⚠ 許可バッジはこのモードでのみ表示されます。',
1088
+ syncWhitelistLabel: 'サブエージェントモデル許可リストの同期',
1089
+ syncWhitelistHelp: '独立したスイッチです(エージェントチームモード不要):6 プールで選択されたモデルの和集合を、DSH の「設定 → サブエージェント → モデル選択」許可リストにまるごと書き込みます。dsh-switchman が唯一の事実源になります。',
1090
+ whitelistSyncOk: '{count} 件を同期しました({time})。',
1091
+ whitelistSyncError: '同期に失敗しました:{error}',
1092
+ whitelistSyncPending: '同期待ち…',
1093
+ whitelistSyncNote: '許可リストの変更は、以降に新しく作成されたセッションにのみ反映されます。',
1094
+ uiSectionTitle: 'インターフェース',
1095
+ uiSectionDescription: 'このプラグイン自身の UI(バッジ、パネル、この設定ページ)の表示言語です。',
1096
+ uiLocaleLabel: 'インターフェース言語',
1097
+ uiLocaleHelp: '「自動」は DeepSeek Harness アプリの言語に従います。言語を選ぶと、このプラグインの UI がその言語に固定されます。',
1098
+ uiLocaleAuto: '自動(DSH に従う)',
1099
+ },
1100
+ ko: {
1101
+ badge: '자율 팀',
1102
+ badgeTip: 'dsh-switchman: 네 가지 내장 프리셋(standard / ptc / minimal / cordis)에 자율 에이전트 팀 디스패치 규율이 주입되어 있습니다',
1103
+ handoverActive: '핸드오버 진행 중',
1104
+ handoverPhaseBackup: '세션 백업 중',
1105
+ handoverPhaseCompacting: '컨텍스트 압축 중',
1106
+ handoverPhaseContinuation: '후속 세션 깨우는 중',
1107
+ handoverActiveTip: 'Switchman이 백그라운드에서 핸드오버 중입니다: 세션을 fork해 백업하고 컨텍스트를 압축하며, 완료되면 작업이 자동으로 이어집니다. 이 동안 세션이 잠시 멈추는 것은 정상입니다.',
1108
+ visionHintNeedsPool: '이 모델은 이미지를 읽을 수 없습니다: dsh-switchman 설정에서 멀티모달 풀 모델을 추가한 뒤, 이미지를 /vision으로 보내 주세요.',
1109
+ visionHintUseVision: '이 모델은 이미지를 읽을 수 없습니다: 이미지는 /vision으로 보내 주세요(자동으로 멀티모달 풀로 라우팅됩니다).',
1110
+ visionAutoConverted: '이미지 직접 전송이 거부되었습니다: 자동으로 /vision으로 다시 보냅니다(멀티모달 풀이 읽습니다).',
1111
+ settingsTitle: 'dsh-switchman',
1112
+ panelLabel: 'Switchman 디스패치 센터',
1113
+ settingsDescription: 'dsh-switchman 기본 설정을 구성합니다.',
1114
+ langSectionTitle: '언어',
1115
+ langSectionDescription: '에이전트 응답, 코드 주석, 작성 문서의 언어를 제어합니다.',
1116
+ langScopeLabel: '언어 범위',
1117
+ langScopeHelp: '이 언어 기본 설정의 저장 위치입니다.',
1118
+ langScopeGlobal: '전역(이 프로필)',
1119
+ langScopeProject: '프로젝트별(.switchman/lang.json)',
1120
+ langProjectNote: '프로젝트 모드: 각 프로젝트는 자신의 .switchman/lang.json을 읽습니다. 최초 응답 내용이 그 파일에 저장되며, 파일이 생길 때까지 매 세션마다 묻습니다. 아래 세 항목은 전역 모드에서만 적용됩니다.',
1121
+ langConversationLabel: '대화 언어',
1122
+ langConversationHelp: '에이전트가 응답과 토론에 사용하는 언어입니다. 설정하지 않으면 처음 사용할 때 한 번만 묻고 기억합니다.',
1123
+ langCommentsLabel: '코드 주석 언어',
1124
+ langCommentsHelp: '에이전트가 코드 주석을 작성하는 언어입니다.',
1125
+ langDocsLabel: '문서 언어',
1126
+ langDocsHelp: '에이전트가 문서를 작성하는 언어입니다.',
1127
+ followConversation: '대화 언어 따르기',
1128
+ notSetAsk: '미설정(처음 사용 시 묻기)',
1129
+ customLanguage: '사용자 지정…',
1130
+ customLanguagePlaceholder: '언어 이름 또는 BCP 태그',
1131
+ customLanguageRequired: '사용자 지정 언어를 입력하세요(1–48자).',
1132
+ currentValue: '현재: {value}',
1133
+ currentValueUnset: '현재: 미설정',
1134
+ suggestedValue: '추천: {value}',
1135
+ save: '저장',
1136
+ saving: '저장 중…',
1137
+ discard: '변경 취소',
1138
+ saveFailed: '이 배포에서 해당 값을 수락하지 않아, 수정할 수 있도록 남겨 두었습니다.',
1139
+ saveConflict: '다른 곳에서 설정이 변경되었습니다. 초안을 버리고 다시 시도하세요.',
1140
+ formLoading: '설정 불러오는 중…',
1141
+ formUnavailable: '이 플러그인이 로드되어 있지 않아 지금은 설정할 수 없습니다.',
1142
+ formReadOnly: '이 배포의 설정은 읽기 전용입니다.',
1143
+ dispatchSectionTitle: '디스패치 풀과 모델 순위',
1144
+ dispatchSectionDescription: '작업 복잡도에 따라 모델을 여섯 개 디스패치 풀로 묶고 능력 순위를 유지합니다. dsh-switchman 위임에만 영향을 줍니다.',
1145
+ dispatchProgress: '{pools}/6개 풀 설정 · {ranked}개 순위 지정 · 모드 {mode}',
1146
+ poolEconomyTitle: '경량 · economy',
1147
+ poolEconomyDesc: '가벼운 일괄 작업과 낮은 복잡도 작업',
1148
+ poolMechanicalTitle: '기계 · mechanical',
1149
+ poolMechanicalDesc: '기계적 재작성과 템플릿 작업',
1150
+ poolMainTitle: '주력 · main',
1151
+ poolMainDesc: '일상적 코딩과 매일 하는 작업',
1152
+ poolHardTitle: '고난도 · hard',
1153
+ poolHardDesc: '어려운 추론과 대규모 리팩터링',
1154
+ poolVisionTitle: '멀티모달 · vision',
1155
+ poolVisionDesc: '이미지 등 멀티모달 작업',
1156
+ poolReviewTitle: '리뷰 · review',
1157
+ poolReviewDesc: '읽기 전용 리뷰와 독립 검증',
1158
+ poolSelectAll: '모두 선택',
1159
+ poolClear: '지우기',
1160
+ poolEmpty: '후보 모델 없음',
1161
+ poolManualLabel: '수동 순서',
1162
+ poolManualHelp: '켜면 목록 순서대로 디스패치합니다(맨 앞이 제1순위). 끄면 능력 순으로 자동 정렬됩니다.',
1163
+ poolManualSelected: '선택됨 · 디스패치 우선순위',
1164
+ poolManualAddable: '모델 추가',
1165
+ poolMoveUp: '위로',
1166
+ poolMoveDown: '아래로',
1167
+ poolRemoveOne: '제거',
1168
+ poolEffortFollow: '레인 따르기',
1169
+ poolEffortLabel: '추론 강도',
1170
+ poolEffortHelp: '이 모델의 추론 강도를 고정합니다. 디스패치 시 레인 기본값보다 우선합니다',
1171
+ catalogLoading: '모델 카탈로그 불러오는 중…',
1172
+ catalogLoadFailed: '모델 카탈로그를 불러올 수 없습니다.',
1173
+ catalogRetry: '다시 시도',
1174
+ catalogPartial: '일부 모델 공급자를 불러오지 못했습니다. 저장된 선택 항목은 여전히 제거할 수 있습니다.',
1175
+ catalogEmpty: '현재 모델을 공개하는 공급자가 없습니다.',
1176
+ catalogUnavailableGroup: '저장되었으나 현재 사용 불가',
1177
+ catalogUnavailable: '현재 사용 불가',
1178
+ unauthorizedBadge: 'DSH 설정의 서브에이전트 모델 선택 허용 목록에 없음',
1179
+ unauthorizedHint: '⚠ 표시가 붙은 모델은 DSH 설정 → 서브에이전트 → 모델 선택에서 허용되지 않았습니다. 에이전트가 명시적으로 지정하면 거부됩니다. DSH 설정에서 허용하거나, 암시적 디스패치를 이용하세요.',
1180
+ rankTitle: '능력 순위',
1181
+ rankDescription: '번호가 능력 순서입니다(가장 강한 것이 앞). 각 항목에 S/A/B/C 티어를 지정할 수 있습니다. 목록은 풀 선택 ∪ 저장된 순위이며, 편집하면 표시된 순서가 그대로 저장됩니다.',
1182
+ rankEmpty: '위 풀에서 모델을 선택하면 순위 목록이 자동으로 나타납니다.',
1183
+ rankTier: '티어',
1184
+ rankTierNone: '—',
1185
+ rankMoveUp: '위로',
1186
+ rankMoveDown: '아래로',
1187
+ rankRemove: '순위에서 제거',
1188
+ enforceLabel: '적용 모드',
1189
+ enforceOff: '끄기',
1190
+ enforceAdvice: '조언',
1191
+ enforceEnforce: '강제',
1192
+ enforceHelpOff: '위임에 풀 지침을 주입하지 않습니다.',
1193
+ enforceHelpAdvice: '풀 지침을 조언으로 주입합니다. 모델이 벗어날 수 있습니다.',
1194
+ enforceHelpEnforce: '풀 지침을 엄격한 제약으로 주입합니다. 벗어나면 거부됩니다.',
1195
+ wmSectionTitle: '컨텍스트 수위',
1196
+ wmSectionDescription: '토큰 사용량에 따른 단계별 강화: 조언, 읽기 제한과 마무리, 자동 핸드오버.',
1197
+ wmSoftLabel: '소프트 수위(soft)',
1198
+ wmSoftHelp: '넘으면 배너가 나타나고 위임이나 컨텍스트 정리를 권장합니다.',
1199
+ wmHardLabel: '하드 수위(hard)',
1200
+ wmHardHelp: '넘으면 읽기 예산이 줄어들고 작업 마무리를 권장합니다.',
1201
+ wmForceLabel: '강제 수위(force)',
1202
+ wmForceHelp: '넘으면 백업 후 압축으로 핸드오버를 권장합니다(자동화 가능).',
1203
+ wmReadBudgetLabel: '읽기 예산',
1204
+ wmReadBudgetHelp: '한 번 읽기당 토큰 예산입니다. 매 라운드 상한은 그 두 배입니다.',
1205
+ wmNumberInvalid: '{min} 이상의 정수를 입력하세요.',
1206
+ wmOrderInvalid: '세 수위는 엄격히 증가해야 합니다: soft < hard < force.',
1207
+ wmDenyModeLabel: '하드 단계 동작',
1208
+ wmDenyModeCap: '제한하고 경고',
1209
+ wmDenyModeDeny: '즉시 거부',
1210
+ wmDenyModeHelpCap: '예산 초과 호출은 통과시키지만 경고를 기록합니다.',
1211
+ wmDenyModeHelpDeny: '예산 초과 호출은 즉시 거부합니다.',
1212
+ wmAutoHandoverLabel: '자동 핸드오버',
1213
+ wmAutoHandoverHelp: '강제 수위에 도달하면 확인 없이 백업하고 압축으로 핸드오버합니다.',
1214
+ wmSubagentTitle: '서브에이전트',
1215
+ wmSubagentCapLabel: '서브에이전트 컨텍스트 상한',
1216
+ wmSubagentCapHelp: '켜면 서브에이전트가 아래 전용 강제 임계값을 사용합니다. 끄면 위 세 수위를 그대로 따릅니다.',
1217
+ wmSubagentForceLabel: '서브에이전트 강제 임계값',
1218
+ wmSubagentForceHelp: '서브에이전트의 force 단계만 덮어씁니다(soft/hard는 메인 세션과 공유). 0이면 위 강제 수위를 따릅니다.',
1219
+ wmSubagentFollowForce: 'force 단계 따르기(0)',
1220
+ wmCommands: '명령: /ctx-pause 수위 개입 일시 중지 · /ctx-resume 재개 · /ctx-handover 지금 백업하고 핸드오버.',
1221
+ teamsSectionTitle: '에이전트 팀',
1222
+ teamsSectionDescription: '디스패치 형태 전환: 끄면 일반 subagent 디스패치입니다(DSH 출고 기본 보수적 팀 정책이 이어받음). 켜면 자율 팀 규율을 주입하고 Agent Teams를 활성화합니다.',
1223
+ teamsModeLabel: '에이전트 팀 모드',
1224
+ teamsModeHelp: '켜면 팀 규율(기본 위임 + 단계별 검증 + 작업판 규율)을 주입하고 DSH의 Agent Teams 번들을 활성화합니다. 디스패치 풀의 ⚠ 허용 배지는 이 모드에서만 표시됩니다.',
1225
+ syncWhitelistLabel: '서브에이전트 모델 허용 목록 동기화',
1226
+ syncWhitelistHelp: '독립 스위치입니다(에이전트 팀 모드 불필요): 여섯 풀에서 선택한 모델의 합집합을 DSH 설정 → 서브에이전트 → 모델 선택 허용 목록에 통째로 씁니다. dsh-switchman이 유일한 사실 원천이 됩니다.',
1227
+ whitelistSyncOk: '{count}건 동기화됨({time}).',
1228
+ whitelistSyncError: '동기화 실패: {error}',
1229
+ whitelistSyncPending: '동기화 대기 중…',
1230
+ whitelistSyncNote: '허용 목록 변경은 이후 새로 만든 세션에만 적용됩니다.',
1231
+ uiSectionTitle: '인터페이스',
1232
+ uiSectionDescription: '이 플러그인 자체 UI(배지, 패널, 이 설정 페이지)의 표시 언어입니다.',
1233
+ uiLocaleLabel: '인터페이스 언어',
1234
+ uiLocaleHelp: '자동은 DeepSeek Harness 앱 언어를 따르고, 언어를 직접 고르면 이 플러그인의 UI가 그 언어로 고정됩니다.',
1235
+ uiLocaleAuto: '자동(DSH 따르기)',
1236
+ },
1237
+ de: {
1238
+ badge: 'Autonomes Team',
1239
+ badgeTip: 'dsh-switchman: Die vier integrierten Presets (standard / ptc / minimal / cordis) tragen die autonome-Agent-Teams-Doktrin',
1240
+ handoverActive: 'Übergabe läuft',
1241
+ handoverPhaseBackup: 'Backup wird erstellt',
1242
+ handoverPhaseCompacting: 'Kontext wird komprimiert',
1243
+ handoverPhaseContinuation: 'Fortsetzung wird geweckt',
1244
+ handoverActiveTip: 'Switchman übergibt gerade im Hintergrund: Eine Backup-Session wird geforkt und der Kontext komprimiert; die Aufgabe läuft danach automatisch weiter. Eine ruhende Session ist in dieser Phase normal.',
1245
+ visionHintNeedsPool: 'Dieses Modell kann keine Bilder lesen: Fügen Sie in den dsh-switchman-Einstellungen Modelle zum Vision-Pool hinzu und senden Sie Bilder dann mit /vision.',
1246
+ visionHintUseVision: 'Dieses Modell kann keine Bilder lesen: Senden Sie Bilder mit /vision (automatisch an den Vision-Pool geleitet).',
1247
+ visionAutoConverted: 'Direkter Bildversand wurde abgelehnt: Er wird automatisch über /vision erneut gesendet (vom Vision-Pool gelesen).',
1248
+ settingsTitle: 'dsh-switchman',
1249
+ panelLabel: 'Switchman',
1250
+ settingsDescription: 'dsh-switchman-Einstellungen konfigurieren.',
1251
+ langSectionTitle: 'Sprache',
1252
+ langSectionDescription: 'Steuert die Sprache von Agent-Antworten, Code-Kommentaren und erstellten Dokumenten.',
1253
+ langScopeLabel: 'Sprach-Geltungsbereich',
1254
+ langScopeHelp: 'Wo diese Spracheinstellungen gespeichert werden.',
1255
+ langScopeGlobal: 'Global (dieses Profil)',
1256
+ langScopeProject: 'Pro Projekt (.switchman/lang.json)',
1257
+ langProjectNote: 'Projektmodus: Jedes Projekt liest seine eigene .switchman/lang.json; Antworten bei der Erstanwendung werden dort gespeichert, und Sessions fragen nach, bis die Datei existiert. Die drei Felder unten gelten nur im globalen Modus.',
1258
+ langConversationLabel: 'Konversationssprache',
1259
+ langConversationHelp: 'Die Sprache, in der Agenten antworten und diskutieren; ohne Festlegung werden Sie bei der ersten Nutzung einmalig gefragt, und die Auswahl wird gemerkt.',
1260
+ langCommentsLabel: 'Sprache für Code-Kommentare',
1261
+ langCommentsHelp: 'Die Sprache, in der Agenten Code-Kommentare schreiben.',
1262
+ langDocsLabel: 'Dokumentsprache',
1263
+ langDocsHelp: 'Die Sprache, in der Agenten Dokumente verfassen.',
1264
+ followConversation: 'Konversationssprache folgen',
1265
+ notSetAsk: 'Nicht gesetzt (bei Erstanwendung fragen)',
1266
+ customLanguage: 'Benutzerdefiniert…',
1267
+ customLanguagePlaceholder: 'Sprachname oder BCP-Tag',
1268
+ customLanguageRequired: 'Geben Sie eine eigene Sprache ein (1–48 Zeichen).',
1269
+ currentValue: 'Aktuell: {value}',
1270
+ currentValueUnset: 'Aktuell: nicht gesetzt',
1271
+ suggestedValue: 'Vorschlag: {value}',
1272
+ save: 'Speichern',
1273
+ saving: 'Speichern…',
1274
+ discard: 'Änderungen verwerfen',
1275
+ saveFailed: 'Diese Werte wurden von der Bereitstellung nicht akzeptiert; sie bleiben zur Korrektur erhalten.',
1276
+ saveConflict: 'Einstellungen wurden andernorts geändert. Verwerfen Sie Ihren Entwurf und versuchen Sie es erneut.',
1277
+ formLoading: 'Einstellungen werden geladen…',
1278
+ formUnavailable: 'Dieses Plugin ist nicht geladen und kann daher gerade nicht konfiguriert werden.',
1279
+ formReadOnly: 'Diese Bereitstellung speichert Einstellungen schreibgeschützt.',
1280
+ dispatchSectionTitle: 'Dispatch-Pools und Modell-Ranking',
1281
+ dispatchSectionDescription: 'Gruppiert Modelle nach Aufgabenkomplexität in sechs Dispatch-Pools und pflegt ein Fähigkeits-Ranking; betrifft nur die Delegation von dsh-switchman.',
1282
+ dispatchProgress: '{pools}/6 Pools gesetzt · {ranked} im Ranking · Modus {mode}',
1283
+ poolEconomyTitle: 'Leicht · economy',
1284
+ poolEconomyDesc: 'Leichte Massen- und geringkomplexe Aufgaben',
1285
+ poolMechanicalTitle: 'Mechanisch · mechanical',
1286
+ poolMechanicalDesc: 'Mechanische Umschreibungen und Vorlagen-Operationen',
1287
+ poolMainTitle: 'Standard · main',
1288
+ poolMainDesc: 'Routiniertes Codieren und Alltagsaufgaben',
1289
+ poolHardTitle: 'Schwer · hard',
1290
+ poolHardDesc: 'Schweres Reasoning und große Refactorings',
1291
+ poolVisionTitle: 'Multimodal · vision',
1292
+ poolVisionDesc: 'Multimodale (Bild-)Arbeit',
1293
+ poolReviewTitle: 'Review · review',
1294
+ poolReviewDesc: 'Nur-Lese-Review und unabhängige Prüfung',
1295
+ poolSelectAll: 'Alle auswählen',
1296
+ poolClear: 'Leeren',
1297
+ poolEmpty: 'Keine Kandidatenmodelle',
1298
+ poolManualLabel: 'Manuelle Reihenfolge',
1299
+ poolManualHelp: 'Ein: Der Versand folgt der gelisteten Reihenfolge (oben = erste Wahl); aus: Lanes werden automatisch nach Fähigkeit sortiert.',
1300
+ poolManualSelected: 'Ausgewählt · Dispatch-Priorität',
1301
+ poolManualAddable: 'Modelle hinzufügen',
1302
+ poolMoveUp: 'Nach oben',
1303
+ poolMoveDown: 'Nach unten',
1304
+ poolRemoveOne: 'Entfernen',
1305
+ poolEffortFollow: 'Lane folgen',
1306
+ poolEffortLabel: 'Aufwand',
1307
+ poolEffortHelp: 'Fixiert den Reasoning-Aufwand dieses Modells; überschreibt beim Dispatch den Lane-Standard',
1308
+ catalogLoading: 'Modellkatalog wird geladen…',
1309
+ catalogLoadFailed: 'Der Modellkatalog konnte nicht geladen werden.',
1310
+ catalogRetry: 'Erneut versuchen',
1311
+ catalogPartial: 'Einige Modell-Provider konnten nicht geladen werden; gespeicherte Auswahl bleibt entfernbar.',
1312
+ catalogEmpty: 'Aktuell bewirbt kein Modell-Provider ein Modell.',
1313
+ catalogUnavailableGroup: 'Gespeichert, aber derzeit nicht verfügbar',
1314
+ catalogUnavailable: 'derzeit nicht verfügbar',
1315
+ unauthorizedBadge: 'für expliziten Subagent-Dispatch in DSH-Einstellungen (Subagents: Modellauswahl) nicht autorisiert',
1316
+ unauthorizedHint: 'Mit ⚠ markierte Modelle sind in DSH-Einstellungen → Subagents → Modellauswahl nicht autorisiert; Agenten, die sie explizit nennen, werden abgelehnt — autorisieren Sie sie in den DSH-Einstellungen oder lassen Sie Agenten implizit delegieren.',
1317
+ rankTitle: 'Fähigkeits-Ranking',
1318
+ rankDescription: 'Nummeriert, stärkstes zuerst; jeder Eintrag kann ein S/A/B/C-Tier verankern. Die Liste ist Pool-Auswahl ∪ gespeichertes Ranking; jede Änderung speichert die angezeigte Reihenfolge.',
1319
+ rankEmpty: 'Wählen Sie oben Modelle in den Pools; die Ranking-Liste erscheint automatisch.',
1320
+ rankTier: 'Tier',
1321
+ rankTierNone: '—',
1322
+ rankMoveUp: 'Nach oben',
1323
+ rankMoveDown: 'Nach unten',
1324
+ rankRemove: 'Aus dem Ranking entfernen',
1325
+ enforceLabel: 'Durchsetzung',
1326
+ enforceOff: 'Aus',
1327
+ enforceAdvice: 'Empfehlung',
1328
+ enforceEnforce: 'Erzwungen',
1329
+ enforceHelpOff: 'Es wird keine Pool-Leitlinie in Delegationen eingespeist.',
1330
+ enforceHelpAdvice: 'Pool-Leitlinien werden als Empfehlung eingespeist; Modelle dürfen abweichen.',
1331
+ enforceHelpEnforce: 'Pool-Leitlinien werden als harte Einschränkung eingespeist; Abweichungen werden abgelehnt.',
1332
+ wmSectionTitle: 'Kontext-Wasserstand',
1333
+ wmSectionDescription: 'Abgestuftes Verhalten nach Token-Nutzung: Empfehlung, gedeckelte Lesevorgänge und Abschluss, automatische Übergabe.',
1334
+ wmSoftLabel: 'Weicher Wasserstand (soft)',
1335
+ wmSoftHelp: 'Danach erscheint ein Banner, und Delegieren bzw. Kontext aufräumen wird empfohlen.',
1336
+ wmHardLabel: 'Harter Wasserstand (hard)',
1337
+ wmHardHelp: 'Danach strafft sich das Lese-Budget, und ein Abschluss wird empfohlen.',
1338
+ wmForceLabel: 'Erzwungener Wasserstand (force)',
1339
+ wmForceHelp: 'Danach Backup erstellen und an die Komprimierung übergeben (automatisch möglich).',
1340
+ wmReadBudgetLabel: 'Lese-Budget',
1341
+ wmReadBudgetHelp: 'Token-Budget pro Lesevorgang; jede Runde ist auf das Doppelte gedeckelt.',
1342
+ wmNumberInvalid: 'Geben Sie eine ganze Zahl von mindestens {min} ein.',
1343
+ wmOrderInvalid: 'Die drei Stufen müssen strikt aufsteigen: soft < hard < force.',
1344
+ wmDenyModeLabel: 'Verhalten der Hard-Stufe',
1345
+ wmDenyModeCap: 'Deckeln und warnen',
1346
+ wmDenyModeDeny: 'Direkt ablehnen',
1347
+ wmDenyModeHelpCap: 'Über-Budget-Aufrufe laufen durch, aber eine Warnung wird protokolliert.',
1348
+ wmDenyModeHelpDeny: 'Über-Budget-Aufrufe werden direkt abgelehnt.',
1349
+ wmAutoHandoverLabel: 'Automatische Übergabe',
1350
+ wmAutoHandoverHelp: 'Beim erzwungenen Wasserstand automatisch sichern und an die Komprimierung übergeben.',
1351
+ wmSubagentTitle: 'Subagents',
1352
+ wmSubagentCapLabel: 'Kontext-Deckel für Subagents',
1353
+ wmSubagentCapHelp: 'Subagents dürfen die eigene erzwungene Schwelle unten nutzen; aus = vollständig den drei Stufen oben folgen.',
1354
+ wmSubagentForceLabel: 'Erzwungene Schwelle für Subagents',
1355
+ wmSubagentForceHelp: 'Überschreibt nur die Force-Stufe der Subagents (soft/hard teilen sich mit der Haupt-Session); 0 folgt dem erzwungenen Wasserstand oben.',
1356
+ wmSubagentFollowForce: 'Der Force-Stufe folgen (0)',
1357
+ wmCommands: 'Befehle: /ctx-pause pausiert Wasserstand-Aktionen · /ctx-resume setzt sie fort · /ctx-handover sichert jetzt und übergibt sofort.',
1358
+ teamsSectionTitle: 'Agent-Teams',
1359
+ teamsSectionDescription: 'Wechselt die Dispatch-Form: Aus ist gewöhnlicher Subagent-Versand (die konservative Werks-Teamrichtlinie von DSH greift); an speist die autonome Team-Doktrin ein und aktiviert Agent Teams.',
1360
+ teamsModeLabel: 'Agent-Teams-Modus',
1361
+ teamsModeHelp: 'Ein: Die Team-Doktrin (standardmäßig delegieren + abgestufte Prüfung + Task-Board-Disziplin) wird eingespeist und das DSH-Agent-Teams-Bundle aktiviert; die ⚠-Autorisierungs-Badges der Dispatch-Pools erscheinen nur in diesem Modus.',
1362
+ syncWhitelistLabel: 'Modell-Whitelist der Subagents synchronisieren',
1363
+ syncWhitelistHelp: 'Unabhängiger Schalter (kein Agent-Teams-Modus nötig): schreibt die Vereinigung der sechs Pools in die Autorisierungsliste von DSH „Einstellungen → Subagents → Modellauswahl“; dsh-switchman wird zur einzigen Quelle der Wahrheit.',
1364
+ whitelistSyncOk: '{count} Einträge synchronisiert ({time}).',
1365
+ whitelistSyncError: 'Synchronisierung fehlgeschlagen: {error}',
1366
+ whitelistSyncPending: 'Warte auf Synchronisierung…',
1367
+ whitelistSyncNote: 'Whitelist-Änderungen wirken sich nur auf später erstellte Sessions aus.',
1368
+ uiSectionTitle: 'Oberfläche',
1369
+ uiSectionDescription: 'Anzeigesprache der eigenen Oberfläche dieses Plugins (Badge, Panel, diese Einstellungsseite).',
1370
+ uiLocaleLabel: 'Sprache der Oberfläche',
1371
+ uiLocaleHelp: 'Auto folgt der App-Sprache von DeepSeek Harness; wählt man eine Sprache, wird die Oberfläche dieses Plugins darauf festgelegt.',
1372
+ uiLocaleAuto: 'Auto (DSH folgen)',
1373
+ },
1374
+ es: {
1375
+ badge: 'Equipo autónomo',
1376
+ badgeTip: 'dsh-switchman: los cuatro preajustes integrados (standard / ptc / minimal / cordis) incorporan la doctrina de equipos de agentes autónomos',
1377
+ handoverActive: 'Traspaso en curso',
1378
+ handoverPhaseBackup: 'creando copia de seguridad',
1379
+ handoverPhaseCompacting: 'compactando contexto',
1380
+ handoverPhaseContinuation: 'despertando continuación',
1381
+ handoverActiveTip: 'Switchman está realizando el traspaso en segundo plano: crea un fork de la sesión de respaldo y compacta el contexto; la tarea continúa automáticamente al terminar. Es normal que la sesión quede quieta durante este intervalo.',
1382
+ visionHintNeedsPool: 'Este modelo no puede leer imágenes: añade modelos del grupo de visión en los ajustes de dsh-switchman y envía las imágenes con /vision.',
1383
+ visionHintUseVision: 'Este modelo no puede leer imágenes: envíalas con /vision (se enrutan automáticamente al grupo de visión).',
1384
+ visionAutoConverted: 'El envío directo de la imagen fue rechazado: se reenvía automáticamente vía /vision (lo lee el grupo de visión).',
1385
+ settingsTitle: 'dsh-switchman',
1386
+ panelLabel: 'Switchman',
1387
+ settingsDescription: 'Configura las preferencias de dsh-switchman.',
1388
+ langSectionTitle: 'Idioma',
1389
+ langSectionDescription: 'Controla el idioma de las respuestas de los agentes, los comentarios de código y los documentos redactados.',
1390
+ langScopeLabel: 'Ámbito del idioma',
1391
+ langScopeHelp: 'Dónde se guardan estas preferencias de idioma.',
1392
+ langScopeGlobal: 'Global (este perfil)',
1393
+ langScopeProject: 'Por proyecto (.switchman/lang.json)',
1394
+ langProjectNote: 'Modo por proyecto: cada proyecto lee su propio .switchman/lang.json; la respuesta del primer uso se guarda allí, y las sesiones preguntan hasta que exista. Los tres campos de abajo solo se aplican en modo global.',
1395
+ langConversationLabel: 'Idioma de conversación',
1396
+ langConversationHelp: 'El idioma en que los agentes responden y debaten; si no se fija, se te pregunta una vez en el primer uso y la elección se recuerda.',
1397
+ langCommentsLabel: 'Idioma de los comentarios',
1398
+ langCommentsHelp: 'El idioma en que los agentes escriben los comentarios de código.',
1399
+ langDocsLabel: 'Idioma de los documentos',
1400
+ langDocsHelp: 'El idioma en que los agentes redactan documentos.',
1401
+ followConversation: 'Seguir el idioma de la conversación',
1402
+ notSetAsk: 'Sin fijar (preguntar en el primer uso)',
1403
+ customLanguage: 'Personalizado…',
1404
+ customLanguagePlaceholder: 'Nombre de idioma o etiqueta BCP',
1405
+ customLanguageRequired: 'Introduce un idioma personalizado (1–48 caracteres).',
1406
+ currentValue: 'Actual: {value}',
1407
+ currentValueUnset: 'Actual: sin fijar',
1408
+ suggestedValue: 'Sugerido: {value}',
1409
+ save: 'Guardar',
1410
+ saving: 'Guardando…',
1411
+ discard: 'Descartar cambios',
1412
+ saveFailed: 'El despliegue no aceptó estos valores; se dejaron para que los corrijas.',
1413
+ saveConflict: 'Los ajustes cambiaron en otro lugar. Descarta tu borrador e inténtalo de nuevo.',
1414
+ formLoading: 'Cargando ajustes…',
1415
+ formUnavailable: 'Este plugin no está cargado, así que no puede configurarse ahora mismo.',
1416
+ formReadOnly: 'Este despliegue guarda los ajustes en modo de solo lectura.',
1417
+ dispatchSectionTitle: 'Grupos de despacho y ranking de modelos',
1418
+ dispatchSectionDescription: 'Agrupa modelos en seis grupos de despacho según la complejidad de la tarea y mantiene un ranking de capacidad; solo afecta a la delegación de dsh-switchman.',
1419
+ dispatchProgress: '{pools}/6 grupos definidos · {ranked} clasificados · modo {mode}',
1420
+ poolEconomyTitle: 'Económico · economy',
1421
+ poolEconomyDesc: 'Tareas por lotes ligeras y de baja complejidad',
1422
+ poolMechanicalTitle: 'Mecánico · mechanical',
1423
+ poolMechanicalDesc: 'Reescrituras mecánicas y operaciones con plantillas',
1424
+ poolMainTitle: 'Principal · main',
1425
+ poolMainDesc: 'Programación rutinaria y tareas cotidianas',
1426
+ poolHardTitle: 'Difícil · hard',
1427
+ poolHardDesc: 'Razonamiento difícil y refactorizaciones a gran escala',
1428
+ poolVisionTitle: 'Visión · vision',
1429
+ poolVisionDesc: 'Trabajo multimodal (imágenes)',
1430
+ poolReviewTitle: 'Revisión · review',
1431
+ poolReviewDesc: 'Revisión de solo lectura y verificación independiente',
1432
+ poolSelectAll: 'Seleccionar todo',
1433
+ poolClear: 'Limpiar',
1434
+ poolEmpty: 'No hay modelos candidatos',
1435
+ poolManualLabel: 'Orden manual',
1436
+ poolManualHelp: 'Activado, el despacho sigue el orden de la lista (el primero es la primera opción); desactivado, los carriles se ordenan automáticamente por capacidad.',
1437
+ poolManualSelected: 'Seleccionados · prioridad de despacho',
1438
+ poolManualAddable: 'Añadir modelos',
1439
+ poolMoveUp: 'Subir',
1440
+ poolMoveDown: 'Bajar',
1441
+ poolRemoveOne: 'Quitar',
1442
+ poolEffortFollow: 'seguir carril',
1443
+ poolEffortLabel: 'esfuerzo',
1444
+ poolEffortHelp: 'Fija el esfuerzo de razonamiento de este modelo; prevalece sobre el valor del carril al despachar',
1445
+ catalogLoading: 'Cargando el catálogo de modelos…',
1446
+ catalogLoadFailed: 'No se pudo cargar el catálogo de modelos.',
1447
+ catalogRetry: 'Reintentar',
1448
+ catalogPartial: 'Algunos proveedores de modelos no se pudieron cargar; las elecciones guardadas siguen pudiendo quitarse.',
1449
+ catalogEmpty: 'Ningún proveedor de modelos ofrece modelos actualmente.',
1450
+ catalogUnavailableGroup: 'Guardados pero no disponibles ahora',
1451
+ catalogUnavailable: 'no disponible actualmente',
1452
+ unauthorizedBadge: 'sin autorización para despacho explícito de subagentes en Ajustes de DSH (subagentes: selección de modelos)',
1453
+ unauthorizedHint: 'Los modelos marcados con ⚠ no están autorizados en Ajustes de DSH → Subagentes → selección de modelos; los agentes que los nombren explícitamente serán rechazados — autorízalos en los Ajustes de DSH o deja que los agentes despachen de forma implícita.',
1454
+ rankTitle: 'Ranking de capacidad',
1455
+ rankDescription: 'Numerados del más fuerte al primero; cada entrada puede anclar un nivel S/A/B/C. La lista es la selección de grupos ∪ el ranking guardado; cualquier edición persiste el orden mostrado.',
1456
+ rankEmpty: 'Selecciona modelos en los grupos de arriba; la lista del ranking aparecerá automáticamente.',
1457
+ rankTier: 'Nivel',
1458
+ rankTierNone: '—',
1459
+ rankMoveUp: 'Subir',
1460
+ rankMoveDown: 'Bajar',
1461
+ rankRemove: 'Quitar del ranking',
1462
+ enforceLabel: 'Aplicación',
1463
+ enforceOff: 'Desactivado',
1464
+ enforceAdvice: 'Consejo',
1465
+ enforceEnforce: 'Obligatorio',
1466
+ enforceHelpOff: 'No se inyecta ninguna guía de grupos en las delegaciones.',
1467
+ enforceHelpAdvice: 'La guía de grupos se inyecta como consejo; los modelos pueden desviarse.',
1468
+ enforceHelpEnforce: 'La guía de grupos se inyecta como restricción estricta; las desviaciones se rechazan.',
1469
+ wmSectionTitle: 'Nivel de contexto',
1470
+ wmSectionDescription: 'Comportamiento por niveles según el uso de tokens: consejos, lecturas limitadas y cierre, traspaso automático.',
1471
+ wmSoftLabel: 'Nivel suave (soft)',
1472
+ wmSoftHelp: 'Al superarlo aparece un aviso y se recomienda delegar o ordenar el contexto.',
1473
+ wmHardLabel: 'Nivel duro (hard)',
1474
+ wmHardHelp: 'Al superarlo se ajusta el presupuesto de lectura y se recomienda cerrar el trabajo.',
1475
+ wmForceLabel: 'Nivel forzado (force)',
1476
+ wmForceHelp: 'Al superarlo, haz copia de seguridad y traspasa a la compactación (puede ser automático).',
1477
+ wmReadBudgetLabel: 'Presupuesto de lectura',
1478
+ wmReadBudgetHelp: 'Presupuesto de tokens por lectura; cada ronda se limita al doble.',
1479
+ wmNumberInvalid: 'Introduce un número entero de {min} o más.',
1480
+ wmOrderInvalid: 'Los tres niveles deben ascender estrictamente: soft < hard < force.',
1481
+ wmDenyModeLabel: 'Comportamiento del nivel duro',
1482
+ wmDenyModeCap: 'Limitar y avisar',
1483
+ wmDenyModeDeny: 'Rechazar directamente',
1484
+ wmDenyModeHelpCap: 'Las llamadas sobre el presupuesto pasan, pero se registra un aviso.',
1485
+ wmDenyModeHelpDeny: 'Las llamadas sobre el presupuesto se rechazan directamente.',
1486
+ wmAutoHandoverLabel: 'Traspaso automático',
1487
+ wmAutoHandoverHelp: 'En el nivel forzado, hace copia de seguridad y traspasa a la compactación automáticamente.',
1488
+ wmSubagentTitle: 'Subagentes',
1489
+ wmSubagentCapLabel: 'Tope de contexto de subagentes',
1490
+ wmSubagentCapHelp: 'Permite que los subagentes usen el umbral forzado propio de abajo; desactivado = seguir por completo los tres niveles de arriba.',
1491
+ wmSubagentForceLabel: 'Umbral forzado de subagentes',
1492
+ wmSubagentForceHelp: 'Solo sobrescribe el nivel forzado de los subagentes (soft/hard se comparten con la sesión principal); 0 sigue el nivel forzado de arriba.',
1493
+ wmSubagentFollowForce: 'Seguir el nivel forzado (0)',
1494
+ wmCommands: 'Comandos: /ctx-pause suspende las acciones del nivel · /ctx-resume las reanuda · /ctx-handover hace copia y traspasa ahora.',
1495
+ teamsSectionTitle: 'Equipos de agentes',
1496
+ teamsSectionDescription: 'Cambia la forma de despacho: desactivado es despacho simple de subagentes (aplica la política conservadora de fábrica de DSH); activado inyecta la doctrina de equipo autónomo y habilita Agent Teams.',
1497
+ teamsModeLabel: 'Modo de equipos de agentes',
1498
+ teamsModeHelp: 'Activado, se inyecta la doctrina de equipo (delegar por defecto + verificación por niveles + disciplina del tablero de tareas) y se habilita el paquete Agent Teams de DSH; las insignias ⚠ de autorización de los grupos de despacho solo se muestran en este modo.',
1499
+ syncWhitelistLabel: 'Sincronizar la lista blanca de modelos de subagentes',
1500
+ syncWhitelistHelp: 'Interruptor independiente (no requiere el modo de equipos): escribe la unión de los seis grupos en la lista de autorización de «Ajustes de DSH → Subagentes → selección de modelos»; dsh-switchman pasa a ser la única fuente de verdad.',
1501
+ whitelistSyncOk: '{count} entradas sincronizadas ({time}).',
1502
+ whitelistSyncError: 'Error de sincronización: {error}',
1503
+ whitelistSyncPending: 'Esperando la sincronización…',
1504
+ whitelistSyncNote: 'Los cambios de la lista blanca solo afectan a las sesiones creadas después.',
1505
+ uiSectionTitle: 'Interfaz',
1506
+ uiSectionDescription: 'Idioma de la interfaz propia de este plugin (insignia, panel, esta página de ajustes).',
1507
+ uiLocaleLabel: 'Idioma de la interfaz',
1508
+ uiLocaleHelp: 'Automático sigue el idioma de la app DeepSeek Harness; al elegir un idioma, la interfaz del plugin se fija en él.',
1509
+ uiLocaleAuto: 'Automático (seguir DSH)',
1510
+ },
1511
+ fr: {
1512
+ badge: 'Équipe autonome',
1513
+ badgeTip: 'dsh-switchman : les quatre préréglages intégrés (standard / ptc / minimal / cordis) embarquent la doctrine d’équipe autonome des Agent Teams',
1514
+ handoverActive: 'Remise en cours',
1515
+ handoverPhaseBackup: 'sauvegarde de la session',
1516
+ handoverPhaseCompacting: 'compactage du contexte',
1517
+ handoverPhaseContinuation: 'réveil de la continuation',
1518
+ handoverActiveTip: 'Switchman effectue la remise en arrière-plan : fork d’une session de sauvegarde et compactage du contexte ; la tâche se poursuit automatiquement une fois terminée. Une session immobile pendant cette fenêtre est normale.',
1519
+ visionHintNeedsPool: 'Ce modèle ne sait pas lire les images : ajoutez des modèles au pool multimodal dans les réglages dsh-switchman, puis envoyez les images avec /vision.',
1520
+ visionHintUseVision: 'Ce modèle ne sait pas lire les images : envoyez-les avec /vision (routage automatique vers le pool multimodal).',
1521
+ visionAutoConverted: 'Envoi d’image refusé : renvoi automatique via /vision (lecture par le pool multimodal).',
1522
+ settingsTitle: 'dsh-switchman',
1523
+ panelLabel: 'Switchman',
1524
+ settingsDescription: 'Configurez les préférences de dsh-switchman.',
1525
+ langSectionTitle: 'Langue',
1526
+ langSectionDescription: 'Détermine la langue des réponses des agents, des commentaires de code et des documents rédigés.',
1527
+ langScopeLabel: 'Portée de la langue',
1528
+ langScopeHelp: 'Là où ces préférences de langue sont conservées.',
1529
+ langScopeGlobal: 'Global (ce profil)',
1530
+ langScopeProject: 'Par projet (.switchman/lang.json)',
1531
+ langProjectNote: 'Mode par projet : chaque projet lit son propre .switchman/lang.json ; les réponses données au premier usage y sont enregistrées, et les sessions posent la question tant qu’il n’existe pas. Les trois champs ci-dessous ne s’appliquent qu’en mode global.',
1532
+ langConversationLabel: 'Langue des conversations',
1533
+ langConversationHelp: 'La langue dans laquelle les agents répondent et discutent ; si elle n’est pas réglée, on vous la demande une fois au premier usage et le choix est retenu.',
1534
+ langCommentsLabel: 'Langue des commentaires de code',
1535
+ langCommentsHelp: 'La langue dans laquelle les agents écrivent les commentaires de code.',
1536
+ langDocsLabel: 'Langue des documents',
1537
+ langDocsHelp: 'La langue dans laquelle les agents rédigent les documents.',
1538
+ followConversation: 'Suivre la langue de la conversation',
1539
+ notSetAsk: 'Non réglée (demander au premier usage)',
1540
+ customLanguage: 'Personnalisée…',
1541
+ customLanguagePlaceholder: 'Nom de langue ou étiquette BCP',
1542
+ customLanguageRequired: 'Saisissez une langue personnalisée (1–48 caractères).',
1543
+ currentValue: 'Actuel : {value}',
1544
+ currentValueUnset: 'Actuel : non réglé',
1545
+ suggestedValue: 'Suggéré : {value}',
1546
+ save: 'Enregistrer',
1547
+ saving: 'Enregistrement…',
1548
+ discard: 'Annuler les modifications',
1549
+ saveFailed: 'Le déploiement n’a pas accepté ces valeurs ; elles ont été laissées à corriger.',
1550
+ saveConflict: 'Les réglages ont changé ailleurs. Abandonnez votre brouillon et réessayez.',
1551
+ formLoading: 'Chargement des réglages…',
1552
+ formUnavailable: 'Ce plugin n’est pas chargé : impossible de le configurer pour le moment.',
1553
+ formReadOnly: 'Ce déploiement stocke les réglages en lecture seule.',
1554
+ dispatchSectionTitle: 'Pools de dispatch et classement des modèles',
1555
+ dispatchSectionDescription: 'Répartit les modèles en six pools de dispatch selon la complexité des tâches et maintient un classement de capacité ; n’affecte que la délégation dsh-switchman.',
1556
+ dispatchProgress: '{pools}/6 pools réglés · {ranked} classés · mode {mode}',
1557
+ poolEconomyTitle: 'Économie',
1558
+ poolEconomyDesc: 'Tâches légères en série et de faible complexité',
1559
+ poolMechanicalTitle: 'Mécanique',
1560
+ poolMechanicalDesc: 'Réécritures mécaniques et opérations sur gabarit',
1561
+ poolMainTitle: 'Principal',
1562
+ poolMainDesc: 'Code au quotidien et tâches courantes',
1563
+ poolHardTitle: 'Difficile',
1564
+ poolHardDesc: 'Raisonnement corsé et refontes à grande échelle',
1565
+ poolVisionTitle: 'Vision',
1566
+ poolVisionDesc: 'Travail multimodal (images)',
1567
+ poolReviewTitle: 'Relecture',
1568
+ poolReviewDesc: 'Relecture en lecture seule et vérification indépendante',
1569
+ poolSelectAll: 'Tout cocher',
1570
+ poolClear: 'Effacer',
1571
+ poolEmpty: 'Aucun modèle candidat',
1572
+ poolManualLabel: 'Ordre manuel',
1573
+ poolManualHelp: 'Activé, le dispatch suit l’ordre affiché (la tête = premier choix) ; désactivé, les couloirs sont ordonnés par capacité automatiquement.',
1574
+ poolManualSelected: 'Sélectionnés · priorité de dispatch',
1575
+ poolManualAddable: 'Ajouter des modèles',
1576
+ poolMoveUp: 'Monter',
1577
+ poolMoveDown: 'Descendre',
1578
+ poolRemoveOne: 'Retirer',
1579
+ poolEffortFollow: 'suivre le couloir',
1580
+ poolEffortLabel: 'effort',
1581
+ poolEffortHelp: 'Épingle l’effort de raisonnement de ce modèle ; il prime le défaut du couloir au dispatch',
1582
+ catalogLoading: 'Chargement du catalogue de modèles…',
1583
+ catalogLoadFailed: 'Le catalogue de modèles n’a pas pu être chargé.',
1584
+ catalogRetry: 'Réessayer',
1585
+ catalogPartial: 'Certains fournisseurs de modèles n’ont pas pu être chargés ; les choix enregistrés restent retirables.',
1586
+ catalogEmpty: 'Aucun fournisseur de modèles n’annonce de modèle pour l’instant.',
1587
+ catalogUnavailableGroup: 'Enregistrés mais actuellement indisponibles',
1588
+ catalogUnavailable: 'actuellement indisponible',
1589
+ unauthorizedBadge: 'non autorisé pour le dispatch enfant explicite dans les réglages DSH (subagents : sélection de modèle)',
1590
+ unauthorizedHint: 'Les modèles marqués ⚠ ne sont pas autorisés dans Réglages DSH → Subagents → sélection de modèle ; les agents qui les nomment explicitement se verront refuser le dispatch — autorisez-les dans les réglages DSH, ou laissez les agents dispatcher implicitement.',
1591
+ rankTitle: 'Classement de capacité',
1592
+ rankDescription: 'Numérotés du plus fort au moins fort ; chaque entrée peut ancrer un tier S/A/B/C. La liste est sélection des pools ∪ classement enregistré ; toute modification rend l’ordre affiché persistant.',
1593
+ rankEmpty: 'Cochez des modèles dans les pools ci-dessus ; la liste de classement apparaît automatiquement.',
1594
+ rankTier: 'Tier',
1595
+ rankTierNone: '—',
1596
+ rankMoveUp: 'Monter',
1597
+ rankMoveDown: 'Descendre',
1598
+ rankRemove: 'Retirer du classement',
1599
+ enforceLabel: 'Exécution',
1600
+ enforceOff: 'Off',
1601
+ enforceAdvice: 'Advice',
1602
+ enforceEnforce: 'Enforce',
1603
+ enforceHelpOff: 'Aucune recommandation de pool n’est injectée dans la délégation.',
1604
+ enforceHelpAdvice: 'Les recommandations de pool sont injectées à titre de conseil (advice) ; les modèles peuvent s’en écarter.',
1605
+ enforceHelpEnforce: 'Les recommandations de pool sont injectées comme contrainte stricte ; tout écart est refusé.',
1606
+ wmSectionTitle: 'Niveau d’eau du contexte',
1607
+ wmSectionDescription: 'Comportement par paliers selon l’usage des tokens : conseil, lectures plafonnées et phase de clôture, remise automatique.',
1608
+ wmSoftLabel: 'Ligne d’eau soft',
1609
+ wmSoftHelp: 'Au-delà, une bannière apparaît et il est conseillé de déléguer ou de ranger le contexte.',
1610
+ wmHardLabel: 'Ligne d’eau hard',
1611
+ wmHardHelp: 'Au-delà, le budget de lecture se resserre et il est conseillé de conclure.',
1612
+ wmForceLabel: 'Ligne d’eau force',
1613
+ wmForceHelp: 'Au-delà, sauvegardez et remettez à la compaction (peut être automatique).',
1614
+ wmReadBudgetLabel: 'Budget de lecture',
1615
+ wmReadBudgetHelp: 'Budget de tokens par lecture ; chaque tour plafonne au double.',
1616
+ wmNumberInvalid: 'Saisissez un nombre entier d’au moins {min}.',
1617
+ wmOrderInvalid: 'Les trois paliers doivent strictement monter : soft < hard < force.',
1618
+ wmDenyModeLabel: 'Comportement au palier hard',
1619
+ wmDenyModeCap: 'Plafonner et avertir',
1620
+ wmDenyModeDeny: 'Refuser d’office',
1621
+ wmDenyModeHelpCap: 'Les appels au-delà du budget passent, mais un avertissement est consigné.',
1622
+ wmDenyModeHelpDeny: 'Les appels au-delà du budget sont refusés d’office.',
1623
+ wmAutoHandoverLabel: 'Remise automatique',
1624
+ wmAutoHandoverHelp: 'À la ligne d’eau force, sauvegarde et remise automatiques à la compaction.',
1625
+ wmSubagentTitle: 'Subagents',
1626
+ wmSubagentCapLabel: 'Plafond de contexte des subagents',
1627
+ wmSubagentCapHelp: 'Laisse les subagents utiliser le seuil force dédié ci-dessous ; désactivé = suivent intégralement les trois paliers ci-dessus.',
1628
+ wmSubagentForceLabel: 'Seuil force des subagents',
1629
+ wmSubagentForceHelp: 'Ne remplace que le palier force des subagents (soft/hard partagés avec la session principale) ; 0 suit la ligne d’eau force ci-dessus.',
1630
+ wmSubagentFollowForce: 'Suivre le palier force (0)',
1631
+ wmCommands: 'Commandes : /ctx-pause suspend les actions de niveau d’eau · /ctx-resume les reprend · /ctx-handover sauvegarde et remet maintenant.',
1632
+ teamsSectionTitle: 'Agent Teams',
1633
+ teamsSectionDescription: 'Change la forme du dispatch : éteint, c’est le dispatch subagent simple (la politique d’équipe prudente d’usine de DSH reprend la main) ; allumé, la doctrine d’équipe autonome est injectée et les Agent Teams sont activés.',
1634
+ teamsModeLabel: 'Mode Agent Teams',
1635
+ teamsModeHelp: 'Activé, la doctrine d’équipe (délégation par défaut + vérification par paliers + discipline du tableau de tâches) est injectée et le bundle DSH Agent Teams est activé ; les badges ⚠ d’autorisation des pools de dispatch n’apparaissent que dans ce mode.',
1636
+ syncWhitelistLabel: 'Synchroniser la liste blanche des modèles de subagents',
1637
+ syncWhitelistHelp: 'Interrupteur indépendant (ne dépend pas du mode Agent Teams) : écrit l’union des six pools dans la liste d’autorisation « Réglages DSH → Subagents → sélection de modèle » ; dsh-switchman devient l’unique source de vérité.',
1638
+ whitelistSyncOk: '{count} entrées synchronisées ({time}).',
1639
+ whitelistSyncError: 'Échec de la synchronisation : {error}',
1640
+ whitelistSyncPending: 'Synchronisation en attente…',
1641
+ whitelistSyncNote: 'Les changements de liste blanche ne s’appliquent qu’aux sessions créées ensuite.',
1642
+ uiSectionTitle: 'Interface',
1643
+ uiSectionDescription: 'Langue d’affichage de l’interface propre du plugin (badge, panneau, cette page de réglages).',
1644
+ uiLocaleLabel: 'Langue de l’interface',
1645
+ uiLocaleHelp: 'Auto suit la langue de l’application DeepSeek Harness ; choisir une langue force l’interface du plugin dans cette langue.',
1646
+ uiLocaleAuto: 'Auto (suivre DSH)',
1647
+ },
1648
+ it: {
1649
+ badge: 'Squadra autonoma',
1650
+ badgeTip: 'dsh-switchman: i quattro preset integrati (standard / ptc / minimal / cordis) portano con sé la dottrina di squadra autonoma degli Agent Teams',
1651
+ handoverActive: 'Handover in corso',
1652
+ handoverPhaseBackup: 'backup della sessione',
1653
+ handoverPhaseCompacting: 'compattazione del contesto',
1654
+ handoverPhaseContinuation: 'risveglio della continuazione',
1655
+ handoverActiveTip: 'Switchman sta facendo l’handover in background: fork di una sessione di backup e compattazione del contesto; finito quello, il task prosegue da solo. Una sessione ferma in questa finestra è normale.',
1656
+ visionHintNeedsPool: 'Questo modello non sa leggere le immagini: aggiungi modelli al pool multimodale nelle impostazioni di dsh-switchman, poi invia le immagini con /vision.',
1657
+ visionHintUseVision: 'Questo modello non sa leggere le immagini: inviale con /vision (instradate automaticamente al pool multimodale).',
1658
+ visionAutoConverted: 'Invio dell’immagine rifiutato: reinvio automatico via /vision (lettura dal pool multimodale).',
1659
+ settingsTitle: 'dsh-switchman',
1660
+ panelLabel: 'Switchman',
1661
+ settingsDescription: 'Configura le preferenze di dsh-switchman.',
1662
+ langSectionTitle: 'Lingua',
1663
+ langSectionDescription: 'Controlla la lingua delle risposte degli agent, dei commenti al codice e dei documenti prodotti.',
1664
+ langScopeLabel: 'Ambito della lingua',
1665
+ langScopeHelp: 'Dove vengono conservate queste preferenze linguistiche.',
1666
+ langScopeGlobal: 'Globale (questo profilo)',
1667
+ langScopeProject: 'Per progetto (.switchman/lang.json)',
1668
+ langProjectNote: 'Modalità per progetto: ogni progetto legge il proprio .switchman/lang.json; le risposte date al primo uso vengono salvate lì, e le sessioni continuano a chiedere finché il file non esiste. I tre campi sottostanti valgono solo in modalità globale.',
1669
+ langConversationLabel: 'Lingua della conversazione',
1670
+ langConversationHelp: 'La lingua in cui gli agent rispondono e discutono; se non è impostata, viene chiesta una volta al primo uso e la scelta viene ricordata.',
1671
+ langCommentsLabel: 'Lingua dei commenti al codice',
1672
+ langCommentsHelp: 'La lingua in cui gli agent scrivono i commenti al codice.',
1673
+ langDocsLabel: 'Lingua dei documenti',
1674
+ langDocsHelp: 'La lingua in cui gli agent redigono i documenti.',
1675
+ followConversation: 'Segui la lingua della conversazione',
1676
+ notSetAsk: 'Non impostata (chiedi al primo uso)',
1677
+ customLanguage: 'Personalizzata…',
1678
+ customLanguagePlaceholder: 'Nome della lingua o tag BCP',
1679
+ customLanguageRequired: 'Inserisci una lingua personalizzata (1–48 caratteri).',
1680
+ currentValue: 'Attuale: {value}',
1681
+ currentValueUnset: 'Attuale: non impostata',
1682
+ suggestedValue: 'Suggerita: {value}',
1683
+ save: 'Salva',
1684
+ saving: 'Salvataggio…',
1685
+ discard: 'Annulla le modifiche',
1686
+ saveFailed: 'Il deployment non ha accettato questi valori; sono stati lasciati a te da correggere.',
1687
+ saveConflict: 'Le impostazioni sono cambiate altrove. Scarta la bozza e riprova.',
1688
+ formLoading: 'Caricamento delle impostazioni…',
1689
+ formUnavailable: 'Questo plugin non è caricato, quindi non è configurabile al momento.',
1690
+ formReadOnly: 'Questo deployment salva le impostazioni in sola lettura.',
1691
+ dispatchSectionTitle: 'Pool di dispatch e classifica dei modelli',
1692
+ dispatchSectionDescription: 'Raggruppa i modelli in sei pool di dispatch per complessità del task e mantiene una classifica di capacità; incide solo sulla delega di dsh-switchman.',
1693
+ dispatchProgress: '{pools}/6 pool impostati · {ranked} classificati · modalità {mode}',
1694
+ poolEconomyTitle: 'Economia',
1695
+ poolEconomyDesc: 'Lavori piccoli in serie e a bassa complessità',
1696
+ poolMechanicalTitle: 'Meccanico',
1697
+ poolMechanicalDesc: 'Riscritture meccaniche e operazioni su schema',
1698
+ poolMainTitle: 'Principale',
1699
+ poolMainDesc: 'Coding di tutti i giorni e attività quotidiane',
1700
+ poolHardTitle: 'Difficile',
1701
+ poolHardDesc: 'Ragionamento complesso e refactoring su larga scala',
1702
+ poolVisionTitle: 'Visione',
1703
+ poolVisionDesc: 'Lavoro multimodale (immagini)',
1704
+ poolReviewTitle: 'Revisione',
1705
+ poolReviewDesc: 'Revisione in sola lettura e verifica indipendente',
1706
+ poolSelectAll: 'Seleziona tutto',
1707
+ poolClear: 'Azzera',
1708
+ poolEmpty: 'Nessun modello candidato',
1709
+ poolManualLabel: 'Ordine manuale',
1710
+ poolManualHelp: 'Attivo, il dispatch segue l’ordine elencato (il primo della lista = prima scelta); spento, le corsie vengono ordinate per capacità automaticamente.',
1711
+ poolManualSelected: 'Selezionati · priorità di dispatch',
1712
+ poolManualAddable: 'Aggiungi modelli',
1713
+ poolMoveUp: 'Sposta su',
1714
+ poolMoveDown: 'Sposta giù',
1715
+ poolRemoveOne: 'Rimuovi',
1716
+ poolEffortFollow: 'segui la corsia',
1717
+ poolEffortLabel: 'effort',
1718
+ poolEffortHelp: 'Fissa il reasoning effort di questo modello; prevale sul default della corsia in fase di dispatch',
1719
+ catalogLoading: 'Caricamento del catalogo modelli…',
1720
+ catalogLoadFailed: 'Impossibile caricare il catalogo dei modelli.',
1721
+ catalogRetry: 'Riprova',
1722
+ catalogPartial: 'Alcuni provider di modelli non sono stati caricati; le scelte salvate restano rimovibili.',
1723
+ catalogEmpty: 'Nessun provider di modelli al momento propone un modello.',
1724
+ catalogUnavailableGroup: 'Salvati ma al momento non disponibili',
1725
+ catalogUnavailable: 'al momento non disponibile',
1726
+ unauthorizedBadge: 'non autorizzato per il dispatch esplicito dei figli nelle impostazioni DSH (subagent: selezione modelli)',
1727
+ unauthorizedHint: 'I modelli contrassegnati ⚠ non sono autorizzati in Impostazioni DSH → Subagent → selezione modelli; gli agent che li nominano esplicitamente vengono negati — autorizzali nelle impostazioni DSH, oppure lascia dispatch implicito agli agent.',
1728
+ rankTitle: 'Classifica di capacità',
1729
+ rankDescription: 'Numerati dal più forte in giù; ogni voce può ancorare una fascia S/A/B/C. L’elenco è selezioni dei pool ∪ classifica salvata; ogni modifica rende persistente l’ordine mostrato.',
1730
+ rankEmpty: 'Seleziona modelli nei pool sopra; la classifica compare da sola.',
1731
+ rankTier: 'Fascia',
1732
+ rankTierNone: '—',
1733
+ rankMoveUp: 'Sposta su',
1734
+ rankMoveDown: 'Sposta giù',
1735
+ rankRemove: 'Rimuovi dalla classifica',
1736
+ enforceLabel: 'Esecuzione',
1737
+ enforceOff: 'Off',
1738
+ enforceAdvice: 'Advice',
1739
+ enforceEnforce: 'Enforce',
1740
+ enforceHelpOff: 'Nessuna raccomandazione di pool viene iniettata nella delega.',
1741
+ enforceHelpAdvice: 'Le raccomandazioni dei pool entrano come consiglio (advice); i modelli possono discostarsene.',
1742
+ enforceHelpEnforce: 'Le raccomandazioni dei pool entrano come vincolo rigido; gli scostamenti vengono rifiutati.',
1743
+ wmSectionTitle: 'Livello dell’acqua del contesto',
1744
+ wmSectionDescription: 'Comportamento a soglie in base ai token usati: consiglio, letture col tetto e chiusura, handover automatico.',
1745
+ wmSoftLabel: 'Soglia soft',
1746
+ wmSoftHelp: 'Superata, compare un banner e conviene delegare o sistemare il contesto.',
1747
+ wmHardLabel: 'Soglia hard',
1748
+ wmHardHelp: 'Superata, il budget di lettura si stringe e conviene chiudere.',
1749
+ wmForceLabel: 'Soglia force',
1750
+ wmForceHelp: 'Superata, backup e handover alla compattazione (può essere automatico).',
1751
+ wmReadBudgetLabel: 'Budget di lettura',
1752
+ wmReadBudgetHelp: 'Budget di token per lettura; ogni turno arriva al massimo al doppio.',
1753
+ wmNumberInvalid: 'Inserisci un numero intero di almeno {min}.',
1754
+ wmOrderInvalid: 'Le tre soglie devono salire rigorosamente: soft < hard < force.',
1755
+ wmDenyModeLabel: 'Comportamento alla soglia hard',
1756
+ wmDenyModeCap: 'Tetto e avviso',
1757
+ wmDenyModeDeny: 'Rifiuto secco',
1758
+ wmDenyModeHelpCap: 'Le chiamate oltre budget passano, ma viene registrato un avviso.',
1759
+ wmDenyModeHelpDeny: 'Le chiamate oltre budget vengono rifiutate sul posto.',
1760
+ wmAutoHandoverLabel: 'Handover automatico',
1761
+ wmAutoHandoverHelp: 'Alla soglia force, backup e handover alla compattazione avvengono da soli.',
1762
+ wmSubagentTitle: 'Subagent',
1763
+ wmSubagentCapLabel: 'Tetto di contesto dei subagent',
1764
+ wmSubagentCapHelp: 'Lascia i subagent usare la soglia force dedicata qui sotto; spento = seguono appieno le tre soglie sopra.',
1765
+ wmSubagentForceLabel: 'Soglia force dei subagent',
1766
+ wmSubagentForceHelp: 'Sostituisce solo la soglia force dei subagent (soft/hard restano condivise con la sessione principale); 0 segue la soglia force sopra.',
1767
+ wmSubagentFollowForce: 'Segui la soglia force (0)',
1768
+ wmCommands: 'Comandi: /ctx-pause sospende le azioni da livello dell’acqua · /ctx-resume le riprende · /ctx-handover fa backup e handover subito.',
1769
+ teamsSectionTitle: 'Agent Teams',
1770
+ teamsSectionDescription: 'Cambia la forma del dispatch: spento è il semplice dispatch via subagent (subentra la politica di squadra prudente di fabbrica di DSH); acceso inietta la dottrina di squadra autonoma e abilita gli Agent Teams.',
1771
+ teamsModeLabel: 'Modalità Agent Teams',
1772
+ teamsModeHelp: 'Accesa, la dottrina di squadra (delega per default + verifica a livelli + disciplina del task board condiviso) viene iniettata e il bundle Agent Teams di DSH viene abilitato; i badge ⚠ di autorizzazione dei pool di dispatch compaiono solo in questa modalità.',
1773
+ syncWhitelistLabel: 'Sincronizza la whitelist dei modelli per i subagent',
1774
+ syncWhitelistHelp: 'Interruttore indipendente (non richiede la modalità Agent Teams): scrive l’unione dei sei pool nella lista di autorizzazione «Impostazioni DSH → Subagent → selezione modelli»; dsh-switchman diventa l’unica fonte di verità.',
1775
+ whitelistSyncOk: 'Sincronizzate {count} voci ({time}).',
1776
+ whitelistSyncError: 'Sincronizzazione fallita: {error}',
1777
+ whitelistSyncPending: 'In attesa di sincronizzare…',
1778
+ whitelistSyncNote: 'Le modifiche alla whitelist valgono solo per le sessioni create dopo.',
1779
+ uiSectionTitle: 'Interfaccia',
1780
+ uiSectionDescription: 'Lingua di visualizzazione dell’interfaccia del plugin stesso (badge, pannello, questa pagina di impostazioni).',
1781
+ uiLocaleLabel: 'Lingua dell’interfaccia',
1782
+ uiLocaleHelp: 'Auto segue la lingua dell’app DeepSeek Harness; scegliere una lingua forza l’interfaccia del plugin in quella lingua.',
1783
+ uiLocaleAuto: 'Auto (segui DSH)',
1784
+ },
1785
+ pt: {
1786
+ badge: 'Equipe autônoma',
1787
+ badgeTip: 'dsh-switchman: os quatro presets embutidos (standard / ptc / minimal / cordis) carregam a doutrina de equipe autônoma do Agent Teams',
1788
+ handoverActive: 'Handover em andamento',
1789
+ handoverPhaseBackup: 'backup da sessão',
1790
+ handoverPhaseCompacting: 'compactação do contexto',
1791
+ handoverPhaseContinuation: 'despertar da continuação',
1792
+ handoverActiveTip: 'O Switchman está fazendo o handover em segundo plano: fork de uma sessão de backup e compactação do contexto; ao terminar, a tarefa continua automaticamente. Uma sessão parada durante essa janela é esperada.',
1793
+ visionHintNeedsPool: 'Este modelo não sabe ler imagens: adicione modelos ao pool multimodal nas configurações do dsh-switchman e depois envie imagens com /vision.',
1794
+ visionHintUseVision: 'Este modelo não sabe ler imagens: envie-as com /vision (roteadas automaticamente para o pool multimodal).',
1795
+ visionAutoConverted: 'Envio da imagem recusado: reenvio automático via /vision (leitura pelo pool multimodal).',
1796
+ settingsTitle: 'dsh-switchman',
1797
+ panelLabel: 'Switchman',
1798
+ settingsDescription: 'Configure as preferências do dsh-switchman.',
1799
+ langSectionTitle: 'Idioma',
1800
+ langSectionDescription: 'Controla o idioma das respostas dos agents, dos comentários de código e dos documentos redigidos.',
1801
+ langScopeLabel: 'Escopo do idioma',
1802
+ langScopeHelp: 'Onde essas preferências de idioma ficam guardadas.',
1803
+ langScopeGlobal: 'Global (este perfil)',
1804
+ langScopeProject: 'Por projeto (.switchman/lang.json)',
1805
+ langProjectNote: 'Modo por projeto: cada projeto lê o próprio .switchman/lang.json; as respostas do primeiro uso são salvas lá, e as sessões perguntam até o arquivo existir. Os três campos abaixo valem apenas no modo global.',
1806
+ langConversationLabel: 'Idioma da conversa',
1807
+ langConversationHelp: 'O idioma em que os agents respondem e discutem; sem valor definido, perguntam uma vez no primeiro uso e a escolha fica guardada.',
1808
+ langCommentsLabel: 'Idioma dos comentários de código',
1809
+ langCommentsHelp: 'O idioma em que os agents escrevem comentários de código.',
1810
+ langDocsLabel: 'Idioma dos documentos',
1811
+ langDocsHelp: 'O idioma em que os agents redigem documentos.',
1812
+ followConversation: 'Seguir o idioma da conversa',
1813
+ notSetAsk: 'Não definido (perguntar no primeiro uso)',
1814
+ customLanguage: 'Personalizado…',
1815
+ customLanguagePlaceholder: 'Nome de idioma ou tag BCP',
1816
+ customLanguageRequired: 'Informe um idioma personalizado (1–48 caracteres).',
1817
+ currentValue: 'Atual: {value}',
1818
+ currentValueUnset: 'Atual: não definido',
1819
+ suggestedValue: 'Sugerido: {value}',
1820
+ save: 'Salvar',
1821
+ saving: 'Salvando…',
1822
+ discard: 'Descartar alterações',
1823
+ saveFailed: 'O deployment não aceitou estes valores; eles ficaram para você corrigir.',
1824
+ saveConflict: 'As configurações mudaram em outro lugar. Descarte o rascunho e tente de novo.',
1825
+ formLoading: 'Carregando configurações…',
1826
+ formUnavailable: 'Este plugin não está carregado, então não pode ser configurado agora.',
1827
+ formReadOnly: 'Este deployment guarda as configurações em modo somente leitura.',
1828
+ dispatchSectionTitle: 'Pools de despacho e ranking de modelos',
1829
+ dispatchSectionDescription: 'Agrupa os modelos em seis pools de despacho por complexidade da tarefa e mantém um ranking de capacidade; afeta apenas o despacho do dsh-switchman.',
1830
+ dispatchProgress: '{pools}/6 pools definidos · {ranked} no ranking · modo {mode}',
1831
+ poolEconomyTitle: 'Economia',
1832
+ poolEconomyDesc: 'Tarefas leves em lote e de baixa complexidade',
1833
+ poolMechanicalTitle: 'Mecânico',
1834
+ poolMechanicalDesc: 'Reescritas mecânicas e operações de molde',
1835
+ poolMainTitle: 'Principal',
1836
+ poolMainDesc: 'Codificação do dia a dia e tarefas correntes',
1837
+ poolHardTitle: 'Difícil',
1838
+ poolHardDesc: 'Raciocínio pesado e refatoração em grande escala',
1839
+ poolVisionTitle: 'Visão',
1840
+ poolVisionDesc: 'Trabalho multimodal (imagens)',
1841
+ poolReviewTitle: 'Revisão',
1842
+ poolReviewDesc: 'Revisão somente leitura e verificação independente',
1843
+ poolSelectAll: 'Marcar todos',
1844
+ poolClear: 'Limpar',
1845
+ poolEmpty: 'Nenhum modelo candidato',
1846
+ poolManualLabel: 'Ordem manual',
1847
+ poolManualHelp: 'Ligado, o despacho segue a ordem listada (o primeiro = primeira escolha); desligado, as faixas são ordenadas por capacidade automaticamente.',
1848
+ poolManualSelected: 'Selecionados · prioridade de despacho',
1849
+ poolManualAddable: 'Adicionar modelos',
1850
+ poolMoveUp: 'Mover para cima',
1851
+ poolMoveDown: 'Mover para baixo',
1852
+ poolRemoveOne: 'Remover',
1853
+ poolEffortFollow: 'seguir a faixa',
1854
+ poolEffortLabel: 'effort',
1855
+ poolEffortHelp: 'Fixa o reasoning effort deste modelo; sobrepõe o padrão da faixa no despacho',
1856
+ catalogLoading: 'Carregando o catálogo de modelos…',
1857
+ catalogLoadFailed: 'Não foi possível carregar o catálogo de modelos.',
1858
+ catalogRetry: 'Tentar de novo',
1859
+ catalogPartial: 'Alguns provedores de modelos não foram carregados; as escolhas salvas continuam removíveis.',
1860
+ catalogEmpty: 'Nenhum provedor de modelos anuncia um modelo no momento.',
1861
+ catalogUnavailableGroup: 'Salvos, mas indisponíveis no momento',
1862
+ catalogUnavailable: 'indisponível no momento',
1863
+ unauthorizedBadge: 'não autorizado para despacho explícito de filhos nas configurações do DSH (subagents: seleção de modelos)',
1864
+ unauthorizedHint: 'Modelos marcados com ⚠ não estão autorizados em Configurações do DSH → Subagents → seleção de modelos; agents que os nomearem explicitamente serão negados — autorize-os nas configurações do DSH, ou deixe os agents despachar implicitamente.',
1865
+ rankTitle: 'Ranking de capacidade',
1866
+ rankDescription: 'Numerados do mais forte para baixo; cada entrada pode ancorar um nível S/A/B/C. A lista é seleção dos pools ∪ ranking salvo; qualquer edição persiste a ordem exibida.',
1867
+ rankEmpty: 'Marque modelos nos pools acima; o ranking aparece sozinho.',
1868
+ rankTier: 'Nível',
1869
+ rankTierNone: '—',
1870
+ rankMoveUp: 'Mover para cima',
1871
+ rankMoveDown: 'Mover para baixo',
1872
+ rankRemove: 'Remover do ranking',
1873
+ enforceLabel: 'Execução',
1874
+ enforceOff: 'Off',
1875
+ enforceAdvice: 'Advice',
1876
+ enforceEnforce: 'Enforce',
1877
+ enforceHelpOff: 'Nenhuma orientação de pool é injetada no despacho.',
1878
+ enforceHelpAdvice: 'A orientação dos pools entra como conselho (advice); os modelos podem desviar.',
1879
+ enforceHelpEnforce: 'A orientação dos pools entra como restrição rígida; desvios são recusados.',
1880
+ wmSectionTitle: 'Nível de água do contexto',
1881
+ wmSectionDescription: 'Comportamento em degraus conforme o uso de tokens: conselho, leituras com teto e encerramento, handover automático.',
1882
+ wmSoftLabel: 'Limiar soft',
1883
+ wmSoftHelp: 'Além dele, aparece um banner e delegar ou arrumar o contexto é recomendado.',
1884
+ wmHardLabel: 'Limiar hard',
1885
+ wmHardHelp: 'Além dele, o orçamento de leitura aperta e convém encerrar.',
1886
+ wmForceLabel: 'Limiar force',
1887
+ wmForceHelp: 'Além dele, backup e handover para a compactação (pode ser automático).',
1888
+ wmReadBudgetLabel: 'Orçamento de leitura',
1889
+ wmReadBudgetHelp: 'Orçamento de tokens por leitura; cada turno se limita ao dobro disso.',
1890
+ wmNumberInvalid: 'Informe um número inteiro de {min} ou mais.',
1891
+ wmOrderInvalid: 'Os três limiares devem subir estritamente: soft < hard < force.',
1892
+ wmDenyModeLabel: 'Comportamento no limiar hard',
1893
+ wmDenyModeCap: 'Limitar e avisar',
1894
+ wmDenyModeDeny: 'Negar na hora',
1895
+ wmDenyModeHelpCap: 'Chamadas acima do orçamento passam, mas um aviso é registrado.',
1896
+ wmDenyModeHelpDeny: 'Chamadas acima do orçamento são negadas na hora.',
1897
+ wmAutoHandoverLabel: 'Handover automático',
1898
+ wmAutoHandoverHelp: 'No limiar force, backup e handover para a compactação acontecem sozinhos.',
1899
+ wmSubagentTitle: 'Subagents',
1900
+ wmSubagentCapLabel: 'Teto de contexto dos subagents',
1901
+ wmSubagentCapHelp: 'Deixa os subagents usar o limiar force dedicado abaixo; desligado = seguem integralmente os três limiares acima.',
1902
+ wmSubagentForceLabel: 'Limiar force dos subagents',
1903
+ wmSubagentForceHelp: 'Sobrepõe apenas o limiar force dos subagents (soft/hard são compartilhados com a sessão principal); 0 segue o limiar force acima.',
1904
+ wmSubagentFollowForce: 'Seguir o limiar force (0)',
1905
+ wmCommands: 'Comandos: /ctx-pause suspende as ações de nível de água · /ctx-resume as retoma · /ctx-handover faz backup e handover agora.',
1906
+ teamsSectionTitle: 'Agent Teams',
1907
+ teamsSectionDescription: 'Muda o formato do despacho: desligado é o despacho simples via subagent (entra a política conservadora de equipe de fábrica do DSH); ligado injeta a doutrina de equipe autônoma e habilita os Agent Teams.',
1908
+ teamsModeLabel: 'Modo Agent Teams',
1909
+ teamsModeHelp: 'Ligado, a doutrina de equipe (delegar por padrão + verificação em níveis + disciplina do quadro de tarefas compartilhado) é injetada e o bundle Agent Teams do DSH fica habilitado; os badges ⚠ de autorização dos pools de despacho aparecem apenas neste modo.',
1910
+ syncWhitelistLabel: 'Sincronizar a whitelist de modelos dos subagents',
1911
+ syncWhitelistHelp: 'Chave independente (não depende do modo Agent Teams): grava a união dos seis pools na lista de autorização “Configurações do DSH → Subagents → seleção de modelos”; o dsh-switchman vira a única fonte da verdade.',
1912
+ whitelistSyncOk: 'Sincronizadas {count} entradas ({time}).',
1913
+ whitelistSyncError: 'Falha na sincronização: {error}',
1914
+ whitelistSyncPending: 'Aguardando sincronizar…',
1915
+ whitelistSyncNote: 'Mudanças na whitelist só valem para sessões criadas depois.',
1916
+ uiSectionTitle: 'Interface',
1917
+ uiSectionDescription: 'Idioma de exibição da interface do próprio plugin (badge, painel, esta página de configurações).',
1918
+ uiLocaleLabel: 'Idioma da interface',
1919
+ uiLocaleHelp: 'Auto segue o idioma do aplicativo DeepSeek Harness; escolher um idioma força a interface do plugin para ele.',
1920
+ uiLocaleAuto: 'Auto (seguir DSH)',
1921
+ },
1922
+ ru: {
1923
+ badge: 'Автономная команда',
1924
+ badgeTip: 'dsh-switchman: четыре встроенных пресета (standard / ptc / minimal / cordis) несут с собой регламент автономной команды Agent Teams',
1925
+ handoverActive: 'Идёт передача',
1926
+ handoverPhaseBackup: 'резервная сессия',
1927
+ handoverPhaseCompacting: 'сжатие контекста',
1928
+ handoverPhaseContinuation: 'пробуждение продолжения',
1929
+ handoverActiveTip: 'Switchman передаёт контекст в фоне: форкает резервную сессию и сжимает контекст; по завершении задача продолжается автоматически. Неподвижная сессия в это окно — это нормально.',
1930
+ visionHintNeedsPool: 'Эта модель не умеет читать изображения: добавьте модели в мультимодальный пул в настройках dsh-switchman и отправляйте картинки через /vision.',
1931
+ visionHintUseVision: 'Эта модель не умеет читать изображения: отправляйте их через /vision (автоматически уйдут в мультимодальный пул).',
1932
+ visionAutoConverted: 'Отправка картинки отклонена: повторная отправка идёт автоматически через /vision (прочитает мультимодальный пул).',
1933
+ settingsTitle: 'dsh-switchman',
1934
+ panelLabel: 'Switchman',
1935
+ settingsDescription: 'Настройка предпочтений dsh-switchman.',
1936
+ langSectionTitle: 'Язык',
1937
+ langSectionDescription: 'Определяет язык ответов агентов, комментариев в коде и создаваемых документов.',
1938
+ langScopeLabel: 'Область действия языка',
1939
+ langScopeHelp: 'Где хранятся эти языковые предпочтения.',
1940
+ langScopeGlobal: 'Глобально (этот профиль)',
1941
+ langScopeProject: 'По проектам (.switchman/lang.json)',
1942
+ langProjectNote: 'Режим по проектам: каждый проект читает свой .switchman/lang.json; ответы при первом использовании сохраняются туда, и сессии спрашивают, пока файл не появится. Три поля ниже действуют только в глобальном режиме.',
1943
+ langConversationLabel: 'Язык беседы',
1944
+ langConversationHelp: 'Язык, на котором агенты отвечают и обсуждают; если не задан, спросят один раз при первом использовании и запомнят выбор.',
1945
+ langCommentsLabel: 'Язык комментариев в коде',
1946
+ langCommentsHelp: 'Язык, на котором агенты пишут комментарии в коде.',
1947
+ langDocsLabel: 'Язык документов',
1948
+ langDocsHelp: 'Язык, на котором агенты составляют документы.',
1949
+ followConversation: 'Следовать языку беседы',
1950
+ notSetAsk: 'Не задан (спросить при первом использовании)',
1951
+ customLanguage: 'Свой язык…',
1952
+ customLanguagePlaceholder: 'Название языка или BCP-тег',
1953
+ customLanguageRequired: 'Введите свой язык (1–48 символов).',
1954
+ currentValue: 'Сейчас: {value}',
1955
+ currentValueUnset: 'Сейчас: не задан',
1956
+ suggestedValue: 'Предложено: {value}',
1957
+ save: 'Сохранить',
1958
+ saving: 'Сохранение…',
1959
+ discard: 'Отменить изменения',
1960
+ saveFailed: 'Развёртывание не приняло эти значения; они оставлены вам на исправление.',
1961
+ saveConflict: 'Настройки изменились в другом месте. Откажитесь от черновика и попробуйте снова.',
1962
+ formLoading: 'Загрузка настроек…',
1963
+ formUnavailable: 'Плагин не загружен, поэтому настроить его сейчас нельзя.',
1964
+ formReadOnly: 'Это развёртывание хранит настройки в режиме только для чтения.',
1965
+ dispatchSectionTitle: 'Пулы диспетчеризации и ранжирование моделей',
1966
+ dispatchSectionDescription: 'Разбивает модели на шесть пулов диспетчеризации по сложности задач и ведёт ранжирование по силе; действует только на делегирование dsh-switchman.',
1967
+ dispatchProgress: '{pools}/6 пулов задано · {ranked} в ранжировании · режим {mode}',
1968
+ poolEconomyTitle: 'Экономия',
1969
+ poolEconomyDesc: 'Мелкие массовые задачи низкой сложности',
1970
+ poolMechanicalTitle: 'Механика',
1971
+ poolMechanicalDesc: 'Механические переработки и шаблонные операции',
1972
+ poolMainTitle: 'Основной',
1973
+ poolMainDesc: 'Повседневный кодинг и рутинные задачи',
1974
+ poolHardTitle: 'Сложный',
1975
+ poolHardDesc: 'Тяжёлые рассуждения и крупные рефакторинги',
1976
+ poolVisionTitle: 'Мультимодальный',
1977
+ poolVisionDesc: 'Мультимодальная работа (изображения)',
1978
+ poolReviewTitle: 'Ревью',
1979
+ poolReviewDesc: 'Ревью только для чтения и независимая проверка',
1980
+ poolSelectAll: 'Выбрать все',
1981
+ poolClear: 'Очистить',
1982
+ poolEmpty: 'Нет моделей-кандидатов',
1983
+ poolManualLabel: 'Ручной порядок',
1984
+ poolManualHelp: 'Включено — диспетчеризация идёт по списку (голова списка = первый выбор); выключено — полосы упорядочиваются по силе автоматически.',
1985
+ poolManualSelected: 'Выбрано · приоритет диспетчеризации',
1986
+ poolManualAddable: 'Добавить модели',
1987
+ poolMoveUp: 'Выше',
1988
+ poolMoveDown: 'Ниже',
1989
+ poolRemoveOne: 'Убрать',
1990
+ poolEffortFollow: 'следовать полосе',
1991
+ poolEffortLabel: 'effort',
1992
+ poolEffortHelp: 'Фиксирует reasoning effort этой модели; при диспетчеризации перекрывает умолчание полосы',
1993
+ catalogLoading: 'Загрузка каталога моделей…',
1994
+ catalogLoadFailed: 'Не удалось загрузить каталог моделей.',
1995
+ catalogRetry: 'Повторить',
1996
+ catalogPartial: 'Часть провайдеров моделей не загрузилась; сохранённый выбор всё ещё можно убрать.',
1997
+ catalogEmpty: 'Ни один провайдер моделей сейчас не объявляет моделей.',
1998
+ catalogUnavailableGroup: 'Сохранённые, но сейчас недоступные',
1999
+ catalogUnavailable: 'сейчас недоступна',
2000
+ unauthorizedBadge: 'не авторизовано для явной диспетчеризации потомков в настройках DSH (субагенты: выбор моделей)',
2001
+ unauthorizedHint: 'Модели с пометкой ⚠ не авторизованы в «Настройки DSH → Субагенты → выбор моделей»; явное их назначение агентом будет отклонено — авторизуйте их в настройках DSH или пусть агенты диспетчеризуют неявно.',
2002
+ rankTitle: 'Ранжирование по силе',
2003
+ rankDescription: 'Нумерация от сильнейшего; каждая запись может привязаться к ступени S/A/B/C. Список — это выбор пулов ∪ сохранённое ранжирование; любое изменение закрепляет показанный порядок.',
2004
+ rankEmpty: 'Отметьте модели в пулах выше — список ранжирования появится сам.',
2005
+ rankTier: 'Ступень',
2006
+ rankTierNone: '—',
2007
+ rankMoveUp: 'Выше',
2008
+ rankMoveDown: 'Ниже',
2009
+ rankRemove: 'Убрать из ранжирования',
2010
+ enforceLabel: 'Режим исполнения',
2011
+ enforceOff: 'Off',
2012
+ enforceAdvice: 'Advice',
2013
+ enforceEnforce: 'Enforce',
2014
+ enforceHelpOff: 'Никакие рекомендации пулов не добавляются в делегирование.',
2015
+ enforceHelpAdvice: 'Рекомендации пулов добавляются как совет (advice); модели могут от них отступать.',
2016
+ enforceHelpEnforce: 'Рекомендации пулов добавляются как жёсткое ограничение; отступления отклоняются.',
2017
+ wmSectionTitle: 'Уровень воды в контексте',
2018
+ wmSectionDescription: 'Ступенчатое поведение по расходу токенов: совет, урезание чтения и подведение итогов, автоматическая передача.',
2019
+ wmSoftLabel: 'Линия soft',
2020
+ wmSoftHelp: 'Выше неё появляется баннер, и советуется делегировать или прибрать контекст.',
2021
+ wmHardLabel: 'Линия hard',
2022
+ wmHardHelp: 'Выше неё бюджет чтения урезается и стоит подвигаться к завершению.',
2023
+ wmForceLabel: 'Линия force',
2024
+ wmForceHelp: 'Выше неё — резервная копия и передача на сжатие (может быть автоматически).',
2025
+ wmReadBudgetLabel: 'Бюджет чтения',
2026
+ wmReadBudgetHelp: 'Бюджет токенов на одно чтение; каждый ход ограничен удвоенным значением.',
2027
+ wmNumberInvalid: 'Введите целое число не меньше {min}.',
2028
+ wmOrderInvalid: 'Три линии должны строго возрастать: soft < hard < force.',
2029
+ wmDenyModeLabel: 'Поведение на линии hard',
2030
+ wmDenyModeCap: 'Урезать и предупредить',
2031
+ wmDenyModeDeny: 'Отклонять сразу',
2032
+ wmDenyModeHelpCap: 'Вызовы сверх бюджета проходят, но предупреждение записывается.',
2033
+ wmDenyModeHelpDeny: 'Вызовы сверх бюджета отклоняются сразу.',
2034
+ wmAutoHandoverLabel: 'Автоматическая передача',
2035
+ wmAutoHandoverHelp: 'На линии force — резервная копия и передача на сжатие автоматически.',
2036
+ wmSubagentTitle: 'Субагенты',
2037
+ wmSubagentCapLabel: 'Потолок контекста субагентов',
2038
+ wmSubagentCapHelp: 'Субагенты используют отдельный порог force ниже; выключено = полностью следуют трём линиям выше.',
2039
+ wmSubagentForceLabel: 'Порог force субагентов',
2040
+ wmSubagentForceHelp: 'Меняет только линию force субагентов (soft/hard общие с главной сессией); 0 — следовать линии force выше.',
2041
+ wmSubagentFollowForce: 'Следовать линии force (0)',
2042
+ wmCommands: 'Команды: /ctx-pause приостанавливает действия по уровню воды · /ctx-resume возобновляет их · /ctx-handover делает резервную копию и передаёт прямо сейчас.',
2043
+ teamsSectionTitle: 'Agent Teams',
2044
+ teamsSectionDescription: 'Переключает форму диспетчеризации: выключено — обычный dispatch через субагентов (вступает консервативная заводская командная политика DSH); включено — внедряется регламент автономной команды и включаются Agent Teams.',
2045
+ teamsModeLabel: 'Режим Agent Teams',
2046
+ teamsModeHelp: 'Включено: внедряется командный регламент (делегирование по умолчанию + многоуровневая проверка + дисциплина общей доски задач) и включается бандл DSH Agent Teams; значки ⚠ авторизации у пулов диспетчеризации показываются только в этом режиме.',
2047
+ syncWhitelistLabel: 'Синхронизировать белый список моделей субагентов',
2048
+ syncWhitelistHelp: 'Независимый переключатель (режим Agent Teams не требуется): записывает объединение шести пулов в список авторизации «Настройки DSH → Субагенты → выбор моделей»; dsh-switchman становится единственным источником истины.',
2049
+ whitelistSyncOk: 'Синхронизировано записей: {count} ({time}).',
2050
+ whitelistSyncError: 'Сбой синхронизации: {error}',
2051
+ whitelistSyncPending: 'Ожидание синхронизации…',
2052
+ whitelistSyncNote: 'Изменения белого списка действуют только на сессии, созданные после.',
2053
+ uiSectionTitle: 'Интерфейс',
2054
+ uiSectionDescription: 'Язык отображения собственного интерфейса плагина (значок, панель, эта страница настроек).',
2055
+ uiLocaleLabel: 'Язык интерфейса',
2056
+ uiLocaleHelp: '«Авто» следует языку приложения DeepSeek Harness; выбор конкретного языка принудительно переводит на него интерфейс плагина.',
2057
+ uiLocaleAuto: 'Авто (следовать DSH)',
750
2058
  },
751
2059
  };
752
2060
 
@@ -792,18 +2100,20 @@ window.__ModuleLoader__.load({
792
2100
  }
793
2101
 
794
2102
  function SwitchmanBadge({
795
- locale,
796
- t,
797
- sessionId,
798
- useProjection,
799
- useSessions,
800
- }) {
2103
+ locale,
2104
+ t,
2105
+ sessionId,
2106
+ useProjection,
2107
+ useSessions,
2108
+ }) {
801
2109
 
802
2110
  // Subscription only: stable snapshot via getLocale() re-renders on switch.
803
2111
  React.useSyncExternalStore(
804
2112
  (fn) => locale.subscribe(fn),
805
2113
  () => locale.getLocale(),
806
2114
  );
2115
+ // Re-render when the manual interface-locale override changes.
2116
+ React.useSyncExternalStore(subscribeUiLocale, () => uiLocaleVersion);
807
2117
  // Live handover cue: during the fork+compact window the session
808
2118
  // GUI has no motion of its own, so the badge polls the Host's
809
2119
  // handover-state route (phases recorded from runHandover's first
@@ -1201,6 +2511,9 @@ window.__ModuleLoader__.load({
1201
2511
  * pattern): height:100% scroll owner outside, reading-width
1202
2512
  * centered column inside. */
1203
2513
  function SwitchmanPanelPage(props) {
2514
+ // Re-render when the manual interface-locale override changes
2515
+ // (panel strings go through the injected t wrapper).
2516
+ React.useSyncExternalStore(subscribeUiLocale, () => uiLocaleVersion);
1204
2517
  return h(
1205
2518
  'div',
1206
2519
  {
@@ -1562,16 +2875,19 @@ window.__ModuleLoader__.load({
1562
2875
  onClear,
1563
2876
  }) {
1564
2877
  const hasCandidates = rows.length > 0 || extras.length > 0;
1565
- /** 授权漂移判定:该路由不在本会话 DSH 授权的子智能体模型内
1566
- * (authorized === null = 未知,不标)。enabled === false 时
1567
- * 一切显式指定都会被拒,所有已选路由都算漂移。仅团队模式
1568
- * 显示:纯 subagent 模式不做显式路由注入,徽标无意义。 */
2878
+ /** Authorization-drift check: this route is not among the subagent
2879
+ * models DSH authorized for this session (authorized === null =
2880
+ * unknown, no mark). When enabled === false every explicit route
2881
+ * is rejected, so all selected routes count as drift. Team mode
2882
+ * only: plain subagent mode does no explicit route injection, the
2883
+ * badge would be meaningless. */
1569
2884
  const drift = (route) =>
1570
2885
  teamsMode === true &&
1571
2886
  authorized !== null &&
1572
2887
  (authorized.enabled === false ||
1573
2888
  !authorized.keys.has(routeKey(route)));
1574
- /** 漂移行的 ⚠ 徽标(悬停/读屏文案见 unauthorizedBadge)。 */
2889
+ /** ⚠ badge for drifted rows (hover/screen-reader text in
2890
+ * unauthorizedBadge). */
1575
2891
  const unauthorizedBadge = () =>
1576
2892
  h(
1577
2893
  'span',
@@ -1582,7 +2898,7 @@ window.__ModuleLoader__.load({
1582
2898
  },
1583
2899
  '⚠',
1584
2900
  );
1585
- /** 显示名查找:覆盖目录行与已存离架行。 */
2901
+ /** Display-name lookup: covers catalog rows and stored off-catalog rows. */
1586
2902
  const nameByKey = new Map(
1587
2903
  [...rows, ...extras]
1588
2904
  .filter((row) => row.header === undefined)
@@ -1591,11 +2907,12 @@ window.__ModuleLoader__.load({
1591
2907
  `${row.providerName} · ${row.modelName}`,
1592
2908
  ]),
1593
2909
  );
1594
- /** effort 查找:该池已配置条目的 key → effort。 */
2910
+ /** Effort lookup: a configured entry's key → effort for this pool. */
1595
2911
  const effortByKey = new Map(
1596
2912
  efforts.map((entry) => [routeKey(entry), entry.effort]),
1597
2913
  );
1598
- /** effort 元数据查找:routeKey → wire reasoning.efforts(无则缺省)。 */
2914
+ /** Effort metadata lookup: routeKey → wire reasoning.efforts (default
2915
+ * when absent). */
1599
2916
  const effortsMetaByKey = new Map(
1600
2917
  [...rows, ...extras]
1601
2918
  .filter(
@@ -1604,9 +2921,10 @@ window.__ModuleLoader__.load({
1604
2921
  )
1605
2922
  .map((row) => [routeKey(row), row.reasoning.efforts]),
1606
2923
  );
1607
- /** 单个已选模型的 effort 下拉选项:优先该模型 wire 里的真实
1608
- * efforts;拿不到时退回 EFFORTS 常量;已存旧值不在列表里时追加,
1609
- * 避免受控 select 错位。 */
2924
+ /** Effort dropdown options for one selected model: prefer the real
2925
+ * efforts from the model's wire metadata; fall back to the EFFORTS
2926
+ * constant when unavailable; append a stored legacy value missing
2927
+ * from the list so the controlled select never misaligns. */
1610
2928
  const effortOptions = (route) => {
1611
2929
  const key = routeKey(route);
1612
2930
  const wireEfforts = effortsMetaByKey.get(key);
@@ -1629,8 +2947,9 @@ window.__ModuleLoader__.load({
1629
2947
  ...pending,
1630
2948
  ];
1631
2949
  };
1632
- /** 单个已选模型的 effort 下拉('' = 跟随泳道默认);阻止冒泡避免
1633
- * 触发外层 label 的 checkbox。 */
2950
+ /** Effort dropdown for one selected model ('' = follow the lane
2951
+ * default); stop propagation so the outer label's checkbox does not
2952
+ * toggle. */
1634
2953
  const effortSelect = (route) =>
1635
2954
  h(
1636
2955
  'select',
@@ -1649,7 +2968,8 @@ window.__ModuleLoader__.load({
1649
2968
  h('option', { value: option.id }, option.name),
1650
2969
  ),
1651
2970
  );
1652
- /** 手动态的「可添加」列表:仅未勾选的目录行,空分组头剔除。 */
2971
+ /** Manual-mode "addable" list: unchecked catalog rows only, empty
2972
+ * group headers dropped. */
1653
2973
  const addableRows = [];
1654
2974
  if (manual) {
1655
2975
  let pendingHeader = null;
@@ -1666,7 +2986,7 @@ window.__ModuleLoader__.load({
1666
2986
  addableRows.push(row);
1667
2987
  }
1668
2988
  }
1669
- /** 标题行右侧的手动序开关。 */
2989
+ /** Manual-order switch on the right of the header row. */
1670
2990
  const manualToggle = h(
1671
2991
  'label',
1672
2992
  { style: STYLE.checkRow, title: t('poolManualHelp') },
@@ -1924,14 +3244,19 @@ window.__ModuleLoader__.load({
1924
3244
  * shipped settings pages' save/conflict model. Pool and ranking
1925
3245
  * candidates come from the live model catalog, refreshed whenever the
1926
3246
  * Host's adapter set changes. */
1927
- function SwitchmanSettingsPage({ t, locale }) {
3247
+ function SwitchmanSettingsPage({ t, locale, setUiLocale }) {
1928
3248
  // Re-render on UI-language switches (drives t() and the suggestion).
1929
3249
  React.useSyncExternalStore(
1930
3250
  (fn) => locale.subscribe(fn),
1931
3251
  () => locale.getLocale(),
1932
3252
  );
3253
+ // Re-render when the manual interface-locale override changes or a
3254
+ // saved override is restored at startup.
3255
+ React.useSyncExternalStore(subscribeUiLocale, () => uiLocaleVersion);
1933
3256
  // Hooks above the availability early-returns keep a stable order.
1934
3257
  const headingId = React.useId();
3258
+ const uiHeadingId = React.useId();
3259
+ const uiSelectId = React.useId();
1935
3260
 
1936
3261
  /** Live settings snapshot from the Host route: { status, writable,
1937
3262
  * values } — mirrors the configForms snapshot shape the page was
@@ -2146,7 +3471,7 @@ window.__ModuleLoader__.load({
2146
3471
  ? pool.filter((route) => routeKey(route) !== key)
2147
3472
  : [...pool, { provider: meta.provider, model: meta.model }],
2148
3473
  );
2149
- // 取消勾选时同步移除该路由的手动 effort 条目
3474
+ // Unchecking a route also drops its pinned effort entry
2150
3475
  if (existed) {
2151
3476
  const { effortsField } = POOL_FIELDS.find(
2152
3477
  (spec) => spec.field === field,
@@ -2163,7 +3488,7 @@ window.__ModuleLoader__.load({
2163
3488
  function setAllPool(field, select) {
2164
3489
  if (!select) {
2165
3490
  edit(field, []);
2166
- // 清空池时同步清空该池的手动 effort 条目
3491
+ // Clearing a pool also clears its pinned effort entries
2167
3492
  const { effortsField } = POOL_FIELDS.find(
2168
3493
  (spec) => spec.field === field,
2169
3494
  );
@@ -2177,7 +3502,8 @@ window.__ModuleLoader__.load({
2177
3502
  edit(field, [...[...catalogIndex.values()].map(clean), ...extras]);
2178
3503
  }
2179
3504
 
2180
- /** 手动序:把 index 处的路由与相邻项交换(边界守卫)。 */
3505
+ /** Manual order: swap the route at index with its neighbor
3506
+ * (boundary-guarded). */
2181
3507
  function movePoolRoute(field, index, delta) {
2182
3508
  const pool = values[field];
2183
3509
  const target = index + delta;
@@ -2190,7 +3516,7 @@ window.__ModuleLoader__.load({
2190
3516
  })));
2191
3517
  }
2192
3518
 
2193
- /** 手动序:移除 index 处的路由。 */
3519
+ /** Manual order: remove the route at index. */
2194
3520
  function removePoolRoute(field, index) {
2195
3521
  const next = [...values[field]];
2196
3522
  const [removed] = next.splice(index, 1);
@@ -2198,7 +3524,7 @@ window.__ModuleLoader__.load({
2198
3524
  provider: route.provider,
2199
3525
  model: route.model,
2200
3526
  })));
2201
- // 同步移除该路由的手动 effort 条目
3527
+ // Drop the route's pinned effort entry alongside
2202
3528
  const { effortsField } = POOL_FIELDS.find(
2203
3529
  (spec) => spec.field === field,
2204
3530
  );
@@ -2210,7 +3536,8 @@ window.__ModuleLoader__.load({
2210
3536
  );
2211
3537
  }
2212
3538
 
2213
- /** 设置/清除某池某路由的手动 effort 条目(effort '' = 移除条目)。 */
3539
+ /** Set/clear a route's pinned effort entry in a pool (effort '' =
3540
+ * remove the entry). */
2214
3541
  function setPoolEffort(effortsField, meta, effort) {
2215
3542
  const key = routeKey(meta);
2216
3543
  const rest = values[effortsField].filter(
@@ -2275,6 +3602,7 @@ window.__ModuleLoader__.load({
2275
3602
  langConversation: values.langConversation.trim(),
2276
3603
  langComments: values.langComments,
2277
3604
  langDocs: values.langDocs,
3605
+ uiLocale: values.uiLocale,
2278
3606
  ...Object.fromEntries(
2279
3607
  POOL_FIELDS.map(({ field }) => [
2280
3608
  field,
@@ -2735,6 +4063,37 @@ window.__ModuleLoader__.load({
2735
4063
  'div',
2736
4064
  { 'data-dsh-switchman': 'settings', style: STYLE.page },
2737
4065
  h('p', { style: STYLE.description }, t('settingsDescription')),
4066
+ h(
4067
+ 'section',
4068
+ { 'aria-labelledby': uiHeadingId, style: STYLE.section },
4069
+ h('h3', { id: uiHeadingId, style: STYLE.heading }, t('uiSectionTitle')),
4070
+ h('p', { style: STYLE.description }, t('uiSectionDescription')),
4071
+ h(
4072
+ 'div',
4073
+ { style: STYLE.rows },
4074
+ h(SettingsRow, {
4075
+ key: 'ui-locale',
4076
+ id: uiSelectId,
4077
+ lines: [],
4078
+ label: t('uiLocaleLabel'),
4079
+ help: t('uiLocaleHelp'),
4080
+ control: h(
4081
+ 'select',
4082
+ selectProps(uiSelectId, values.uiLocale ?? 'auto', (value) => {
4083
+ edit('uiLocale', value);
4084
+ setUiLocale?.(value);
4085
+ }),
4086
+ ...UI_LOCALE_OPTIONS.map((option) =>
4087
+ h(
4088
+ 'option',
4089
+ { key: option.value, value: option.value },
4090
+ option.value === 'auto' ? t('uiLocaleAuto') : option.label,
4091
+ ),
4092
+ ),
4093
+ ),
4094
+ }),
4095
+ ),
4096
+ ),
2738
4097
  h(
2739
4098
  'section',
2740
4099
  { 'aria-labelledby': headingId, style: STYLE.section },
@@ -3214,17 +4573,79 @@ window.__ModuleLoader__.load({
3214
4573
  inject: ['slots', 'locale'],
3215
4574
  apply(ctx) {
3216
4575
  ctx.effect(() => ctx.locale.register(NS, DICTS));
3217
- const t = ctx.locale.bind(NS);
3218
- // 报告当前生效的 UI 语言给 host 半场(决定语言询问指引的
3219
- // 提问语言;fire-and-forget,失败静默——host 会退回
3220
- // settings 的 locale.preference,再退回英文)。3 秒后补报
3221
- // 一次,覆盖 host 路由晚于本页就绪的启动窗口。
4576
+ const baseT = ctx.locale.bind(NS);
4577
+ // Manual interface-locale override: "auto" keeps following the
4578
+ // DSH app language (baseT); any other value resolves this
4579
+ // plugin's own strings from DICTS (zh/en) or the inline
4580
+ // EXTRA_UI_DICTS table. Every failure path degrades back to
4581
+ // baseT — never a hard error.
4582
+ let uiLocale = 'auto';
4583
+ const formatUiValue = (text, params) =>
4584
+ typeof params === 'object' && params !== null
4585
+ ? text.replace(/\{(\w+)\}/g, (match, name) =>
4586
+ name in params ? String(params[name]) : match,
4587
+ )
4588
+ : text;
4589
+ const warnedUiTags = new Set();
4590
+ const dictForUiLocale = (tag) => {
4591
+ if (tag === 'en' || tag === 'zh') return DICTS[tag];
4592
+ const dict = EXTRA_UI_DICTS[tag];
4593
+ if (dict === undefined && !warnedUiTags.has(tag)) {
4594
+ warnedUiTags.add(tag);
4595
+ console.warn('[dsh-switchman] no inline UI dictionary for locale', tag);
4596
+ }
4597
+ return dict ?? null;
4598
+ };
4599
+ const t = (key, params) => {
4600
+ if (uiLocale !== 'auto') {
4601
+ const text = dictForUiLocale(uiLocale)?.[key];
4602
+ if (typeof text === 'string') return formatUiValue(text, params);
4603
+ }
4604
+ return baseT(key, params);
4605
+ };
4606
+ /** Apply an interface-locale choice immediately (preview
4607
+ * before the settings write lands) and wake every subscribed
4608
+ * component. All dictionaries are inline, so the switch
4609
+ * paints on the next render — no async gap. */
4610
+ const applyUiLocale = (tag) => {
4611
+ if (tag === uiLocale) return;
4612
+ uiLocale = tag;
4613
+ notifyUiLocale();
4614
+ };
4615
+ // Report the active UI locale to the host half (it decides the
4616
+ // question language for the language-preference prompt;
4617
+ // fire-and-forget, silent on failure — the host falls back to
4618
+ // the settings' locale.preference, then to English). One extra
4619
+ // report after 3s covers the startup window where the host
4620
+ // routes become ready after this page.
3222
4621
  const reportUiLocale = () =>
3223
4622
  void api.post('ui-locale', {
3224
- locale: ctx.locale?.getLocale?.().active ?? '',
4623
+ locale:
4624
+ uiLocale !== 'auto'
4625
+ ? uiLocale
4626
+ : ctx.locale?.getLocale?.().active ?? '',
3225
4627
  });
3226
4628
  reportUiLocale();
3227
4629
  setTimeout(reportUiLocale, 3000);
4630
+ // Pick up a saved interface-locale override at startup so the
4631
+ // badge and panels already render in it without a settings
4632
+ // visit. Fail-open: any error keeps the DSH app language.
4633
+ void (async () => {
4634
+ try {
4635
+ const reply = await api.get('config');
4636
+ const tag = reply.value?.values?.uiLocale;
4637
+ if (reply.ok && typeof tag === 'string' && tag !== 'auto' && tag !== '') {
4638
+ applyUiLocale(tag);
4639
+ // The override may have landed after the initial
4640
+ // report went out; re-report the effective locale
4641
+ // so the host prompt language matches what the
4642
+ // user actually sees.
4643
+ reportUiLocale();
4644
+ }
4645
+ } catch {
4646
+ /* fail-open: keep the DSH app language */
4647
+ }
4648
+ })();
3228
4649
  // The session scope hands the badge the standard kit: the open
3229
4650
  // session's id and its live projection face (the model line),
3230
4651
  // plus the sessions service for the un-retained fallback.
@@ -3268,7 +4689,7 @@ window.__ModuleLoader__.load({
3268
4689
  {
3269
4690
  name: 'main',
3270
4691
  key: 'dsh-switchman',
3271
- inject: () => ({ t, locale: ctx.locale }),
4692
+ inject: () => ({ t, locale: ctx.locale, setUiLocale: applyUiLocale }),
3272
4693
  },
3273
4694
  SwitchmanPanelPage,
3274
4695
  ),
@@ -3303,7 +4724,7 @@ window.__ModuleLoader__.load({
3303
4724
  order: 50,
3304
4725
  label: () => t('settingsTitle'),
3305
4726
  },
3306
- () => h(SwitchmanSettingsPage, { t, locale: ctx.locale }),
4727
+ () => h(SwitchmanSettingsPage, { t, locale: ctx.locale, setUiLocale: applyUiLocale }),
3307
4728
  ),
3308
4729
  );
3309
4730
  // The same configuration surface on the bundle's own Plugins
@@ -3315,7 +4736,7 @@ window.__ModuleLoader__.load({
3315
4736
  name: 'plugins.bundle.config',
3316
4737
  key: 'dsh-switchman',
3317
4738
  },
3318
- () => h(SwitchmanSettingsPage, { t, locale: ctx.locale }),
4739
+ () => h(SwitchmanSettingsPage, { t, locale: ctx.locale, setUiLocale: applyUiLocale }),
3319
4740
  ),
3320
4741
  );
3321
4742
  },