@goodandready/dsh-russian-lang 0.3.25 → 0.3.27
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/README.md +20 -11
- package/bin/dsh-i18n.mjs +20 -10
- package/glossary.json +206 -0
- package/lib/client.js +176 -112
- package/lib/locales/plugins/15-commandcode.json +1 -1
- package/lib/locales/plugins/17-dsh-context.json +1 -1
- package/lib/locales/plugins/26-config-manager.json +1 -1
- package/lib/locales/plugins/34-key-rotation.json +1 -1
- package/lib/translator.js +4 -1
- package/package.json +4 -2
- package/lib/client.template.js +0 -2800
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
<h3>Полная русская локализация, умная типографика и исправление раскладки клавиатуры для DeepSeek Harness</h3>
|
|
6
6
|
|
|
7
7
|
<p align="center">
|
|
8
|
-
<a href="https://www.npmjs.com/package/@goodandready/dsh-russian-lang"><img src="https://img.shields.io/badge/npm-v0.3.
|
|
8
|
+
<a href="https://www.npmjs.com/package/@goodandready/dsh-russian-lang"><img src="https://img.shields.io/badge/npm-v0.3.27-6366f1.svg?style=for-the-badge&labelColor=1e1b4b" alt="npm version"></a>
|
|
9
9
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-10b981.svg?style=for-the-badge&color=10b981&labelColor=064e3b" alt="license"></a>
|
|
10
10
|
<a href="https://github.com/topics/dsh-plugin"><img src="https://img.shields.io/badge/DSH-Plugin-8b5cf6.svg?style=for-the-badge&labelColor=2e1065" alt="DSH Plugin"></a>
|
|
11
11
|
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node-20%2B-f59e0b.svg?style=for-the-badge&labelColor=451a03" alt="Node version"></a>
|
|
@@ -14,7 +14,7 @@
|
|
|
14
14
|
<p align="center">
|
|
15
15
|
<img src="https://img.shields.io/badge/DSH-v0.2.0--rc.2%2B-blue.svg?style=for-the-badge&labelColor=1e1b4b" alt="DSH v0.1.7-rc.2+">
|
|
16
16
|
<img src="https://img.shields.io/badge/Покрытие-100%25-10b981.svg?style=for-the-badge&labelColor=064e3b" alt="Покрытие 100%">
|
|
17
|
-
<img src="https://img.shields.io/badge/Ключей_UI-
|
|
17
|
+
<img src="https://img.shields.io/badge/Ключей_UI-8584-6366f1.svg?style=for-the-badge&labelColor=1e1b4b" alt="8584 ключей">
|
|
18
18
|
<img src="https://img.shields.io/badge/Ручная_вычитка-100%25-0ea5e9.svg?style=for-the-badge&labelColor=082f49" alt="100% ручная вычитка">
|
|
19
19
|
</p>
|
|
20
20
|
|
|
@@ -85,7 +85,7 @@ graph LR
|
|
|
85
85
|
|
|
86
86
|
## ✨ Полный обзор возможностей
|
|
87
87
|
|
|
88
|
-
### 1. 🌐 100% покрытие ядра DSH (
|
|
88
|
+
### 1. 🌐 100% покрытие ядра DSH (58 пространств имён, 2 442 ключа)
|
|
89
89
|
* **Диалоги и переписка (`conversation`)**: лента сообщений, ветки обсуждений, карточки вызова инструментов, статус генерации и рассуждений (thinking traces).
|
|
90
90
|
* **Модели и провайдеры (`settings.models`)**: каталог моделей, параметры инференса, управление токенами и ключами API.
|
|
91
91
|
* **Трейсы рассуждений (`trajectory`)**: детальные шаги, параметры вызовов инструментов, временные метки и визуализация размышлений модели.
|
|
@@ -94,9 +94,9 @@ graph LR
|
|
|
94
94
|
* **Планировщик и инвентарь (`schedule.catalog`, `settings.pluginInventory`, `settings.plugins`)**: фоновые задания, периодичность, фильтры и каталог установленных плагинов.
|
|
95
95
|
* **Права доступа и безопасность (`permission.access`, `plan`, `skill`)**: пресеты прав (полный доступ, только чтение, запись в рабочую область), выполнение планов и навыки.
|
|
96
96
|
|
|
97
|
-
> **О качестве перевода.** Все **
|
|
97
|
+
> **О качестве перевода.** Все **8 584 ключа интерфейса (2 442 ядра + 6 142 плагинов) переведены на 100% и вычитаны вручную**. Черновой машинный перевод полностью замещён проверенными формулировками (`draft = 0`). Перевод регулярно валидируется автоматическими линтерами целостности плейсхолдеров, проверкой соблюдения глоссария (`glossary.json`) и детекторами переполнения верстки. Нашли неточность — кнопка «Сообщить о проблеме перевода» в карточке настроек создаёт готовый issue.
|
|
98
98
|
|
|
99
|
-
### 2. 🧩 Встроенный перевод 65+ плагинов экосистемы DSH (
|
|
99
|
+
### 2. 🧩 Встроенный перевод 65+ плагинов экосистемы DSH (6 142 ключа)
|
|
100
100
|
Локализация автоматически распространяется на все ключевые плагины экосистемы DeepSeek Harness:
|
|
101
101
|
* **`dsh-session-control`** — расширенное управление сессиями: закрепление диалогов, архив по периодам, просмотр расшифровок и фильтрация шума;
|
|
102
102
|
* **`dsh-kanban` и `task-board`** — канбан-доски задач, карточки, чек-листы, дедлайны, критерии готовности (DoD) и шлюз приёмки (Acceptance Gate);
|
|
@@ -149,7 +149,7 @@ graph LR
|
|
|
149
149
|
|
|
150
150
|
### 7. ⚡ Оптимизации производительности и архитектурная безопасность
|
|
151
151
|
* **Пакетная обработка MutationObserver**: оптимизированный наблюдатель мутаций интерфейса с адаптивным debounce (16 мс) предотвращает лавинообразные перерисовки и перерасчёт макета (reflow) при интенсивном рендеринге списков и стриминге LLM-токенов.
|
|
152
|
-
* **Защита HTTP-маршрутов словарей (405 Method Not Allowed)**: серверные эндпоинты `/dict/core`, `/dict/plugins`, `/dict/all
|
|
152
|
+
* **Защита HTTP-маршрутов словарей (405 Method Not Allowed)**: серверные эндпоинты `/api/dsh-russian-lang/dict/core`, `/api/dsh-russian-lang/dict/plugins`, `/api/dsh-russian-lang/dict/all` строго защищены и принимают только безопасные методы GET/HEAD.
|
|
153
153
|
* **Клиентский бандл с запасом**: оптимизированная архитектура и компактный бутстрап обеспечивают размер клиентского скрипта 153.7 KiB (запас более 10 KiB до предельного лимита).
|
|
154
154
|
|
|
155
155
|
### 8. 🔤 Нативная интеграция в ядро
|
|
@@ -167,22 +167,31 @@ dsh plugin --profile web add @goodandready/dsh-russian-lang
|
|
|
167
167
|
|
|
168
168
|
---
|
|
169
169
|
|
|
170
|
-
## ⚙️ Параметры конфигурации (`settings.yaml`)
|
|
170
|
+
## ⚙️ Параметры конфигурации (`settings.yaml` / профиль Cordis)
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
|
|
172
|
+
В актуальных версиях DSH (v0.2.0-rc.2+, v0.1.7+) конфигурация плагина управляется штатно через managed-форму в веб-интерфейсе (**Настройки → Плагины → Русская локализация**) либо в профиле/конфиге под идентификатором плагина `dsh-russian-lang` (согласно `cordis.patch.yml`).
|
|
173
|
+
|
|
174
|
+
Для полной обратной совместимости с ранними версиями ядра (DSH <= 0.1.6) плагин также автоматически поддерживает чтение из легаси-пространства `russian-lang`.
|
|
175
|
+
|
|
176
|
+
Схема параметров объявлена в [`lib/index.js`](lib/index.js), все поля необязательные:
|
|
174
177
|
|
|
175
178
|
```yaml
|
|
176
|
-
|
|
179
|
+
# Актуальный формат (DSH v0.2.0-rc.2+ / v0.1.7+):
|
|
180
|
+
dsh-russian-lang:
|
|
177
181
|
enabled: true # Русский язык интерфейса
|
|
178
182
|
typography:
|
|
179
183
|
enabled: true # Ёлочки, длинные тире, неразрывные пробелы
|
|
180
184
|
yo: false # Восстанавливать «ё» (по умолчанию выключено)
|
|
181
185
|
agentPrompt: false # Просить агента отвечать по-русски
|
|
182
186
|
overrides: {} # Свои значения для любых ключей перевода
|
|
187
|
+
|
|
188
|
+
# Легаси-формат (DSH <= 0.1.6, поддерживается автоматически как fallback):
|
|
189
|
+
# russian-lang:
|
|
190
|
+
# enabled: true
|
|
191
|
+
# ...
|
|
183
192
|
```
|
|
184
193
|
|
|
185
|
-
|
|
194
|
+
Удобнее всего настраивать параметры визуально в интерфейсе: **Настройки → Плагины → Русская локализация**.
|
|
186
195
|
|
|
187
196
|
Исправление раскладки (<kbd>Alt+L</kbd>) и браузерный спелчек включаются вместе с
|
|
188
197
|
русским языком и отдельных ключей не имеют.
|
package/bin/dsh-i18n.mjs
CHANGED
|
@@ -6,6 +6,10 @@ import { fileURLToPath } from 'node:url'
|
|
|
6
6
|
const __dirname = path.dirname(fileURLToPath(import.meta.url))
|
|
7
7
|
const ROOT = path.resolve(__dirname, '..')
|
|
8
8
|
|
|
9
|
+
function escapeRegExp(string) {
|
|
10
|
+
return string.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
|
|
11
|
+
}
|
|
12
|
+
|
|
9
13
|
function getPkgVersion() {
|
|
10
14
|
try {
|
|
11
15
|
const pkg = JSON.parse(fs.readFileSync(path.join(ROOT, 'package.json'), 'utf8'))
|
|
@@ -55,7 +59,7 @@ function extractKeys(targetDir, defaultNs = 'common') {
|
|
|
55
59
|
walk(fullPath)
|
|
56
60
|
} else if (entry.isFile() && extensions.has(path.extname(entry.name))) {
|
|
57
61
|
const code = fs.readFileSync(fullPath, 'utf8')
|
|
58
|
-
const tMatches = code.matchAll(/\bt\(\s*['"`]([a-zA-Z0-9_.-]+)['"`]\s
|
|
62
|
+
const tMatches = code.matchAll(/\bt\(\s*['"`]([a-zA-Z0-9_.-]+)['"`]\s*[,)]/g)
|
|
59
63
|
for (const m of tMatches) {
|
|
60
64
|
result[defaultNs][m[1]] = result[defaultNs][m[1]] || ''
|
|
61
65
|
}
|
|
@@ -88,6 +92,11 @@ function validateDict(filePath, glossaryPath) {
|
|
|
88
92
|
return false
|
|
89
93
|
}
|
|
90
94
|
|
|
95
|
+
if (!data || typeof data !== 'object' || Array.isArray(data)) {
|
|
96
|
+
console.error(`Ошибка структуры JSON в ${filePath}: корневой элемент должен быть объектом`)
|
|
97
|
+
return false
|
|
98
|
+
}
|
|
99
|
+
|
|
91
100
|
let errors = []
|
|
92
101
|
let warnings = []
|
|
93
102
|
let totalKeys = 0
|
|
@@ -103,7 +112,7 @@ function validateDict(filePath, glossaryPath) {
|
|
|
103
112
|
function checkString(ns, key, val) {
|
|
104
113
|
totalKeys++
|
|
105
114
|
if (typeof val !== 'string') {
|
|
106
|
-
errors.push(`[${ns}:${key}] Значение должно быть строкой, получено: ${typeof val}`)
|
|
115
|
+
errors.push(`[${ns}:${key}] Значение должно быть строкой, получено: ${val === null ? 'null' : Array.isArray(val) ? 'массив' : typeof val}`)
|
|
107
116
|
return
|
|
108
117
|
}
|
|
109
118
|
|
|
@@ -117,13 +126,12 @@ function validateDict(filePath, glossaryPath) {
|
|
|
117
126
|
}
|
|
118
127
|
|
|
119
128
|
if (glossary) {
|
|
120
|
-
const lower = val.toLowerCase()
|
|
121
129
|
for (const [term, info] of Object.entries(glossary)) {
|
|
122
130
|
if (Array.isArray(info.forbidden)) {
|
|
123
131
|
for (const forbidden of info.forbidden) {
|
|
124
|
-
const
|
|
125
|
-
const re = new RegExp(
|
|
126
|
-
if (re.test(
|
|
132
|
+
const esc = escapeRegExp(forbidden)
|
|
133
|
+
const re = new RegExp(`(?<=[^\\p{L}\\p{N}]|^)${esc}(?=[^\\p{L}\\p{N}]|$)`, 'iu')
|
|
134
|
+
if (re.test(val)) {
|
|
127
135
|
warnings.push(`[${ns}:${key}] Запрещённый термин по глоссарию "${forbidden}" (рекомендуется: "${info.canonical}")`)
|
|
128
136
|
}
|
|
129
137
|
}
|
|
@@ -134,10 +142,12 @@ function validateDict(filePath, glossaryPath) {
|
|
|
134
142
|
|
|
135
143
|
for (const ns of Object.keys(data)) {
|
|
136
144
|
const section = data[ns]
|
|
137
|
-
if (typeof section
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
145
|
+
if (!section || typeof section !== 'object' || Array.isArray(section)) {
|
|
146
|
+
errors.push(`[${ns}] Пространство имён должно быть объектом, получено: ${section === null ? 'null' : Array.isArray(section) ? 'массив' : typeof section}`)
|
|
147
|
+
continue
|
|
148
|
+
}
|
|
149
|
+
for (const [k, v] of Object.entries(section)) {
|
|
150
|
+
checkString(ns, k, v)
|
|
141
151
|
}
|
|
142
152
|
}
|
|
143
153
|
|
package/glossary.json
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Канонический глоссарий терминов DeepSeek Harness (DSH) и AI-экосистемы",
|
|
5
|
+
"terms": {
|
|
6
|
+
"workspace": {
|
|
7
|
+
"canonical": "Рабочая область",
|
|
8
|
+
"allowed": [
|
|
9
|
+
"Рабочая область",
|
|
10
|
+
"Воркспейс"
|
|
11
|
+
],
|
|
12
|
+
"forbidden": [
|
|
13
|
+
"Рабочее место",
|
|
14
|
+
"Рабочий стол",
|
|
15
|
+
"Пространство задач"
|
|
16
|
+
],
|
|
17
|
+
"description": "Изолированная рабочая директория/проект агента"
|
|
18
|
+
},
|
|
19
|
+
"subagent": {
|
|
20
|
+
"canonical": "Субагент",
|
|
21
|
+
"allowed": [
|
|
22
|
+
"Субагент",
|
|
23
|
+
"Дочерний агент"
|
|
24
|
+
],
|
|
25
|
+
"forbidden": [
|
|
26
|
+
"Подагент",
|
|
27
|
+
"Младший агент",
|
|
28
|
+
"Вспомогательный агент"
|
|
29
|
+
],
|
|
30
|
+
"description": "Автономный дочерний агент"
|
|
31
|
+
},
|
|
32
|
+
"prompt": {
|
|
33
|
+
"canonical": "Промпт",
|
|
34
|
+
"allowed": [
|
|
35
|
+
"Промпт",
|
|
36
|
+
"Инструкция",
|
|
37
|
+
"Системный промпт"
|
|
38
|
+
],
|
|
39
|
+
"forbidden": [
|
|
40
|
+
"Затравка",
|
|
41
|
+
"Побуждение",
|
|
42
|
+
"Внушение"
|
|
43
|
+
],
|
|
44
|
+
"description": "Инструкция или текстовый ввод для модели"
|
|
45
|
+
},
|
|
46
|
+
"tool": {
|
|
47
|
+
"canonical": "Инструмент",
|
|
48
|
+
"allowed": [
|
|
49
|
+
"Инструмент",
|
|
50
|
+
"Вызов инструмента"
|
|
51
|
+
],
|
|
52
|
+
"forbidden": [
|
|
53
|
+
"Орудие",
|
|
54
|
+
"Утилита"
|
|
55
|
+
],
|
|
56
|
+
"description": "Функция или инструмент, вызываемый агентом (tool/tool call)"
|
|
57
|
+
},
|
|
58
|
+
"session": {
|
|
59
|
+
"canonical": "Сессия",
|
|
60
|
+
"allowed": [
|
|
61
|
+
"Сессия",
|
|
62
|
+
"Диалог",
|
|
63
|
+
"Чат"
|
|
64
|
+
],
|
|
65
|
+
"forbidden": [
|
|
66
|
+
"Заседание",
|
|
67
|
+
"Сеанс связи"
|
|
68
|
+
],
|
|
69
|
+
"description": "Отдельный поток диалога или сессия работы"
|
|
70
|
+
},
|
|
71
|
+
"skill": {
|
|
72
|
+
"canonical": "Навык",
|
|
73
|
+
"allowed": [
|
|
74
|
+
"Навык",
|
|
75
|
+
"Навыки",
|
|
76
|
+
"Skill"
|
|
77
|
+
],
|
|
78
|
+
"forbidden": [
|
|
79
|
+
"Умение",
|
|
80
|
+
"Мастерство"
|
|
81
|
+
],
|
|
82
|
+
"description": "Подключаемый модуль навыков агента"
|
|
83
|
+
},
|
|
84
|
+
"plugin": {
|
|
85
|
+
"canonical": "Плагин",
|
|
86
|
+
"allowed": [
|
|
87
|
+
"Плагин",
|
|
88
|
+
"Плагины"
|
|
89
|
+
],
|
|
90
|
+
"forbidden": [
|
|
91
|
+
"Встраиваемый модуль"
|
|
92
|
+
],
|
|
93
|
+
"description": "Плагин Cordis / DSH"
|
|
94
|
+
},
|
|
95
|
+
"provider": {
|
|
96
|
+
"canonical": "Провайдер",
|
|
97
|
+
"allowed": [
|
|
98
|
+
"Провайдер",
|
|
99
|
+
"Провайдеры"
|
|
100
|
+
],
|
|
101
|
+
"forbidden": [
|
|
102
|
+
"Поставщик",
|
|
103
|
+
"Поставщики"
|
|
104
|
+
],
|
|
105
|
+
"description": "Провайдер LLM API (OpenAI, DeepSeek, Ollama и др.)"
|
|
106
|
+
},
|
|
107
|
+
"token": {
|
|
108
|
+
"canonical": "Токен",
|
|
109
|
+
"allowed": [
|
|
110
|
+
"Токен",
|
|
111
|
+
"Токены"
|
|
112
|
+
],
|
|
113
|
+
"forbidden": [
|
|
114
|
+
"Жетон",
|
|
115
|
+
"Жетоны"
|
|
116
|
+
],
|
|
117
|
+
"description": "Единица расхода контекста LLM"
|
|
118
|
+
},
|
|
119
|
+
"thinking": {
|
|
120
|
+
"canonical": "Размышления",
|
|
121
|
+
"allowed": [
|
|
122
|
+
"Размышления",
|
|
123
|
+
"Рассуждения",
|
|
124
|
+
"Цепочка рассуждений"
|
|
125
|
+
],
|
|
126
|
+
"forbidden": [
|
|
127
|
+
"Думание",
|
|
128
|
+
"Мышление модели"
|
|
129
|
+
],
|
|
130
|
+
"description": "Трейс внутренних рассуждений (thinking traces) модели"
|
|
131
|
+
},
|
|
132
|
+
"effort": {
|
|
133
|
+
"canonical": "Уровень рассуждений",
|
|
134
|
+
"allowed": [
|
|
135
|
+
"Уровень рассуждений",
|
|
136
|
+
"Усилие рассуждений",
|
|
137
|
+
"Усилие"
|
|
138
|
+
],
|
|
139
|
+
"forbidden": [
|
|
140
|
+
"Старание",
|
|
141
|
+
"Напряжение"
|
|
142
|
+
],
|
|
143
|
+
"description": "Параметр reasoning effort модели"
|
|
144
|
+
},
|
|
145
|
+
"approval": {
|
|
146
|
+
"canonical": "Подтверждение",
|
|
147
|
+
"allowed": [
|
|
148
|
+
"Подтверждение",
|
|
149
|
+
"Одобрение"
|
|
150
|
+
],
|
|
151
|
+
"forbidden": [
|
|
152
|
+
"Апробация",
|
|
153
|
+
"Санкционирование"
|
|
154
|
+
],
|
|
155
|
+
"description": "Запрос подтверждения опасного действия пользователем"
|
|
156
|
+
},
|
|
157
|
+
"deliverables": {
|
|
158
|
+
"canonical": "Результаты работы",
|
|
159
|
+
"allowed": [
|
|
160
|
+
"Результаты работы",
|
|
161
|
+
"Файлы результатов",
|
|
162
|
+
"Результаты"
|
|
163
|
+
],
|
|
164
|
+
"forbidden": [
|
|
165
|
+
"Поставки",
|
|
166
|
+
"Доставляемые элементы"
|
|
167
|
+
],
|
|
168
|
+
"description": "Созданные агентом итоговые файлы"
|
|
169
|
+
},
|
|
170
|
+
"branch": {
|
|
171
|
+
"canonical": "Ветка",
|
|
172
|
+
"allowed": [
|
|
173
|
+
"Ветка",
|
|
174
|
+
"Ветвление"
|
|
175
|
+
],
|
|
176
|
+
"forbidden": [
|
|
177
|
+
"Ответвление",
|
|
178
|
+
"Ветвь"
|
|
179
|
+
],
|
|
180
|
+
"description": "Ветка диалога или Git-ветка"
|
|
181
|
+
},
|
|
182
|
+
"checkpoint": {
|
|
183
|
+
"canonical": "Контрольная точка",
|
|
184
|
+
"allowed": [
|
|
185
|
+
"Контрольная точка",
|
|
186
|
+
"Чекпоинт"
|
|
187
|
+
],
|
|
188
|
+
"forbidden": [
|
|
189
|
+
"Точка проверки",
|
|
190
|
+
"Контрольный пункт"
|
|
191
|
+
],
|
|
192
|
+
"description": "Точка сохранения состояния сессии или памяти"
|
|
193
|
+
},
|
|
194
|
+
"command_code": {
|
|
195
|
+
"canonical": "Command Code",
|
|
196
|
+
"allowed": [
|
|
197
|
+
"Command Code"
|
|
198
|
+
],
|
|
199
|
+
"forbidden": [
|
|
200
|
+
"Код команды",
|
|
201
|
+
"Командный код"
|
|
202
|
+
],
|
|
203
|
+
"description": "Название провайдера и расширения Command Code (commandcode.ai)"
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|