dsh-plugin-term-dictionary 0.0.0-stage → 1.1.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.
@@ -0,0 +1,614 @@
1
+ "use strict";
2
+
3
+ /**
4
+ * Browser-side copy.
5
+ *
6
+ * `zh` is the key-set source of truth; `en` is checked complete against it by the
7
+ * bundle's own test. Every string the panel, the popup and the toast show lives
8
+ * here, so a locale change reaches all three through one store.
9
+ */
10
+
11
+ /** Simplified Chinese dictionary (the key-set source of truth). */
12
+ const zh = {
13
+ title: "术语词典",
14
+ subtitle: "自动收录对话中的专业术语",
15
+ nav: "术语词典",
16
+
17
+ explainParagraphOn: "参考段落",
18
+ explainParagraphHint: "生成解释时把术语所在的整段话交给模型,而不只是它出现的那一句",
19
+ explainLangName: "解释语言",
20
+ explainLangHint: "解释用什么语言写(跟随界面 / 中文 / 英文);zh 字段始终是中文",
21
+ explainLang_auto: "跟随界面",
22
+ explainLang_zh: "中文",
23
+ explainLang_en: "英文",
24
+ explainDepthName: "详细程度",
25
+ explainDepthHint: "解释写多详细",
26
+ entryColumnsName: "词条排列",
27
+ entryColumnsHint: "一列排下去很长;「自动」按面板宽度铺成多列,窄了就回到一列。",
28
+ entryColumns_auto: "自动",
29
+ entryColumns_1: "1 列",
30
+ entryColumns_2: "2 列",
31
+ entryColumns_3: "3 列",
32
+ entryRowsName: "词条行高",
33
+ entryRowsHint: "多列排版时,同一行的卡片要不要一样高。统一高度不会在矮卡片下面留出空条;各按各自更紧凑。",
34
+ entryRows_uniform: "统一高度",
35
+ entryRows_compact: "各按各自",
36
+ explainDepth_brief: "一句话",
37
+ explainDepth_normal: "标准",
38
+ explainDepth_detailed: "详细",
39
+
40
+ collectIdentifiersOn: "收代码术语",
41
+ collectIdentifiersHint: "是否自动收录 data-conversation-region、Set-Content 这类代码名(默认不收)",
42
+ collectMinLengthName: "最短词长",
43
+ collectMinLengthOption: "{count} 字",
44
+ collectMinLengthHint: "自动收录的最短词长,太短的碎片不收",
45
+ collectCjkOn: "收中文术语",
46
+ collectCjkHint: "是否自动收录中文术语",
47
+
48
+ settingsTitle: "术语词典设置",
49
+ settingsSubtitle: "这里的选择只影响本机这一个页面,不会写进词典内容。",
50
+ settingsOpen: "设置",
51
+ transferTitle: "导入 / 导出",
52
+ packsTitle: "词条包",
53
+ packsSubtitle: "把这份词典打包给别人,或从别人的包、分享码、源里取词条。",
54
+ transferSubtitle: "把词条导出成文件,或从文件导入词条",
55
+ transferExportTitle: "导出",
56
+ transferExportHint: "导出全部词条,或只导出选中的分类(分类就是词条的「领域」)。",
57
+ transferScopeAll: "全部",
58
+ transferScopeDomains: "按分类",
59
+ transferNoDomains: "还没有任何分类——先给词条填上「领域」再回来。",
60
+ transferSelectAll: "全选",
61
+ transferSelectNone: "全不选",
62
+ transferDownload: "下载 JSON",
63
+ transferCopy: "复制 JSON",
64
+ transferImportTitle: "导入",
65
+ transferImportHint: "选择一个 JSON 文件。已存在的词条会原样保留;你删除过的词条默认不复活;导入完成后会报告各自的条数。",
66
+ transferIncludeDeleted: "导入我删除过的词条",
67
+ transferIncludeDeletedHint: "勾选后,文件里那些你删除过的词条会被导入,并从「已删除」里撤回。不勾选则它们留在删除列表里。",
68
+ transferConfirmTitle: "「{name}」里有什么",
69
+ transferWillImport: "将导入 {count} 条",
70
+ transferWillSkipExisting: "已有 {count} 条(跳过)",
71
+ transferWillSkipDeleted: "你删过 {count} 条(默认跳过)",
72
+ transferConfirm: "确认导入",
73
+ transferShown: "已切到「全部」并清空搜索,好让刚导入的词条就在眼前。",
74
+ transferFolderTitle: "导入文件夹",
75
+ transferFolderHint: "选一个文件夹,把里面的 .json 全部读一遍(导出的词典、下载的包文件都认)。不是 JSON 的文件直接忽略;读不了的会点名列出。",
76
+ transferFolderAsGroup: "按文件夹建立分组(文件夹名就是组名)",
77
+ transferFolderLabel: "文件夹里的 {count} 个文件",
78
+ transferFolderFound: "文件夹里 {files} 个 .json,用上 {used} 个",
79
+ transferFolderSkipped: "跳过 {count} 个:",
80
+ transferFolderAllSkipped: "这个文件夹里 {count} 个 .json 都读不了",
81
+ transferNoJson: "这个文件夹里没有 .json 文件",
82
+ transferReport: "导入 {imported} 条;跳过:已存在 {existing} 条、你删除过 {deleted} 条、重复或无效 {duplicates} 条。",
83
+ transferFailed: "操作失败:{message}",
84
+ settingsBack: "返回词条列表",
85
+ hoverNoGloss: "这个词条还没有解释。",
86
+ hoverOpenEntry: "点击查看词典词条",
87
+ hoverInName: "悬停读入延迟",
88
+ hoverInHint: "指针停在词上多久才弹出卡片(0–200 毫秒)。调大更稳,调小更灵敏。",
89
+ hoverOutName: "悬停读出延迟",
90
+ hoverOutHint: "指针离开后卡片再留多久(0–200 毫秒)。0 表示立即消失——留太久会显得迟钝。",
91
+ hoverUnit: "毫秒",
92
+
93
+ search: "搜索术语、解释或领域",
94
+ searchEmpty: "没有匹配的词条",
95
+ empty: "还没有词条。对话里出现专业术语时,本插件会自动收录;也可以在回复中用鼠标选中词句,或直接点击术语。",
96
+ emptyAll: "还没有词条",
97
+ loading: "正在读取词典…",
98
+ count: "{total} 条 · {unexplained} 条待补充",
99
+ countShort: "{total} 条",
100
+
101
+ filterAll: "全部",
102
+ filterUnexplained: "待补充",
103
+ filterPinned: "已钉选",
104
+ filterFlagged: "已标记",
105
+ filterDeleted: "已删除",
106
+
107
+ flaggedHint: "这里是你标记过的词条:写了什么问题、以及有没有把解释判为不可信。撤回会把两者一起清掉。",
108
+ flaggedEmpty: "没有已标记的词条",
109
+ flaggedUntrusted: "不可信",
110
+ flaggedAt: "标记于 {time}",
111
+ flaggedClear: "撤回标记",
112
+ toastFlagCleared: "已撤回「{term}」的标记",
113
+
114
+ feedbackTitle: "反馈",
115
+ feedbackHint: "记下这条词条哪里不对。勾上「不可信」之后,自动解释不会再覆盖它——想要新解释就在上面按「用模型生成解释」,那一次模型会知道上一个被否掉了。",
116
+ feedbackKindName: "问题类型",
117
+ // The kind ids carry hyphens, so these three keys must be quoted — a bare `a-b:` is a subtraction.
118
+ "feedbackKind_wrong-gloss": "解释不对",
119
+ "feedbackKind_wrong-term": "术语不对",
120
+ "feedbackKind_should-not-collect": "不该收录",
121
+ feedbackKind_other: "其他",
122
+ feedbackUntrustedOn: "解释不可信",
123
+ feedbackUntrustedHint: "自动解释不再覆盖它;你手动重新生成时,模型会知道上一个被否掉了",
124
+ feedbackNoteLabel: "补充说明",
125
+ feedbackNotePlaceholder: "例如:这里说的 quorum 是写入确认的副本数,不是「多数派确认」",
126
+ feedbackExportTitle: "反馈报告",
127
+ feedbackExportHint: "把 {count} 条标记导出成一个文件。报告只含术语、类型、你的说明和时间——不含会话原文;当前解释可以另外勾选附上。",
128
+ feedbackIncludeGloss: "附上当前解释文本",
129
+ feedbackDownload: "下载反馈",
130
+ feedbackCopy: "复制反馈",
131
+ feedbackRecord: "记入产品反馈",
132
+ feedbackRecordHint: "也可以把上面这份摘要记进宿主自己的会话反馈日志。那条通道只写在本机、不进模型上下文,所以它到不了作者手里——要让人看到内容级的问题,还是把报告发出去。",
133
+ feedbackState_sending: "正在记录…",
134
+ feedbackState_ok: "已记入反馈日志",
135
+ feedbackState_unavailable: "这个组合没有反馈通道(报告仍然可以导出)",
136
+ // Quoted: the state ids carry hyphens, and a bare `a-b:` is a subtraction.
137
+ "feedbackState_session-not-found": "这个会话宿主已经没有了,换一个会话再试",
138
+ "feedbackState_no-session": "还没看到过会话,先回对话里点一下词条再回来",
139
+ feedbackState_failed: "宿主拒绝了这条记录",
140
+
141
+ packShareTitle: "分享这份词典",
142
+ packShareHint: "包只带术语本身(术语、中文名、解释、例句、分类、别名)——不带上下文、不带你的备注、不带你对解释的判断,也不带已删除的词条。",
143
+ packNameLabel: "包名",
144
+ packNamePlaceholder: "例如:后端黑话",
145
+ packAuthorLabel: "署名",
146
+ packAuthorPlaceholder: "例如:lakerian",
147
+ packLicenseLabel: "许可",
148
+ packLicensePlaceholder: "例如:CC-BY-4.0",
149
+ packMakeCode: "生成分享码",
150
+ packMakeFile: "生成文件",
151
+ packDownload: "下载 .json",
152
+ packDigest: "sha256 {sha}… · {bytes} 字节",
153
+ packCodeLabel: "分享码",
154
+ packCopyCode: "复制分享码",
155
+ packCodeCopied: "已复制分享码",
156
+ packBuilt: "已生成:{count} 条",
157
+ packReadTitle: "从分享码导入",
158
+ packReadHint: "把别人给的分享码粘进来,先看里面有什么,再决定导不导。",
159
+ packCodePlaceholder: "dshpack1:…",
160
+ packRead: "读取",
161
+ packPreviewTitle: "「{name}」里有什么",
162
+ packCount: "{count} 条",
163
+ packExplained: "其中 {count} 条有解释",
164
+ packImport: "导入",
165
+ packPreview: "预览",
166
+ packLoading: "取回中…",
167
+ packReady: "已取回,见上方预览",
168
+ packNoChecksum: "索引没有给校验和",
169
+ packChecksum: "sha256",
170
+ packSourcesTitle: "源",
171
+ packSourcesHint: "源就是别人托管的一个静态 index.json。只接受 https(http、file、带账号密码的 URL 都会被拒)。",
172
+ packNoSources: "还没有添加源",
173
+ packBuiltInSource: "内置",
174
+ packRemoveSource: "移除",
175
+ packAddSourceLabel: "添加源",
176
+ packAddSourcePlaceholder: "https://cdn.jsdelivr.net/gh/…/index.json",
177
+ packAddSource: "添加",
178
+ packRefresh: "刷新",
179
+ packRefreshed: "{count} 个源有内容",
180
+ packSourceOk: "{count} 个包",
181
+ packSourceStale: "源暂时连不上,显示的是上次取到的内容",
182
+ packSourceKnown: "这个源已经在列表里了",
183
+ packSourceAdded: "已添加",
184
+ packNoHost: "宿主没接上,这一步做不了",
185
+ packEmpty: "词典里还没有词条,先收几个再分享",
186
+
187
+ // 键里带连字符的必须加引号(裸 `a-b:` 是减法)。
188
+ packError_empty: "词典是空的,没有可发布的词条",
189
+ "packError_empty-scope": "选中的分类里没有词条——这是选择的问题,不是词典的问题",
190
+ "packError_too-many": "一个包最多 2000 条,先按分类切一份",
191
+ "packError_not-a-code": "这不是分享码(分享码以 dshpack1: 开头)",
192
+ "packError_empty-code": "分享码是空的",
193
+ "packError_corrupt": "分享码坏了——多半是粘贴时丢了字符,重新复制一次",
194
+ "packError_too-large": "这个码解出来的内容超过 4 MiB 上限",
195
+ "packError_not-a-pack": "这段内容不是词条包",
196
+ "packError_unsupported-version": "这个包的版本比当前插件新,先升级插件",
197
+ "packError_no-entries": "包里没有任何词条",
198
+ "packError_no-usable-entries": "包里的词条一条都用不了(缺 term)",
199
+ "packError_not-an-object": "内容不是一个对象",
200
+ "packError_not-json": "源返回的不是 JSON",
201
+ "packError_unreachable": "取不到(网络、超时或证书问题)",
202
+ "packError_checksum-mismatch": "校验和对不上——内容和索引承诺的不是同一份,已拒绝",
203
+ "packError_no-url": "没填地址",
204
+ "packError_bad-url": "地址格式不对",
205
+ "packError_not-https": "只接受 https 地址",
206
+ "packError_credentials-in-url": "URL 里不要带账号密码",
207
+ "packError_url-too-long": "地址太长了",
208
+ "packError_no-fetch": "这个环境没有可用的网络取回能力",
209
+ "packError_unknown": "失败了(原因未知)",
210
+
211
+ deletedHint: "删除过的词条留在这里,自动收录和导入都不会让它复活。撤回后它回到词条列表。",
212
+ deletedEmpty: "没有已删除的词条",
213
+ deletedAt: "删除于 {time}",
214
+ revive: "撤回",
215
+ toastRevived: "已恢复「{term}」",
216
+
217
+ pinned: "已钉选",
218
+ copyEntry: "复制词条",
219
+ toastCopied: "已复制「{term}」",
220
+ copyUnavailable: "这台机器不允许写入剪贴板(可以手动选中文本复制,或导出 JSON)",
221
+ unexplained: "待补充",
222
+ seenTimes: "出现 {count} 次",
223
+ lastSeen: "最近 {time}",
224
+ noDefinition: "暂无解释",
225
+ domainUnknown: "未分类",
226
+
227
+ editorTitle: "新建词条",
228
+ editorTitleEdit: "编辑词条",
229
+ termLabel: "术语",
230
+ translationLabel: "中文译名",
231
+ zhPlaceholder: "例如 事件溯源",
232
+ glossLabel: "解释",
233
+ usageLabel: "用法示例",
234
+ notesLabel: "备注",
235
+ domainLabel: "领域",
236
+ groupLabel: "分组",
237
+ groupOpen: "进入这个分组",
238
+ groupGo: "回到「{name}」",
239
+ groupCount: "{count} 条",
240
+ groupEmpty: "这一层只有分组,还没有词条。",
241
+ groupPlaceholder: "留空 = 顶层;用 / 分层,例如 backend/net",
242
+ termPlaceholder: "例如 event sourcing",
243
+ glossPlaceholder: "用一两句话说明它的含义",
244
+ usagePlaceholder: "可选:一句例子或典型用法",
245
+ notesPlaceholder: "可选:与你项目相关的补充",
246
+ domainPlaceholder: "例如 软件工程",
247
+
248
+ save: "保存",
249
+ saveAndClose: "保存",
250
+ cancel: "取消",
251
+ edit: "编辑",
252
+ remove: "删除",
253
+ removeConfirm: "删除这个词条?",
254
+ pin: "钉选",
255
+ unpin: "取消钉选",
256
+ generate: "用模型生成解释",
257
+ generating: "正在生成…",
258
+ generateFailed: "生成失败:{message}",
259
+ generateNoHost: "当前环境无法调用模型,请手动填写解释。",
260
+ retrySync: "重试同步",
261
+ syncFailed: "词典同步失败:{message}",
262
+ syncedLocal: "仅保存在本机",
263
+ exportJson: "复制 JSON",
264
+ exportDone: "已复制到剪贴板",
265
+ exportFailed: "复制失败",
266
+ clearAll: "清空词典",
267
+ clearConfirm: "将删除 {removed} 条词条;你钉选的 {kept} 条会保留。此操作不可撤销。",
268
+ close: "关闭",
269
+ addTerm: "新建词条",
270
+ openDictionary: "打开术语词典",
271
+ storageReadOnly: "词典无法写入磁盘,本次改动只在本页有效",
272
+ storageAt: "词典文件:{path}",
273
+
274
+ selectAdd: "添加词条",
275
+ selectAddTitle: "选中「{term}」添加词条",
276
+ popupUnknown: "词典里还没有这个词条",
277
+ popupCreate: "创建词条",
278
+ popupGenerating: "正在生成解释…",
279
+ popupNoHost: "无法调用模型,请手动创建词条。",
280
+ popupSourceGlossary: "内置词库",
281
+ popupSourceLlm: "模型生成",
282
+ popupSourceUser: "我的词条",
283
+ popupSourceHeuristic: "自动收录",
284
+ popupSourceAuto: "自动收录",
285
+ popupSourceImport: "导入",
286
+
287
+ toastAdded: "已收录「{term}」",
288
+ toastUpdated: "已更新「{term}」",
289
+ toastRemoved: "已删除「{term}」",
290
+ toastAutoAdded: "自动收录了 {count} 个术语",
291
+ toastExplainUnavailable: "自动解释不可用:{message}",
292
+ toastUndo: "撤销",
293
+
294
+ autoDetectOn: "自动收录",
295
+ autoDetectHint: "agent 回复中出现新术语时自动建立词条",
296
+ annotateOn: "划出术语",
297
+ annotateHint: "在回复中给已收录的术语加下划线",
298
+ autoExplainOn: "自动解释",
299
+ autoExplainHint: "收录后立即用模型生成解释;关掉则词条停在「待补充」",
300
+
301
+ selectEnter: "批量选择",
302
+ selectExit: "退出选择",
303
+ selectAll: "全选",
304
+ selectNone: "取消全选",
305
+ selectedCount: "已选 {count} 条",
306
+ deleteSelected: "删除所选",
307
+ deleteSelectedConfirm: "删除选中的 {count} 个词条?",
308
+
309
+ dismiss: "知道了"
310
+ };
311
+
312
+ /** English dictionary, checked complete against the zh key set. */
313
+ const en = {
314
+ title: "Term Dictionary",
315
+ subtitle: "Collects technical terms from the conversation",
316
+ nav: "Dictionary",
317
+
318
+ explainParagraphOn: "Whole paragraph",
319
+ explainParagraphHint: "Give the model the whole paragraph the term appeared in, not just its sentence",
320
+ explainLangName: "Explanation language",
321
+ explainLangHint: "Which language the explanation is written in (UI / Chinese / English); the zh field stays Chinese",
322
+ explainLang_auto: "Follow UI",
323
+ explainLang_zh: "Chinese",
324
+ explainLang_en: "English",
325
+ explainDepthName: "Explanation depth",
326
+ explainDepthHint: "How much the explanation says",
327
+ entryColumnsName: "Entry layout",
328
+ entryColumnsHint: "One column makes a very long strip; 自动 fills the panel width with as many columns as fit, and falls back to one when it is narrow.",
329
+ entryColumns_auto: "Auto",
330
+ entryColumns_1: "1 column",
331
+ entryColumns_2: "2 columns",
332
+ entryColumns_3: "3 columns",
333
+ entryRowsName: "Row height",
334
+ entryRowsHint: "In a multi-column layout, whether the cards in one row share a height. Uniform leaves no empty strip under the short ones; compact keeps each card tight.",
335
+ entryRows_uniform: "Uniform",
336
+ entryRows_compact: "Compact",
337
+ explainDepth_brief: "One line",
338
+ explainDepth_normal: "Normal",
339
+ explainDepth_detailed: "Detailed",
340
+
341
+ collectIdentifiersOn: "Collect code names",
342
+ collectIdentifiersHint: "Whether names like data-conversation-region or Set-Content are collected automatically (off by default)",
343
+ collectMinLengthName: "Minimum term length",
344
+ collectMinLengthOption: "{count}",
345
+ collectMinLengthHint: "Shortest term automatic collection will record",
346
+ collectCjkOn: "Collect Chinese terms",
347
+ collectCjkHint: "Whether Chinese terms are collected automatically",
348
+
349
+ settingsTitle: "Term dictionary settings",
350
+ settingsSubtitle: "These choices affect this page on this machine only; they are not written into the dictionary.",
351
+
352
+ packShareTitle: "Share this dictionary",
353
+ packShareHint: "A pack carries the terms themselves (term, Chinese name, explanation, example, category, aliases) — never the context, your notes, your verdicts on explanations, or anything you deleted.",
354
+ packNameLabel: "Pack name",
355
+ packNamePlaceholder: "e.g. Backend jargon",
356
+ packAuthorLabel: "Author",
357
+ packAuthorPlaceholder: "e.g. lakerian",
358
+ packLicenseLabel: "License",
359
+ packLicensePlaceholder: "e.g. CC-BY-4.0",
360
+ packMakeCode: "Make a share code",
361
+ packMakeFile: "Make a file",
362
+ packDownload: "Download .json",
363
+ packDigest: "sha256 {sha}… · {bytes} bytes",
364
+ packCodeLabel: "Share code",
365
+ packCopyCode: "Copy the code",
366
+ packCodeCopied: "Share code copied",
367
+ packBuilt: "Built: {count} entries",
368
+ packReadTitle: "Import from a share code",
369
+ packReadHint: "Paste a code somebody gave you, see what is in it, then decide.",
370
+ packCodePlaceholder: "dshpack1:…",
371
+ packRead: "Read",
372
+ packPreviewTitle: "What “{name}” holds",
373
+ packCount: "{count} entries",
374
+ packExplained: "{count} of them explained",
375
+ packImport: "Import",
376
+ packPreview: "Preview",
377
+ packLoading: "fetching…",
378
+ packReady: "fetched — see the preview above",
379
+ packNoChecksum: "the index promised no checksum",
380
+ packChecksum: "sha256",
381
+ packSourcesTitle: "Sources",
382
+ packSourcesHint: "A source is somebody's static index.json. Only https is accepted (http, file and URLs carrying credentials are refused).",
383
+ packNoSources: "No sources yet",
384
+ packBuiltInSource: "built in",
385
+ packRemoveSource: "Remove",
386
+ packAddSourceLabel: "Add a source",
387
+ packAddSourcePlaceholder: "https://cdn.jsdelivr.net/gh/…/index.json",
388
+ packAddSource: "Add",
389
+ packRefresh: "Refresh",
390
+ packRefreshed: "{count} sources answered",
391
+ packSourceOk: "{count} packs",
392
+ packSourceStale: "the source is unreachable — this is what it said last time",
393
+ packSourceKnown: "that source is already in the list",
394
+ packSourceAdded: "Added",
395
+ packNoHost: "the host is not reachable, so this step cannot run",
396
+ packEmpty: "the dictionary has no entries yet — collect a few first",
397
+
398
+ // Hyphenated ids: quoted, or `a-b:` reads as a subtraction.
399
+ packError_empty: "the dictionary is empty, so there is nothing to publish",
400
+ "packError_empty-scope": "the chosen categories hold no entries — that is the selection, not the dictionary",
401
+ "packError_too-many": "a pack holds at most 2000 entries; publish it by category instead",
402
+ "packError_not-a-code": "that is not a share code (they start with dshpack1:)",
403
+ "packError_empty-code": "the share code is empty",
404
+ "packError_corrupt": "the share code is damaged — a character was probably lost in the paste",
405
+ "packError_too-large": "that code expands past the 4 MiB limit",
406
+ "packError_not-a-pack": "that content is not a term pack",
407
+ "packError_unsupported-version": "this pack is newer than the plugin; update the plugin first",
408
+ "packError_no-entries": "the pack holds no entries",
409
+ "packError_no-usable-entries": "none of the pack's entries can be used (no term)",
410
+ "packError_not-an-object": "the content is not an object",
411
+ "packError_not-json": "the source did not answer with JSON",
412
+ "packError_unreachable": "could not fetch it (network, timeout or certificate)",
413
+ "packError_checksum-mismatch": "the checksum does not match — what arrived is not what the index promised, so it was refused",
414
+ "packError_no-url": "no address was given",
415
+ "packError_bad-url": "that address is malformed",
416
+ "packError_not-https": "only https addresses are accepted",
417
+ "packError_credentials-in-url": "do not put credentials in the URL",
418
+ "packError_url-too-long": "that address is too long",
419
+ "packError_no-fetch": "this environment has no way to fetch",
420
+ "packError_unknown": "it failed (reason unknown)",
421
+ settingsOpen: "Settings",
422
+ transferTitle: "Import / export",
423
+ packsTitle: "Term packs",
424
+ packsSubtitle: "Package this dictionary for somebody else, or take terms from their pack, share code or source.",
425
+ transferTitle: "Import / Export",
426
+ transferSubtitle: "Write the dictionary to a file, or read entries back from one",
427
+ transferExportTitle: "Export",
428
+ transferExportHint: "Export every entry, or only the categories you pick (a category is an entry's domain).",
429
+ transferScopeAll: "Everything",
430
+ transferScopeDomains: "By category",
431
+ transferNoDomains: "No categories yet — give some entries a domain first.",
432
+ transferSelectAll: "Select all",
433
+ transferSelectNone: "Select none",
434
+ transferDownload: "Download JSON",
435
+ transferCopy: "Copy JSON",
436
+ transferImportTitle: "Import",
437
+ transferImportHint: "Choose a JSON file. Entries you already have are left as they are, and entries you deleted stay deleted unless you say otherwise below; the counts are reported when it finishes.",
438
+ transferIncludeDeleted: "Import entries I deleted",
439
+ transferIncludeDeletedHint: "When ticked, entries in the file that you had deleted are imported and retracted from the deleted list. Unticked, they stay there.",
440
+ transferConfirmTitle: "What “{name}” holds",
441
+ transferWillImport: "{count} entries will be imported",
442
+ transferWillSkipExisting: "{count} already here (skipped)",
443
+ transferWillSkipDeleted: "{count} you deleted (skipped by default)",
444
+ transferConfirm: "Import them",
445
+ transferShown: "Moved to All and cleared the search, so what was imported is in front of you.",
446
+ transferFolderTitle: "Import a folder",
447
+ transferFolderHint: "Pick a folder and every .json inside it is read: exported dictionaries and downloaded pack files both. Files that are not JSON are ignored, and any that cannot be read are named.",
448
+ transferFolderAsGroup: "Build groups from the folders (the folder name is the group)",
449
+ transferFolderLabel: "{count} files in the folder",
450
+ transferFolderFound: "{files} .json files in the folder, {used} of them usable",
451
+ transferFolderSkipped: "{count} skipped:",
452
+ transferFolderAllSkipped: "none of the {count} .json files in that folder could be read",
453
+ transferNoJson: "that folder holds no .json files",
454
+ transferReport: "Imported {imported}; skipped {existing} already here, {deleted} you deleted, {duplicates} duplicate or unusable.",
455
+ transferFailed: "That did not work: {message}",
456
+ settingsBack: "Back to the entries",
457
+ hoverNoGloss: "This entry has no explanation yet.",
458
+ hoverOpenEntry: "Click to open the dictionary entry",
459
+ hoverInName: "Hover appear delay",
460
+ hoverInHint: "How long the pointer must rest on a term before the card appears (0–200 ms). Higher is steadier, lower is quicker.",
461
+ hoverOutName: "Hover disappear delay",
462
+ hoverOutHint: "How long the card lingers after the pointer leaves (0–200 ms). 0 means it goes at once — lingering reads as lag.",
463
+ hoverUnit: "ms",
464
+
465
+ search: "Search terms, explanations or domains",
466
+ searchEmpty: "No matching entries",
467
+ empty: "No entries yet. The plugin picks up technical terms from agent replies automatically; you can also select a phrase with the mouse, or click a term directly.",
468
+ emptyAll: "No entries yet",
469
+ loading: "Loading dictionary…",
470
+ count: "{total} entries · {unexplained} to explain",
471
+ countShort: "{total} entries",
472
+
473
+ filterAll: "All",
474
+ filterUnexplained: "To explain",
475
+ filterPinned: "Pinned",
476
+ filterFlagged: "Flagged",
477
+ filterDeleted: "Deleted",
478
+
479
+ flaggedHint: "Entries you commented on: what was wrong, and whether the explanation is marked untrusted. Clearing removes both.",
480
+ flaggedEmpty: "Nothing has been flagged",
481
+ flaggedUntrusted: "Untrusted",
482
+ flaggedAt: "Flagged {time}",
483
+ flaggedClear: "Clear",
484
+ toastFlagCleared: "Cleared the remark on “{term}”",
485
+
486
+ feedbackTitle: "Feedback",
487
+ feedbackHint: "Say what is wrong with this entry. With “untrusted” on, the automatic explainer stops overwriting it — press “Generate an explanation” above to ask for a new one, and that attempt is told the last answer was rejected.",
488
+ feedbackKindName: "What is wrong",
489
+ // Quoted for the same reason as the Chinese block: the ids carry hyphens.
490
+ "feedbackKind_wrong-gloss": "Wrong explanation",
491
+ "feedbackKind_wrong-term": "Wrong term",
492
+ "feedbackKind_should-not-collect": "Should not be collected",
493
+ feedbackKind_other: "Other",
494
+ feedbackUntrustedOn: "Explanation untrusted",
495
+ feedbackUntrustedHint: "The automatic explainer stops overwriting it; a manual retry is told the last answer was rejected",
496
+ feedbackNoteLabel: "Note",
497
+ feedbackNotePlaceholder: "e.g. quorum here means the number of replicas that must confirm a write, not “the majority agrees”",
498
+ feedbackExportTitle: "Feedback report",
499
+ feedbackExportHint: "Write the {count} flagged entries to a file. The report holds terms, kinds, your notes and times — never the conversation; the current explanations can be attached by ticking the box.",
500
+ feedbackIncludeGloss: "Attach the current explanations",
501
+ feedbackDownload: "Download report",
502
+ feedbackCopy: "Copy report",
503
+ feedbackRecord: "Record as product feedback",
504
+ feedbackRecordHint: "The summary above can also go into the host's own session feedback log. That channel stays on this machine and never enters a model's context, so it cannot reach the author — to have the content-level problem seen, send the report.",
505
+ feedbackState_sending: "Recording…",
506
+ feedbackState_ok: "Recorded in the feedback log",
507
+ feedbackState_unavailable: "this composition has no feedback channel (the report still exports)",
508
+ // Quoted for the same reason as the Chinese block.
509
+ "feedbackState_session-not-found": "the host no longer has this session — try from another one",
510
+ "feedbackState_no-session": "no conversation seen yet — open the chat and click a term first",
511
+ feedbackState_failed: "the host refused the remark",
512
+
513
+ deletedHint: "Entries you deleted wait here; collection and import leave them alone. Restoring one puts it back in the list.",
514
+ deletedEmpty: "Nothing has been deleted",
515
+ deletedAt: "Deleted {time}",
516
+ revive: "Restore",
517
+ toastRevived: "Restored “{term}”",
518
+
519
+ pinned: "Pinned",
520
+ copyEntry: "Copy entry",
521
+ toastCopied: "Copied “{term}”",
522
+ copyUnavailable: "this machine does not allow writing to the clipboard (select the text by hand, or export the JSON)",
523
+ unexplained: "To explain",
524
+ seenTimes: "Seen {count} times",
525
+ lastSeen: "Last seen {time}",
526
+ noDefinition: "No explanation yet",
527
+ domainUnknown: "Unclassified",
528
+
529
+ editorTitle: "New entry",
530
+ editorTitleEdit: "Edit entry",
531
+ termLabel: "Term",
532
+ translationLabel: "Chinese name",
533
+ zhPlaceholder: "e.g. 事件溯源",
534
+ glossLabel: "Explanation",
535
+ usageLabel: "Usage",
536
+ notesLabel: "Notes",
537
+ domainLabel: "Domain",
538
+ groupLabel: "Group",
539
+ groupOpen: "Open this group",
540
+ groupGo: "Go back to {name}",
541
+ groupCount: "{count} entries",
542
+ groupEmpty: "This level holds only groups so far.",
543
+ groupPlaceholder: "empty = top level; use / to nest, e.g. backend/net",
544
+ termPlaceholder: "e.g. event sourcing",
545
+ glossPlaceholder: "Say what it means in one or two sentences",
546
+ usagePlaceholder: "Optional: an example or typical use",
547
+ notesPlaceholder: "Optional: notes for your project",
548
+ domainPlaceholder: "e.g. Software engineering",
549
+
550
+ save: "Save",
551
+ saveAndClose: "Save",
552
+ cancel: "Cancel",
553
+ edit: "Edit",
554
+ remove: "Delete",
555
+ removeConfirm: "Delete this entry?",
556
+ pin: "Pin",
557
+ unpin: "Unpin",
558
+ generate: "Generate an explanation",
559
+ generating: "Generating…",
560
+ generateFailed: "Generation failed: {message}",
561
+ generateNoHost: "No model is reachable here. Please write the explanation yourself.",
562
+ retrySync: "Retry sync",
563
+ syncFailed: "Dictionary sync failed: {message}",
564
+ syncedLocal: "Stored on this machine only",
565
+ exportJson: "Copy JSON",
566
+ exportDone: "Copied to the clipboard",
567
+ exportFailed: "Copy failed",
568
+ clearAll: "Clear dictionary",
569
+ clearConfirm: "Delete {removed} entries; the {kept} you pinned will be kept. This cannot be undone.",
570
+ close: "Close",
571
+ addTerm: "New entry",
572
+ openDictionary: "Open the term dictionary",
573
+ storageReadOnly: "The dictionary file is not writable; changes last only for this page",
574
+ storageAt: "Dictionary file: {path}",
575
+
576
+ selectAdd: "Add entry",
577
+ selectAddTitle: "Add an entry for “{term}”",
578
+ popupUnknown: "This term is not in the dictionary yet",
579
+ popupCreate: "Create entry",
580
+ popupGenerating: "Generating an explanation…",
581
+ popupNoHost: "No model is reachable. Please create the entry by hand.",
582
+ popupSourceGlossary: "Built-in glossary",
583
+ popupSourceLlm: "Generated by a model",
584
+ popupSourceUser: "My entry",
585
+ popupSourceHeuristic: "Auto-collected",
586
+ popupSourceAuto: "Auto-collected",
587
+ popupSourceImport: "Imported",
588
+
589
+ toastAdded: "Added “{term}”",
590
+ toastUpdated: "Updated “{term}”",
591
+ toastRemoved: "Deleted “{term}”",
592
+ toastAutoAdded: "Collected {count} terms",
593
+ toastExplainUnavailable: "Automatic explanation unavailable: {message}",
594
+ toastUndo: "Undo",
595
+
596
+ autoDetectOn: "Auto-collect",
597
+ autoDetectHint: "Create an entry when a new term appears in an agent reply",
598
+ annotateOn: "Underline terms",
599
+ annotateHint: "Underline known terms in replies",
600
+ autoExplainOn: "Auto-explain",
601
+ autoExplainHint: "Ask the model for an explanation as soon as a term is collected; off leaves entries unexplained",
602
+
603
+ selectEnter: "Select",
604
+ selectExit: "Exit selection",
605
+ selectAll: "Select all",
606
+ selectNone: "Clear selection",
607
+ selectedCount: "{count} selected",
608
+ deleteSelected: "Delete selected",
609
+ deleteSelectedConfirm: "Delete the {count} selected entries?",
610
+
611
+ dismiss: "Got it"
612
+ };
613
+
614
+ module.exports = { zh, en };