@ragnoryok1/dsh-client-locale-ru 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +968 -0
- package/NAMESPACES.md +93 -0
- package/README.en.md +551 -0
- package/README.md +563 -287
- package/README.zh.md +267 -0
- package/assets/banner.jpg +0 -0
- package/images/plugins-ru.png +0 -0
- package/images/settings-ru.png +0 -0
- package/lib/client.js +2157 -163
- package/lib/index.d.ts +8 -2
- package/lib/typography.d.ts +31 -0
- package/lib/typography.js +36 -16
- package/package.json +58 -21
- package/assets/banner.png +0 -0
- package/assets/icon.png +0 -0
- package/lib/client.d.ts +0 -6
- package/lib/client.js.map +0 -1
package/NAMESPACES.md
ADDED
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
<!-- Сгенерировано `npm run namespaces`; проверяется `npm run check:namespaces`. -->
|
|
2
|
+
# Что переведено
|
|
3
|
+
|
|
4
|
+
Пакет переводит **77 namespace** — 4495 строк. Колонка «как это выглядит»
|
|
5
|
+
берёт заголовок самого namespace (то, что читает пользователь), а не отдельное описание:
|
|
6
|
+
список нельзя разойтись с переводами.
|
|
7
|
+
|
|
8
|
+
Колонка «источник» говорит, откуда взят английский текст: «харнесс» — собственные словари
|
|
9
|
+
клиента, «пакет@версия» — словарь стороннего плагина, выгруженный из его собственной
|
|
10
|
+
публикации (`npm run fetch:plugins`). Плагины проверяются теми же правилами, поэтому
|
|
11
|
+
список — это обещание, а не перечень.
|
|
12
|
+
|
|
13
|
+
| namespace | как это выглядит | строк | источник |
|
|
14
|
+
|---|---|---|---|
|
|
15
|
+
| `agent-team` | Команда агентов | 25 | харнесс |
|
|
16
|
+
| `approval` | — | 5 | харнесс |
|
|
17
|
+
| `chat` | — | 200 | харнесс |
|
|
18
|
+
| `claude-code-mods` | — | 4 | харнесс |
|
|
19
|
+
| `command` | — | 28 | харнесс |
|
|
20
|
+
| `common` | — | 41 | харнесс |
|
|
21
|
+
| `conversation` | — | 379 | харнесс |
|
|
22
|
+
| `cordis` | — | 51 | харнесс |
|
|
23
|
+
| `cotTranslation` | — | 32 | харнесс |
|
|
24
|
+
| `deepseek-model-label-1017` | — | 1 | харнесс |
|
|
25
|
+
| `deliverables` | — | 60 | харнесс |
|
|
26
|
+
| `documentHtml` | HTML | 4 | харнесс |
|
|
27
|
+
| `documentMarkdown` | — | 4 | харнесс |
|
|
28
|
+
| `dsh-skill-explorer` | — | 75 | @linxin666/dsh-client-ui-skill-explorer@0.4.7 |
|
|
29
|
+
| `dsh-ssh` | — | 154 | @linxin666/dsh-ssh@0.4.7 |
|
|
30
|
+
| `dsh-web-ui-market` | — | 106 | @linxin666/dsh-client-ui-market@0.4.7 |
|
|
31
|
+
| `dsh-web-ui-preset-center` | — | 46 | @linxin666/dsh-client-ui-preset-center@0.4.7 |
|
|
32
|
+
| `dsh-web-ui-session-archive` | — | 124 | @linxin666/dsh-session-archive@0.4.7 |
|
|
33
|
+
| `dsh-web-ui-usage` | — | 63 | @linxin666/dsh-usage@0.4.7 |
|
|
34
|
+
| `feedback` | — | 20 | харнесс |
|
|
35
|
+
| `git-graph` | — | 63 | @linxin666/dsh-client-ui-git-graph@0.4.7 |
|
|
36
|
+
| `goal` | — | 12 | харнесс |
|
|
37
|
+
| `inspectorPanel` | Инспектор Node.js | 4 | харнесс |
|
|
38
|
+
| `job` | — | 50 | харнесс |
|
|
39
|
+
| `liangshen` | — | 42 | @linxin666/dsh-liangshen@0.4.7 |
|
|
40
|
+
| `model` | — | 23 | харнесс |
|
|
41
|
+
| `open-in-app` | — | 45 | харнесс |
|
|
42
|
+
| `permission.access` | Права доступа | 20 | харнесс |
|
|
43
|
+
| `pet` | — | 81 | @linxin666/dsh-pet@0.4.7 |
|
|
44
|
+
| `plan` | — | 17 | харнесс |
|
|
45
|
+
| `pluginManager` | Плагины | 227 | харнесс |
|
|
46
|
+
| `pluginMarket` | Обзор плагинов | 78 | харнесс |
|
|
47
|
+
| `question` | — | 31 | харнесс |
|
|
48
|
+
| `reference` | — | 15 | харнесс |
|
|
49
|
+
| `remote` | Удалённый доступ | 115 | @linxin666/dsh-remote-web-ui@0.4.7 |
|
|
50
|
+
| `schedule.catalog` | — | 90 | харнесс |
|
|
51
|
+
| `schedule.manager` | Задачи автоматизации | 207 | харнесс |
|
|
52
|
+
| `secretMask` | — | 2 | харнесс |
|
|
53
|
+
| `session-inspector` | — | 52 | харнесс |
|
|
54
|
+
| `session-log-download` | — | 10 | харнесс |
|
|
55
|
+
| `settings` | Настройки | 41 | харнесс |
|
|
56
|
+
| `settings.account` | Учётная запись | 94 | харнесс |
|
|
57
|
+
| `settings.agentLoop` | Цикл агента | 12 | харнесс |
|
|
58
|
+
| `settings.agentPreset` | Пресеты агента | 47 | харнесс |
|
|
59
|
+
| `settings.locale` | — | 1 | харнесс |
|
|
60
|
+
| `settings.models` | Модели | 134 | харнесс |
|
|
61
|
+
| `settings.permission` | Права доступа | 20 | харнесс |
|
|
62
|
+
| `settings.pluginInventory` | — | 37 | харнесс |
|
|
63
|
+
| `settings.plugins` | Встроенные плагины | 5 | харнесс |
|
|
64
|
+
| `settings.sessionLog` | — | 4 | харнесс |
|
|
65
|
+
| `settings.shell` | Командная оболочка | 14 | харнесс |
|
|
66
|
+
| `settings.subagent` | — | 35 | харнесс |
|
|
67
|
+
| `settings.theme` | — | 25 | харнесс |
|
|
68
|
+
| `settings.webSearch` | Веб-поиск | 27 | харнесс |
|
|
69
|
+
| `shortcuts` | Горячие клавиши | 56 | харнесс |
|
|
70
|
+
| `shortcuts.layout` | — | 1 | харнесс |
|
|
71
|
+
| `sidebar` | — | 5 | харнесс |
|
|
72
|
+
| `sidebarBrowser` | — | 26 | харнесс |
|
|
73
|
+
| `sidebarCodePreview` | Код | 3 | харнесс |
|
|
74
|
+
| `sidebarDocumentPreview` | — | 22 | харнесс |
|
|
75
|
+
| `sidebarExcel` | Таблица | 15 | харнесс |
|
|
76
|
+
| `sidebarFiles` | — | 17 | харнесс |
|
|
77
|
+
| `sidebarImage` | Изображение | 11 | харнесс |
|
|
78
|
+
| `sidebarOffice` | Документ Office | 15 | харнесс |
|
|
79
|
+
| `sidebarPdf` | PDF | 15 | харнесс |
|
|
80
|
+
| `sidebarRight` | — | 34 | харнесс |
|
|
81
|
+
| `sidebarTerminal` | Терминал | 28 | харнесс |
|
|
82
|
+
| `skill` | — | 8 | харнесс |
|
|
83
|
+
| `slash.menu` | — | 9 | харнесс |
|
|
84
|
+
| `subagent` | — | 79 | харнесс |
|
|
85
|
+
| `task-board` | — | 437 | @linxin666/dsh-client-ui-task-board@0.4.7 |
|
|
86
|
+
| `task-board-github` | — | 113 | @linxin666/dsh-client-ui-task-board-github@0.4.7 |
|
|
87
|
+
| `trajectory` | — | 196 | харнесс |
|
|
88
|
+
| `update` | — | 43 | @linxin666/dsh-update@0.4.7 |
|
|
89
|
+
| `voice-input` | — | 109 | харнесс |
|
|
90
|
+
| `workflowRun` | — | 20 | харнесс |
|
|
91
|
+
| `workspace` | — | 131 | харнесс |
|
|
92
|
+
|
|
93
|
+
Итого: **77** namespace, **4495** строк.
|
package/README.en.md
ADDED
|
@@ -0,0 +1,551 @@
|
|
|
1
|
+
<!-- deepseek-harness-meta
|
|
2
|
+
{
|
|
3
|
+
"name": "Russian (ru) language pack for DeepSeek Harness",
|
|
4
|
+
"version": "0.2.1",
|
|
5
|
+
"tags": ["localization", "russian", "i18n", "web-gui", "language-pack"],
|
|
6
|
+
"description": "Full Russian interface for the DeepSeek Harness web GUI: 77 namespaces, 4495 translated strings, Russian screen typography, and a locale audit in CI pinned to a harness tag. Includes the automation-task manager and the reminder catalog.",
|
|
7
|
+
"icon": "https://raw.githubusercontent.com/Ragnoryok1/dsh-client-locale-ru/main/assets/icon.png",
|
|
8
|
+
"compatible_versions": ["v0.2.1-rc.2", "v0.2.1-rc.1", "v0.2.1-alpha.5", "v0.2.1-alpha.4", "v0.2.1-alpha.3", "v0.2.1-alpha.2", "v0.2.1-alpha.1", "v0.2.0-rc.2", "v0.2.0-rc.1", "v0.1.7-rc.2", "v0.1.7-rc.1", "v0.1.7-alpha.2"],
|
|
9
|
+
"screenshots": "images",
|
|
10
|
+
"install_method": "dsh plugin --profile web add @ragnoryok1/dsh-client-locale-ru"
|
|
11
|
+
}
|
|
12
|
+
-->
|
|
13
|
+
|
|
14
|
+
# @ragnoryok1/dsh-client-locale-ru
|
|
15
|
+
|
|
16
|
+
[Русский](README.md) | **English** | [中文](README.zh.md)
|
|
17
|
+
|
|
18
|
+

|
|
19
|
+
|
|
20
|
+
[](https://www.npmjs.com/package/@ragnoryok1/dsh-client-locale-ru)
|
|
21
|
+
[](LICENSE)
|
|
22
|
+
[](https://github.com/Ragnoryok1/dsh-client-locale-ru/actions/workflows/verify.yml)
|
|
23
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
24
|
+
[](https://github.com/Ragnoryok1/dsh-client-locale-ru)
|
|
25
|
+
[](https://github.com/Ragnoryok1/dsh-client-locale-ru)
|
|
26
|
+
|
|
27
|
+
Russian (`ru`) language pack for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) web GUI (`dsh`). It registers `ru` as a selectable client language through the locale service (`ctx.locale.addLanguage`) plus one dictionary per namespace — 77 namespaces, 4,495 strings, built against dsh `0.2.1-rc.2`. Install with `dsh plugin --profile web add @ragnoryok1/dsh-client-locale-ru`, then pick **Русский** in Settings → General. Missing keys fall back to English, so a newer harness keeps working. The scope is the harness's own client interface only — third-party plugin dictionaries are deliberately out of scope, and 11 of the 17 most-downloaded ecosystem plugins ship no strings of their own, so they are already Russian through these namespaces. MIT, community-maintained, not affiliated with DeepSeek.
|
|
28
|
+
|
|
29
|
+
> **If the pack was useful to you, please star the repository.** It is the only signal that a
|
|
30
|
+
> translation is wanted, and it is what decides which parts get worked on next.
|
|
31
|
+
|
|
32
|
+
---
|
|
33
|
+
|
|
34
|
+
The complete inventory is in [NAMESPACES.md](NAMESPACES.md): 77 namespaces, 4495 strings, with the bundled plugin dictionaries marked.
|
|
35
|
+
|
|
36
|
+
The plugin names and descriptions on the Plugins page cannot come from this pack: the harness
|
|
37
|
+
keeps them in `locale/<language>.json` inside each package, builds a translation map from them,
|
|
38
|
+
and its locale service resolves that map without consulting dictionaries at all — «maps do not
|
|
39
|
+
consult registered dictionaries». 221 harness packages ship `locale/en.json`, 219 of them ship
|
|
40
|
+
`locale/zh.json`, and **none ships `locale/ru.json`**, so those 261 strings stay English with any
|
|
41
|
+
language pack; only `locale/ru.json` files on the harness side can close them.
|
|
42
|
+
`scripts/descriptor-coverage.mjs` counts that gap so it is not mixed into our dictionary coverage; the mechanism and the 32 prepared translations are in `docs/descriptor-upstream.md`.
|
|
43
|
+
Plugins outside the harness tree are translated the same way, but their English comes from
|
|
44
|
+
their own publication: `plugins/<namespace>.json` records the package, version, licence and the
|
|
45
|
+
English strings extracted from its bundle (`npm run fetch:plugins`). `npm run report:plugins`
|
|
46
|
+
shows what in your installation is still English: it walks the profile's `node_modules`, reads
|
|
47
|
+
each plugin's own dictionary and compares its keys with ours. A plugin without a dictionary is
|
|
48
|
+
reported as such — there is nothing to translate until it asks for one — and a plugin that
|
|
49
|
+
already carries its own Russian is marked separately. That is how dictionaries
|
|
50
|
+
that would otherwise not exist at all get covered — today `update` (43 strings) for
|
|
51
|
+
`@linxin666/dsh-update`, `git-graph` (63 strings) for `@linxin666/dsh-client-ui-git-graph`,
|
|
52
|
+
`dsh-web-ui-usage` (63 strings) for `@linxin666/dsh-usage` and `dsh-web-ui-session-archive`
|
|
53
|
+
(124 strings) for `@linxin666/dsh-session-archive`, `pet` (81 strings) for `@linxin666/dsh-pet`
|
|
54
|
+
`remote` (115 strings) for `@linxin666/dsh-remote-web-ui`, `dsh-skill-explorer`
|
|
55
|
+
(75 strings) for `@linxin666/dsh-client-ui-skill-explorer` and `dsh-web-ui-market`
|
|
56
|
+
(106 strings) for `@linxin666/dsh-client-ui-market`, `liangshen` (42 strings) for
|
|
57
|
+
`@linxin666/dsh-liangshen` and `dsh-web-ui-preset-center` (46 strings) for
|
|
58
|
+
`@linxin666/dsh-client-ui-preset-center`, `dsh-ssh` (154 strings) for `@linxin666/dsh-ssh` and
|
|
59
|
+
`task-board` (437 strings) for `@linxin666/dsh-client-ui-task-board` and `task-board-github`
|
|
60
|
+
(113 strings) for `@linxin666/dsh-client-ui-task-board-github` — all thirteen extractable
|
|
61
|
+
dictionaries of that family, each translated in full. Another pack's Russian is never copied: there would be nothing to verify it
|
|
62
|
+
against, while the audit compares our value with the English template of that same plugin.
|
|
63
|
+
|
|
64
|
+
## What it looks like
|
|
65
|
+
|
|
66
|
+
Russian in the language list and the translated settings sections (the screenshots were taken in build `0.1.8`:
|
|
67
|
+
the same screen, but the wording and some sections have changed since — the font-size caption, for one, now reads
|
|
68
|
+
«Влияет только на содержимое диалога»):):
|
|
69
|
+
|
|
70
|
+

|
|
71
|
+
|
|
72
|
+

|
|
73
|
+
|
|
74
|
+
Both screenshots are cropped at the left edge of the panel: workspace and session names are
|
|
75
|
+
not in frame.
|
|
76
|
+
|
|
77
|
+
Russian locale (`ru`) for the [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) web GUI (`dsh`).
|
|
78
|
+
|
|
79
|
+
The plugin adds **Russian** as a selectable language through the locale's language-pack contract: `ctx.locale.addLanguage({ id: 'ru', label: 'Русский', fallback: 'en' })` plus one `ru` dictionary per namespace. Once **Русский** is picked in Settings → General, the interface switches over immediately.
|
|
80
|
+
|
|
81
|
+
> **If the package was useful to you, give it a star.** It is the only way to show that a
|
|
82
|
+
> translation is wanted, and it genuinely affects which tasks get taken on. Not a single
|
|
83
|
+
> “like” button in the interface does that.
|
|
84
|
+
>
|
|
85
|
+
> The repository, meanwhile, remains the place where the state of the translation is visible:
|
|
86
|
+
> a [CHANGELOG](CHANGELOG.md) breaking down every release (including the mistakes that were found
|
|
87
|
+
> in it by its own maintainers), the CI checks, and the list of what is deliberately not translated.
|
|
88
|
+
|
|
89
|
+
## Installation
|
|
90
|
+
|
|
91
|
+
This is a **hybrid plugin** (`dsh.bundle` + `dsh.client`), so it installs as an ordinary profile bundle through `dsh plugin`:
|
|
92
|
+
|
|
93
|
+
```sh
|
|
94
|
+
dsh plugin --profile web add @ragnoryok1/dsh-client-locale-ru
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
After that, the next time `dsh web` starts, **Русский** will appear in the settings. A separate `pnpm add` into a built `dsh web` is not needed — the plugin pulls in the built-in locale through the `locale` service.
|
|
98
|
+
|
|
99
|
+
The manifest is checked against the harness's own rules rather than by eye (`npm run check:manifest`, part of `verify`). Each rule was read out of the harness sources and each is a failure the user would otherwise meet first: `parseDshClient` accepts `platform` as any string while the consumers keep only `platform === 'web'`, so a typo like `'Web'` would **silently drop** the client half; a declared `dsh.client` without the `./client` export makes `client-modules` throw; and `dsh.bundle.patch` has to point at a file that exists.
|
|
100
|
+
|
|
101
|
+
Installing from GitHub works too: `dsh plugin --profile web add Ragnoryok1/dsh-client-locale-ru` (the form the plugin catalogue generates, without the npm scope) installs the repository archive, and the built `lib/` is committed — no build runs on your machine, and none is needed. That is exactly why `npm run check:built` (part of `verify`) rebuilds `lib/` and compares it with the commit: a stale bundle in git would reach the user, while the audit would never see it, because the audit reads the sources. The published package is 482 kB: the banner ships as JPEG, and the icon and source map stay out of the npm payload.
|
|
102
|
+
|
|
103
|
+
## Why hybrid
|
|
104
|
+
|
|
105
|
+
`dsh web` takes client (UI) plugins only from **workspace packages**, and an external npm package carrying just a `dsh.client` is not picked up. For an external plugin with a UI half to be installable, it has to declare **`dsh.bundle`** (the profile layer), whose `cordis.patch.yml` adds the client entry `locale-ru` to the browser roster through `- insert:`. Other third-party plugins are built the same way (for example `@zseven-w/dsh-android`).
|
|
106
|
+
|
|
107
|
+
## How it works
|
|
108
|
+
|
|
109
|
+
- **Host half** (`lib/index.js`) — an empty `apply()`: a language plugin needs no server logic, it only provides a valid cordis entry for the Loader.
|
|
110
|
+
- **Browser half** (`lib/client.js`) — registers `ru` and the dictionaries through the `locale` service (injected from `ctx`). There are no framework runtime imports — only the service.
|
|
111
|
+
- **No runtime dependencies** — `lib/client.js` imports no other packages, so it does not drag in heavy dependencies.
|
|
112
|
+
- **Effects** — the language and the dictionaries are registered through `ctx.effect(...)`, so they are unloaded together with the plugin (HMR-safe).
|
|
113
|
+
- **Plural forms** — the locale contract carries no pluralization rules: components choose the
|
|
114
|
+
form as `count === 1 ? 'key.one' : 'key.other'`, while Russian needs three (1 вызов /
|
|
115
|
+
2 вызова / 5 вызовов). The package takes that over: alongside `.one` and `.other` the
|
|
116
|
+
dictionaries carry `.few` and `.many`, and a wrapper around the runtime's `translate`
|
|
117
|
+
recomputes the form with `Intl.PluralRules('ru')` for any call carrying a numeric `count`
|
|
118
|
+
or `n`. The number decides, not the key the component picked, so «2 вызова инструментов»
|
|
119
|
+
and «5 вызовов инструментов» come out of the same call site. The forms are not limited to
|
|
120
|
+
paired keys: where the harness passes a number to a key it never paired (`terminal.expand`
|
|
121
|
+
with `{n}`), the pack adds its own `.one` / `.few` / `.many` — «Показать ещё 1 строку /
|
|
122
|
+
3 строки / 7 строк» — and the wrapper looks a form up for those keys too. Where a form does
|
|
123
|
+
not fit (a sentence carrying several numbers), the value is rewritten to be count-neutral:
|
|
124
|
+
«Символов: {total}» instead of «{total} символов», «файлов: {files}» instead of
|
|
125
|
+
«{files} файлов». Checked by `npm run check:plural` at counts 0, 1, 2, 3, 5 and 22, on an
|
|
126
|
+
unpaired key, on a fractional count, and on a foreign language pack whose forms our rules
|
|
127
|
+
must not rewrite.
|
|
128
|
+
- **Fallback** — a missing Russian key falls back to `en` (the configured `fallback`).
|
|
129
|
+
|
|
130
|
+
## Typography
|
|
131
|
+
|
|
132
|
+
The package brings already-rendered Russian text into line with typographic rules: guillemets
|
|
133
|
+
(«ёлочки») instead of straight quotes, an em dash instead of a hyphen between words, an ellipsis
|
|
134
|
+
instead of three dots, a non-breaking space between a number and the following word or unit of
|
|
135
|
+
measurement (so that «187 плагинов» does not break across two lines), and the same space after a
|
|
136
|
+
short word — a preposition, a conjunction or a particle — so that «в режим» wraps as a whole
|
|
137
|
+
instead of leaving «в» alone at the end of a line. The rules are deliberately conservative: they
|
|
138
|
+
fire only on unambiguous patterns, and code, input fields, editable text and elements with
|
|
139
|
+
`data-typography="off"` are not touched at all. A second pass changes nothing.
|
|
140
|
+
|
|
141
|
+
A rule for numeric ranges (an en dash in «5–10») is **deliberately absent**: the only string in
|
|
142
|
+
the whole pack with a hyphen between digits is the cron example `0 9 * * 1-5`, and a dash would
|
|
143
|
+
corrupt it. Measured, not assumed.
|
|
144
|
+
|
|
145
|
+
The rules are checked by a script rather than by eye: `npm run check:typography`.
|
|
146
|
+
|
|
147
|
+
The pass itself sees text nodes only, while a dictionary value also travels into attributes —
|
|
148
|
+
`title`, `aria-label`, `placeholder` — that it never reaches. The values are therefore checked
|
|
149
|
+
separately: the pack may not contain a straight quote, a hyphen standing for a dash, a dash
|
|
150
|
+
without spaces, or three dots. Otherwise the same string would look different depending on
|
|
151
|
+
where it landed, and in a hint or a screen-reader label the rules would not work at all.
|
|
152
|
+
|
|
153
|
+
Text that changes **after** the first pass — token counters, timers, progress — is rewritten
|
|
154
|
+
again, so a live «4 с» keeps its non-breaking space. This is checked on a real document rather
|
|
155
|
+
than on strings: `npm run check:typography:dom` (jsdom, six cases — the first pass, a later text
|
|
156
|
+
change, an added subtree, disposal, a foreign language, and a language switch).
|
|
157
|
+
|
|
158
|
+
The pass runs **only while Russian is active**: the rules are Russian, and applying them to
|
|
159
|
+
another language would edit text this pack does not own — `"quotes"` would become «quotes» in an
|
|
160
|
+
English interface. The pack listens to `locale/change` and starts or stops the pass on a switch
|
|
161
|
+
rather than on installation.
|
|
162
|
+
|
|
163
|
+
## Checks
|
|
164
|
+
|
|
165
|
+
```sh
|
|
166
|
+
npm run build # the three outputs
|
|
167
|
+
npm run check:typography # 18 typography rules, including "leave alone"
|
|
168
|
+
npm run check:locale # dictionaries side by side: 6 checks
|
|
169
|
+
npm run check:plural # plural forms: 1 вызов / 2 вызова / 5 вызовов
|
|
170
|
+
npm run check:composition # composed phrases: «Пн, Ср в 09:00», «Раз в 2 дня»
|
|
171
|
+
npm run check:namespaces # NAMESPACES.md matches the built bundle
|
|
172
|
+
npm run check:tarball # what gets installed: the archive is unpacked and checked
|
|
173
|
+
npm run check:workflows # both workflows run the whole verify chain
|
|
174
|
+
npm run check:readmes:pairs # the three READMEs move together (recorded section hashes)
|
|
175
|
+
npm run audit -- <harness tree> # the locale audit
|
|
176
|
+
npm run verify -- <harness tree> # everything together
|
|
177
|
+
|
|
178
|
+
npm run namespaces # regenerate NAMESPACES.md and pack-count.json
|
|
179
|
+
npm run readmes:record # re-record section hashes after editing all three READMEs
|
|
180
|
+
npm run diff:harness -- <old> <new> # what the harness reworded under us
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
A separate check composes phrases the way the harness does and reads the result whole. The
|
|
184
|
+
audit compares a value with its own template, so a phrase that is correct in isolation but
|
|
185
|
+
broken by substitution stays invisible to it: `frequency.weekly` was filled as «По {weekdays}
|
|
186
|
+
в {time} », while the days arrive as «Пн, Ср» — producing «По Пн, Ср в 09:00», which no
|
|
187
|
+
line-by-line check can see. The same way «Каждые 2 дня» (now «Раз в 2 дня»), «Каждый день в
|
|
188
|
+
09:00 (Europe/Moscow)» and a composed interval with the plural forms are pinned. The third find
|
|
189
|
+
of the same kind: `time.locale` is not text but a tag for `Intl`, and it was `en` — a rule
|
|
190
|
+
restricted to a month read «Каждый день в January», and the zone label «Moscow Standard Time»
|
|
191
|
+
inside a Russian interface. The tag is `ru` now (the harness's Chinese dictionary uses `zh-CN`
|
|
192
|
+
the same way), and the month sits in parentheses: «Каждый день (январь, март)».
|
|
193
|
+
|
|
194
|
+
The same part-by-part reading found the cron wording: abbreviations («Каждые {step} мин»,
|
|
195
|
+
«Каждые {count} ч») and bookish turns («в минуту {minutes}», «минуты {minutes} в часы
|
|
196
|
+
{hours}»). The counted parts gained plural forms — «Каждые 3 минуты» / «Каждые 5 минут»,
|
|
197
|
+
«Каждые 2 часа» / «Каждые 6 часов» — and the rest were rewritten into one readable labelled
|
|
198
|
+
style: «Каждый час, минуты: 5, 30», «минуты: 5, часы: 09–17». The whole schedule sentence is
|
|
199
|
+
asserted end to end: «Пн–Пт каждые 5 минут». The date stamps are pinned the same way: «5 окт. 2026 г., 15:51» and the zone label «Москва, стандартное время» come from Intl with our tag, without a single Latin word.
|
|
200
|
+
|
|
201
|
+
The audit runs in CI (`.github/workflows/verify.yml`) against a **pinned harness tag**,
|
|
202
|
+
not against some random local checkout. The same run also fires **weekly on a schedule**: a
|
|
203
|
+
translation rots without anyone editing it — the upstream moves on, everything is green
|
|
204
|
+
locally, and the drift surfaces only when a user builds. The gates cover completeness (keys and
|
|
205
|
+
namespaces), plural forms, placeholders, English and Chinese residue, terminology, Latin words in
|
|
206
|
+
prose, text hygiene, edge spaces, style, typography of values, «ё», composed phrases, the length
|
|
207
|
+
of settings sidebar labels and the advertised numbers — and every one of them has already caught
|
|
208
|
+
real defects. Beside them the audit
|
|
209
|
+
prints **advisory reports**,
|
|
210
|
+
which are not gates because they need a human decision: how many namespaces were compared and
|
|
211
|
+
which could not be linked, whether any «number + inflecting word» is left, and whether a short
|
|
212
|
+
string grew past 2.8× its English (a layout risk — «Effort» → «Уровень рассуждения» is normal
|
|
213
|
+
Russian length, not a defect).
|
|
214
|
+
|
|
215
|
+
The audit reads harness templates in the shape the harness writes them: a literal, an **array of
|
|
216
|
+
paragraphs** (that is how the preset guides are stored) and a **reference to a constant**
|
|
217
|
+
(`'hint.plan': PLAN_NEXT_ACTION_EN`). While only the first shape was read, ten keys — eight of
|
|
218
|
+
them whole guide documents — silently fell out of every comparison. And the other way round: an
|
|
219
|
+
empty policy file (`keep-english.json`, a `terminology.json` section) now fails the audit instead
|
|
220
|
+
of widening a gate unnoticed. The numbers the READMEs advertise are checked against the pack the
|
|
221
|
+
same way, because a stale count is simply a wrong claim — and the same numbers are read from the
|
|
222
|
+
`package.json` description, which is what npm shows in search and on the package page (that is
|
|
223
|
+
where «55 namespaces» lived longest) — including the grouped spelling: the
|
|
224
|
+
old leads said `2 489`, and the gate only read the ungrouped form, so the pattern now accepts
|
|
225
|
+
thousands separators. The sentence naming the harness version the pack was built against is
|
|
226
|
+
checked next to it, against the tag the workflow pins, because that workflow is what verifies
|
|
227
|
+
the pack (both leads claimed `0.2.1-alpha.2` while CI had already moved to
|
|
228
|
+
`dsh-v0.2.1-rc.2`). The published size is measured there too: `npm run check:size` packs the
|
|
229
|
+
archive and compares the advertised kilobytes with the real ones, allowing one kilobyte of slack
|
|
230
|
+
because gzip compresses slightly differently across Node builds while the sentence rounds to
|
|
231
|
+
whole kilobytes.
|
|
232
|
+
|
|
233
|
+
- **dead namespaces** — every namespace the package registers has to
|
|
234
|
+
exist in the harness. In 0.1.6 the schedule catalog translations were registered
|
|
235
|
+
under the name `schedule.manager`, whereas `schedule.catalog` is what reads them: the per-key
|
|
236
|
+
coverage check nonetheless reported «всё переведено»;
|
|
237
|
+
- **plural-form pairs** — the `.one`/`.other` sets have to match, because the client
|
|
238
|
+
chooses the form as `count === 1 ? '.one' : '.other'`. That is not enough for Russian:
|
|
239
|
+
every pair also needs `.few` and `.many`, or the wrapper quietly falls back to the neutral
|
|
240
|
+
`.other` and shows «2 д» where «2 дня» was possible. The check runs **per namespace** —
|
|
241
|
+
the wrapper looks the form up in the namespace that asked, so a pair missing on one screen
|
|
242
|
+
while present on another would otherwise stay invisible. It found the four time units
|
|
243
|
+
(`unit.day/hour/minute/second` in `schedule.catalog`) and `trigger` in the task manager;
|
|
244
|
+
the units stopped being abbreviations («д», «ч», «мин») and gained full forms in the right
|
|
245
|
+
case — «через 2 дня», «через 5 часов», and «Каждые 2 дня» became «Раз в 2 дня». The same
|
|
246
|
+
requirement covers the keys the pack added itself (`terminal.expand` and its kin: the
|
|
247
|
+
harness passes them a count but never pairs them) — their forms rest on us alone, and
|
|
248
|
+
losing one would be invisible to everything else;
|
|
249
|
+
- **placeholders** — a Russian value has to carry exactly the `{name}` placeholders its
|
|
250
|
+
English template carries: an extra one reaches the screen literally
|
|
251
|
+
(`Заняло {duration}7мин 26с`, fixed in #2), a dropped one silently removes the
|
|
252
|
+
interpolated value. Packages that ship only the Chinese dictionary are compared
|
|
253
|
+
against `zh`. Our **own plural forms** — the `.few`/`.many` we add, and the `.one` of a key
|
|
254
|
+
the harness never paired — do not exist upstream, so each is compared with the template of
|
|
255
|
+
a sibling form of the same word (`.one`/`.other`) or of the key itself. Without that, 52
|
|
256
|
+
values were never checked at all: that is exactly how a `{count}` can disappear from a form
|
|
257
|
+
and leave the sentence without its number.
|
|
258
|
+
- **residue** — a value has to be Russian: an exact copy of the English template, a leftover
|
|
259
|
+
Chinese character, or an empty string where the template has text is a defect. English
|
|
260
|
+
copies are allowed only by a decision recorded in `scripts/keep-english.json` (addresses,
|
|
261
|
+
format-only strings, protocol and tool names, abbreviations), so a new untranslated line
|
|
262
|
+
cannot slip through unnoticed. The decisions themselves are checked too: an entry that no
|
|
263
|
+
longer excuses anything fails the build — either its key left the pack, or the value was
|
|
264
|
+
translated and the decision went stale. This is how the `deepSeekBaseUrl` entry was found:
|
|
265
|
+
the English template gained a note about `DEEPSEEK_BASE_URL`, while the input placeholder
|
|
266
|
+
has to be a bare example URL, so that note would have been noise inside the field. The entry
|
|
267
|
+
is gone, the value stays. A decision may also name a closed list: `chat · app.*` allows
|
|
268
|
+
thirty application names in one line, because a dictionary of application names is a list of
|
|
269
|
+
names. And a value with no word outside its placeholders (`{from}–{to}`, `{percent}%`, `, `)
|
|
270
|
+
needs no decision at all: there is nothing in it to translate, so the policy stays about
|
|
271
|
+
words rather than about punctuation. The residue rule reads **every** template of a key, not
|
|
272
|
+
only the `en` block: 60 values in dictionaries with an unrecognised block used to go
|
|
273
|
+
unexamined, while now 2911 values are compared, 68 of them covered by decisions (38 entries,
|
|
274
|
+
one of them a pattern), and the zone is gone as a class. The rule did not become wider:
|
|
275
|
+
an empty value is a defect only where no template is empty either, since Russian justly
|
|
276
|
+
drops the prefix that English drops too (`message.stepProcess.sharedPrefix`).
|
|
277
|
+
- **dead keys** — a key no harness dictionary defines and no harness source names is a
|
|
278
|
+
leftover from an older version: it shows nothing and only misleads. Such keys fail the
|
|
279
|
+
build. A key a component still asks for stays in the advisory report, because the pack's
|
|
280
|
+
value is what reaches the screen.
|
|
281
|
+
- **terminology** — one concept, one rendering. Forbidden variants («кеш» for «кэш», «сеанс»
|
|
282
|
+
for «сессия», «этап» for «шаг») fail the build, and `scripts/terminology.json` keeps both
|
|
283
|
+
the decision and counts of the chosen forms, so drift shows up before it becomes a defect.
|
|
284
|
+
The check immediately found `confirm.description` translated two ways in two namespaces —
|
|
285
|
+
«шаги» and «этапы». One word may not be spelled both with and without «ё»: «ещё» next to
|
|
286
|
+
«еще» reads as machine translation, so the check folds «ё» to «е» and fails on two spellings
|
|
287
|
+
of one folded form. Real distinct pairs such as «все» and «всё» are declared in
|
|
288
|
+
`scripts/yo-pairs.json`, and a declaration whose spellings left the pack fails as well. The
|
|
289
|
+
same report covers Latin words inside Russian phrases: a product,
|
|
290
|
+
command or code token is allowed, an ordinary English word in a sentence is not. A product name
|
|
291
|
+
has to be spelled the way the harness spells it: «Github Desktop» for «GitHub Desktop» reads as a
|
|
292
|
+
typo in the product's own name, and the pack is the only place it can appear. The reference is
|
|
293
|
+
the English templates; a word the harness writes only in lowercase («cursor», «desktop») does not
|
|
294
|
+
count, because there a capital is exactly the product name. Next to it
|
|
295
|
+
comes mechanical hygiene: double spaces, a space before punctuation, unpaired «ёлочки» and
|
|
296
|
+
brackets, a non-breaking space inside a value, and edge spaces — a value that starts or ends
|
|
297
|
+
with one is glued to a neighbour by the component, so it has to match the English template
|
|
298
|
+
of its own namespace. The same template checks style: a terminator the English carries must
|
|
299
|
+
not disappear (this is how `registryCustomHint` was found without its period), and the case
|
|
300
|
+
of the first letter has to match — except for acronyms like `JSON` and templates that open
|
|
301
|
+
with a placeholder. The address to the reader is checked on its own: inside a sentence the
|
|
302
|
+
Russian interface writes «вы» lowercase, and «Вы» with a capital letter only at the start of
|
|
303
|
+
a sentence, where it is nothing but spelling. Finally the pack is compared with itself: one
|
|
304
|
+
English sentence has to come back as one Russian sentence. When two namespaces render it
|
|
305
|
+
differently — templates of four words or more are compared, because a short label legitimately
|
|
306
|
+
follows its context — the build fails. This is how `confirm.description` was found: one
|
|
307
|
+
rendering promised to «пропускать шаги подтверждения», the other to «уменьшать число шагов»,
|
|
308
|
+
and the English «subsequent tasks» had become «текущей задаче» in the second. A deliberate
|
|
309
|
+
divergence is declared in `scripts/one-rendering.json` with its reason, and an exception that
|
|
310
|
+
no longer matches anything fails as well — otherwise the list of decisions would quietly widen
|
|
311
|
+
the check. The opposite direction is printed as an advisory: the same Russian answer to
|
|
312
|
+
**different** English sentences of four words or more hints at a copy-paste — a hint carried
|
|
313
|
+
over from a neighbouring key, or two distinct facts collapsed into one phrase. It cannot be a
|
|
314
|
+
gate, because Russian legitimately merges words English keeps apart, so both sides are printed
|
|
315
|
+
together and a human decides.
|
|
316
|
+
|
|
317
|
+
A separate workflow watches the tag itself: `watch-upstream` compares the pinned tag with
|
|
318
|
+
the harness tags once a week, opens an issue with the steps when a newer one exists, and turns
|
|
319
|
+
the run red — so lagging behind is found on a schedule rather than in a user's screenshot. The
|
|
320
|
+
version comparison is checked without the network (`npm run check:upstream`: prerelease order,
|
|
321
|
+
equal versions, a move between lines) and is
|
|
322
|
+
part of `verify`: a release has to outrank its own prereleases, or the watch would fire forever.
|
|
323
|
+
|
|
324
|
+
The coverage number is not a gate: some sections are deliberately left in English. Next to it
|
|
325
|
+
the audit prints a **per-namespace** report: it rebuilds the namespace-to-dictionary link from
|
|
326
|
+
whoever registers it (`NS`, or a literal in `locale.register`; `bind` and `PropsLocale` only read
|
|
327
|
+
a namespace) and lists keys missing from both their own namespace and the shared `common`
|
|
328
|
+
dictionary the runtime falls back to. A global name comparison cannot see those holes: a
|
|
329
|
+
translation filed under another namespace counts as coverage while the screen shows English.
|
|
330
|
+
The report is advisory — the same key name can mean different things in different namespaces
|
|
331
|
+
(`list.aria` is "Active reminders" in the catalog and "Background jobs" in jobs), so a
|
|
332
|
+
translation is copied across namespaces only where one dictionary serves both. On the pinned
|
|
333
|
+
tag the report is empty: every string the harness renders in a namespace we register lives in
|
|
334
|
+
that namespace. All 56 of the pack's namespaces are compared — the link comes both from a
|
|
335
|
+
dictionary imported beside the registration and from the names that registration passes
|
|
336
|
+
(`locale.register(NS, { zh, en })`); without the second rule `common` and `settings.locale`,
|
|
337
|
+
whose dictionaries sit in a neighbouring directory, would stay uncovered. The other direction is
|
|
338
|
+
a failure rather than a report: a namespace the harness registers and fills with keys, which the
|
|
339
|
+
pack never registers, leaves that screen in English while key coverage still looks complete.
|
|
340
|
+
This is how `settings.sessionLog` was found — the “Upload Session Log” switch on the general
|
|
341
|
+
settings page.
|
|
342
|
+
|
|
343
|
+
## Coverage scope: the official interface only
|
|
344
|
+
|
|
345
|
+
The package translates **the harness client's own namespaces** — 77 namespaces, reconciled against
|
|
346
|
+
the pinned tag. Third-party plugin dictionaries are deliberately out of scope, and here is
|
|
347
|
+
why.
|
|
348
|
+
|
|
349
|
+
We checked the 17 most-downloaded plugins in the ecosystem (npm, `keywords:dsh-plugin`,
|
|
350
|
+
monthly downloads) and looked at which of them ship strings of their own at all:
|
|
351
|
+
|
|
352
|
+
| What we found | Plugins |
|
|
353
|
+
|---|---|
|
|
354
|
+
| **No strings of their own** — the interface takes its text from harness namespaces | **11 of 17** |
|
|
355
|
+
| A large dictionary of their own (confirmed by hand) | 2 — `dshmarket` (~1262 keys), `@nanmicoder/dsh-agent-teams` (420) |
|
|
356
|
+
| `.d.ts` types only, no strings | 1 — `dsh-plugin-model-proxy` |
|
|
357
|
+
| Needs a separate check | 3 |
|
|
358
|
+
|
|
359
|
+
The practical consequence: for **11 of the 17** most popular plugins the Russian interface
|
|
360
|
+
already works — their text lives in the shared harness namespaces, which the package translates
|
|
361
|
+
in full. A separate dictionary is needed only where a plugin carries strings of its own, and such
|
|
362
|
+
a dictionary is a commitment to track someone else's releases: `dshmarket` is already at version 1.66.3,
|
|
363
|
+
and its keys change independently of the harness.
|
|
364
|
+
|
|
365
|
+
That is why there is one package and one commitment here: **the official interface, translated and
|
|
366
|
+
verified**, with no race after other people's dictionaries. Need a specific plugin? Open an issue:
|
|
367
|
+
a dictionary for it is possible as a separate layer pinned to a version, rather than as a silent
|
|
368
|
+
promise that «покрыто всё».
|
|
369
|
+
|
|
370
|
+
## Development
|
|
371
|
+
|
|
372
|
+
```sh
|
|
373
|
+
pnpm install
|
|
374
|
+
pnpm run build # tsdown -> lib/index.js (node half) + lib/client.js (client bundle)
|
|
375
|
+
npm pack # -> ragnoryok1-dsh-client-locale-ru-<version>.tgz
|
|
376
|
+
```
|
|
377
|
+
|
|
378
|
+
`lib/client.js` is built in the format the `dsh` client loader understands (`__ModuleLoader__.load`) and exports `inject`/`apply`.
|
|
379
|
+
|
|
380
|
+
## Releases
|
|
381
|
+
|
|
382
|
+
Publishing to npm is done by the `publish` workflow on a tag — the credentials live in a repository
|
|
383
|
+
secret (`NPM_TOKEN`), so the token never has to be typed into a terminal or passed around.
|
|
384
|
+
Publishing by hand from a machine is possible, but unnecessary.
|
|
385
|
+
|
|
386
|
+
```
|
|
387
|
+
npm version 0.3.0 --no-git-tag-version # поднять версию в package.json
|
|
388
|
+
# …и синхронно обновить версию в блоке deepseek-harness-meta в этом README
|
|
389
|
+
git commit -am "release: 0.3.0" && git tag v0.3.0 && git push origin v0.3.0
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
Before publishing, the workflow checks:
|
|
393
|
+
|
|
394
|
+
1. the version in the tag matches the version in `package.json`;
|
|
395
|
+
2. the version in the `deepseek-harness-meta` block matches `package.json` — the marketplace takes it from there,
|
|
396
|
+
and reads it **only on first indexing**, so a mismatch does not fix itself;
|
|
397
|
+
3. the typography (18 rules);
|
|
398
|
+
4. the localization audit against the pinned harness tag — dead namespaces, duplicates and plural-form
|
|
399
|
+
pairs will fail and stop the publication;
|
|
400
|
+
5. **compatibility with every version in `compatible_versions`**: each one's locale runtime is
|
|
401
|
+
downloaded from npm and three suites — language coexistence, plural forms and composed phrases
|
|
402
|
+
— run against it (`npm run check:compat`, part of CI), so the promise in the meta block is
|
|
403
|
+
checked rather than assumed.
|
|
404
|
+
|
|
405
|
+
The declaration itself is checked separately (`npm run check:peers`, part of `verify`): the harness
|
|
406
|
+
reads our `peerDependencies` for `@deepseek-ai/dsh*` not as package versions but as a range of
|
|
407
|
+
**runtime versions**, with `includePrerelease`, and a range that fails to satisfy the running dsh
|
|
408
|
+
makes the user see an incompatibility warning and an exemption prompt. The script runs that rule
|
|
409
|
+
over every claimed version — all eight pass today.
|
|
410
|
+
|
|
411
|
+
To check all the same things locally, without publishing:
|
|
412
|
+
|
|
413
|
+
```
|
|
414
|
+
npm run verify -- путь/к/дереву/харнесса
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
The workflow also has a manual run with a «только проверки, без публикации» toggle
|
|
418
|
+
(`workflow_dispatch` → `dry-run`).
|
|
419
|
+
|
|
420
|
+
## Contents
|
|
421
|
+
|
|
422
|
+
- `src/client/dicts.ts` — the Russian dictionaries (77 namespaces, 4495 translations, ~3000 lines). This is where the main value lies.
|
|
423
|
+
- `src/client/index.ts` — the client plugin entry point (registration of `ru` + the dictionaries).
|
|
424
|
+
- `src/index.ts` — the empty host half (`apply()`).
|
|
425
|
+
- `cordis.patch.yml` — the profile patch (`- insert:` of the client entry `locale-ru`).
|
|
426
|
+
|
|
427
|
+
## What is translated
|
|
428
|
+
|
|
429
|
+
The current set follows the harness tags: the keys were taken from the matching commit, and keys
|
|
430
|
+
added later fall back to `en` on lookup, so the package does not break the interface on newer versions.
|
|
431
|
+
|
|
432
|
+
### 0.1.7 — dead namespace fixed, task manager translated, plural forms rewritten
|
|
433
|
+
|
|
434
|
+
The headline item in the release is **a fix for a mistake from 0.1.6**. At the time it was recorded
|
|
435
|
+
that the namespace `schedule.catalog` had been retired and that `schedule.manager` had taken its place.
|
|
436
|
+
In reality **both** namespaces live in the harness, separately: `schedule.catalog` is the reminder
|
|
437
|
+
catalog in the session header with frequencies and units, `schedule.manager` is the new automation-task
|
|
438
|
+
manager. Because of that wrong conclusion, ~30 translation strings (reminders, frequency, time
|
|
439
|
+
units) were registered under a name nobody reads and were **never shown** in the interface. The
|
|
440
|
+
catalog is now registered as `schedule.catalog`.
|
|
441
|
+
|
|
442
|
+
- **fixed:** the schedule catalog translations are visible again — `trigger.*`, `list.*`,
|
|
443
|
+
`delete.*`, `frequency.*`, `cron.*`, `unit.*`, `relative.*`, `mark.aria`, `hover.more`;
|
|
444
|
+
- **`schedule.manager` added** (188 keys) — the automation-task manager entirely in
|
|
445
|
+
Russian: the task panel and catalog, search, status filter, task details and its tabs,
|
|
446
|
+
the **run log** with retention rules, the schedule editor (date, time, hour, minute,
|
|
447
|
+
second, time zone, repeat interval), repeat rules (once, every N minutes/hours/
|
|
448
|
+
seconds, daily, Mon–Fri, weekly, custom cron), the cron form with date and minute
|
|
449
|
+
pickers, deletion with confirmation, notifications and cards;
|
|
450
|
+
- **plural forms rewritten** (17 key pairs): forms that broke on the numbers 2–4
|
|
451
|
+
were replaced with ones that are correct for any `n ≥ 2` — for example «2 субагентов» → «Субагентов: 2»,
|
|
452
|
+
«каждые 2 часов» → «каждые 2 ч». Another 8 strings with `{count}` before an inflected word
|
|
453
|
+
were switched to abbreviations: «ещё 3 строк» → «ещё 3 стр.»;
|
|
454
|
+
- **7 missing keys added**: `blocked.composer`,
|
|
455
|
+
`defaultWorkspace.title`, `schedule.active`, `settings.transcript.expanded`,
|
|
456
|
+
`status.scheduled`, `status.overdue` and the namespace `shortcuts.layout` (the label for
|
|
457
|
+
the command that shows the left panel);
|
|
458
|
+
- **a new check in the project:** a namespace-name audit. The previous coverage check
|
|
459
|
+
compared keys inside a namespace but never compared the names themselves, so an entire
|
|
460
|
+
namespace could be registered under a non-existent name and quietly do nothing. Names
|
|
461
|
+
are now extracted from every way they can be declared (`const NS`/`SETTINGS_NS`/`namespace`,
|
|
462
|
+
`locale.register`, `locale.bind`, `PropsLocale<…>`) and compared as sets.
|
|
463
|
+
|
|
464
|
+
0.1.2 added sections that 0.1.1 did not have: `open-in-app` («Открыть в
|
|
465
|
+
приложении»), `sidebarFiles`, `sidebarRight` (the right sidebar with files) and
|
|
466
|
+
`sidebarCodePreview` (code preview). It also updated the keys that changed in
|
|
467
|
+
harness 0.1.5 and removed 21 keys that no longer exist there.
|
|
468
|
+
|
|
469
|
+
In 0.1.3 the package caught up with harness 0.1.6-alpha.1: 139 keys and 7 new
|
|
470
|
+
sections were added — `sidebarTerminal` (the terminal in the right sidebar), `settings.archivedSessions`
|
|
471
|
+
(archived sessions) and the document-preview family (`sidebarDocumentPreview`,
|
|
472
|
+
`documentHtml`, `sidebarImage`, `documentMarkdown`, `sidebarPdf`). Besides that, the experimental
|
|
473
|
+
«Автопроверка» was translated (`permission.access`: `auto.*`), along with the command-palette
|
|
474
|
+
labels and tokens, the endpoint fields in the model settings, and the
|
|
475
|
+
changes in `conversation`, `trajectory`, `chat`, `session-log-download`.
|
|
476
|
+
28 keys that had disappeared from the harness were removed.
|
|
477
|
+
|
|
478
|
+
The coverage check runs against the harness sources: for each namespace the
|
|
479
|
+
key sets are compared, so the next release starts from an exact
|
|
480
|
+
“add / check / remove” list.
|
|
481
|
+
|
|
482
|
+
In 0.1.6 the package caught up with harness **0.1.7-rc.2**: **252 keys** added, 18 updated,
|
|
483
|
+
26 removed, and two new namespaces added. The changes:
|
|
484
|
+
|
|
485
|
+
- **`shortcuts`** (new namespace, 56 keys) — the hotkey editor: recording
|
|
486
|
+
a combination, conflicts, reserved combinations, hints for macOS and
|
|
487
|
+
Windows, restoring the default values;
|
|
488
|
+
- **`schedule.manager`** (70 keys at the time) — the automation-task manager: list,
|
|
489
|
+
deletion, repeat, run history, Cron expressions. **It was wrongly recorded that
|
|
490
|
+
the namespace `schedule.catalog` had been retired by this; 0.1.7 fixed that — both
|
|
491
|
+
namespaces exist side by side**;
|
|
492
|
+
- **`settings.account`** (50 keys) — the app's first launch: the welcome,
|
|
493
|
+
the choice of purpose and of how much of the work is shown, topping up the balance, signing out of
|
|
494
|
+
the account while tasks are running;
|
|
495
|
+
- added the labels for adding and removing tools on the fly
|
|
496
|
+
(`message.tools*`, `trajectory.layout.*`), the right sidebar commands
|
|
497
|
+
(`sidebarRight`), the «сначала выберите сессию» states in the panels, and updated
|
|
498
|
+
the name of the settings section: «Инструменты для кода» instead of «Инструментов
|
|
499
|
+
разработчика»;
|
|
500
|
+
- 18 keys updated to match the changed English text, 26 removed. A single term,
|
|
501
|
+
«рабочая папка», instead of «рабочей области» in one place.
|
|
502
|
+
|
|
503
|
+
In 0.1.5 the package caught up with harness **0.1.7-rc.1**: **49 keys** added, 13 updated,
|
|
504
|
+
16 removed, and the namespace `directory-browser` dropped (it is gone in rc.1). There appeared
|
|
505
|
+
the labels for the steps tools go through (`message.stepProcess.prepare.*` and `done.*` —
|
|
506
|
+
reading images, writing files, preparing for code search, web search,
|
|
507
|
+
subagent coordination and others), full-screen image viewing
|
|
508
|
+
(`image.*`), the «Стандартный» and «Подробный» modes for showing the work, installing plugins
|
|
509
|
+
from GitHub with a timeout and a Chinese mirror, the warning about an incompatible
|
|
510
|
+
plugin version, the choice of model download source for voice input, and `Cordis` command
|
|
511
|
+
messages. The wording was tightened where upstream replaced “teammate/agent”
|
|
512
|
+
with “subagent” and “Beta” with “Experimental”.
|
|
513
|
+
|
|
514
|
+
0.1.5 also fixed the counting unit in the plugin inventory: it was «187 плагины»,
|
|
515
|
+
now it is «187 плагинов». The built-in interface screenshots were translated too, npm
|
|
516
|
+
keywords were added, and the peer range of `@deepseek-ai/dsh-client-locale`
|
|
517
|
+
(`>=0.1.0-rc.2 <0.2.0`) was fixed — previously `^0.1.0` did not resolve, because the package
|
|
518
|
+
is published only under prerelease versions.
|
|
519
|
+
|
|
520
|
+
In 0.1.4 the package caught up with harness **0.1.7-alpha.2** — the biggest jump:
|
|
521
|
+
**905 keys** added, 29 changed, 126 removed. New sections:
|
|
522
|
+
|
|
523
|
+
- **`pluginManager`** — the built-in plugin panel: installation, removal,
|
|
524
|
+
enabling and disabling components, versions, registries and install hints;
|
|
525
|
+
- **`settings.account`** — the DeepSeek account: sign-in, balance, spend,
|
|
526
|
+
API key;
|
|
527
|
+
- the separate settings sections the former `settings.plugins` split into:
|
|
528
|
+
**`settings.agentLoop`**, **`settings.shell`**, **`settings.subagent`**,
|
|
529
|
+
**`settings.webSearch`**;
|
|
530
|
+
- **`sidebarBrowser`** — the built-in browser in the right panel (address, sandbox,
|
|
531
|
+
restoring the page);
|
|
532
|
+
- **`sidebarExcel`** and **`sidebarOffice`** — preview of Office spreadsheets and
|
|
533
|
+
documents; zooming (`zoom.*`) was added to PDFs and images;
|
|
534
|
+
- **`voice-input`** — experimental voice input.
|
|
535
|
+
|
|
536
|
+
Also translated were the new texts in `conversation` (+194), `chat` (+53),
|
|
537
|
+
`workspace` (+43: session archive, pinning), `deliverables` (+31: the review of
|
|
538
|
+
work changes), `job` (+24: live output of background tasks), `settings` (+22:
|
|
539
|
+
desktop app update), `plan`, `open-in-app`, `trajectory`,
|
|
540
|
+
`model`, `reference`, `session-log-download`, and in the agent-mode
|
|
541
|
+
guides (`settings.agentPreset`, 12 long texts). The section
|
|
542
|
+
`settings.archivedSessions` was removed: in 0.1.7 upstream dropped that package, and the session
|
|
543
|
+
archive moved to `workspace`.
|
|
544
|
+
|
|
545
|
+
## License
|
|
546
|
+
|
|
547
|
+
MIT
|
|
548
|
+
|
|
549
|
+
## Changelog
|
|
550
|
+
|
|
551
|
+
[CHANGELOG.md](CHANGELOG.md) — what was in each release.
|