@ragnoryok1/dsh-client-locale-ru 0.1.7 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +69 -3
- package/README.md +98 -9
- package/assets/banner.png +0 -0
- package/assets/icon.png +0 -0
- package/images/plugins-ru.png +0 -0
- package/images/settings-ru.png +0 -0
- package/lib/client.js +213 -4
- package/lib/client.js.map +1 -1
- package/lib/typography.js +89 -0
- package/package.json +13 -4
package/CHANGELOG.md
CHANGED
|
@@ -3,8 +3,74 @@
|
|
|
3
3
|
Все значимые изменения пакета. Формат основан на [Keep a Changelog](https://keepachangelog.com/ru/1.1.0/),
|
|
4
4
|
версии — по [SemVer](https://semver.org/lang/ru/).
|
|
5
5
|
|
|
6
|
-
Пакет следует за харнессом: целевая версия — `dsh 0.1
|
|
7
|
-
(`>=0.1.0-rc.2 <0.
|
|
6
|
+
Пакет следует за харнессом: целевая версия — `dsh 0.2.1-alpha.1` и новее
|
|
7
|
+
(`>=0.1.0-rc.2 <0.3.0` для `@deepseek-ai/dsh-client-locale`).
|
|
8
|
+
|
|
9
|
+
## [0.2.0] — 2026-10-03
|
|
10
|
+
|
|
11
|
+
### Добавлено
|
|
12
|
+
|
|
13
|
+
- **Синхронизация с `dsh 0.2.1-alpha.1`**: 76 новых ключей — пять новых namespace
|
|
14
|
+
(`settings.agentPreset`, `settings.account`, `inspectorPanel`, `claude-code-mods`,
|
|
15
|
+
`session-inspector`) и три расширенных (`pluginManager` +8, `workspace` +2,
|
|
16
|
+
`schedule.manager` +1). Покрытие — **2364 из 2364** ключей новой базы.
|
|
17
|
+
- Переведены панель инспектора сессий (52 строки), установка плагинов из npm/Git/каталога,
|
|
18
|
+
режим создания плагина агентом и напоминание о том, что сессия субагента не получает
|
|
19
|
+
доставленные уведомления.
|
|
20
|
+
|
|
21
|
+
### Исправлено
|
|
22
|
+
|
|
23
|
+
- **Три имени namespace сверены с кодом харнесса**: предположения по документации
|
|
24
|
+
(`agent-preset`, `account`, `inspector`) оказались неверными — настоящие имена
|
|
25
|
+
`settings.agentPreset`, `settings.account` и `inspectorPanel`. Переводы под
|
|
26
|
+
неверными именами не показывались бы никогда.
|
|
27
|
+
- **Аудит получил новый гейт**: namespace, объявленный дважды, перекрывает сам себя в
|
|
28
|
+
объектном литерале и молча роняет все переводы внутри, при этом покрытие по ключам
|
|
29
|
+
остаётся полным. Проверено: с дублем аудит падает с кодом 1.
|
|
30
|
+
|
|
31
|
+
### Изменено
|
|
32
|
+
|
|
33
|
+
- Версия пакета поднята до **0.2.0** — пакет следует за веткой харнесса 0.2.x.
|
|
34
|
+
- Аудит в CI переведён на тег `dsh-v0.2.1-alpha.1`.
|
|
35
|
+
|
|
36
|
+
## [0.1.9] — 2026-10-02
|
|
37
|
+
|
|
38
|
+
### Добавлено
|
|
39
|
+
|
|
40
|
+
- **Синхронизация с `dsh 0.2.0-rc.2`**: 37 новых ключей в шести namespace — `chat`
|
|
41
|
+
(единицы длительности и строка «Углублённый анализ»), `conversation` (вопросы,
|
|
42
|
+
ожидающие ответа), `model` (пустой поиск), `pluginManager` (подсказки установки,
|
|
43
|
+
несовместимость версий, порядок обновления), `question` (асинхронные вопросы:
|
|
44
|
+
ожидание, ответы, пропуск) и `workspace` (сессии без названия).
|
|
45
|
+
Покрытие — **2287 из 2287** ключей новой базы.
|
|
46
|
+
- **Расширен диапазон совместимости** до `>=0.1.0-rc.2 <0.3.0`: контракт локали
|
|
47
|
+
(`addLanguage` и `register`) в 0.2.0 не изменился, проверено по дереву тега.
|
|
48
|
+
|
|
49
|
+
### Изменено
|
|
50
|
+
|
|
51
|
+
- Аудит в CI переведён на тег `dsh-v0.2.0-rc.2`; проверка против 0.1.7-rc.2
|
|
52
|
+
по-прежнему проходит (2264 из 2264), поэтому пакет работает на обеих ветках.
|
|
53
|
+
|
|
54
|
+
## [0.1.8] — 2026-09-27
|
|
55
|
+
|
|
56
|
+
### Добавлено
|
|
57
|
+
|
|
58
|
+
- **Русская экранная типографика** (`src/client/typography.ts`): «ёлочки» вместо прямых
|
|
59
|
+
кавычек, длинное тире между словами, многоточие, неразрывный пробел между числом и
|
|
60
|
+
следующим словом или единицей измерения. Правила осторожные: код, поля ввода,
|
|
61
|
+
редактируемый текст и `[data-typography="off"]` не трогаются, повторный проход ничего не
|
|
62
|
+
меняет. Работает как `ctx.effect`, поэтому выгружается вместе с плагином.
|
|
63
|
+
- **Проверки в CI** (`.github/workflows/verify.yml`): сборка, 12 правил типографики
|
|
64
|
+
(`scripts/check-typography.mjs`) и аудит локали (`scripts/audit.mjs`) против
|
|
65
|
+
**закреплённого тега** харнеса. Новые npm-скрипты: `check:typography`, `audit`, `verify`.
|
|
66
|
+
- Раздел README **«Область покрытия»** с измерением: из 17 самых скачиваемых плагинов
|
|
67
|
+
экосистемы 11 не поставляют собственных строк, поэтому их русский интерфейс обеспечивают
|
|
68
|
+
словари харнеса; словари сторонних плагинов в область пакета не входят.
|
|
69
|
+
|
|
70
|
+
### Исправлено
|
|
71
|
+
|
|
72
|
+
- **Число переводов в документации**: 2598 → **2304**. Прежняя цифра считала повторяющиеся
|
|
73
|
+
имена ключей в разных namespace дважды.
|
|
8
74
|
|
|
9
75
|
## [0.1.7] — 2026-09-27
|
|
10
76
|
|
|
@@ -48,7 +114,7 @@
|
|
|
48
114
|
|
|
49
115
|
### Состояние
|
|
50
116
|
|
|
51
|
-
52 namespace,
|
|
117
|
+
52 namespace, 2304 перевода, ~2700 строк. Проверки: 0 отсутствующих ключей против
|
|
52
118
|
`dsh 0.1.7-rc.2`, 0 мёртвых namespace, 45/45 пар ключей с формами числа.
|
|
53
119
|
|
|
54
120
|
## [0.1.6] — 2026-09-25
|
package/README.md
CHANGED
|
@@ -1,30 +1,57 @@
|
|
|
1
|
+
<!-- deepseek-harness-meta
|
|
2
|
+
{
|
|
3
|
+
"name": "Russian (ru) language pack for DeepSeek Harness",
|
|
4
|
+
"version": "0.2.0",
|
|
5
|
+
"tags": ["localization", "russian", "i18n", "web-gui", "language-pack"],
|
|
6
|
+
"description": "Full Russian interface for the DeepSeek Harness web GUI: 53 namespaces, 2418 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-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
|
+
|
|
1
14
|
# @ragnoryok1/dsh-client-locale-ru
|
|
2
15
|
|
|
16
|
+

|
|
17
|
+
|
|
3
18
|
[](https://www.npmjs.com/package/@ragnoryok1/dsh-client-locale-ru)
|
|
4
19
|
[](LICENSE)
|
|
5
|
-
[](https://github.com/Ragnoryok1/dsh-client-locale-ru/actions/workflows/verify.yml)
|
|
21
|
+
[](https://github.com/deepseek-ai/deepseek-harness)
|
|
22
|
+
[](https://github.com/Ragnoryok1/dsh-client-locale-ru)
|
|
23
|
+
[](https://github.com/Ragnoryok1/dsh-client-locale-ru)
|
|
24
|
+
|
|
25
|
+
**In English.** 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 — 52 namespaces, 2,341 strings, built against dsh `0.2.0-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. Details below are in Russian.
|
|
8
26
|
|
|
9
|
-
**
|
|
27
|
+
> **If the pack was useful to you, please star the repository.** It is the only signal that a
|
|
28
|
+
> translation is wanted, and it is what decides which parts get worked on next.
|
|
10
29
|
|
|
11
30
|
---
|
|
12
31
|
|
|
13
32
|
## Как это выглядит
|
|
14
33
|
|
|
15
|
-
Русский в списке языков и переведённые разделы настроек (снимки сделаны в
|
|
34
|
+
Русский в списке языков и переведённые разделы настроек (снимки сделаны в сборке `0.1.8`):
|
|
16
35
|
|
|
17
36
|

|
|
18
37
|
|
|
19
|
-

|
|
20
39
|
|
|
21
|
-
|
|
22
|
-
|
|
40
|
+
Оба снимка обрезаны по левой границе панели: в кадр не попадают названия рабочих
|
|
41
|
+
пространств и сессий.
|
|
23
42
|
|
|
24
43
|
Русская локаль (`ru`) для веб-интерфейса [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness) (`dsh`).
|
|
25
44
|
|
|
26
45
|
Плагин добавляет **русский** как выбираемый язык через контракт языковых пакетов локали: `ctx.locale.addLanguage({ id: 'ru', label: 'Русский', fallback: 'en' })` и по `ru`-словарю на каждый namespace. После выбора **Русский** в Settings → General интерфейс переключается сразу.
|
|
27
46
|
|
|
47
|
+
> **Если пакет вам пригодился — поставьте звезду.** Это единственный способ показать, что
|
|
48
|
+
> перевод нужен, и он реально влияет на то, какие задачи берут в работу. Ни одна кнопка
|
|
49
|
+
> «нравится» в интерфейсе не делает этого.
|
|
50
|
+
>
|
|
51
|
+
> Репозиторий при этом остаётся местом, где видно состояние перевода: [CHANGELOG](CHANGELOG.md)
|
|
52
|
+
> с разбором каждого релиза (включая ошибки, которые находили в нём сами), проверки в CI и
|
|
53
|
+
> перечень того, что сознательно не переводится.
|
|
54
|
+
|
|
28
55
|
## Установка
|
|
29
56
|
|
|
30
57
|
Это **гибридный плагин** (`dsh.bundle` + `dsh.client`), поэтому он ставится как обычный профиль-бандл через `dsh plugin`:
|
|
@@ -54,6 +81,68 @@ dsh plugin --profile web add @ragnoryok1/dsh-client-locale-ru
|
|
|
54
81
|
«ещё 3 стр.»). Ни одна видимая строка не показывает неверную форму числа.
|
|
55
82
|
- **Фолбэк** — отсутствующий русский ключ падает на `en` (настроенный `fallback`).
|
|
56
83
|
|
|
84
|
+
## Типографика
|
|
85
|
+
|
|
86
|
+
Пакет приводит уже отрисованный русский текст к типографским правилам: «ёлочки» вместо
|
|
87
|
+
прямых кавычек, длинное тире вместо дефиса между словами, многоточие вместо трёх точек и
|
|
88
|
+
неразрывный пробел между числом и следующим словом или единицей измерения (чтобы «187
|
|
89
|
+
плагинов» не разрывалось на две строки). Правила намеренно осторожны: срабатывают только
|
|
90
|
+
на однозначных шаблонах, а код, поля ввода, редактируемый текст и элементы с
|
|
91
|
+
`data-typography="off"` не трогаются вообще. Повторный проход ничего не меняет.
|
|
92
|
+
|
|
93
|
+
Правила проверяются скриптом, а не на глаз: `npm run check:typography`.
|
|
94
|
+
|
|
95
|
+
## Проверки
|
|
96
|
+
|
|
97
|
+
```sh
|
|
98
|
+
npm run build # сборка трёх выходов
|
|
99
|
+
npm run check:typography # 12 правил типографики, включая «не трогать»
|
|
100
|
+
npm run audit -- <дерево харнеса> # аудит локали
|
|
101
|
+
npm run verify -- <дерево харнеса> # всё вместе
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
Аудит выполняется в CI (`.github/workflows/verify.yml`) против **закреплённого тега**
|
|
105
|
+
харнеса, а не против случайного локального чекаута. Гейтом проверяются две вещи, и обе
|
|
106
|
+
уже ловили настоящие дефекты:
|
|
107
|
+
|
|
108
|
+
- **мёртвые namespace** — каждый namespace, который регистрирует пакет, обязан
|
|
109
|
+
существовать в харнессе. В 0.1.6 переводы каталога расписания были зарегистрированы
|
|
110
|
+
под именем `schedule.manager`, тогда как читает их `schedule.catalog`: проверка покрытия
|
|
111
|
+
по ключам при этом рапортовала «всё переведено»;
|
|
112
|
+
- **пары форм числа** — множества `.one`/`.other` должны совпадать, потому что клиент
|
|
113
|
+
выбирает форму как `count === 1 ? '.one' : '.other'`.
|
|
114
|
+
|
|
115
|
+
Число покрытия выводится, но не является гейтом: точный список «добавить / удалить»
|
|
116
|
+
требует сравнения ключей **по namespace** (это делает релизная оснастка), а сравнение имён
|
|
117
|
+
ключей глобально отметило бы разделы, которые пакет сознательно оставляет на английском.
|
|
118
|
+
|
|
119
|
+
## Область покрытия: только официальный интерфейс
|
|
120
|
+
|
|
121
|
+
Пакет переводит **собственные namespace клиента харнесса** — 53 namespace, сверенные с
|
|
122
|
+
закреплённым тегом. Словари сторонних плагинов в область сознательно не входят, и вот
|
|
123
|
+
почему.
|
|
124
|
+
|
|
125
|
+
Мы проверили 17 самых скачиваемых плагинов экосистемы (npm, `keywords:dsh-plugin`,
|
|
126
|
+
скачивания за месяц) и посмотрели, какие из них вообще поставляют собственные строки:
|
|
127
|
+
|
|
128
|
+
| Что обнаружено | Плагинов |
|
|
129
|
+
|---|---|
|
|
130
|
+
| **Своих строк нет** — интерфейс берёт текст из namespace харнеса | **11 из 17** |
|
|
131
|
+
| Крупный собственный словарь (подтверждено вручную) | 2 — `dshmarket` (~1262 ключа), `@nanmicoder/dsh-agent-teams` (420) |
|
|
132
|
+
| Только типы `.d.ts`, строк нет | 1 — `dsh-plugin-model-proxy` |
|
|
133
|
+
| Требует отдельной проверки | 3 |
|
|
134
|
+
|
|
135
|
+
Практическое следствие: у **11 из 17** популярнейших плагинов русский интерфейс уже
|
|
136
|
+
работает — их текст лежит в общих namespace харнеса, которые пакет переводит полностью.
|
|
137
|
+
Отдельный словарь нужен только там, где плагин везёт свои строки, а такой словарь — это
|
|
138
|
+
обязательство следить за чужими релизами: у `dshmarket` уже версия 1.66.3, и её ключи
|
|
139
|
+
меняются независимо от харнеса.
|
|
140
|
+
|
|
141
|
+
Поэтому здесь один пакет и одно обязательство: **официальный интерфейс, переведённый и
|
|
142
|
+
проверенный**, без гонки за чужими словарями. Нужен конкретный плагин — заведите issue:
|
|
143
|
+
словарь для него возможен как отдельный слой, привязанный к версии, а не как молчаливое
|
|
144
|
+
обещание «покрыто всё».
|
|
145
|
+
|
|
57
146
|
## Разработка
|
|
58
147
|
|
|
59
148
|
```sh
|
|
@@ -66,7 +155,7 @@ npm pack # -> ragnoryok1-dsh-client-locale-ru-<version>.tgz
|
|
|
66
155
|
|
|
67
156
|
## Содержимое
|
|
68
157
|
|
|
69
|
-
- `src/client/dicts.ts` — русские словари (
|
|
158
|
+
- `src/client/dicts.ts` — русские словари (53 namespace, 2418 перевод, ~2900 строк). Это и есть основная ценность.
|
|
70
159
|
- `src/client/index.ts` — точка входа клиентского плагина (регистрация `ru` + словарей).
|
|
71
160
|
- `src/index.ts` — пустая host-половина (`apply()`).
|
|
72
161
|
- `cordis.patch.yml` — профиль-патч (`- insert:` клиентской строки `locale-ru`).
|
|
Binary file
|
package/assets/icon.png
ADDED
|
Binary file
|
package/images/plugins-ru.png
CHANGED
|
Binary file
|
package/images/settings-ru.png
CHANGED
|
Binary file
|
package/lib/client.js
CHANGED
|
@@ -57,6 +57,12 @@ window.__ModuleLoader__.load({
|
|
|
57
57
|
},
|
|
58
58
|
"settings.locale": { "language.title": "Язык" },
|
|
59
59
|
"settings.agentPreset": {
|
|
60
|
+
"standardUnavailable": "Стандартный режим недоступен. Восстановите его или выберите другой доступный режим.",
|
|
61
|
+
"createPlugin": "Пусть агент создаст плагин",
|
|
62
|
+
"createPluginDescription": "Войдите в режим создания и сделайте свой плагин для DSH",
|
|
63
|
+
"createPluginChecking": "Проверяем, доступен ли режим создания",
|
|
64
|
+
"createPluginUnavailable": "Временно недоступно. Откройте это меню ещё раз, чтобы повторить",
|
|
65
|
+
"createPluginMissing": "Режим создания не входит в эту сборку",
|
|
60
66
|
"seatHint": "Выберите пресет агента для новой задачи",
|
|
61
67
|
"headerHint": "Пресет агента, выбранный при запуске этой задачи",
|
|
62
68
|
"nav": "Пресеты агента",
|
|
@@ -139,6 +145,12 @@ window.__ModuleLoader__.load({
|
|
|
139
145
|
"token.export": "экспорт"
|
|
140
146
|
},
|
|
141
147
|
"conversation": {
|
|
148
|
+
"ask.pending": "продолжено; ответ всё ещё можно дать",
|
|
149
|
+
"ask.pendingDetail": "На эти вопросы всё ещё можно ответить из поля ввода.",
|
|
150
|
+
"ask.reopen": "Ответить",
|
|
151
|
+
"ask.review": "Посмотреть ответы",
|
|
152
|
+
"ask.closed": "завершён",
|
|
153
|
+
"ask.closedDetail": "Вопрос закрыт; результат — в беседе ниже.",
|
|
142
154
|
"hint.plan": "опишите вашу задачу, чтобы составить план",
|
|
143
155
|
"hint.goal": "опишите цель для длительной задачи",
|
|
144
156
|
"hint.goal.active": "цель активна — edit / pause / resume / clear",
|
|
@@ -654,6 +666,7 @@ window.__ModuleLoader__.load({
|
|
|
654
666
|
"toast.recorded": "Спасибо за отзыв"
|
|
655
667
|
},
|
|
656
668
|
"model": {
|
|
669
|
+
"search.empty": "Нет подходящих моделей.",
|
|
657
670
|
"command.description": "Выбор модели для этого диалога",
|
|
658
671
|
"option.loadError": "Не удалось загрузить каталог: {message}",
|
|
659
672
|
"trigger.fallback": "Выбрать модель",
|
|
@@ -1207,6 +1220,21 @@ window.__ModuleLoader__.load({
|
|
|
1207
1220
|
"layout.toolsRemovedCount": "удалено: {count}"
|
|
1208
1221
|
},
|
|
1209
1222
|
"question": {
|
|
1223
|
+
"error.resubmit": "Ответ не успел дойти до продолжения работы; отправьте его ещё раз.",
|
|
1224
|
+
"status.sent": "Ответ отправлен; панель не удалось закрыть.",
|
|
1225
|
+
"wait.takeTime": "Не спешите",
|
|
1226
|
+
"wait.countdown": "Продолжу через {seconds} с",
|
|
1227
|
+
"wait.paused": "Пауза · осталось {seconds} с",
|
|
1228
|
+
"wait.held": "Жду вашего ответа",
|
|
1229
|
+
"wait.continued": "Работа продолжена — ответить ещё можно",
|
|
1230
|
+
"review.status": "Есть ответ",
|
|
1231
|
+
"review.skipped": "Этот вопрос был пропущен.",
|
|
1232
|
+
"reply.label": "Ответить на прежние вопросы",
|
|
1233
|
+
"reply.open": "Показать подробности вопроса",
|
|
1234
|
+
"reply.close": "Скрыть подробности вопроса",
|
|
1235
|
+
"reply.answerLabel": "Ответ: ",
|
|
1236
|
+
"reply.skipped": "Пропущен",
|
|
1237
|
+
"nav.close": "Закрыть панель — открыть снова можно из вызова инструмента",
|
|
1210
1238
|
"error.incomplete": "Сначала завершите этот вопрос.",
|
|
1211
1239
|
"error.unanswered": "Выберите вариант или введите свой ответ.",
|
|
1212
1240
|
"nav.prev": "Предыдущий вопрос",
|
|
@@ -1244,6 +1272,9 @@ window.__ModuleLoader__.load({
|
|
|
1244
1272
|
"status.interrupted": "Прервано"
|
|
1245
1273
|
},
|
|
1246
1274
|
"workspace": {
|
|
1275
|
+
"session.untitled": "Без названия",
|
|
1276
|
+
"draft.workspaceRequired": "Сначала выберите рабочее пространство.",
|
|
1277
|
+
"draft.initializationFailed": "Не удалось заполнить черновик. Повторите попытку немного позже.",
|
|
1247
1278
|
"group.ungrouped": "Без группы",
|
|
1248
1279
|
"session.new": "Новая сессия",
|
|
1249
1280
|
"section.workspaces": "Рабочие пространства",
|
|
@@ -1451,6 +1482,10 @@ window.__ModuleLoader__.load({
|
|
|
1451
1482
|
"menu.feedback": "Отзыв"
|
|
1452
1483
|
},
|
|
1453
1484
|
"chat": {
|
|
1485
|
+
"chat.deepDivingFor": "Углублённый анализ: {duration} ···",
|
|
1486
|
+
"duration.secondUnit": "с",
|
|
1487
|
+
"duration.minuteUnit": "мин ",
|
|
1488
|
+
"duration.hourUnit": "ч ",
|
|
1454
1489
|
"view.chat": "Чат",
|
|
1455
1490
|
"number.groupSeparator": " ",
|
|
1456
1491
|
"duration.compactSeconds": "{seconds} с",
|
|
@@ -1993,6 +2028,7 @@ window.__ModuleLoader__.load({
|
|
|
1993
2028
|
},
|
|
1994
2029
|
"settings.account": {
|
|
1995
2030
|
"close": "Закрыть",
|
|
2031
|
+
"noResponse": "Что-то пошло не так. Проверьте подключение к сети и попробуйте ещё раз.",
|
|
1996
2032
|
"addApiKey": "Добавить API-ключ",
|
|
1997
2033
|
"retry": "Войти снова",
|
|
1998
2034
|
"loginTitle": "Начать",
|
|
@@ -2088,7 +2124,89 @@ window.__ModuleLoader__.load({
|
|
|
2088
2124
|
"bonusNoticeTitle": "Бонус начислен",
|
|
2089
2125
|
"bonusEmpty": "Бонус отсутствует"
|
|
2090
2126
|
},
|
|
2127
|
+
"claude-code-mods": {
|
|
2128
|
+
"band": "Модификаторы Claude Code",
|
|
2129
|
+
"pressing": "Работа…",
|
|
2130
|
+
"press.failed": "Не сработала кнопка: {message}",
|
|
2131
|
+
"press.stale": "Эта кнопка относилась к предыдущему рисунку; полоса обновилась"
|
|
2132
|
+
},
|
|
2133
|
+
"inspectorPanel": {
|
|
2134
|
+
"resize": "Изменить высоту панели NodeJS Inspector",
|
|
2135
|
+
"frameTitle": "NodeJS Inspector"
|
|
2136
|
+
},
|
|
2137
|
+
"session-inspector": {
|
|
2138
|
+
"tab.title": "Журнал сессии",
|
|
2139
|
+
"tab.description": "Анализ сырых логов и сгруппированных сообщений чата текущей сессии на боковой панели.",
|
|
2140
|
+
"view.presentation": "Представление",
|
|
2141
|
+
"view.sessionLog": "Сырой лог",
|
|
2142
|
+
"view.chatNode": "Группа чата",
|
|
2143
|
+
"picker.pick": "Выбрать элемент в виде чата",
|
|
2144
|
+
"picker.cancel": "Отменить выбор (Esc)",
|
|
2145
|
+
"picker.instructions": "Наведите в основном чате для предпросмотра, затем щёлкните для выбора. Esc отменяет.",
|
|
2146
|
+
"picker.noMatch": "В этой таблице нет подходящей записи. Выберите другой элемент или нажмите Esc для отмены.",
|
|
2147
|
+
"picker.noChat": "Сначала откройте эту сессию в основном чате.",
|
|
2148
|
+
"table.id": "Индекс",
|
|
2149
|
+
"table.type": "Тип",
|
|
2150
|
+
"filter.title": "Фильтр по типам",
|
|
2151
|
+
"filter.input": "Ключевое слово",
|
|
2152
|
+
"filter.placeholder": "Введите фрагмент, например delta",
|
|
2153
|
+
"filter.help": "Содержит совпадение (*слово*). Enter подтверждает; Esc отменяет.",
|
|
2154
|
+
"filter.candidates": "Подсказки по типу",
|
|
2155
|
+
"filter.loading": "Ищем подсказки…",
|
|
2156
|
+
"filter.failed": "Не удалось загрузить подсказки по типу.",
|
|
2157
|
+
"filter.noCandidates": "Подсказок нет. Ключевое слово всё равно можно применить.",
|
|
2158
|
+
"filter.clear": "Очистить",
|
|
2159
|
+
"filter.cancel": "Отмена",
|
|
2160
|
+
"filter.apply": "Применить фильтр",
|
|
2161
|
+
"filter.context": "Родительский контекст подходящей записи",
|
|
2162
|
+
"table.location": "Т/С",
|
|
2163
|
+
"table.time": "Время (UTC)",
|
|
2164
|
+
"table.data": "Данные",
|
|
2165
|
+
"table.older": "Загрузить более ранние",
|
|
2166
|
+
"table.loading": "Загрузка…",
|
|
2167
|
+
"table.latest": "Следить за новыми",
|
|
2168
|
+
"table.empty": "Нет записей",
|
|
2169
|
+
"table.raw": "Сырые данные",
|
|
2170
|
+
"table.rawError": "Не удалось сериализовать эту запись. Выберите другую, чтобы продолжить.",
|
|
2171
|
+
"table.resizeDetails": "Изменить высоту панели сырых данных",
|
|
2172
|
+
"table.close": "Закрыть",
|
|
2173
|
+
"table.expand": "Развернуть потомков",
|
|
2174
|
+
"table.collapse": "Свернуть потомков",
|
|
2175
|
+
"table.removed": "Эта запись была удалена или закрыта. Выберите актуальную.",
|
|
2176
|
+
"object.node": "Узел",
|
|
2177
|
+
"object.nodeData": "Данные узла",
|
|
2178
|
+
"object.group": "Группа",
|
|
2179
|
+
"object.groupData": "Данные группы",
|
|
2180
|
+
"object.turn": "Ход",
|
|
2181
|
+
"object.turnData": "Данные хода",
|
|
2182
|
+
"object.step": "Шаг",
|
|
2183
|
+
"object.stepData": "Данные шага",
|
|
2184
|
+
"object.accessor": "[Геттер/сеттер, не вычислено]",
|
|
2185
|
+
"object.empty": "Пусто",
|
|
2186
|
+
"object.absent": "[Пустой слот]",
|
|
2187
|
+
"object.properties": "Другие свойства",
|
|
2188
|
+
"object.more": "Показать больше",
|
|
2189
|
+
"object.navigation": "Навигация по сырым данным"
|
|
2190
|
+
},
|
|
2091
2191
|
"pluginManager": {
|
|
2192
|
+
"infoLabel": "О плагинах",
|
|
2193
|
+
"infoDescription": "Здесь настраиваются официальные плагины, а также устанавливаются и управляются остальные. Список встроенных плагинов и их состояние — в разделе «Настройки → Встроенные плагины».",
|
|
2194
|
+
"refreshError": "Не удалось обновить. Попробуйте ещё раз.",
|
|
2195
|
+
"installGitTemplateHint": "Замените на настоящий адрес Git-репозитория.",
|
|
2196
|
+
"installPathTemplateHint": "Замените на настоящий путь к локальному каталогу плагинов.",
|
|
2197
|
+
"installUpgradeNotice": "Установленные плагины пока не обновляются автоматически. Чтобы обновить плагин, удалите его и установите новую версию. В следующих выпусках обновление станет удобнее.",
|
|
2198
|
+
"sentenceSeparator": " ",
|
|
2199
|
+
"chooseAddMethod": "Выберите способ добавления плагина",
|
|
2200
|
+
"installExisting": "Установить сторонний плагин",
|
|
2201
|
+
"installExistingDescription": "Поддерживаются npm-пакеты, Git-репозитории и локальные каталоги",
|
|
2202
|
+
"sourceTitle": "Источник",
|
|
2203
|
+
"sourceSpec": "Исходный код",
|
|
2204
|
+
"sourceBuiltIn": "Встроенный",
|
|
2205
|
+
"sourceVersion": "Текущая версия",
|
|
2206
|
+
"installDoneOtherVersion": "По политике безопасности цепочки поставок pnpm (minimumReleaseAge) версии, опубликованные недавно, не ставятся автоматически, поэтому вместо {version} установлена {installed}. Новая версия ещё не прошла этот срок ожидания и может содержать нераспознанный вредоносный код или дефекты. Если нужна версия {version}, удалите текущую и установите {exact}, чтобы запросить именно её.",
|
|
2207
|
+
"installProblemShipped": "Этот плагин входит в состав DSH; его обновят вместе с DSH",
|
|
2208
|
+
"reasonIncompatibleInstall": "Установите версию плагина, совместимую с этой сборкой DSH.",
|
|
2209
|
+
"reasonIncompatibleInstalled": "Удалите его и установите версию, совместимую с этой сборкой DSH.",
|
|
2092
2210
|
"panel": "Плагины",
|
|
2093
2211
|
"title": "Плагины",
|
|
2094
2212
|
"intro": "Добавление плагинов и управление ими",
|
|
@@ -2454,6 +2572,7 @@ window.__ModuleLoader__.load({
|
|
|
2454
2572
|
"hover.more": "ещё {count}"
|
|
2455
2573
|
},
|
|
2456
2574
|
"schedule.manager": {
|
|
2575
|
+
"timing.subagentSession": "Эта сессия принадлежит субагенту, который не получает доставленные напоминания.",
|
|
2457
2576
|
"panel": "Задачи автоматизации",
|
|
2458
2577
|
"title": "Задачи автоматизации",
|
|
2459
2578
|
"new.action": "Создать",
|
|
@@ -2703,14 +2822,103 @@ window.__ModuleLoader__.load({
|
|
|
2703
2822
|
}
|
|
2704
2823
|
};
|
|
2705
2824
|
//#endregion
|
|
2825
|
+
//#region src/client/typography.ts
|
|
2826
|
+
/**
|
|
2827
|
+
* Russian screen typography for translated strings.
|
|
2828
|
+
*
|
|
2829
|
+
* The harness locale contract is a flat `Record<string, string>`, so a
|
|
2830
|
+
* language pack cannot reach the composed sentences a component builds from
|
|
2831
|
+
* several keys, and cannot ask the host to insert typography. The rendered DOM
|
|
2832
|
+
* is the one place where every translated string passes through, so this module
|
|
2833
|
+
* rewrites text nodes in place. The rules are deliberately conservative: they
|
|
2834
|
+
* only fire on unambiguous straight-quote and spaced-hyphen patterns, and the
|
|
2835
|
+
* DOM pass skips code, form fields and editable content.
|
|
2836
|
+
*/
|
|
2837
|
+
/** Straight double quotes around a span become Russian guillemets. */
|
|
2838
|
+
const QUOTED = /"([^"\n]{1,200})"/g;
|
|
2839
|
+
/** A spaced hyphen between two words is an em dash in Russian typography. */
|
|
2840
|
+
const SPACED_HYPHEN = /(?<=[\p{L}\p{N}»\)]) - (?=[\p{L}\p{N}«\(])/gu;
|
|
2841
|
+
/** Three dots in running text are an ellipsis. */
|
|
2842
|
+
const ELLIPSIS = /\.{3}(?=\s|$)/g;
|
|
2843
|
+
/** A digit followed by a lowercase letter keeps a non-breaking space. */
|
|
2844
|
+
const NUMBER_UNIT = /(\d) ([а-яё]{1,24})(?![а-яё])/giu;
|
|
2845
|
+
/** Non-breaking space keeps a number attached to a short unit-like token. */
|
|
2846
|
+
const NUMBER_SYMBOL = /(\d) ([%°₽$€£]|кб|КБ|МБ|ГБ)(?=\s|$)/giu;
|
|
2847
|
+
/** Guillemets, em dash, ellipsis, and non-breaking spaces in running text. */
|
|
2848
|
+
function applyRussianTypography(text) {
|
|
2849
|
+
return text.replace(QUOTED, "«$1»").replace(SPACED_HYPHEN, " — ").replace(ELLIPSIS, "…").replace(NUMBER_UNIT, "$1\xA0$2").replace(NUMBER_SYMBOL, "$1\xA0$2");
|
|
2850
|
+
}
|
|
2851
|
+
/** Elements whose text is code, data or user input and must stay verbatim. */
|
|
2852
|
+
const SKIP_SELECTOR = [
|
|
2853
|
+
"code",
|
|
2854
|
+
"pre",
|
|
2855
|
+
"kbd",
|
|
2856
|
+
"samp",
|
|
2857
|
+
"var",
|
|
2858
|
+
"textarea",
|
|
2859
|
+
"input",
|
|
2860
|
+
"select",
|
|
2861
|
+
"option",
|
|
2862
|
+
"[contenteditable]:not([contenteditable=\"false\"])",
|
|
2863
|
+
"[data-typography=\"off\"]"
|
|
2864
|
+
].join(",");
|
|
2865
|
+
/** Text nodes already rewritten, so a later pass leaves them alone. */
|
|
2866
|
+
const processed = /* @__PURE__ */ new WeakSet();
|
|
2867
|
+
/** Whether the node sits inside content that must not be rewritten. */
|
|
2868
|
+
function isSkipped(node) {
|
|
2869
|
+
const element = node.nodeType === Node.ELEMENT_NODE ? node : node.parentElement;
|
|
2870
|
+
return element === null || element.closest(SKIP_SELECTOR) !== null;
|
|
2871
|
+
}
|
|
2872
|
+
function rewriteNode(node) {
|
|
2873
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
2874
|
+
if (processed.has(node)) return;
|
|
2875
|
+
processed.add(node);
|
|
2876
|
+
const before = node.data;
|
|
2877
|
+
const after = applyRussianTypography(before);
|
|
2878
|
+
if (after !== before) node.data = after;
|
|
2879
|
+
return;
|
|
2880
|
+
}
|
|
2881
|
+
if (node.nodeType !== Node.ELEMENT_NODE || isSkipped(node)) return;
|
|
2882
|
+
for (const child of node.childNodes) rewriteNode(child);
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* Start the typography pass on a document and keep it current as the app
|
|
2886
|
+
* renders. Returns a disposer that stops observing.
|
|
2887
|
+
*
|
|
2888
|
+
* @param doc - document whose body carries the rendered interface.
|
|
2889
|
+
* @returns disposer removing the observer.
|
|
2890
|
+
*/
|
|
2891
|
+
function startRussianTypography(doc) {
|
|
2892
|
+
const root = doc.body;
|
|
2893
|
+
if (root === null) return () => {};
|
|
2894
|
+
rewriteNode(root);
|
|
2895
|
+
const observer = new MutationObserver((records) => {
|
|
2896
|
+
for (const record of records) {
|
|
2897
|
+
if (record.type === "characterData") {
|
|
2898
|
+
if (isSkipped(record.target)) continue;
|
|
2899
|
+
rewriteNode(record.target);
|
|
2900
|
+
continue;
|
|
2901
|
+
}
|
|
2902
|
+
for (const added of record.addedNodes) rewriteNode(added);
|
|
2903
|
+
}
|
|
2904
|
+
});
|
|
2905
|
+
observer.observe(root, {
|
|
2906
|
+
childList: true,
|
|
2907
|
+
characterData: true,
|
|
2908
|
+
subtree: true
|
|
2909
|
+
});
|
|
2910
|
+
return () => observer.disconnect();
|
|
2911
|
+
}
|
|
2912
|
+
//#endregion
|
|
2706
2913
|
//#region src/client/index.ts
|
|
2707
2914
|
/** Required service: the locale registry that owns languages and dictionaries. */
|
|
2708
2915
|
const inject = ["locale"];
|
|
2709
2916
|
/**
|
|
2710
|
-
* Client plugin body: add `ru` to the selectable language catalog
|
|
2711
|
-
* a ru dictionary for every namespace this pack contributes
|
|
2712
|
-
* an effect, so the contributed
|
|
2713
|
-
*
|
|
2917
|
+
* Client plugin body: add `ru` to the selectable language catalog, register
|
|
2918
|
+
* a ru dictionary for every namespace this pack contributes, and start the
|
|
2919
|
+
* Russian typography pass. Registration is an effect, so the contributed
|
|
2920
|
+
* language, dictionaries and the typography observer are torn down with this
|
|
2921
|
+
* plugin's fiber.
|
|
2714
2922
|
* @param ctx - client root context.
|
|
2715
2923
|
*/
|
|
2716
2924
|
function apply(ctx) {
|
|
@@ -2720,6 +2928,7 @@ window.__ModuleLoader__.load({
|
|
|
2720
2928
|
fallback: "en"
|
|
2721
2929
|
}), "locale-ru: language");
|
|
2722
2930
|
for (const [ns, dict] of Object.entries(RU_DICTS)) ctx.effect(() => ctx.locale.register(ns, "ru", dict), `locale-ru: ${ns} dictionary`);
|
|
2931
|
+
ctx.effect(() => startRussianTypography(document), "locale-ru: typography");
|
|
2723
2932
|
}
|
|
2724
2933
|
//#endregion
|
|
2725
2934
|
exports.apply = apply;
|