dsh-cait 1.0.3 → 1.0.5
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/CHANGELOG.md +410 -352
- package/LICENSE +201 -201
- package/README.ja.md +55 -14
- package/README.md +466 -423
- package/README.zh-CN.md +429 -390
- package/client/components.js +2408 -2377
- package/client/helpers.js +103 -103
- package/client/locales.js +751 -730
- package/client/rpc.js +93 -93
- package/client/styles.js +258 -258
- package/client.js +3608 -3556
- package/icon.svg +8 -8
- package/index.js +45 -45
- package/lib/api.js +223 -223
- package/lib/docx.js +392 -389
- package/lib/epub.js +355 -0
- package/lib/errors.js +8 -8
- package/lib/formats.js +972 -917
- package/lib/glossary.js +178 -178
- package/lib/html.js +271 -0
- package/lib/import-export.js +650 -605
- package/lib/libraries.js +183 -183
- package/lib/markdown.js +28 -28
- package/lib/mt.js +152 -152
- package/lib/persistence.js +341 -321
- package/lib/pptx.js +89 -89
- package/lib/preprocess.js +65 -0
- package/lib/segmenter.js +84 -84
- package/lib/similarity.js +113 -113
- package/lib/store-utils.js +342 -339
- package/lib/store.js +746 -734
- package/lib/tm.js +160 -160
- package/lib/tmx.js +85 -85
- package/lib/tools.js +472 -472
- package/lib/xlsx.js +218 -218
- package/lib/xml.js +31 -31
- package/locale/en.json +11 -11
- package/locale/zh.json +11 -11
- package/package.json +83 -83
- package/scripts/build-client.mjs +13 -13
package/README.md
CHANGED
|
@@ -1,423 +1,466 @@
|
|
|
1
|
-
<p align="center">
|
|
2
|
-
<img src="icon.svg" width="76" alt="CAIT icon" />
|
|
3
|
-
</p>
|
|
4
|
-
|
|
5
|
-
<h1 align="center">CAIT</h1>
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
<strong>Computer-aided translation, inside DeepSeek Harness.</strong><br/>
|
|
9
|
-
Translation memory · glossary · segment editor · MT assistance · document tabs · Office / subtitle / localization formats
|
|
10
|
-
</p>
|
|
11
|
-
<p align="center">
|
|
12
|
-
<a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.md">English</a>
|
|
13
|
-
</p>
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
<p align="center">
|
|
17
|
-
<img alt="
|
|
18
|
-
<img alt="DSH 0.2.x" src="https://img.shields.io/badge/DSH-0.2.x-4d6bfe.svg" />
|
|
19
|
-
<img alt="Tests:
|
|
20
|
-
<img alt="No API key required" src="https://img.shields.io/badge/API%20key-not%20required-6b7280.svg" />
|
|
21
|
-
</p>
|
|
22
|
-
|
|
23
|
-
CAIT adds a CAT workbench to the DSH Web UI and Desktop. It opens from a
|
|
24
|
-
left-sidebar entry, keeps one shared store behind the workbench and seven agent
|
|
25
|
-
tools, and covers the practical path from importing a source file to exporting a
|
|
26
|
-
translated document.
|
|
27
|
-
|
|
28
|
-
> **Tested with DSH `0.2.2-rc.1`.** CAIT uses DSH's own model routes and
|
|
29
|
-
> credentials; it never asks for an API key. The internal fallback provider is
|
|
30
|
-
> still called `mock`, but the UI labels it **Glossary substitution (offline)**.
|
|
31
|
-
|
|
32
|
-
## Why CAIT
|
|
33
|
-
|
|
34
|
-
| | |
|
|
35
|
-
|---|---|
|
|
36
|
-
| **Native to DSH** | A real sidebar panel, a main workbench, DSH theme tokens, and the same store for humans and agents. No iframe, no separate app. |
|
|
37
|
-
| **TM that explains itself** | Multiple TM libraries, mounted-only lookup, exact / near-exact / high / medium / low fuzzy grades, and automatic write-back on confirm. |
|
|
38
|
-
| **Glossary-aware editing** | Multiple term bases, source-language filtering, inline highlighting, click-to-insert terms, and per-term case sensitivity. |
|
|
39
|
-
| **A document workflow** | Tabs, close/reopen, recent-document cleanup, duplicate-import reuse, and progress per document. |
|
|
40
|
-
| **Real format coverage** | TXT, Markdown, DOCX, TMX, CSV, SRT/VTT, PO, XLIFF 1.2/2.0/SDLXLIFF, HTML, JSON, XLSX, PPTX, and RTF. |
|
|
41
|
-
| **Agent-ready** | Seven tools share the open document and store, so an agent can translate alongside you. |
|
|
42
|
-
|
|
43
|
-
## Quick start
|
|
44
|
-
|
|
45
|
-
1. Install CAIT and open it from the **CAIT** row in the left sidebar.
|
|
46
|
-
2. Choose **New page**, then drop a source file or paste text.
|
|
47
|
-
3. Set the source and target languages.
|
|
48
|
-
4. Translate the current segment; the right panel shows TM matches, glossary hits,
|
|
49
|
-
and an MT suggestion.
|
|
50
|
-
5. **Confirm & next** writes the pair to the default mounted TM.
|
|
51
|
-
6. Export target-only, bilingual, or a format-preserving document.
|
|
52
|
-
|
|
53
|
-
Typing in the editor is a draft and stays in memory. Confirming a segment (or an
|
|
54
|
-
explicit structural change) writes the snapshot. The open workbench polls the
|
|
55
|
-
Host revision every two seconds, so changes made by an agent appear without a
|
|
56
|
-
manual reload.
|
|
57
|
-
|
|
58
|
-
## Features
|
|
59
|
-
|
|
60
|
-
### Translation memory
|
|
61
|
-
|
|
62
|
-
- Multiple TM libraries with id, name, mount state, and a default write library.
|
|
63
|
-
- Exact, near-exact, and three fuzzy bands:
|
|
64
|
-
- `near_exact` compares a key that ignores digits, punctuation, and whitespace;
|
|
65
|
-
it does not depend on a score cutoff.
|
|
66
|
-
- `high_fuzzy` is `>= 0.85`, `medium_fuzzy` is `0.75–0.85`, `low_fuzzy` is
|
|
67
|
-
below `0.75` (above the configurable floor, default `0.55`).
|
|
68
|
-
- Fuzzy scoring is lexical: 72% character-bigram Dice + 28% token Jaccard.
|
|
69
|
-
Latin text uses words; CJK text uses individual characters. There is no
|
|
70
|
-
stemming, synonym, or semantic matching.
|
|
71
|
-
- Lookups only see mounted libraries. `cat_submit_translation` accepts an optional
|
|
72
|
-
`targetTmId`; an unmounted target is rejected with `TM_NOT_MOUNTED`.
|
|
73
|
-
- `bootstrap().tm.entries` is a 40-entry preview of mounted entries;
|
|
74
|
-
`bootstrap().tm.count` is the mounted count and `bootstrap().tm.total` is the
|
|
75
|
-
all-library count. Use `cat_lookup_tm` or the library modal for full data.
|
|
76
|
-
- TMX 1.4 `<tu>/<tuv>/<seg>` import/export. Inline TMX placeholders are flattened
|
|
77
|
-
to plain text with an explicit warning.
|
|
78
|
-
|
|
79
|
-
### Glossary
|
|
80
|
-
|
|
81
|
-
- Multiple glossary libraries with mount state and a default write library.
|
|
82
|
-
- Live source highlighting and click-to-insert term chips.
|
|
83
|
-
- CSV/TSV import, per-term notes, source-language filtering, and a
|
|
84
|
-
`caseSensitive` flag honored by both the workbench and `cat_lookup_glossary`.
|
|
85
|
-
- Language codes are canonicalized (`EN` → `en`, `ZH_cn` → `zh-CN`).
|
|
86
|
-
|
|
87
|
-
### Workbench
|
|
88
|
-
|
|
89
|
-
- Paragraph/sentence segmentation with a per-segment target editor.
|
|
90
|
-
- Draft saving, confirm-and-next, previous/next navigation, and progress.
|
|
91
|
-
- Document tabs; closing a tab does not delete the document.
|
|
92
|
-
- **Open existing document** reopens a closed document.
|
|
93
|
-
- Interface language switch in **Settings → Interface**: *Follow DSH language*
|
|
94
|
-
(default), 简体中文, English, or 日本語. It applies to the workbench and the
|
|
95
|
-
sidebar label right away, and changes only the CAIT UI — never the document's
|
|
96
|
-
source or target language.
|
|
97
|
-
- The trash dialog beside the picker deletes one closed document or all closed
|
|
98
|
-
documents; deletion is permanent and does not touch TM, glossary, or other
|
|
99
|
-
documents.
|
|
100
|
-
- Re-importing identical content in the same format reuses the existing document
|
|
101
|
-
instead of creating a duplicate. The fingerprint covers languages, source,
|
|
102
|
-
format, and exchange metadata.
|
|
103
|
-
- Responsive density: the workbench measures its DSH panel and applies a
|
|
104
|
-
`--cait-u` multiplier of 1×–1.8×. A 1600×900 panel renders at ~1.32× and a
|
|
105
|
-
2560×1440 panel at 1.8×; short windows stay at 1× rather than shrinking.
|
|
106
|
-
|
|
107
|
-
###
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
-
|
|
112
|
-
|
|
113
|
-
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
|
139
|
-
|
|
|
140
|
-
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
|
255
|
-
|
|
|
256
|
-
| `
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
1
|
+
<p align="center">
|
|
2
|
+
<img src="icon.svg" width="76" alt="CAIT icon" />
|
|
3
|
+
</p>
|
|
4
|
+
|
|
5
|
+
<h1 align="center">CAIT</h1>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<strong>Computer-aided translation, inside DeepSeek Harness.</strong><br/>
|
|
9
|
+
Translation memory · glossary · segment editor · MT assistance · document tabs · Office / subtitle / localization formats
|
|
10
|
+
</p>
|
|
11
|
+
<p align="center">
|
|
12
|
+
<a href="README.zh-CN.md">简体中文</a> · <a href="README.ja.md">日本語</a> · <a href="README.md">English</a>
|
|
13
|
+
</p>
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
<p align="center">
|
|
17
|
+
<a href="https://www.npmjs.com/package/dsh-cait"><img alt="npm version" src="https://img.shields.io/npm/v/dsh-cait.svg" /></a>
|
|
18
|
+
<img alt="DSH 0.2.x" src="https://img.shields.io/badge/DSH-0.2.x-4d6bfe.svg" />
|
|
19
|
+
<img alt="Tests: 15 suites" src="https://img.shields.io/badge/tests-15%20suites-brightgreen.svg" />
|
|
20
|
+
<img alt="No API key required" src="https://img.shields.io/badge/API%20key-not%20required-6b7280.svg" />
|
|
21
|
+
</p>
|
|
22
|
+
|
|
23
|
+
CAIT adds a CAT workbench to the DSH Web UI and Desktop. It opens from a
|
|
24
|
+
left-sidebar entry, keeps one shared store behind the workbench and seven agent
|
|
25
|
+
tools, and covers the practical path from importing a source file to exporting a
|
|
26
|
+
translated document.
|
|
27
|
+
|
|
28
|
+
> **Tested with DSH `0.2.2-rc.1`.** CAIT uses DSH's own model routes and
|
|
29
|
+
> credentials; it never asks for an API key. The internal fallback provider is
|
|
30
|
+
> still called `mock`, but the UI labels it **Glossary substitution (offline)**.
|
|
31
|
+
|
|
32
|
+
## Why CAIT
|
|
33
|
+
|
|
34
|
+
| | |
|
|
35
|
+
|---|---|
|
|
36
|
+
| **Native to DSH** | A real sidebar panel, a main workbench, DSH theme tokens, and the same store for humans and agents. No iframe, no separate app. |
|
|
37
|
+
| **TM that explains itself** | Multiple TM libraries, mounted-only lookup, exact / near-exact / high / medium / low fuzzy grades, and automatic write-back on confirm. |
|
|
38
|
+
| **Glossary-aware editing** | Multiple term bases, source-language filtering, inline highlighting, click-to-insert terms, and per-term case sensitivity. |
|
|
39
|
+
| **A document workflow** | Tabs, close/reopen, recent-document cleanup, duplicate-import reuse, and progress per document. |
|
|
40
|
+
| **Real format coverage** | TXT, Markdown, DOCX, EPUB, TMX, CSV, SRT/VTT, PO, XLIFF 1.2/2.0/SDLXLIFF, HTML, JSON, XLSX, PPTX, and RTF. |
|
|
41
|
+
| **Agent-ready** | Seven tools share the open document and store, so an agent can translate alongside you. |
|
|
42
|
+
|
|
43
|
+
## Quick start
|
|
44
|
+
|
|
45
|
+
1. Install CAIT and open it from the **CAIT** row in the left sidebar.
|
|
46
|
+
2. Choose **New page**, then drop a source file or paste text.
|
|
47
|
+
3. Set the source and target languages.
|
|
48
|
+
4. Translate the current segment; the right panel shows TM matches, glossary hits,
|
|
49
|
+
and an MT suggestion.
|
|
50
|
+
5. **Confirm & next** writes the pair to the default mounted TM.
|
|
51
|
+
6. Export target-only, bilingual, or a format-preserving document.
|
|
52
|
+
|
|
53
|
+
Typing in the editor is a draft and stays in memory. Confirming a segment (or an
|
|
54
|
+
explicit structural change) writes the snapshot. The open workbench polls the
|
|
55
|
+
Host revision every two seconds, so changes made by an agent appear without a
|
|
56
|
+
manual reload.
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
### Translation memory
|
|
61
|
+
|
|
62
|
+
- Multiple TM libraries with id, name, mount state, and a default write library.
|
|
63
|
+
- Exact, near-exact, and three fuzzy bands:
|
|
64
|
+
- `near_exact` compares a key that ignores digits, punctuation, and whitespace;
|
|
65
|
+
it does not depend on a score cutoff.
|
|
66
|
+
- `high_fuzzy` is `>= 0.85`, `medium_fuzzy` is `0.75–0.85`, `low_fuzzy` is
|
|
67
|
+
below `0.75` (above the configurable floor, default `0.55`).
|
|
68
|
+
- Fuzzy scoring is lexical: 72% character-bigram Dice + 28% token Jaccard.
|
|
69
|
+
Latin text uses words; CJK text uses individual characters. There is no
|
|
70
|
+
stemming, synonym, or semantic matching.
|
|
71
|
+
- Lookups only see mounted libraries. `cat_submit_translation` accepts an optional
|
|
72
|
+
`targetTmId`; an unmounted target is rejected with `TM_NOT_MOUNTED`.
|
|
73
|
+
- `bootstrap().tm.entries` is a 40-entry preview of mounted entries;
|
|
74
|
+
`bootstrap().tm.count` is the mounted count and `bootstrap().tm.total` is the
|
|
75
|
+
all-library count. Use `cat_lookup_tm` or the library modal for full data.
|
|
76
|
+
- TMX 1.4 `<tu>/<tuv>/<seg>` import/export. Inline TMX placeholders are flattened
|
|
77
|
+
to plain text with an explicit warning.
|
|
78
|
+
|
|
79
|
+
### Glossary
|
|
80
|
+
|
|
81
|
+
- Multiple glossary libraries with mount state and a default write library.
|
|
82
|
+
- Live source highlighting and click-to-insert term chips.
|
|
83
|
+
- CSV/TSV import, per-term notes, source-language filtering, and a
|
|
84
|
+
`caseSensitive` flag honored by both the workbench and `cat_lookup_glossary`.
|
|
85
|
+
- Language codes are canonicalized (`EN` → `en`, `ZH_cn` → `zh-CN`).
|
|
86
|
+
|
|
87
|
+
### Workbench
|
|
88
|
+
|
|
89
|
+
- Paragraph/sentence segmentation with a per-segment target editor.
|
|
90
|
+
- Draft saving, confirm-and-next, previous/next navigation, and progress.
|
|
91
|
+
- Document tabs; closing a tab does not delete the document.
|
|
92
|
+
- **Open existing document** reopens a closed document.
|
|
93
|
+
- Interface language switch in **Settings → Interface**: *Follow DSH language*
|
|
94
|
+
(default), 简体中文, English, or 日本語. It applies to the workbench and the
|
|
95
|
+
sidebar label right away, and changes only the CAIT UI — never the document's
|
|
96
|
+
source or target language.
|
|
97
|
+
- The trash dialog beside the picker deletes one closed document or all closed
|
|
98
|
+
documents; deletion is permanent and does not touch TM, glossary, or other
|
|
99
|
+
documents.
|
|
100
|
+
- Re-importing identical content in the same format reuses the existing document
|
|
101
|
+
instead of creating a duplicate. The fingerprint covers languages, source,
|
|
102
|
+
format, and exchange metadata.
|
|
103
|
+
- Responsive density: the workbench measures its DSH panel and applies a
|
|
104
|
+
`--cait-u` multiplier of 1×–1.8×. A 1600×900 panel renders at ~1.32× and a
|
|
105
|
+
2560×1440 panel at 1.8×; short windows stay at 1× rather than shrinking.
|
|
106
|
+
|
|
107
|
+
### Preprocessing
|
|
108
|
+
|
|
109
|
+
Imported source text passes through a preprocessing stage before segmentation:
|
|
110
|
+
|
|
111
|
+
- Collapse repeated spaces and tabs, trim indentation, and merge consecutive
|
|
112
|
+
blank lines.
|
|
113
|
+
- Remove zero-width characters and stray control characters.
|
|
114
|
+
- Placeholder tokens (`{1}`, `{2}`, …), punctuation, casing, and paragraph order
|
|
115
|
+
are left untouched, so XLIFF/HTML/EPUB inline markup still round-trips.
|
|
116
|
+
- The three steps are independently switchable in **Settings → Preprocessing** and
|
|
117
|
+
are persisted with the other settings. They apply to new imports and
|
|
118
|
+
`createDocument` calls; existing documents are not rewritten.
|
|
119
|
+
|
|
120
|
+
### MT assistance
|
|
121
|
+
|
|
122
|
+
CAIT does not own an endpoint or key. The selector is built from DSH:
|
|
123
|
+
|
|
124
|
+
- `ctx.llm.listProviders()` supplies registered provider routes.
|
|
125
|
+
- `ctx.loader.entries()` is consulted for `config.providers` when available.
|
|
126
|
+
- `ctx.llm.listModels(provider)` supplies model ids; CAIT selects the first model
|
|
127
|
+
by default.
|
|
128
|
+
- `ctx.llm.stream({ provider, model, messages, temperature, purpose: 'cait-mt' })`
|
|
129
|
+
performs the call; CAIT concatenates `text-delta` chunks.
|
|
130
|
+
|
|
131
|
+
If no usable route exists, the selected route disappears, or it has no models,
|
|
132
|
+
CAIT falls back to offline glossary substitution and says so in the UI and in the
|
|
133
|
+
`cat_suggest_mt` result. Stream failures are logged in the Host with
|
|
134
|
+
provider/model/code/status; the client receives only `MT_PROVIDER_FAILED`.
|
|
135
|
+
|
|
136
|
+
## Supported formats
|
|
137
|
+
|
|
138
|
+
| Format | Import | Export | Notes |
|
|
139
|
+
| --- | :---: | :---: | --- |
|
|
140
|
+
| TXT / Markdown | ✅ | ✅ | Paragraph and sentence segmentation |
|
|
141
|
+
| CSV | ✅ | ✅ | Comma, semicolon, tab, or pipe delimiter auto-detected; source/target column by header name or 1-based number; existing bilingual export |
|
|
142
|
+
| DOCX | ✅ | ✅ | Body paragraphs; table blocks are excluded from import. Export patches the original package, keeping styles, numbering, images, headers, tables, and layout. |
|
|
143
|
+
| EPUB | ✅ | ✅ | EPUB 3 spine order; XHTML text blocks with inline markup kept as tokens and patched back into the retained package. DRM-protected, fixed-layout, and scripted EPUBs are not supported. |
|
|
144
|
+
| TMX 1.4 | ✅ | ✅ | Common `<tu>/<tuv>/<seg>` subset; inline markup flattened with warning |
|
|
145
|
+
| SRT / WebVTT | ✅ | ✅ | One cue per segment, timings/settings/identifier retained; semantic tags kept; invalid ranges rejected |
|
|
146
|
+
| PO | ✅ | ✅ | Contexts, plural forms, translator comments, obsolete `#~` entries |
|
|
147
|
+
| XLIFF 1.2 | ✅ | ✅ | Inline tags become `{n}` tokens; missing tokens block confirmation |
|
|
148
|
+
| XLIFF 2.0 | ✅ | ✅ | Basic `<unit><segment><source>/<target>` subset |
|
|
149
|
+
| SDLXLIFF | ✅ | ✅ | Basic XLIFF 1.2 path; SDL-specific extensions are not round-tripped |
|
|
150
|
+
| HTML | ✅ | ✅ | Text blocks and inline tags preserved; document CSS/layout is not rebuilt |
|
|
151
|
+
| JSON | ✅ | ✅ | String-path subset; object/array structure preserved via a template; keys and numbers are not translated |
|
|
152
|
+
| XLSX | ✅ | ✅ | First worksheet; `Source`/`Target` headers or columns A/B; export is a new two-column workbook |
|
|
153
|
+
| PPTX | ✅ | ✅* | Source-preserving export; requires the imported `.pptx` package. Body text only; notes/charts/SmartArt not imported. |
|
|
154
|
+
| RTF | ✅ | ✅ | Basic paragraphs, `\uN`, `\'hh`, control words; original styling not round-tripped |
|
|
155
|
+
|
|
156
|
+
\* PPTX export fails with `PPTX_SOURCE_REQUIRED` when the retained source package
|
|
157
|
+
is missing rather than silently producing an unformatted deck.
|
|
158
|
+
|
|
159
|
+
Exchange metadata (subtitle timings, PO contexts/plurals/comments, XLIFF ids and
|
|
160
|
+
inline token maps, JSON paths/templates, XLSX rows, PPTX slide/paragraph positions,
|
|
161
|
+
EPUB spine hrefs and block indexes) is stored on the document/segments and persists
|
|
162
|
+
in the snapshot.
|
|
163
|
+
|
|
164
|
+
### PDF is not supported
|
|
165
|
+
|
|
166
|
+
CAIT does not import PDF, and future releases will not add PDF support. PDF is a
|
|
167
|
+
fixed-layout print format: it has no logical paragraphs, reading order, or inline
|
|
168
|
+
markup. Text extracted from it is fragmented across drawing operations, loses
|
|
169
|
+
headings, tables, and inline emphasis, and produces segments that are poor input
|
|
170
|
+
for translation memory and MT — in other words, PDF is extremely unsuitable for
|
|
171
|
+
AI-related work.
|
|
172
|
+
|
|
173
|
+
To translate PDF content, convert it to a supported format first, for example:
|
|
174
|
+
|
|
175
|
+
```sh
|
|
176
|
+
pandoc input.pdf -t docx -o output.docx # or -t html, -t markdown
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
Adobe Acrobat's **Export to Word/HTML**, LibreOffice, or any other converter that
|
|
180
|
+
produces DOCX, HTML, EPUB, or plain text works too. Scanned PDFs need OCR before
|
|
181
|
+
conversion; CAIT has no image OCR stage.
|
|
182
|
+
|
|
183
|
+
## Install
|
|
184
|
+
|
|
185
|
+
CAIT installs as a DSH bundle; the published package name is `dsh-cait` and the
|
|
186
|
+
plugin itself shows up as **CAIT** in the left sidebar. The in-app plugin
|
|
187
|
+
manager owns the `desktop` profile, so use it rather than editing the profile's
|
|
188
|
+
`package.json`.
|
|
189
|
+
|
|
190
|
+
### From npm
|
|
191
|
+
|
|
192
|
+
In DSH Desktop (or any profile with the `plugin_manager` tool):
|
|
193
|
+
|
|
194
|
+
```text
|
|
195
|
+
plugin_manager install_bundle target: dsh-cait
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Pin a release with `dsh-cait@1.0.5`, or ask for the newest one with
|
|
199
|
+
`dsh-cait@latest`. The manager resolves the registry package, applies the bundle
|
|
200
|
+
patch, and activates the plugin — no hand-written profile rows.
|
|
201
|
+
|
|
202
|
+
With a CLI-managed profile:
|
|
203
|
+
|
|
204
|
+
```sh
|
|
205
|
+
dsh plugin --profile web add dsh-cait
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
Replace `web` with your profile name, and restart `dsh web` if your host
|
|
209
|
+
requires it.
|
|
210
|
+
|
|
211
|
+
### From this repository
|
|
212
|
+
|
|
213
|
+
GitHub:
|
|
214
|
+
|
|
215
|
+
```text
|
|
216
|
+
plugin_manager install_bundle target: github:JoviLecca/dsh-CAIT
|
|
217
|
+
```
|
|
218
|
+
|
|
219
|
+
Local checkout:
|
|
220
|
+
|
|
221
|
+
```text
|
|
222
|
+
plugin_manager install_bundle target: /absolute/path/to/dsh-CAIT
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
Then reload DSH. The **CAIT** entry appears in the left sidebar.
|
|
226
|
+
|
|
227
|
+
### From source
|
|
228
|
+
|
|
229
|
+
```sh
|
|
230
|
+
git clone <this-repository> dsh-CAIT
|
|
231
|
+
cd dsh-CAIT
|
|
232
|
+
npm run build:client
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
For a local `--patch` overlay, add a row pointing at this directory:
|
|
236
|
+
|
|
237
|
+
```yaml
|
|
238
|
+
# _dev/cait.patch.yml
|
|
239
|
+
- insert:
|
|
240
|
+
- id: cait-dev
|
|
241
|
+
name: 'C:\absolute\path\to\dsh-CAIT'
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
```powershell
|
|
245
|
+
dsh web --patch C:\absolute\path\to\dsh-CAIT\_dev\cait.patch.yml
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
`--patch` is a launcher option; place it after the app name (`web`) and before
|
|
249
|
+
any app arguments. Use either the overlay or the installed bundle in a profile,
|
|
250
|
+
not both.
|
|
251
|
+
|
|
252
|
+
## Configuration
|
|
253
|
+
|
|
254
|
+
| Option | Default | Meaning |
|
|
255
|
+
| --- | --- | --- |
|
|
256
|
+
| `dataDir` | `""` | Directory for `store.json` and `sources/`. Empty means `$DSH_HOME/cait`. Absolute, relative, and `~/...` paths are accepted. |
|
|
257
|
+
|
|
258
|
+
```yaml
|
|
259
|
+
- id: dsh-cait
|
|
260
|
+
name: dsh-cait
|
|
261
|
+
config:
|
|
262
|
+
dataDir: 'D:\CAT\cait-data'
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
The snapshot stores documents, open tabs, TM, glossary, libraries, mounts, and
|
|
266
|
+
non-secret settings. Imported DOCX/PPTX/EPUB source packages live in `sources/`.
|
|
267
|
+
|
|
268
|
+
In-app settings (**Settings**) live in the snapshot rather than in the YAML
|
|
269
|
+
above: source/target language, fuzzy threshold, TM result limit, MT
|
|
270
|
+
route/model/temperature, and the interface language (`uiLang`: `auto` | `zh` |
|
|
271
|
+
`en` | `ja`, default `auto` = follow the DSH locale).
|
|
272
|
+
Segment confirmations use a strict write: if the snapshot cannot be written, the
|
|
273
|
+
confirm fails with `PERSISTENCE_FAILED` (503) and rolls back the in-memory
|
|
274
|
+
confirmation. Other structural edits remain best-effort and surface
|
|
275
|
+
`bootstrap().storage.error` in the workbench banner.
|
|
276
|
+
|
|
277
|
+
If the snapshot is corrupt or has an unknown version, CAIT logs a warning, moves
|
|
278
|
+
it to `store.json.corrupt-<timestamp>`, and starts empty instead of failing
|
|
279
|
+
activation. Version-1 snapshots are migrated to version 2 with default TM and
|
|
280
|
+
glossary libraries.
|
|
281
|
+
|
|
282
|
+
## Agent tools
|
|
283
|
+
|
|
284
|
+
| Tool | Purpose |
|
|
285
|
+
| --- | --- |
|
|
286
|
+
| `cat_get_segment` | Current segment with TM matches and glossary hits |
|
|
287
|
+
| `cat_submit_translation` | Confirm a target, write to a mounted TM (optional `targetTmId`), advance |
|
|
288
|
+
| `cat_lookup_tm` | Graded TM lookup across mounted libraries |
|
|
289
|
+
| `cat_lookup_glossary` | Query mounted glossaries; honors `caseSensitive` |
|
|
290
|
+
| `cat_list_documents` | List documents and progress |
|
|
291
|
+
| `cat_switch_document` | Select the active document |
|
|
292
|
+
| `cat_suggest_mt` | MT via the selected DSH route, or the explicit offline fallback |
|
|
293
|
+
|
|
294
|
+
The workbench and tools share one `CatStore`, so an agent can translate the same
|
|
295
|
+
document the user has open.
|
|
296
|
+
|
|
297
|
+
## Architecture
|
|
298
|
+
|
|
299
|
+
```mermaid
|
|
300
|
+
flowchart LR
|
|
301
|
+
UI["DSH Web UI<br/>(sidebar + workbench)"] --> Client["client.js<br/>generated Web bundle"]
|
|
302
|
+
Client --> API["/cait/api/rpc<br/>same-origin JSON"]
|
|
303
|
+
Tools["7 agent tools"] --> Store["CatStore"]
|
|
304
|
+
API --> Store
|
|
305
|
+
Store --> Snapshot[("store.json<br/>+ sources/")]
|
|
306
|
+
```
|
|
307
|
+
|
|
308
|
+
- **Host** (`index.js`, `lib/`) owns the store, persistence, import/export, tools,
|
|
309
|
+
and the private API.
|
|
310
|
+
- **Client** (`client/`) is plain React loaded through DSH's module loader and
|
|
311
|
+
rendered into `sidebar.panellist` and `main`. It styles only with
|
|
312
|
+
`--dsw-alias-*` tokens.
|
|
313
|
+
- `client.js` is generated; edit `client/*.js` and run `npm run build:client`.
|
|
314
|
+
|
|
315
|
+
<details>
|
|
316
|
+
<summary><strong>Project layout</strong></summary>
|
|
317
|
+
|
|
318
|
+
```text
|
|
319
|
+
cait/
|
|
320
|
+
├─ package.json
|
|
321
|
+
├─ cordis.patch.yml
|
|
322
|
+
├─ index.js # Host half
|
|
323
|
+
├─ client.js # generated Web bundle
|
|
324
|
+
├─ client/ # helpers, styles, RPC, components, locales, entry
|
|
325
|
+
├─ scripts/build-client.mjs
|
|
326
|
+
├─ icon.svg
|
|
327
|
+
├─ locale/{en,zh,ja}.json
|
|
328
|
+
├─ NOTICE
|
|
329
|
+
├─ README.md
|
|
330
|
+
├─ README.zh-CN.md
|
|
331
|
+
├─ README.ja.md
|
|
332
|
+
├─ CHANGELOG.md
|
|
333
|
+
├─ lib/
|
|
334
|
+
│ ├─ store.js # CatStore facade + document/segment core
|
|
335
|
+
│ ├─ errors.js
|
|
336
|
+
│ ├─ store-utils.js
|
|
337
|
+
│ ├─ libraries.js # TM/glossary registries + mounts
|
|
338
|
+
│ ├─ tm.js
|
|
339
|
+
│ ├─ glossary.js
|
|
340
|
+
│ ├─ persistence.js
|
|
341
|
+
│ ├─ import-export.js
|
|
342
|
+
│ ├─ formats.js # CSV/SRT/VTT/PO/XLIFF/HTML/JSON/RTF
|
|
343
|
+
│ ├─ html.js # Shared HTML/XHTML run scanner + patcher
|
|
344
|
+
│ ├─ epub.js # EPUB package read / spine import / patch export
|
|
345
|
+
│ ├─ preprocess.js # Import-time source cleaning stage
|
|
346
|
+
│ ├─ xlsx.js
|
|
347
|
+
│ ├─ pptx.js
|
|
348
|
+
│ ├─ segmenter.js
|
|
349
|
+
│ ├─ similarity.js
|
|
350
|
+
│ ├─ tmx.js
|
|
351
|
+
│ ├─ docx.js
|
|
352
|
+
│ ├─ markdown.js
|
|
353
|
+
│ ├─ xml.js
|
|
354
|
+
│ ├─ mt.js
|
|
355
|
+
│ ├─ tools.js
|
|
356
|
+
│ └─ api.js
|
|
357
|
+
└─ _dev/ # tests, fixtures, local patch overlay
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
</details>
|
|
361
|
+
|
|
362
|
+
## Development
|
|
363
|
+
|
|
364
|
+
Requires Node.js 22+ and DSH `0.2.x`. Tested with DSH `0.2.2-rc.1` and Node
|
|
365
|
+
`26.7.0`.
|
|
366
|
+
|
|
367
|
+
```sh
|
|
368
|
+
npm run build:client
|
|
369
|
+
node --check client.js
|
|
370
|
+
|
|
371
|
+
node _dev/test-core.mjs
|
|
372
|
+
node _dev/test-imports.mjs
|
|
373
|
+
node _dev/test-formats.mjs
|
|
374
|
+
node _dev/test-epub.mjs
|
|
375
|
+
node _dev/test-preprocess.mjs
|
|
376
|
+
node _dev/test-second-tier.mjs
|
|
377
|
+
node _dev/test-docx-export.mjs
|
|
378
|
+
node _dev/test-api.mjs
|
|
379
|
+
node _dev/test-plugin.mjs
|
|
380
|
+
node _dev/test-persistence.mjs
|
|
381
|
+
node _dev/test-documents.mjs
|
|
382
|
+
node _dev/test-libraries.mjs
|
|
383
|
+
node _dev/test-mounts.mjs
|
|
384
|
+
node _dev/test-ui-scale.mjs
|
|
385
|
+
node _dev/test-mt.mjs
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
The import/export fixtures are `_dev/sample.docx`, `_dev/sample-table.docx`, and
|
|
389
|
+
`_dev/sample-format.docx`; regenerate them with the matching
|
|
390
|
+
`python _dev/make-*.py` scripts. All 15 suites should pass.
|
|
391
|
+
|
|
392
|
+
### Releasing
|
|
393
|
+
|
|
394
|
+
`npm publish` runs `prepublishOnly`, which rebuilds `client.js` from the
|
|
395
|
+
`client/` fragments and syntax-checks the result, so a release cannot ship a
|
|
396
|
+
stale bundle. Publishing from the repository root:
|
|
397
|
+
|
|
398
|
+
```sh
|
|
399
|
+
npm publish
|
|
400
|
+
```
|
|
401
|
+
|
|
402
|
+
`.github/workflows/publish.yml` does the same from CI on a published GitHub
|
|
403
|
+
release, using npm Trusted Publishing (OIDC) instead of a stored token, and it
|
|
404
|
+
refuses to publish when the release tag does not match `package.json`.
|
|
405
|
+
|
|
406
|
+
The very first release has to be published locally, because a trusted publisher
|
|
407
|
+
can only be configured for a package that already exists:
|
|
408
|
+
|
|
409
|
+
```sh
|
|
410
|
+
npm login
|
|
411
|
+
npm publish
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Afterwards open the package on npmjs.com, go to
|
|
415
|
+
**Settings → Trusted publishing**, and add the repository `JoviLecca/dsh-CAIT`
|
|
416
|
+
with the workflow file `publish.yml`. Later releases can then be published from
|
|
417
|
+
GitHub with a release.
|
|
418
|
+
|
|
419
|
+
## Security model
|
|
420
|
+
|
|
421
|
+
- The Host API is mounted at `/cait/api`, restricted to same-origin/trusted
|
|
422
|
+
requests by `ctx.connection.requestRejection`.
|
|
423
|
+
- RPC bodies are JSON, capped at 32 MB, and return `413 BODY_TOO_LARGE` beyond
|
|
424
|
+
that.
|
|
425
|
+
- `clearTM` / `clearGlossary` require `params.confirm === true` in addition to
|
|
426
|
+
the browser trust check; the UI asks before sending it.
|
|
427
|
+
- CAIT never receives, stores, or returns an API key. DSH credentials stay inside
|
|
428
|
+
the selected provider adapter.
|
|
429
|
+
- Persistence is one snapshot with last-write-wins semantics; it is not a
|
|
430
|
+
multi-user journal.
|
|
431
|
+
|
|
432
|
+
## Known limits and roadmap
|
|
433
|
+
|
|
434
|
+
- No PDF import; PDF is intentionally out of scope (see
|
|
435
|
+
[PDF is not supported](#pdf-is-not-supported)). No image OCR yet.
|
|
436
|
+
- EPUB import follows the spine and body XHTML text blocks; DRM-protected,
|
|
437
|
+
fixed-layout, scripted, and MathML-heavy books are not supported.
|
|
438
|
+
- DOCX import skips tables, headers, footnotes, fields, alt text, and tracked
|
|
439
|
+
deletions. DOCX export leaves those regions in the source language.
|
|
440
|
+
- Mixed-run DOCX/PPTX paragraphs inherit the first run's formatting.
|
|
441
|
+
- PPTX import covers body text, not notes, charts, or SmartArt.
|
|
442
|
+
- XLSX import/export is a two-column table; cell styles, formulas, merged cells,
|
|
443
|
+
images, and extra sheets are not preserved.
|
|
444
|
+
- HTML/RTF export does not round-trip original styling; JSON translates string
|
|
445
|
+
values only.
|
|
446
|
+
- TM matching is lexical, not semantic; no stemming, synonyms, or embeddings.
|
|
447
|
+
- Library rename/delete and per-tab mount state are not implemented yet.
|
|
448
|
+
- The workbench UI ships in Chinese, English, and Japanese, switchable in
|
|
449
|
+
Settings; this README ships in English, Simplified Chinese, and Japanese, and
|
|
450
|
+
the English version is the source of truth.
|
|
451
|
+
|
|
452
|
+
Planned next: image/vision input through a multimodal DSH route, richer library
|
|
453
|
+
management, style-preserving XLSX output, and XLIFF `<alt-trans>` / notes support.
|
|
454
|
+
|
|
455
|
+
## Changelog and versioning
|
|
456
|
+
|
|
457
|
+
See [CHANGELOG.md](CHANGELOG.md). `v1.0.0` was the first public release;
|
|
458
|
+
`v1.0.1` adds the Japanese UI and the in-app interface language switch,
|
|
459
|
+
`v1.0.2` makes *Follow DSH language* honour the DSH locale, `v1.0.3`
|
|
460
|
+
publishes the package to npm, `v1.0.4` moves later releases to the
|
|
461
|
+
provenance-publishing workflow, and `v1.0.5` adds EPUB, import preprocessing,
|
|
462
|
+
and the PDF policy. The project was developed as `0.1.0` and
|
|
463
|
+
renumbered for the GitHub release.
|
|
464
|
+
|
|
465
|
+
> **License:** Apache License 2.0 — see [LICENSE](LICENSE). Redistributions must
|
|
466
|
+
> retain the attribution in [NOTICE](NOTICE).
|