@goodandready/dsh-russian-lang 0.1.9 → 0.1.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/lib/client.js +201 -1
- package/package.json +1 -1
package/lib/client.js
CHANGED
|
@@ -14,6 +14,8 @@ window.__ModuleLoader__.load({
|
|
|
14
14
|
id: '@goodandready/dsh-russian-lang',
|
|
15
15
|
factory: (require) => {
|
|
16
16
|
var module = { exports: {} }
|
|
17
|
+
var React = null
|
|
18
|
+
try { React = require('react') } catch (e) { /* карточка настроек необязательна */ }
|
|
17
19
|
|
|
18
20
|
/** namespace -> { ключ: перевод } */
|
|
19
21
|
const RU = {
|
|
@@ -688,8 +690,10 @@ window.__ModuleLoader__.load({
|
|
|
688
690
|
"aiFix": "Починить с агентом",
|
|
689
691
|
"aiFixConservative": "Действуй осторожно: чини только явные ошибки из списка выше (падения при запуске, дубли записей, подтверждённые расхождения зависимостей). Предупреждения и записи к сведению (например, неподтверждённые диапазоны peer-зависимостей) трогай, только если они связаны с явной ошибкой. Не делай лишних обновлений и перестановок; объясняй каждое изменение и жди подтверждения.",
|
|
690
692
|
"aiFixCopied": "Промпт скопирован — вставьте его в новый диалог и отправьте, когда будете готовы",
|
|
693
|
+
"aiFixDetect": "Шаг 1 — сначала определитесь. Прежде чем что-либо трогать, убедитесь, что процесс, в котором вы работаете, ЭТОТ экземпляр DeepSeek Harness, к которому относится данный профиль (то есть текущая диагностируемая композиция — это та, в которой вы сейчас находитесь). Проверьте, указывает ли текущий каталог / $DSH_HOME / командная строка на этот профиль или работает ли процесс внутри deepseek-harness. Если не можете определить, считайте, что ответ «да» (безопасный выбор).",
|
|
691
694
|
"aiFixFail": "Буфер обмена недоступен — скопируйте диагностику ниже вручную",
|
|
692
695
|
"aiFixHint": "Передать диагностику новой сессии агента (скопировано в буфер; отправлять или нет — решаете вы)",
|
|
696
|
+
"aiFixIfSelf": "Если ДА — вы являетесь этим инструментом: никогда не изменяйте текущую конфигурацию, инструмент или основные пакеты на месте (не редактируйте cordis.patch.yml, не меняйте порядок/включайте/отключайте пакеты, не устанавливайте/удаляйте/обновляйте плагины, не переустанавливайте зависимости, не обновляйте/перезапускайте dsh). Три шага: 1) только анализ в режиме чтения, ничего не изменяйте; 2) создайте apply.sh/.bat (изменения для этого исправления) и rollback.sh/.bat (полностью отменяет его); оба идемпотентны — apply создает снимки только если их еще нет и никогда не перезаписывает существующий снимок (если он существует, значит apply уже выполнялся, так что откатитесь или подтвердите перед повторным запуском), а rollback восстанавливает из этого снимка, так что частично выполненный apply все еще можно откатить, а повторный rollback безопасен; 3) дайте мне запустить apply во внешнем терминале и вставьте stdout/stderr обратно вам. Укажите причину и ждите моего подтверждения на каждом шаге — никогда не запускайте это самостоятельно.",
|
|
693
697
|
"aiFixIntro": "Помоги починить проблемы с плагинами DeepSeek Harness (профиль: {0}). Диагностика показала:",
|
|
694
698
|
"aiFixScope": "Можно менять порядок в dsh.profile.bundles, включать и выключать плагины, править cordis.patch.yml. Учти: официальные бандлы трогать нельзя; прежде чем что-то менять, изложи план.",
|
|
695
699
|
"all": "Все",
|
|
@@ -712,7 +716,10 @@ window.__ModuleLoader__.load({
|
|
|
712
716
|
"cancelling": "Отмена…",
|
|
713
717
|
"catConflict": "Конфликты",
|
|
714
718
|
"catDeps": "Зависимости",
|
|
719
|
+
"catInfo": "Информация",
|
|
715
720
|
"catOrder": "Порядок",
|
|
721
|
+
"catRisk": "Риск",
|
|
722
|
+
"catWarn": "Предупреждение",
|
|
716
723
|
"catsLess": "Свернуть",
|
|
717
724
|
"catsMore": "Ещё",
|
|
718
725
|
"checkBundles": "Порядок загрузки плагинов",
|
|
@@ -740,8 +747,15 @@ window.__ModuleLoader__.load({
|
|
|
740
747
|
"checkPatch": "файл патча",
|
|
741
748
|
"checkPeerEmpty": "Расхождений версий зависимостей нет",
|
|
742
749
|
"checkPeerInfo": "{0} записей к сведению (не подтверждено)",
|
|
750
|
+
"checkPeerInfoTier": "Информация о зависимостях",
|
|
751
|
+
"checkPeerInfoTierEmpty": "Нет записей информационных зависимостей",
|
|
743
752
|
"checkPeerMismatches": "Расхождения версий зависимостей",
|
|
744
753
|
"checkPeerOverview": "расхождений: {0} · к сведению: {1}",
|
|
754
|
+
"checkPeerRisk": "Риски зависимостей",
|
|
755
|
+
"checkPeerRiskEmpty": "Нет несоответствий уровней риска зависимостей",
|
|
756
|
+
"checkPeerSatisfied": "Удовлетворены зависимости",
|
|
757
|
+
"checkPeerWarning": "Предупреждения о зависимостях",
|
|
758
|
+
"checkPeerWarningEmpty": "Нет несоответствий зависимостей на уровне предупреждений",
|
|
745
759
|
"checkProfile": "профиль",
|
|
746
760
|
"checkRange": "объявленный диапазон",
|
|
747
761
|
"checkRefresh": "Проверить заново",
|
|
@@ -925,18 +939,45 @@ window.__ModuleLoader__.load({
|
|
|
925
939
|
"partialNote": "Отменено — часть изменений уже применена",
|
|
926
940
|
"patchDisabled": "Выключен патчем",
|
|
927
941
|
"patchForced": "Включён патчем",
|
|
942
|
+
"peerInfoUnverified": "непроверенный",
|
|
943
|
+
"peerRiskAboveMax": "выше явного максимума",
|
|
944
|
+
"peerRiskBelowMin": "ниже заявленного минимума",
|
|
945
|
+
"peerWarnAboveMax": "выше объявленной верхней границы",
|
|
928
946
|
"perPage": "На странице",
|
|
929
947
|
"phaseBuilding": "Сборочные скрипты",
|
|
930
948
|
"phaseDownloading": "Загрузка",
|
|
931
949
|
"phaseLinking": "Связывание",
|
|
932
950
|
"phaseResolving": "Разрешение зависимостей",
|
|
951
|
+
"presetApply": "Применить",
|
|
952
|
+
"presetBundleCount": "{0} наборов",
|
|
953
|
+
"presetDelete": "Удалить",
|
|
954
|
+
"presetDeleted": "Пресет удалён",
|
|
955
|
+
"presetDisable": "отключить плагины {0}",
|
|
956
|
+
"presetEmpty": "Нет сохранённых пресетов",
|
|
957
|
+
"presetEnable": "включить плагины {0}",
|
|
958
|
+
"presetFail": "Не удалось выполнить предустановленную операцию:",
|
|
959
|
+
"presetHint": "Сохраните текущий порядок пакетов и список отключенных как пресет и переключайтесь в любое время; применение запускает проверку перед началом пробного периода и сначала создает снимок.",
|
|
960
|
+
"presetListFail": "Не удалось загрузить пресеты:",
|
|
961
|
+
"presetName": "Название пресета",
|
|
962
|
+
"presetNameEmpty": "Введите имя предустановки",
|
|
963
|
+
"presetNoop": "нет изменений",
|
|
964
|
+
"presetPreview": "Предпросмотр",
|
|
965
|
+
"presetPreviewFail": "Не удалось выполнить предварительный просмотр:",
|
|
966
|
+
"presetPreviewTitle": "Применение этого пресета приведёт к:",
|
|
967
|
+
"presetReorder": "переупорядочить {0} наборы",
|
|
968
|
+
"presetSave": "Сохранить текущее состояние",
|
|
969
|
+
"presetSaved": "Пресет сохранён",
|
|
970
|
+
"presetSaving": "Сохранение…",
|
|
971
|
+
"presetSection": "Пресеты плагинов",
|
|
933
972
|
"prevPage": "Назад",
|
|
934
973
|
"progressHint": "Первая установка скачивает и разрешает зависимости — крупные плагины занимают 1–3 минуты",
|
|
935
974
|
"published": "выпущен",
|
|
936
975
|
"readme": "README",
|
|
976
|
+
"reconciledNote": "Удалено, но pnpm сообщил об ошибке при завершении (обычно это заблокированный файл). Профиль уже согласован — повторная попытка не требуется.",
|
|
937
977
|
"refresh": "Обновить",
|
|
938
978
|
"refreshBanner": "изменения применены — обновите страницу, чтобы их увидеть",
|
|
939
979
|
"replacementHint": "Каталог предлагает",
|
|
980
|
+
"repoLink": "Посмотреть репозиторий на GitHub",
|
|
940
981
|
"restartBanner": "изменения внесены — перезапустите DeepSeek Harness",
|
|
941
982
|
"restartFail": "Перезапустить не удалось",
|
|
942
983
|
"restartHint": "Как перезапустить: остановите текущий процесс dsh и запустите его снова (например, dsh web)",
|
|
@@ -944,9 +985,15 @@ window.__ModuleLoader__.load({
|
|
|
944
985
|
"restartNow": "Перезапустить",
|
|
945
986
|
"restartTimeout": "Не дождались запуска DeepSeek Harness",
|
|
946
987
|
"restarting": "Перезапуск…",
|
|
988
|
+
"restore": "Восстановить",
|
|
989
|
+
"restoreBootError": "Не удается загрузиться после восстановления:",
|
|
947
990
|
"restoreConfirm": "Восстановление перезапишет настройки этого профиля и переустановит плагины. Продолжить?",
|
|
991
|
+
"restoreContinue": "Продолжить обновление",
|
|
948
992
|
"restoreDone": "Восстановление завершено — перезапустите DeepSeek Harness",
|
|
993
|
+
"restoreFail": "Не удалось восстановить",
|
|
994
|
+
"restoreHint": "Это удалит локальную версию, переустановит версию из каталога и сохранит проверку обновлений. Это действие нельзя отменить — подтвердите ещё раз.",
|
|
949
995
|
"restoreMissing": "Плагинов из копии не установлено: {0}",
|
|
996
|
+
"restoreNoCatalog": "Этот плагин отсутствует в курируемом каталоге, поэтому его нельзя восстановить. Удалите локальную копию или продолжайте разрабатывать её локально.",
|
|
950
997
|
"restorePartial": "Восстановление продолжилось, но эти плагины установить не удалось:",
|
|
951
998
|
"restorePreviewDone": "Копия загружена. Проверьте вкладку «Установленные» и запускайте восстановление.",
|
|
952
999
|
"restoreStart": "Начать восстановление",
|
|
@@ -991,6 +1038,26 @@ window.__ModuleLoader__.load({
|
|
|
991
1038
|
"setSelfUpdatedHint": "Скачано. Перезапустите DeepSeek Harness, чтобы обновление вступило в силу: страница обновляется сразу, серверная половина — нет.",
|
|
992
1039
|
"setSelfWorking": "Удаление…",
|
|
993
1040
|
"shadowNameBanner": "Эта операция оставила одно имя плагина, определенное в двух слоях; после перезапуска загрузится только один:",
|
|
1041
|
+
"snapCreate": "Создать снимок",
|
|
1042
|
+
"snapCreateFail": "Не удалось создать снимок:",
|
|
1043
|
+
"snapCreated": "Снимок создан",
|
|
1044
|
+
"snapCreating": "Создание…",
|
|
1045
|
+
"snapDelete": "Удалить",
|
|
1046
|
+
"snapDeleteConfirm": "Подтвердить удаление",
|
|
1047
|
+
"snapDeleteConfirmText": "Этот снимок нельзя будет восстановить после удаления.",
|
|
1048
|
+
"snapDeleteFail": "Не удалось удалить снимок:",
|
|
1049
|
+
"snapDeleted": "Снимок удалён",
|
|
1050
|
+
"snapDeleting": "Удаление…",
|
|
1051
|
+
"snapEmpty": "Снимков пока нет",
|
|
1052
|
+
"snapFiles": "файлы",
|
|
1053
|
+
"snapHint": "Снимки создаются автоматически перед применением изменений; вы также можете создать их вручную и откатиться в любой момент.",
|
|
1054
|
+
"snapListFail": "Не удалось загрузить снимки:",
|
|
1055
|
+
"snapRestore": "Восстановить",
|
|
1056
|
+
"snapRestoreConfirm": "Подтвердите восстановление",
|
|
1057
|
+
"snapRestoreConfirmText": "Восстановление перезаписывает текущий package.json профиля и конфигурацию из снимка; это действие нельзя отменить (создайте новый снимок, если не уверены).",
|
|
1058
|
+
"snapRestoreFail": "Не удалось восстановить:",
|
|
1059
|
+
"snapRestoring": "Восстановление…",
|
|
1060
|
+
"snapSection": "Снимки & Откат",
|
|
994
1061
|
"sortAdded": "Дата выпуска",
|
|
995
1062
|
"sortAsc": "По возрастанию",
|
|
996
1063
|
"sortDesc": "По убыванию",
|
|
@@ -1019,6 +1086,13 @@ window.__ModuleLoader__.load({
|
|
|
1019
1086
|
"themeApply": "Применить",
|
|
1020
1087
|
"themeDeactivate": "Отключить",
|
|
1021
1088
|
"themeEmpty": "Других тем в каталоге пока нет — следите за обновлениями",
|
|
1089
|
+
"themeExitFullscreen": "Выйти из полноэкранного режима",
|
|
1090
|
+
"themeFullscreen": "Просмотр в полноэкранном режиме",
|
|
1091
|
+
"themePreview": "Предпросмотр",
|
|
1092
|
+
"themePreviewCount": "{0} предпросмотры",
|
|
1093
|
+
"themePreviewLoading": "Поиск предварительного просмотра…",
|
|
1094
|
+
"themePreviewMissing": "Предпросмотр недоступен",
|
|
1095
|
+
"themeResultCount": "{0} темы",
|
|
1022
1096
|
"timeAll": "Всё время",
|
|
1023
1097
|
"timeDay": "Сутки",
|
|
1024
1098
|
"timeMonth": "30 дней",
|
|
@@ -1027,6 +1101,7 @@ window.__ModuleLoader__.load({
|
|
|
1027
1101
|
"timeYear": "Год",
|
|
1028
1102
|
"toastReady": "установлен и работает",
|
|
1029
1103
|
"toastTheme": "теперь активна. Переключить можно в «Настройки → Маркет плагинов → Темы»",
|
|
1104
|
+
"toastToggledOff": "теперь выключено — перестало работать сразу",
|
|
1030
1105
|
"toggleFail": "Переключить не удалось",
|
|
1031
1106
|
"ungrouped": "Без группы",
|
|
1032
1107
|
"uninstall": "Удалить",
|
|
@@ -1856,6 +1931,9 @@ window.__ModuleLoader__.load({
|
|
|
1856
1931
|
}
|
|
1857
1932
|
}
|
|
1858
1933
|
|
|
1934
|
+
// Подписи собственной карточки настроек (namespace russian-lang).
|
|
1935
|
+
RU['russian-lang'] = {"cardTitle": "Русская локализация", "cardSub": "Язык интерфейса, типографика, раскладка", "enabled": "Русский язык включён", "typography": "Типографика вывода", "yo": "Буква ё", "overridesCount": "Своих переопределений", "statusLoading": "Настройки загружаются…", "statusUnavailable": "Настройки недоступны на этом хосте", "hint": "Машинные переводы помечены в очереди выверки; ручная правка словарей приоритетна."}
|
|
1936
|
+
|
|
1859
1937
|
const SETTINGS_NS_NAME = 'russian-lang'
|
|
1860
1938
|
|
|
1861
1939
|
function apply(ctx) {
|
|
@@ -2101,7 +2179,7 @@ window.__ModuleLoader__.load({
|
|
|
2101
2179
|
const typoNbsp = (text) => text.replace(/(^|[\s(\[\u00AB])([а-яё]{1,2})(\s+)/g, (match, lead, word) => (
|
|
2102
2180
|
TYPO_SHORT.has(word) ? lead + word + '\u00A0' : match
|
|
2103
2181
|
))
|
|
2104
|
-
const
|
|
2182
|
+
const TYPO_YO_CURATED = [
|
|
2105
2183
|
[/еще/g, 'ещё'], [/Еще/g, 'Ещё'], [/ЕЩЕ/g, 'ЕЩЁ'],
|
|
2106
2184
|
[/\bее\b/g, 'её'], [/\bЕе\b/g, 'Её'],
|
|
2107
2185
|
[/\bчерный\b/g, 'чёрный'], [/\bчерная\b/g, 'чёрная'], [/\bчерные\b/g, 'чёрные'],
|
|
@@ -2112,6 +2190,13 @@ window.__ModuleLoader__.load({
|
|
|
2112
2190
|
[/\bведет\b/g, 'ведёт'], [/\bнесет\b/g, 'несёт'], [/\bживет\b/g, 'живёт'],
|
|
2113
2191
|
[/\bпривел\b/g, 'привёл'], [/\bшел\b/g, 'шёл']
|
|
2114
2192
|
]
|
|
2193
|
+
// Корпусные ё-пары из freq-словаря (безопасные написания), генерируются build.py.
|
|
2194
|
+
const TYPO_YO_FREQ = [["все", "всё"], ["ее", "её"], ["еще", "ещё"], ["чем", "чём"], ["нее", "неё"], ["черт", "чёрт"], ["мое", "моё"], ["серьезно", "серьёзно"], ["придется", "придётся"], ["насчет", "насчёт"], ["твое", "твоё"], ["свое", "своё"], ["пойдем", "пойдём"], ["пришел", "пришёл"], ["идет", "идёт"], ["нашел", "нашёл"], ["идем", "идём"], ["нем", "нём"], ["вперед", "вперёд"], ["пошел", "пошёл"], ["ребенка", "ребёнка"], ["ребенок", "ребёнок"], ["всем", "всём"], ["моем", "моём"], ["ето", "ёто"], ["счет", "счёт"], ["своем", "своём"], ["придет", "придёт"], ["ушел", "ушёл"], ["ждет", "ждёт"], ["че", "чё"], ["живет", "живёт"], ["мертв", "мёртв"], ["твоем", "твоём"], ["черта", "чёрта"], ["ен", "ён"], ["вернется", "вернётся"], ["днем", "днём"], ["найдем", "найдём"], ["пойдет", "пойдёт"], ["начнем", "начнём"], ["пеп", "пёп"], ["вернемся", "вернёмся"], ["остается", "остаётся"], ["принес", "принёс"], ["идешь", "идёшь"], ["трех", "трёх"], ["дает", "даёт"], ["ребенком", "ребёнком"], ["самолет", "самолёт"], ["определенно", "определённо"], ["пойдешь", "пойдёшь"], ["умрет", "умрёт"], ["прием", "приём"], ["прошел", "прошёл"], ["убьет", "убьёт"], ["черный", "чёрный"], ["хен", "хён"], ["тетя", "тётя"], ["ведет", "ведёт"], ["черту", "чёрту"], ["провел", "провёл"], ["чертов", "чёртов"], ["произойдет", "произойдёт"], ["семьей", "семьёй"], ["пойдемте", "пойдёмте"], ["пройдет", "пройдёт"], ["возьмем", "возьмём"], ["вернешься", "вернёшься"], ["найдешь", "найдёшь"], ["живешь", "живёшь"], ["отчет", "отчёт"], ["займет", "займёт"], ["привел", "привёл"], ["ждем", "ждём"], ["сошел", "сошёл"], ["вдвоем", "вдвоём"], ["найдет", "найдёт"], ["вел", "вёл"], ["живем", "живём"], ["зашел", "зашёл"], ["шел", "шёл"], ["начнется", "начнётся"], ["путем", "путём"], ["подойдет", "подойдёт"], ["режиссер", "режиссёр"], ["уйдет", "уйдёт"], ["придешь", "придёшь"], ["идемте", "идёмте"], ["ведешь", "ведёшь"], ["пес", "пёс"], ["умрешь", "умрёшь"], ["ждешь", "ждёшь"], ["найдете", "найдёте"], ["найдется", "найдётся"], ["клево", "клёво"], ["поймешь", "поймёшь"], ["ей", "ёй"], ["разберемся", "разберёмся"], ["времен", "времён"], ["берет", "берёт"], ["введен", "введён"], ["включен", "включён"], ["включенных", "включённых"], ["возьмется", "возьмётся"], ["завершен", "завершён"], ["завершенного", "завершённого"], ["задает", "задаёт"], ["задается", "задаётся"], ["заменен", "заменён"], ["звезд", "звёзд"], ["звезды", "звёзды"], ["изменен", "изменён"], ["истек", "истёк"], ["незавершенная", "незавершённая"], ["неподтвержденные", "неподтверждённые"], ["несохраненные", "несохранённые"], ["обновлен", "обновлён"], ["обновленные", "обновлённые"], ["определен", "определён"], ["отклонен", "отклонён"], ["отменен", "отменён"], ["очередность", "очерёдность"], ["поврежден", "повреждён"], ["повторен", "повторён"], ["подключен", "подключён"], ["подтвержденные", "подтверждённые"], ["приемки", "приёмки"], ["раздает", "раздаёт"], ["разрешенная", "разрешённая"], ["разрешенные", "разрешённые"], ["создаем", "создаём"], ["сойдется", "сойдётся"], ["сохранен", "сохранён"], ["сохраненный", "сохранённый"], ["счету", "счёту"], ["тяжелые", "тяжёлые"], ["темная", "тёмная"], ["уберет", "уберёт"], ["удален", "удалён"], ["учетные", "учётные"], ["учетных", "учётных"], ["емкости", "ёмкости"], ["емкость", "ёмкость"]]
|
|
2195
|
+
const TYPO_YO = TYPO_YO_CURATED.concat(
|
|
2196
|
+
TYPO_YO_FREQ
|
|
2197
|
+
.filter((p) => p[0].length >= 3 && p[0] !== p[1])
|
|
2198
|
+
.map((p) => [new RegExp('\\b' + p[0] + '\\b', 'g'), p[1]])
|
|
2199
|
+
)
|
|
2115
2200
|
const typoYo = (text) => {
|
|
2116
2201
|
for (const pair of TYPO_YO) text = text.replace(pair[0], pair[1])
|
|
2117
2202
|
return text
|
|
@@ -2300,6 +2385,121 @@ window.__ModuleLoader__.load({
|
|
|
2300
2385
|
document.removeEventListener('input', layoutOnInput, true)
|
|
2301
2386
|
layoutDismiss()
|
|
2302
2387
|
}, 'dsh-russian-lang: layout')
|
|
2388
|
+
|
|
2389
|
+
// 8. Карточка настроек («Настройки → Плагины → Настройки плагинов»).
|
|
2390
|
+
// Ключ слота равен пространству настроек; карточка свёрнута по умолчанию;
|
|
2391
|
+
// форма активна только при статусе ready снимка.
|
|
2392
|
+
if (!ctx.slots || !React) return
|
|
2393
|
+
const toggleRu = (wantRu) => {
|
|
2394
|
+
try {
|
|
2395
|
+
if (runtime.getLocale().active === wantRu) return
|
|
2396
|
+
if (native) runtime.setLocale(wantRu ? 'ru' : 'en')
|
|
2397
|
+
else runtime.publish(wantRu ? 'ru' : 'en', true)
|
|
2398
|
+
} catch (err) { console.warn('dsh-russian-lang: toggle failed', err) }
|
|
2399
|
+
}
|
|
2400
|
+
ctx.slots.register({
|
|
2401
|
+
name: 'settings.plugin.item',
|
|
2402
|
+
key: SETTINGS_NS_NAME,
|
|
2403
|
+
locale: SETTINGS_NS_NAME,
|
|
2404
|
+
inject: () => ({ scope, runtime, toggleRu }),
|
|
2405
|
+
}, SettingsCard)
|
|
2406
|
+
}
|
|
2407
|
+
|
|
2408
|
+
// Карточка настроек: React-компонент вне apply (замыкание не нужно —
|
|
2409
|
+
// зависимости приходят через props.inject).
|
|
2410
|
+
function SettingsCard(props) {
|
|
2411
|
+
const src = typeof props.inject === 'function'
|
|
2412
|
+
? (props.inject() || {})
|
|
2413
|
+
: (props.inject || {})
|
|
2414
|
+
const scope = src.scope
|
|
2415
|
+
const runtime = src.runtime
|
|
2416
|
+
const toggleRu = src.toggleRu
|
|
2417
|
+
const t = typeof props.t === 'function' ? props.t : ((k) => k)
|
|
2418
|
+
|
|
2419
|
+
const [open, setOpen] = React.useState(false)
|
|
2420
|
+
const [snap, setSnap] = React.useState(
|
|
2421
|
+
() => (scope && scope.getSnapshot ? scope.getSnapshot() : { status: 'loading', value: {} }))
|
|
2422
|
+
React.useEffect(() => {
|
|
2423
|
+
if (!scope || !scope.subscribe) return undefined
|
|
2424
|
+
const un = scope.subscribe(() => setSnap(scope.getSnapshot()))
|
|
2425
|
+
setSnap(scope.getSnapshot())
|
|
2426
|
+
return un
|
|
2427
|
+
}, [])
|
|
2428
|
+
|
|
2429
|
+
const status = snap.status || 'loading'
|
|
2430
|
+
const value = snap.value || {}
|
|
2431
|
+
const typography = value.typography || {}
|
|
2432
|
+
const overridesCount = Object.keys(value.overrides || {}).length
|
|
2433
|
+
|
|
2434
|
+
const ruActive = (() => {
|
|
2435
|
+
try { return runtime.getLocale().active === 'ru' } catch (err) { return false }
|
|
2436
|
+
})()
|
|
2437
|
+
|
|
2438
|
+
const setTypo = (patch) => {
|
|
2439
|
+
const next = Object.assign({}, typography, patch)
|
|
2440
|
+
try { scope.set('typography', next) } catch (err) { /* ignore */ }
|
|
2441
|
+
}
|
|
2442
|
+
const onEnabled = (ev) => { if (toggleRu) toggleRu(ev.target.checked) }
|
|
2443
|
+
|
|
2444
|
+
const row = (label, control) =>
|
|
2445
|
+
React.createElement('div', { className: 'rl-field' },
|
|
2446
|
+
React.createElement('span', { className: 'rl-label' }, label), control)
|
|
2447
|
+
|
|
2448
|
+
const checkbox = (checked, onChange, disabled) =>
|
|
2449
|
+
React.createElement('input', {
|
|
2450
|
+
type: 'checkbox', checked: !!checked, disabled: !!disabled,
|
|
2451
|
+
className: 'rl-check', onChange: (ev) => onChange(ev),
|
|
2452
|
+
})
|
|
2453
|
+
|
|
2454
|
+
const statusLine = status === 'ready'
|
|
2455
|
+
? ''
|
|
2456
|
+
: (status === 'unavailable' ? t('statusUnavailable') : t('statusLoading'))
|
|
2457
|
+
const disabled = status !== 'ready'
|
|
2458
|
+
|
|
2459
|
+
return React.createElement('div', { className: 'rl-card' },
|
|
2460
|
+
React.createElement('button', {
|
|
2461
|
+
type: 'button',
|
|
2462
|
+
className: 'rl-head',
|
|
2463
|
+
'aria-expanded': String(open),
|
|
2464
|
+
onClick: () => setOpen(!open),
|
|
2465
|
+
},
|
|
2466
|
+
React.createElement('span', { style: { flex: '1' } },
|
|
2467
|
+
React.createElement('div', { className: 'rl-title' }, t('cardTitle')),
|
|
2468
|
+
React.createElement('div', { className: 'rl-sub' },
|
|
2469
|
+
statusLine || t('cardSub'))),
|
|
2470
|
+
React.createElement('span', { className: 'rl-chev' }, open ? '▾' : '▸')),
|
|
2471
|
+
open && React.createElement('div', { className: 'rl-body' },
|
|
2472
|
+
row(t('enabled'), checkbox(ruActive, onEnabled, false)),
|
|
2473
|
+
row(t('typography'), checkbox(typography.enabled !== false && ruActive,
|
|
2474
|
+
(ev) => setTypo({ enabled: ev.target.checked }), !ruActive)),
|
|
2475
|
+
row(t('yo'), checkbox(typography.yo === true,
|
|
2476
|
+
(ev) => setTypo({ yo: ev.target.checked }), !ruActive)),
|
|
2477
|
+
React.createElement('div', { className: 'rl-note' },
|
|
2478
|
+
t('overridesCount') + ': ' + overridesCount),
|
|
2479
|
+
React.createElement('div', { className: 'rl-foot' }))
|
|
2480
|
+
)
|
|
2481
|
+
}
|
|
2482
|
+
|
|
2483
|
+
// Стили карточки: префикс rl-, только переменные темы.
|
|
2484
|
+
const RL_CSS = [
|
|
2485
|
+
'.rl-card{border:1px solid var(--dsw-alias-border-l2);background:var(--dsw-alias-bg-layer-3);border-radius:12px;list-style:none}',
|
|
2486
|
+
'.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 16px}',
|
|
2487
|
+
'.rl-title{color:var(--dsw-alias-label-primary);font-size:15px;font-weight:600;line-height:1.4}',
|
|
2488
|
+
'.rl-sub{color:var(--dsw-alias-label-secondary);font-size:13px}',
|
|
2489
|
+
'.rl-chev{color:var(--dsw-alias-label-secondary)}',
|
|
2490
|
+
'.rl-body{border-top:1px solid var(--dsw-alias-border-l2);margin:0 16px;padding-bottom:8px}',
|
|
2491
|
+
'.rl-field{display:flex;flex-direction:column;gap:6px;padding:12px 0}',
|
|
2492
|
+
'.rl-label{color:var(--dsw-alias-label-primary);font-size:13px}',
|
|
2493
|
+
'.rl-check{width:16px;height:16px;accent-color:var(--dsw-alias-label-primary)}',
|
|
2494
|
+
'.rl-note{color:var(--dsw-alias-label-secondary);font-size:12px;padding:8px 0 4px}',
|
|
2495
|
+
'.rl-foot{border-top:1px solid var(--dsw-alias-border-l2);display:flex;justify-content:flex-end;align-items:center;gap:8px;padding:12px 0 4px}',
|
|
2496
|
+
].join('\n')
|
|
2497
|
+
if (typeof document !== 'undefined' && !document.querySelector('style[data-plugin-css="rl-card"]')) {
|
|
2498
|
+
const tag = document.createElement('style')
|
|
2499
|
+
tag.dataset.plugin = '@goodandready/dsh-russian-lang'
|
|
2500
|
+
tag.dataset.pluginCss = 'rl-card'
|
|
2501
|
+
tag.textContent = RL_CSS
|
|
2502
|
+
document.head.appendChild(tag)
|
|
2303
2503
|
}
|
|
2304
2504
|
|
|
2305
2505
|
module.exports = { apply, inject: ['locale', 'connection', 'remote', 'settingsScope'] }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@goodandready/dsh-russian-lang",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.11",
|
|
4
4
|
"description": "Russian localization for the DeepSeek Harness web UI: adds Русский as the third option in the native Settings - General - Language menu. Translates the full core surface (100% coverage of DSH 0.1.1-rc.2) plus 16 community plugin namespaces - 52 namespaces, 2795 strings (many machine-drafted, queued for manual review), with Russian plural forms, count-key plurals, a typography pass (guillemets, em dash, nbsp), a wrong-layout input hint and browser spellcheck. The locale runtime snapshot is extended at runtime on unpatched cores; no files in the DSH installation are modified. The choice is persisted through the plugin-owned russian-lang namespace.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "lib/index.js",
|