@goodandready/dsh-russian-lang 0.3.10 → 0.3.11
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
CHANGED
|
@@ -12,9 +12,9 @@
|
|
|
12
12
|
</p>
|
|
13
13
|
|
|
14
14
|
<p align="center">
|
|
15
|
-
<img src="https://img.shields.io/badge/DSH-v0.1.7--rc.
|
|
15
|
+
<img src="https://img.shields.io/badge/DSH-v0.1.7--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-8110-6366f1.svg?style=for-the-badge&labelColor=1e1b4b" alt="8110 ключей">
|
|
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
|
|
|
@@ -52,9 +52,9 @@ graph LR
|
|
|
52
52
|
DSH[Web UI Интерфейс] --> Loader[Загрузчик локализации dsh-russian-lang]
|
|
53
53
|
end
|
|
54
54
|
|
|
55
|
-
subgraph TranslationLayer [Слой перевода и адаптации —
|
|
56
|
-
Loader --> CoreDict[
|
|
57
|
-
Loader --> PluginDict[
|
|
55
|
+
subgraph TranslationLayer [Слой перевода и адаптации — 8110 ключей / 100% вычитано]
|
|
56
|
+
Loader --> CoreDict[59 Пространств имён ядра DSH / 2415 ключей]
|
|
57
|
+
Loader --> PluginDict[65+ Плагинов экосистемы DSH / 5695 ключей]
|
|
58
58
|
Loader --> PluralEngine[Движок грамматических Plural-форм: 1/2/5]
|
|
59
59
|
end
|
|
60
60
|
|
|
@@ -85,7 +85,7 @@ graph LR
|
|
|
85
85
|
|
|
86
86
|
## ✨ Полный обзор возможностей
|
|
87
87
|
|
|
88
|
-
### 1. 🌐 100% покрытие ядра DSH (
|
|
88
|
+
### 1. 🌐 100% покрытие ядра DSH (59 Пространств имён, 2415 ключей)
|
|
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
|
+
> **О качестве перевода.** Все **8110 ключей интерфейса (2146 ядра + 6589 плагинов) переведены на 100% и вычитаны вручную**. Черновой машинный перевод полностью замещён проверенными формулировками (`draft = 0`). Перевод регулярно валидируется автоматическими линтерами целостности плейсхолдеров, проверкой соблюдения глоссария (`glossary.json`) и детекторами переполнения верстки. Нашли неточность — кнопка «Сообщить о проблеме перевода» в карточке настроек создаёт готовый issue.
|
|
98
98
|
|
|
99
|
-
### 2. 🧩 Встроенный перевод
|
|
99
|
+
### 2. 🧩 Встроенный перевод 65+ плагинов экосистемы DSH (5695 ключей)
|
|
100
100
|
Локализация автоматически распространяется на все ключевые плагины экосистемы DeepSeek Harness:
|
|
101
101
|
* **`dsh-session-control`** — расширенное управление сессиями: закрепление диалогов, архив по периодам, просмотр расшифровок и фильтрация шума;
|
|
102
102
|
* **`dsh-kanban` и `task-board`** — канбан-доски задач, карточки, чек-листы, дедлайны, критерии готовности (DoD) и шлюз приёмки (Acceptance Gate);
|
package/lib/client.js
CHANGED
|
@@ -390,7 +390,7 @@ if (res.matched) {results.push({ item: cmd, ...res })
|
|
|
390
390
|
}}
|
|
391
391
|
return results.sort((a, b) => b.score - a.score).map((r) => r.item)
|
|
392
392
|
}
|
|
393
|
-
const RU = {"common":{"back":"Назад","
|
|
393
|
+
const RU = {"common":{"back":"Назад","cancel":"Отмена","close":"Закрыть","collapse":"Свернуть","copied":"Скопировано","copy":"Копировать","delete":"Удалить","edit":"Изменить","expand":"Развернуть","loading":"Загрузка…","more":"Ещё","next":"Дальше","ok":"ОК","retry":"Повторить","save":"Сохранить","search":"Поиск","submit":"Отправить"},"dsh-cron":{"sidebar.label":"Задачи по расписанию"},"dsh-usage-stats":{"footer.todayLabel":"Сегодня"},"pluginMarket":{"trigger":"Магазин плагинов"}}
|
|
394
394
|
const ZH_RU = {}
|
|
395
395
|
RU['russian-lang'] = {"cardTitle":"Русская локализация","cardSub":"Язык интерфейса, типографика, раскладка","badgeRu":"🟢 RU активен","badgeEn":"⚪ EN активен","badgeCoverage":"🟢 100% (7,902 ключа)","badgeSmartUx":"⚡ Smart UX активен","secLanguage":"🌐 Язык интерфейса","secLanguageDesc":"Нативное переключение языка интерфейса DSH на русский без перезагрузки страницы.","enabled":"Русский язык включён","enabledDesc":"Переключает язык интерфейса DeepSeek Harness на русский.","quickSwitchNote":"Быстрый переключатель RU ⇄ EN доступен в шапке сессии рядом с кнопками диалога.","secTypography":"✍️ Умная типографика и ввод (Smart UX)","secTypographyDesc":"Автоматическое улучшение текстов по нормам русской типографики во время диалога и набора.","typography":"Типографика вывода","typographyDesc":"Исправляет типографику ответов модели: кавычки-«ёлочки», тире («—») вместо дефисов, неразрывные пробелы после предлогов.","yo":"Буква «ё»","yoDesc":"Восстанавливать «ё» в частых словах (ещё, чёрный, идёт и др.), написанных через «е». Неоднозначные слова (все/всё) не трогаются.","liveInput":"Живая типографика инпута","liveInputDesc":"Форматировать текст сообщения перед отправкой: кавычки «», тире — и неразрывные пробелы. Внимание: изменяет отправляемый агенту текст (команды и флаги с латиницей защищены).","slashAliases":"Русские алиасы команд","slashAliasesDesc":"Поддержка русских команд: /цель -> /goal, /сжать -> /compact, /план -> /plan, /справка -> /help, /память -> /memory.","altLHintText":"Мгновенная конвертация раскладки текущего поля (ghbdtn ⇄ привет, /vjltkm ⇄ /model). В углу поля ввода также отображается метка раскладки.","secAgentPrompt":"🤖 Системный промпт агента","secAgentPromptDesc":"Официальная секция расширения DSH systemPrompt для ведения диалога на русском языке.","agentPrompt":"Русский промпт агента","agentPromptDesc":"Добавляет в системный промпт инструкцию отвечать по-русски в выбранном стиле.","agentPromptPreset":"Стиль ответов агента","presetExpert":"Технический эксперт (строгая терминология, чистый код)","presetWriter":"Технический писатель (Markdown, таблицы, ГОСТ)","presetConcise":"Лаконичный режим (кратко, без лишней воды)","presetReviewer":"Код-ревьюер (поиск багов, безопасность, аудит)","presetArchitect":"Системный архитектор (контракты, масштабируемость)","presetTutor":"Наставник (понятные объяснения, пошаговый разбор)","secUpdater":"🔄 Обновление языкового пакета","secUpdaterDesc":"Проверка наличия новых релизов в реестре npm и обновление в один клик.","updaterCurrent":"Текущая версия: v{version}","updaterLatest":"Доступна новая версия: v{version}","updaterUpToDate":"Установлена актуальная версия","updaterChecking":"Проверка…","updaterCheckBtn":"Проверить обновления","updaterBtn":"Обновить до v{version} в 1 клик","updaterUpdating":"Установка обновления…","updaterSuccess":"✅ Плагин успешно обновлён! Перезапустите DSH для применения.","updaterFailed":"❌ Не удалось проверить/обновить плагин. Проверьте сеть или логи сервера.","badgeUpdateAvailable":"Доступно обновление","badgeUpToDate":"Актуальная версия","secTranslator":"🌐 Перевод сообщений ассистента","secTranslatorDesc":"Настройка перевода ответов модели в чате на русский язык (локально в Docker или онлайн).","translateEngine":"Движок перевода","engineOff":"Выключен (по умолчанию, без сетевых вызовов)","engineLocal":"Локальный LibreTranslate (приватно, ~600 МБ RAM)","engineGoogle":"Google Translate (онлайн)","googleWarn":"⚠️ Внимание: при онлайн-переводе текст сообщений ассистента передаётся на публичные серверы Google для перевода на лету. Не используйте для конфиденциальных данных.","localStatusRunning":"🟢 Контейнер LibreTranslate активен","localStatusStopped":"⚪ Контейнер LibreTranslate не запущен","localStartBtn":"Запустить LibreTranslate в Docker (~600 МБ RAM)","localStarting":"Запуск контейнера…","localInfo":"LibreTranslate запускается изолированно в Docker на сервере, потребляет ~500–700 МБ RAM и переводит на 100% локально.","secOverrides":"✍️ Пользовательские переопределения (Custom Overrides)","secOverridesDesc":"Возможность заменить любую формулировку интерфейса DSH на собственную. Переопределения сохраняются в настройках и имеют наивысший приоритет.","overrideKeyPlaceholder":"Ключ (например, common.back или settings.title)","overrideValuePlaceholder":"Ваш русский перевод","overrideAddBtn":"Добавить","overrideEmpty":"Переопределений пока нет.","overrideDelete":"Удалить","overrideTip":"💡 Совет: зажмите Alt и кликните на любой переведённый элемент интерфейса, чтобы открыть всплывающий инспектор перевода и сразу изменить формулировку.","secSupport":"📊 Покрытие экосистемы и поддержка","secSupportDesc":"Словари синхронизированы с DSH v0.1.6-alpha.1. 100.0% UI-покрытие ядра и всех установленных плагинов (7,902 ключа) без черновых машинных переводов.","statNamespaces":"Пространств имён","statCoreKeys":"Ключей ядра","statPluginKeys":"Ключей плагинов","overridesCount":"Своих переопределений","statusLoading":"Настройки загружаются…","statusUnavailable":"Настройки недоступны на этом хосте","translateTurn":"Перевести на русский","reportIssue":"Сообщить о неточности перевода","exportMdHint":"Экспорт диалога в Markdown доступен по кнопке [ 📥 MD ] в шапке сессии.","translateTurnHint":"Перевод ответов ассистента на русский доступен по кнопке [ RU ↗ ] на блоках сообщений."}
|
|
396
396
|
const SETTINGS_NS_NAME = 'russian-lang'
|
|
@@ -1113,7 +1113,7 @@ setTimeout(() => { copyKeyBtn.textContent = '📋' }, 1500)
|
|
|
1113
1113
|
}}
|
|
1114
1114
|
const copyReportBtn = modal.querySelector('.rl-copy-report-btn')
|
|
1115
1115
|
if (copyReportBtn) {copyReportBtn.onclick = () => {const snippet = typeof generateBugReportSnippet === 'function'
|
|
1116
|
-
? generateBugReportSnippet({ key: k, ns, original: origText || rawText, current: rawText, override: textarea.value.trim(), pkgVersion: '0.3.
|
|
1116
|
+
? generateBugReportSnippet({ key: k, ns, original: origText || rawText, current: rawText, override: textarea.value.trim(), pkgVersion: '0.3.11' })
|
|
1117
1117
|
: ('### Репорт: ' + (k || rawText) + '\n- Исходный: ' + (origText || rawText) + '\n- Перевод: ' + textarea.value.trim())
|
|
1118
1118
|
try { navigator.clipboard.writeText(snippet) } catch (err) { void err; }
|
|
1119
1119
|
copyReportBtn.textContent = '✓ Скопировано'
|
|
@@ -1400,7 +1400,7 @@ const [snap, setSnap] = React.useState(() => (scope && scope.getSnapshot ? scope
|
|
|
1400
1400
|
const [ruActive, setRuActive] = React.useState(() => { try { return runtime.getLocale().active === 'ru' } catch (e) { return false } })
|
|
1401
1401
|
const [typo, setTypoState] = React.useState(() =>
|
|
1402
1402
|
(snap.value && snap.value.typography) || {})
|
|
1403
|
-
const [upStatus, setUpStatus] = React.useState({currentVersion: '0.3.
|
|
1403
|
+
const [upStatus, setUpStatus] = React.useState({currentVersion: '0.3.11',latestVersion: undefined,updateAvailable: false
|
|
1404
1404
|
})
|
|
1405
1405
|
const [upLoading, setUpLoading] = React.useState(false)
|
|
1406
1406
|
const [upMsg, setUpMsg] = React.useState(null)
|
|
@@ -1493,7 +1493,7 @@ scope.set('agentPromptPreset', val)
|
|
|
1493
1493
|
} catch (err) { console.warn('dsh-russian-lang: set agentPromptPreset failed', err) }}},React.createElement('option', { value: 'technical_expert' }, t('presetExpert')),React.createElement('option', { value: 'tech_writer' }, t('presetWriter')),React.createElement('option', { value: 'concise' }, t('presetConcise')),React.createElement('option', { value: 'code_reviewer' }, t('presetReviewer')),React.createElement('option', { value: 'architect' }, t('presetArchitect')),React.createElement('option', { value: 'tutor' }, t('presetTutor')))),presetInfo ? React.createElement('div', { className: 'rl-preview-box' },React.createElement('div', { style: { fontWeight: 600, marginBottom: '4px', color: 'var(--dsw-alias-label-primary)' } }, '💬 ' + presetInfo.label + ':'),presetInfo.text
|
|
1494
1494
|
) : null
|
|
1495
1495
|
) : null
|
|
1496
|
-
),React.createElement('div', { className: 'rl-section-card' },React.createElement('div', { className: 'rl-section-title' },React.createElement('span', null, t('secUpdater')),React.createElement('span', { className: 'rl-badge ' + (upStatus.updateAvailable ? 'rl-badge-warn' : 'rl-badge-ok') },upStatus.updateAvailable ? t('badgeUpdateAvailable') : t('badgeUpToDate'))),React.createElement('div', { className: 'rl-section-desc' }, t('secUpdaterDesc')),React.createElement('div', { className: 'rl-item-card' },React.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: '8px' } },React.createElement('div', null,React.createElement('div', { style: { fontWeight: 600, color: 'var(--dsw-alias-label-primary)' } },t('updaterCurrent').replace('{version}', upStatus.currentVersion || '0.3.
|
|
1496
|
+
),React.createElement('div', { className: 'rl-section-card' },React.createElement('div', { className: 'rl-section-title' },React.createElement('span', null, t('secUpdater')),React.createElement('span', { className: 'rl-badge ' + (upStatus.updateAvailable ? 'rl-badge-warn' : 'rl-badge-ok') },upStatus.updateAvailable ? t('badgeUpdateAvailable') : t('badgeUpToDate'))),React.createElement('div', { className: 'rl-section-desc' }, t('secUpdaterDesc')),React.createElement('div', { className: 'rl-item-card' },React.createElement('div', { style: { display: 'flex', justifyContent: 'space-between', alignItems: 'center', flexWrap: 'wrap', gap: '8px' } },React.createElement('div', null,React.createElement('div', { style: { fontWeight: 600, color: 'var(--dsw-alias-label-primary)' } },t('updaterCurrent').replace('{version}', upStatus.currentVersion || '0.3.11')),upStatus.updateAvailable
|
|
1497
1497
|
? React.createElement('div', { style: { color: 'var(--dsw-alias-state-warning-primary)', marginTop: '2px', fontWeight: 500 } },t('updaterLatest').replace('{version}', upStatus.latestVersion || ''))
|
|
1498
1498
|
: React.createElement('div', { style: { color: 'var(--dsw-alias-label-secondary)', marginTop: '2px' } },t('updaterUpToDate'))),upStatus.updateAvailable
|
|
1499
1499
|
? React.createElement('button', {type: 'button',className: 'rl-btn rl-btn-primary',disabled: upLoading,onClick: triggerUpdate,}, upLoading ? t('updaterUpdating') : t('updaterBtn').replace('{version}', upStatus.latestVersion || ''))
|
|
@@ -1531,7 +1531,7 @@ if (!input) return
|
|
|
1531
1531
|
try {const parsed = JSON.parse(input)
|
|
1532
1532
|
if (parsed && typeof parsed === 'object') {const merged = Object.assign({}, overrides, parsed)
|
|
1533
1533
|
scope.set('overrides', merged)
|
|
1534
|
-
}} catch (err) { alert('Ошибка разбора JSON: ' + (err && err.message || err)) }}}, '📥 Импорт JSON'))),React.createElement('div', { className: 'rl-section-card' },React.createElement('div', { className: 'rl-section-title' },React.createElement('span', null, t('secSupport')),React.createElement('span', { className: 'rl-badge rl-badge-ok' }, '🟢 100.0%')),React.createElement('div', { className: 'rl-section-desc' }, t('secSupportDesc')),React.createElement('div', { className: 'rl-grid-3' },React.createElement('div', { className: 'rl-stat-box' },React.createElement('div', { className: 'rl-stat-val' }, '113'),React.createElement('div', { className: 'rl-stat-label' }, t('statNamespaces'))),React.createElement('div', { className: 'rl-stat-box' },React.createElement('div', { className: 'rl-stat-val' }, '1 225'),React.createElement('div', { className: 'rl-stat-label' }, t('statCoreKeys'))),React.createElement('div', { className: 'rl-stat-box' },React.createElement('div', { className: 'rl-stat-val' }, '5 924'),React.createElement('div', { className: 'rl-stat-label' }, t('statPluginKeys')))),React.createElement('div', { className: 'rl-actions-row' },React.createElement('a', {href: makeIssueUrl({}, '0.3.
|
|
1534
|
+
}} catch (err) { alert('Ошибка разбора JSON: ' + (err && err.message || err)) }}}, '📥 Импорт JSON'))),React.createElement('div', { className: 'rl-section-card' },React.createElement('div', { className: 'rl-section-title' },React.createElement('span', null, t('secSupport')),React.createElement('span', { className: 'rl-badge rl-badge-ok' }, '🟢 100.0%')),React.createElement('div', { className: 'rl-section-desc' }, t('secSupportDesc')),React.createElement('div', { className: 'rl-grid-3' },React.createElement('div', { className: 'rl-stat-box' },React.createElement('div', { className: 'rl-stat-val' }, '113'),React.createElement('div', { className: 'rl-stat-label' }, t('statNamespaces'))),React.createElement('div', { className: 'rl-stat-box' },React.createElement('div', { className: 'rl-stat-val' }, '1 225'),React.createElement('div', { className: 'rl-stat-label' }, t('statCoreKeys'))),React.createElement('div', { className: 'rl-stat-box' },React.createElement('div', { className: 'rl-stat-val' }, '5 924'),React.createElement('div', { className: 'rl-stat-label' }, t('statPluginKeys')))),React.createElement('div', { className: 'rl-actions-row' },React.createElement('a', {href: makeIssueUrl({}, '0.3.11'),target: '_blank',rel: 'noopener noreferrer',className: 'rl-btn rl-btn-primary'
|
|
1535
1535
|
}, '💬 ' + t('reportIssue')),React.createElement('div', { className: 'rl-hint-text', style: { flex: 1 } },t('exportMdHint')))))))
|
|
1536
1536
|
}
|
|
1537
1537
|
const RL_CSS = ['.rl-modal-mask{position:fixed;top:0;left:0;width:100vw;height:100vh;background:var(--dsw-alias-bg-mask);display:flex;align-items:center;justify-content:center;z-index:99999;backdrop-filter:blur(2px)}.rl-modal-box{background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l1);border-radius:10px;width:calc(100vw - 40px);max-width:500px;box-shadow:var(--dsw-alias-shadow-l3);display:flex;flex-direction:column;gap:12px;padding:18px}.rl-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none;overflow:hidden;transition:border-color .15s ease}.rl-head{appearance:none;width:100%;font:inherit;color:inherit;text-align:left;cursor:pointer;background:0 0;border:0;border-radius:12px;display:flex;align-items:center;gap:12px;padding:14px 18px}.rl-head:hover{background:var(--dsw-alias-bg-layer-2)}.rl-head-main{flex:1;display:flex;flex-direction:column;gap:4px}.rl-title{color:var(--dsw-alias-label-primary);font-size:16px;font-weight:600;line-height:1.4;display:flex;align-items:center;flex-wrap:wrap;gap:8px}.rl-sub{color:var(--dsw-alias-label-secondary);font-size:13px}.rl-chev{margin-left:auto;flex:none;color:var(--dsw-alias-label-tertiary);display:inline-flex;transition:transform .16s}.rl-chev-open{transform:rotate(180deg)}.rl-body{border-top:1px solid var(--dsw-alias-border-l2);padding:18px}.rl-page{display:flex;flex-direction:column;gap:16px;max-width:960px}.rl-section-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:10px;padding:16px 18px;display:flex;flex-direction:column;gap:12px}.rl-section-title{font-size:14px;font-weight:600;color:var(--dsw-alias-label-primary);display:flex;align-items:center;justify-content:space-between;gap:8px}.rl-section-desc{font-size:12px;color:var(--dsw-alias-label-secondary);margin-top:-4px;line-height:1.4}.rl-grid-2{display:grid;grid-template-columns:repeat(auto-fit, minmax(280px, 1fr));gap:10px}.rl-grid-3{display:grid;grid-template-columns:repeat(auto-fit, minmax(140px, 1fr));gap:10px}.rl-badge{font-size:11px;padding:2px 8px;border-radius:999px;border:1px solid var(--dsw-alias-border-l2);display:inline-flex;align-items:center;gap:4px;font-weight:500}.rl-badge-ok{border-color:var(--dsw-alias-state-success-primary);color:var(--dsw-alias-state-success-primary);background:color-mix(in srgb, var(--dsw-alias-state-success-primary) 8%, transparent)}.rl-badge-warn{border-color:var(--dsw-alias-state-warning-primary);color:var(--dsw-alias-state-warning-primary);background:color-mix(in srgb, var(--dsw-alias-state-warning-primary) 8%, transparent)}.rl-badge-dim{border-color:var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);background:var(--dsw-alias-bg-layer-3)}.rl-item-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:4px}.rl-item-head{display:flex;align-items:center;justify-content:space-between;gap:8px}.rl-item-label{font-size:13px;font-weight:500;color:var(--dsw-alias-label-primary);display:flex;align-items:center;gap:8px;cursor:pointer}.rl-item-desc{font-size:11px;color:var(--dsw-alias-label-secondary);line-height:1.4}.rl-stat-box{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:8px;padding:10px 12px;display:flex;flex-direction:column;gap:2px}.rl-stat-val{font-size:16px;font-weight:700;color:var(--dsw-alias-label-primary)}.rl-stat-label{font-size:11px;color:var(--dsw-alias-label-secondary);letter-spacing:0.3px}.rl-hotkey-box{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:8px;padding:10px 12px;font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.4;display:flex;align-items:flex-start;gap:10px}.rl-hotkey-tag{font-size:11px;font-weight:700;padding:2px 6px;border-radius:4px;background:var(--dsw-alias-bg-layer-1);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-primary);white-space:nowrap}.rl-preview-box{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:8px;padding:10px 12px;font-size:12px;color:var(--dsw-alias-label-secondary);line-height:1.4}.rl-btn{appearance:none;font:inherit;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);border-radius:8px;padding:6px 12px;font-size:12px;background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);font-weight:500;display:inline-flex;align-items:center;justify-content:center;gap:6px;transition:all .15s ease;text-decoration:none}.rl-btn:hover:not(:disabled){background:var(--dsw-alias-bg-layer-1);border-color:var(--dsw-alias-label-secondary)}.rl-btn-primary{background:var(--dsw-alias-label-primary);color:var(--dsw-alias-bg-layer-3);border-color:transparent}.rl-btn-primary:hover:not(:disabled){opacity:0.9}.rl-select{height:32px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-primary);border-radius:6px;padding:0 8px;font-size:12px;outline:none;width:100%;max-width:380px}.rl-select:focus{border-color:var(--dsw-alias-state-brand-primary)}.rl-check{width:16px;height:16px;accent-color:var(--dsw-alias-label-primary);cursor:pointer;flex-shrink:0}.rl-hint-text{font-size:11px;color:var(--dsw-alias-label-secondary);line-height:1.4}.rl-actions-row{display:flex;flex-wrap:wrap;align-items:center;gap:12px;padding-top:4px}.rl-lang-chip{appearance:none;cursor:pointer;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);color:var(--dsw-alias-label-secondary);font-size:11px;font-weight:700;padding:2px 7px;border-radius:6px;display:inline-flex;align-items:center;transition:all .15s;margin:0 4px}.rl-lang-chip:hover{border-color:var(--dsw-alias-label-primary);color:var(--dsw-alias-label-primary)}.rl-lang-chip-active{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2)}.rl-action-btn{appearance:none;background:0 0;border:1px solid transparent;border-radius:4px;color:var(--dsw-alias-label-secondary);cursor:pointer;font-size:11px;padding:2px 5px;display:inline-flex;align-items:center;transition:all .15s}.rl-action-btn:hover{color:var(--dsw-alias-label-primary);border-color:var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3)}.rl-action-btn-active{color:var(--dsw-alias-label-primary);background:var(--dsw-alias-bg-layer-2);border-color:var(--dsw-alias-border-l2)}.rl-turn-translation{margin:8px 0;padding:10px 12px;border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-2);border-radius:8px;font-size:13px;line-height:1.5}.rl-trans-head{display:flex;justify-content:space-between;align-items:center;margin-bottom:6px;border-bottom:1px solid var(--dsw-alias-border-l2);padding-bottom:4px}.rl-trans-title{font-size:11px;font-weight:600;color:var(--dsw-alias-label-secondary);text-transform:uppercase;letter-spacing:0.5px}.rl-trans-tools{display:flex;gap:4px}.rl-trans-btn{appearance:none;background:var(--dsw-alias-bg-layer-3);border:1px solid var(--dsw-alias-border-l2);color:var(--dsw-alias-label-secondary);cursor:pointer;padding:2px 7px;border-radius:4px;font-size:11px}.rl-trans-btn:hover{background:var(--dsw-alias-bg-layer-1);color:var(--dsw-alias-label-primary)}.rl-trans-body{color:var(--dsw-alias-label-primary);white-space:pre-wrap;word-break:break-word;user-select:text}.rl-export-md-btn{appearance:none;border:1px solid var(--dsw-alias-border-l2);height:32px;color:var(--dsw-alias-label-primary);cursor:pointer;background:transparent;border-radius:18px;justify-content:center;align-items:center;gap:4px;padding:6px 12px;font-size:13px;font-weight:500;display:inline-flex;white-space:nowrap;margin-left:6px;transition:all .15s ease}.rl-export-md-btn:hover{background:var(--dsw-alias-interactive-bg-hover)}.rl-inspector-hover{position:absolute;pointer-events:none;border:2px solid var(--dsw-alias-state-brand-primary);border-radius:4px;background:color-mix(in srgb,var(--dsw-alias-state-brand-primary) 12%,transparent);box-shadow:0 0 10px color-mix(in srgb,var(--dsw-alias-state-brand-primary) 30%,transparent);z-index:99998;transition:all .06s ease;display:none}.rl-inspector-badge{position:absolute;bottom:calc(100% + 4px);left:0;background:var(--dsw-alias-state-brand-primary);color:var(--dsw-alias-label-inverse);font-size:10px;font-weight:600;padding:2px 6px;border-radius:4px;white-space:nowrap;box-shadow:var(--dsw-alias-shadow-l2);pointer-events:none}.rl-inspector-pill{position:fixed;bottom:18px;right:18px;background:var(--dsw-alias-bg-layer-2);color:var(--dsw-alias-label-primary);border:1px solid var(--dsw-alias-border-l1);border-radius:20px;padding:6px 12px;box-shadow:var(--dsw-alias-shadow-l3);display:none;align-items:center;gap:8px;font-size:12px;z-index:99990;user-select:none}.rl-inspector-pill-active{border-color:var(--dsw-alias-state-brand-primary);box-shadow:0 0 12px color-mix(in srgb,var(--dsw-alias-state-brand-primary) 35%,transparent)}'
|