@goodandready/dsh-russian-lang 0.3.15 → 0.3.17

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 CHANGED
@@ -1,9 +1,10 @@
1
1
  window.__ModuleLoader__.load({id: '@goodandready/dsh-russian-lang',factory: (require) => {var module = { exports: {} }
2
2
  var React = null
3
- try { React = require('react') } catch (e) { }
3
+ try { React = require('react') } catch (e) { void e; }
4
4
  let isInspectorActive = false
5
5
  let hoverBoxEl = null
6
6
  let pillEl = null
7
+ let updateInspectorPill = () => {}
7
8
  const numberFormat = new Intl.NumberFormat('ru-RU')
8
9
  const compactNumberFormat = new Intl.NumberFormat('ru-RU', { notation: 'compact', compactDisplay: 'short' })
9
10
  const relativeTimeFormat = new Intl.RelativeTimeFormat('ru-RU', { numeric: 'auto' })
@@ -396,8 +397,9 @@ RU['russian-lang'] = {"cardTitle":"Русская локализация","cardS
396
397
  const SETTINGS_NS_NAME = 'russian-lang'
397
398
  const FORM_NS = 'dsh-russian-lang'
398
399
  const LEGACY_NS = 'russian-lang'
399
- const ROW_CONFIG_KEY = '@goodandready/dsh-russian-lang#russian-lang'
400
+ const ROW_CONFIG_KEY = '@goodandready/dsh-russian-lang#' + FORM_NS
400
401
  function apply(ctx) {const runtime = ctx.locale
402
+ const configForms = ctx && ctx.configForms
401
403
  const resolveScope = (c) => {try {if (c && c.configForms) return c.configForms.get(FORM_NS)
402
404
  if (c && c.settingsScope) return c.settingsScope.bind({ namespace: LEGACY_NS })
403
405
  } catch (err) { void err }
@@ -416,7 +418,7 @@ if (typeof dict !== 'object' || !dict) continue
416
418
  if (!RU[ns]) {RU[ns] = dict
417
419
  ctx.effect(() => {try { return ctx.locale.register(ns, 'ru', dict) } catch (err) { return () => {} }}, 'dsh-russian-lang: ' + ns)
418
420
  } else {Object.assign(RU[ns], dict)
419
- try { ctx.locale.register(ns, 'ru', RU[ns]) } catch (_) {}}}}
421
+ try { ctx.locale.register(ns, 'ru', RU[ns]) } catch (_) { void _; }}}}
420
422
  const CACHE_NAME = 'dsh-ru-cache-v1'
421
423
  const loadLocalDict = (key) => {try {const raw = typeof localStorage !== 'undefined' ? localStorage.getItem('dsh_ru_' + key) : null
422
424
  return raw ? JSON.parse(raw) : null
@@ -501,13 +503,13 @@ return value && value.overrides ? value.overrides : {}} catch (err) { return {}
501
503
  const getPluginLocalizationStatus = makePluginLocalizationStatus(RU)
502
504
  const lookupChain = () => {try {const chain = runtime.fallbackChain && runtime.fallbackChain(runtime.getLocale().active)
503
505
  if (Array.isArray(chain) && chain.length) return chain
504
- } catch (err) { }
506
+ } catch (err) { void err; }
505
507
  return [runtime.getLocale().active]
506
508
  }
507
509
  const translationRegistry = new Map()
508
510
  const lookup = (ns, key) => (runtime.lookup.length >= 3 ? runtime.lookup(ns, key, lookupChain()) : runtime.lookup(ns, key))
509
511
  const syncLang = () => {try {if (typeof document !== 'undefined' && document.documentElement && runtime.getLocale().active === 'ru') document.documentElement.lang = 'ru-RU'
510
- } catch (err) { }}
512
+ } catch (err) { void err; }}
511
513
  const RUNTIME_PROP_NAMES = ['plural','pluralForm','formatDate','formatCompactNumber','formatTokens','formatNumber','formatRelativeTime','formatCurrency','inflect','getPluginLocalizationStatus','stemRussian','fuzzyMatchRu','humanizeError']
512
514
  ctx.effect(() => {const origTranslate = runtime.translate
513
515
  const origProps = {}
@@ -542,7 +544,7 @@ return () => {runtime.translate = origTranslate
542
544
  for (const p of RUNTIME_PROP_NAMES) {if (origProps[p] !== undefined) runtime[p] = origProps[p]
543
545
  else delete runtime[p]
544
546
  }
545
- if (typeof removeLang === 'function') { try { removeLang() } catch (_) { } }}}, 'dsh-russian-lang: runtime-lifecycle')
547
+ if (typeof removeLang === 'function') { try { removeLang() } catch (_) { void _; } }}}, 'dsh-russian-lang: runtime-lifecycle')
546
548
  const syncFlag = () => {if (!legacyFlagMode) return
547
549
  try {const wantRu = runtime.getLocale().active === 'ru'
548
550
  const value = scope.getSnapshot().value || {}
@@ -558,7 +560,7 @@ runtime.setLocale('ru')
558
560
  let booted = false
559
561
  const tryBoot = () => {if (booted) return
560
562
  try {const value = scope.getSnapshot().value
561
- if (legacyFlagMode && value && value.enabled === true) { booted = true; activate() }} catch (err) { }}
563
+ if (legacyFlagMode && value && value.enabled === true) { booted = true; activate() }} catch (err) { void err; }}
562
564
  ctx.effect(() => scope.subscribe(tryBoot), 'dsh-russian-lang: boot')
563
565
  tryBoot()
564
566
  const unsubscribeLang = runtime.subscribe(syncLang)
@@ -602,11 +604,11 @@ if (node.matches(EDITABLE)) spellOn(node)
602
604
  node.querySelectorAll ? node.querySelectorAll(EDITABLE).forEach(spellOn) : null
603
605
  }}})
604
606
  spellObserver.observe(document.body, { childList: true, subtree: true })
605
- } catch (err) { }}
607
+ } catch (err) { void err; }}
606
608
  const unsubscribeSpell = runtime.subscribe(syncSpell)
607
609
  ctx.effect(() => {return () => {unsubscribeSpell()
608
610
  if (spellObserver) spellObserver.disconnect()
609
- try { document.querySelectorAll('[' + SPELL_ON + ']').forEach(spellOff) } catch (err) { }}}, 'dsh-russian-lang: spellcheck')
611
+ try { document.querySelectorAll('[' + SPELL_ON + ']').forEach(spellOff) } catch (err) { void err; }}}, 'dsh-russian-lang: spellcheck')
610
612
  syncSpell()
611
613
  const ZH_CJK = /[\u3400-\u9fff\uf900-\ufaff]/
612
614
  const ZH_RE_ESC = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')
@@ -667,9 +669,10 @@ const trimmed = val.trim()
667
669
  if (curOverrides[trimmed] !== undefined) {node.nodeValue = val.replace(trimmed, curOverrides[trimmed])
668
670
  continue
669
671
  }
670
- if (trimmed.length >= 1 && ZH_CJK.test(val)) {hits.push(node)
671
- } else if (trimmed.length >= 1 && DOM_EN_TEXT[trimmed]) {const p = node.parentElement
672
- if (p && !p.closest('code, pre, script, style, textarea, input, select, kbd, samp, [contenteditable="true"], [data-composer-input], [role="textbox"]')) {node.nodeValue = val.replace(trimmed, DOM_EN_TEXT[trimmed])
672
+ const p = node.parentElement
673
+ const isProtected = p && p.closest('code, pre, script, style, textarea, input, select, kbd, samp, [contenteditable="true"], [data-composer-input], [role="textbox"], .chat-message, .markdown-body')
674
+ if (trimmed.length >= 1 && ZH_CJK.test(val)) {if (!isProtected) hits.push(node)
675
+ } else if (trimmed.length >= 1 && DOM_EN_TEXT[trimmed]) {if (!isProtected) {node.nodeValue = val.replace(trimmed, DOM_EN_TEXT[trimmed])
673
676
  }}}
674
677
  for (const node of hits) {const next = zhTranslateText(node.nodeValue)
675
678
  if (next && next !== node.nodeValue) node.nodeValue = next
@@ -685,7 +688,7 @@ if (root.getAttribute) {for (const attr of ['title', 'placeholder', 'aria-label'
685
688
  if (v) {const tr = v.trim()
686
689
  if (DOM_EN_TEXT[tr]) root.setAttribute(attr, v.replace(tr, DOM_EN_TEXT[tr]))
687
690
  else if (DOM_EN_ATTRS[tr]) root.setAttribute(attr, v.replace(tr, DOM_EN_ATTRS[tr]))
688
- }}}} catch (err) { }}
691
+ }}}} catch (err) { void err; }}
689
692
  let zhObserver = null
690
693
  let zhDebounceTimer = null
691
694
  let zhWalking = false
@@ -715,7 +718,7 @@ document.addEventListener('pointerup', onInteraction, { passive: true })
715
718
  document.addEventListener('click', onInteraction, { passive: true })
716
719
  }
717
720
  queueZhWalk()
718
- } catch (err) { }}
721
+ } catch (err) { void err; }}
719
722
  const unsubscribeZh = runtime.subscribe(syncZhDom)
720
723
  ctx.effect(() => {return () => {unsubscribeZh()
721
724
  if (zhObserver) zhObserver.disconnect()
@@ -759,7 +762,7 @@ for (const root of typoPending) {if (root.nodeType === 3) typoNode(root, conf)
759
762
  else typoWalk(root, conf)
760
763
  }
761
764
  typoPending.clear()
762
- } catch (err) { }}
765
+ } catch (err) { void err; }}
763
766
  const typoPending = new Set()
764
767
  const queueTypo = (roots) => {for (const r of roots) typoPending.add(r)
765
768
  if (!typoQueued) typoQueued = requestAnimationFrame(flushTypo)
@@ -776,7 +779,7 @@ for (const record of records) {if (record.type === 'childList') {for (const adde
776
779
  if (roots.length > 0) queueTypo(roots)
777
780
  })
778
781
  typoObserver.observe(document.body, { childList: true, subtree: true })
779
- } catch (err) { }}
782
+ } catch (err) { void err; }}
780
783
  const unsubscribeTypo = runtime.subscribe(syncTypo)
781
784
  ctx.effect(() => {return () => {unsubscribeTypo()
782
785
  if (typoObserver) typoObserver.disconnect()
@@ -951,7 +954,7 @@ if (c) { layoutShowHint(el, c.converted, 'ru'); return }}
951
954
  if (cyrCount > 0 && latCount === 0 && value.trim().startsWith('/')) {const c = layoutFixCandidate(value, 'cyr2lat')
952
955
  if (c) { layoutShowHint(el, c.converted, 'cmd'); return }}
953
956
  layoutDismiss()
954
- } catch (err) { }}
957
+ } catch (err) { void err; }}
955
958
  const unsubscribeLayout = runtime.subscribe(layoutOnInput)
956
959
  const layoutOnKeydown = (ev) => {const el = layoutCurrentInput(ev)
957
960
  if (!el) return
@@ -1038,7 +1041,7 @@ document.body.appendChild(hoverBoxEl)
1038
1041
  }
1039
1042
  return hoverBoxEl
1040
1043
  }
1041
- const updateInspectorPill = () => {if (typeof document === 'undefined') return
1044
+ updateInspectorPill = () => {if (typeof document === 'undefined') return
1042
1045
  if (!pillEl) {pillEl = document.createElement('div')
1043
1046
  pillEl.id = 'dsh-ru-inspector-pill'
1044
1047
  pillEl.className = 'rl-inspector-pill'
@@ -1051,7 +1054,7 @@ if (hoverBoxEl) hoverBoxEl.style.display = 'none'
1051
1054
  document.body.appendChild(pillEl)
1052
1055
  }
1053
1056
  pillEl.style.display = isInspectorActive ? 'flex' : 'none'
1054
- if (isInspectorActive) pillEl.classList.add('rl-inspector-pill-active')
1057
+ if (isInspectorActive && pillEl.classList) pillEl.classList.add('rl-inspector-pill-active')
1055
1058
  }
1056
1059
  const openInspectorModal = (meta, rawText, targetElement) => {if (typeof document === 'undefined') return
1057
1060
  if (hoverBoxEl) hoverBoxEl.style.display = 'none'
@@ -1126,7 +1129,7 @@ setTimeout(() => { copyKeyBtn.textContent = '📋' }, 1500)
1126
1129
  }}
1127
1130
  const copyReportBtn = modal.querySelector('.rl-copy-report-btn')
1128
1131
  if (copyReportBtn) {copyReportBtn.onclick = () => {const snippet = typeof generateBugReportSnippet === 'function'
1129
- ? generateBugReportSnippet({ key: k, ns, original: origText || rawText, current: rawText, override: textarea.value.trim(), pkgVersion: '0.3.15' })
1132
+ ? generateBugReportSnippet({ key: k, ns, original: origText || rawText, current: rawText, override: textarea.value.trim(), pkgVersion: '0.3.16' })
1130
1133
  : ('### Репорт: ' + (k || rawText) + '\n- Исходный: ' + (origText || rawText) + '\n- Перевод: ' + textarea.value.trim())
1131
1134
  try { navigator.clipboard.writeText(snippet) } catch (err) { void err; }
1132
1135
  copyReportBtn.textContent = '✓ Скопировано'
@@ -1243,28 +1246,29 @@ if (!ctx.slots || !React) return
1243
1246
  const toggleRu = (wantRu) => {try {if (runtime.getLocale().active === wantRu) return
1244
1247
  runtime.setLocale(wantRu ? 'ru' : 'en')
1245
1248
  } catch (err) { console.warn('dsh-russian-lang: toggle failed', err) }}
1246
- try {ctx.slots.inject('plugins.item', () =>
1247
- ctx.slots.register({name: 'plugins.item',id: SETTINGS_NS_NAME,order: 60,label: () => 'Russian language',locale: SETTINGS_NS_NAME,inject: () => ({ scope, runtime, toggleRu }),}, SettingsCard),)
1249
+ const registerPluginsItem = () => {ctx.slots.inject('plugins.item', () =>
1250
+ ctx.slots.register({name: 'plugins.item',id: FORM_NS,order: 60,label: () => 'Russian language',locale: SETTINGS_NS_NAME,inject: () => ({ scope, runtime, toggleRu }),}, SettingsCard),)
1251
+ }
1252
+ if (typeof configForms?.whileServed === 'function') {ctx.effect(() => configForms.whileServed([FORM_NS], registerPluginsItem), 'dsh-russian-lang: plugins.item')
1253
+ } else {registerPluginsItem()
1254
+ }
1248
1255
  ctx.slots.inject('plugins.row.config', () =>
1249
1256
  ctx.slots.register({name: 'plugins.row.config',key: ROW_CONFIG_KEY,locale: SETTINGS_NS_NAME,inject: () => ({ scope, runtime, toggleRu }),}, SettingsCard),)
1250
- ctx.slots.inject('settings.plugin.item', () =>
1251
- ctx.slots.register({name: 'settings.plugin.item',key: SETTINGS_NS_NAME,locale: SETTINGS_NS_NAME,inject: () => ({ scope, runtime, toggleRu }),}, SettingsCard),)
1252
- } catch (err) { console.warn('dsh-russian-lang: settings slot unavailable', err) }
1253
1257
  try {ctx.slots.inject('conversation.session.header.utilities', () =>
1254
1258
  ctx.slots.register({name: 'conversation.session.header.utilities',id: 'dsh-russian-lang-quick-switch',order: 100,locale: SETTINGS_NS_NAME,inject: () => ({ runtime, toggleRu }),}, QuickLangSwitch),)
1255
- } catch (err) { }
1259
+ } catch (err) { void err; }
1256
1260
  try {ctx.slots.inject('conversation.chat.assistant-actions', () =>
1257
1261
  ctx.slots.register({name: 'conversation.chat.assistant-actions',id: 'dsh-russian-lang-translate-action',order: 50,locale: SETTINGS_NS_NAME,inject: () => ({ runtime }),}, TranslateTurnAction),)
1258
- } catch (err) { }
1262
+ } catch (err) { void err; }
1259
1263
  try {ctx.slots.inject('conversation.session.header.utilities', () =>
1260
1264
  ctx.slots.register({name: 'conversation.session.header.utilities',id: 'dsh-russian-lang-md-export',order: 101,locale: SETTINGS_NS_NAME,inject: () => ({ runtime }),}, ExportMarkdownButton),)
1261
- } catch (err) { }}
1265
+ } catch (err) { void err; }}
1262
1266
  function QuickLangSwitch(props) {const inj = typeof props.inject === 'function' ? (props.inject() || {}) : (props.inject || {})
1263
1267
  const runtime = props.runtime || inj.runtime
1264
1268
  const toggleRu = props.toggleRu || inj.toggleRu
1265
1269
  const [locale, setLocaleState] = React.useState(runtime ? (runtime.getLocale().active || 'en') : 'ru')
1266
1270
  React.useEffect(() => {if (!runtime) return
1267
- return runtime.subscribe(() => {try { setLocaleState(runtime.getLocale().active || 'en') } catch (e) { }})
1271
+ return runtime.subscribe(() => {try { setLocaleState(runtime.getLocale().active || 'en') } catch (e) { void e; }})
1268
1272
  }, [runtime])
1269
1273
  const isRu = locale === 'ru'
1270
1274
  return React.createElement('button', {type: 'button',className: 'rl-lang-chip' + (isRu ? ' rl-lang-chip-active' : ''),title: isRu ? 'Интерфейс: Русский (нажмите для переключения на EN)' : 'Interface: English (click for RU)',onClick: () => { if (toggleRu) toggleRu(!isRu) },}, React.createElement('span', { className: 'rl-lang-text' }, isRu ? 'RU' : 'EN'))
@@ -1413,7 +1417,7 @@ const [snap, setSnap] = React.useState(() => (scope && scope.getSnapshot ? scope
1413
1417
  const [ruActive, setRuActive] = React.useState(() => { try { return runtime.getLocale().active === 'ru' } catch (e) { return false } })
1414
1418
  const [typo, setTypoState] = React.useState(() =>
1415
1419
  (snap.value && snap.value.typography) || {})
1416
- const [upStatus, setUpStatus] = React.useState({currentVersion: '0.3.15',latestVersion: undefined,updateAvailable: false
1420
+ const [upStatus, setUpStatus] = React.useState({currentVersion: '0.3.16',latestVersion: undefined,updateAvailable: false
1417
1421
  })
1418
1422
  const [upLoading, setUpLoading] = React.useState(false)
1419
1423
  const [upMsg, setUpMsg] = React.useState(null)
@@ -1461,7 +1465,7 @@ if (s.value && s.value.typography) setTypoState(s.value.typography)
1461
1465
  setSnap(scope.getSnapshot())
1462
1466
  return un
1463
1467
  }, [scope])
1464
- React.useEffect(() => {try {const un = runtime.subscribe(() => {try { setRuActive(runtime.getLocale().active === 'ru') } catch (e) { }})
1468
+ React.useEffect(() => {try {const un = runtime.subscribe(() => {try { setRuActive(runtime.getLocale().active === 'ru') } catch (e) { void e; }})
1465
1469
  return un
1466
1470
  } catch (e) { return undefined }}, [runtime])
1467
1471
  const status = snap.status || 'loading'
@@ -1506,7 +1510,7 @@ scope.set('agentPromptPreset', val)
1506
1510
  } 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
1507
1511
  ) : null
1508
1512
  ) : null
1509
- ),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.15')),upStatus.updateAvailable
1513
+ ),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.16')),upStatus.updateAvailable
1510
1514
  ? React.createElement('div', { style: { color: 'var(--dsw-alias-state-warning-primary)', marginTop: '2px', fontWeight: 500 } },t('updaterLatest').replace('{version}', upStatus.latestVersion || ''))
1511
1515
  : React.createElement('div', { style: { color: 'var(--dsw-alias-label-secondary)', marginTop: '2px' } },t('updaterUpToDate'))),upStatus.updateAvailable
1512
1516
  ? React.createElement('button', {type: 'button',className: 'rl-btn rl-btn-primary',disabled: upLoading,onClick: triggerUpdate,}, upLoading ? t('updaterUpdating') : t('updaterBtn').replace('{version}', upStatus.latestVersion || ''))
@@ -1539,12 +1543,12 @@ try { scope.set('overrides', next) } catch (_e) { void _e }},}, t('overrideDelet
1539
1543
  updateInspectorPill()
1540
1544
  },}, isInspectorActive ? '🔍 Инспектор перевода (включён)' : '🔍 Включить инспектор перевода (Alt+I)'),React.createElement('button', {type: 'button',className: 'rl-btn',style: { fontSize: '11px' },onClick: () => {try {navigator.clipboard.writeText(JSON.stringify(overrides, null, 2))
1541
1545
  alert('Оверрайды скопированы в буфер обмена как JSON!')
1542
- } catch (err) { void err; }}}, '📤 Экспорт JSON'),React.createElement('button', {type: 'button',className: 'rl-btn',style: { fontSize: '11px' },onClick: () => {const input = prompt('Вставьте JSON с оверрайдами:')
1546
+ } catch (err) { void err; }}}, '📤 Экспорт JSON'),React.createElement('button', {type: 'button',className: 'rl-btn',style: { fontSize: '11px' },onClick: () => {const input = typeof window !== 'undefined' && typeof window.prompt === 'function' ? window.prompt('Вставьте JSON с оверрайдами:') : null
1543
1547
  if (!input) return
1544
1548
  try {const parsed = JSON.parse(input)
1545
1549
  if (parsed && typeof parsed === 'object') {const merged = Object.assign({}, overrides, parsed)
1546
1550
  scope.set('overrides', merged)
1547
- }} 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.15'),target: '_blank',rel: 'noopener noreferrer',className: 'rl-btn rl-btn-primary'
1551
+ }} 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.16'),target: '_blank',rel: 'noopener noreferrer',className: 'rl-btn rl-btn-primary'
1548
1552
  }, '💬 ' + t('reportIssue')),React.createElement('div', { className: 'rl-hint-text', style: { flex: 1 } },t('exportMdHint')))))))
1549
1553
  }
1550
1554
  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)}'
@@ -15,11 +15,12 @@ window.__ModuleLoader__.load({
15
15
  factory: (require) => {
16
16
  var module = { exports: {} }
17
17
  var React = null
18
- try { React = require('react') } catch (e) { /* карточка настроек необязательна */ }
18
+ try { React = require('react') } catch (e) { /* карточка настроек необязательна */ void e; }
19
19
 
20
20
  let isInspectorActive = false
21
21
  let hoverBoxEl = null
22
22
  let pillEl = null
23
+ let updateInspectorPill = () => {}
23
24
 
24
25
  //__PURE_JS__
25
26
 
@@ -39,10 +40,11 @@ window.__ModuleLoader__.load({
39
40
  const FORM_NS = 'dsh-russian-lang'
40
41
  const LEGACY_NS = 'russian-lang'
41
42
  // Plugins page row seat (DSH 0.1.6-alpha.2): key = '<package name>#<row id>'.
42
- const ROW_CONFIG_KEY = '@goodandready/dsh-russian-lang#russian-lang'
43
+ const ROW_CONFIG_KEY = '@goodandready/dsh-russian-lang#' + FORM_NS
43
44
 
44
45
  function apply(ctx) {
45
46
  const runtime = ctx.locale
47
+ const configForms = ctx && ctx.configForms
46
48
  const resolveScope = (c) => {
47
49
  try {
48
50
  if (c && c.configForms) return c.configForms.get(FORM_NS)
@@ -84,7 +86,7 @@ window.__ModuleLoader__.load({
84
86
  }, 'dsh-russian-lang: ' + ns)
85
87
  } else {
86
88
  Object.assign(RU[ns], dict)
87
- try { ctx.locale.register(ns, 'ru', RU[ns]) } catch (_) {}
89
+ try { ctx.locale.register(ns, 'ru', RU[ns]) } catch (_) { /* bestEffort */ void _; }
88
90
  }
89
91
  }
90
92
  }
@@ -248,7 +250,7 @@ window.__ModuleLoader__.load({
248
250
  try {
249
251
  const chain = runtime.fallbackChain && runtime.fallbackChain(runtime.getLocale().active)
250
252
  if (Array.isArray(chain) && chain.length) return chain
251
- } catch (err) { /* ignore */ }
253
+ } catch (err) { /* ignore */ void err; }
252
254
  return [runtime.getLocale().active]
253
255
  }
254
256
  const translationRegistry = new Map()
@@ -256,7 +258,7 @@ window.__ModuleLoader__.load({
256
258
  const syncLang = () => {
257
259
  try {
258
260
  if (typeof document !== 'undefined' && document.documentElement && runtime.getLocale().active === 'ru') document.documentElement.lang = 'ru-RU'
259
- } catch (err) { /* ignore */ }
261
+ } catch (err) { /* ignore */ void err; }
260
262
  }
261
263
  const RUNTIME_PROP_NAMES = ['plural','pluralForm','formatDate','formatCompactNumber','formatTokens','formatNumber','formatRelativeTime','formatCurrency','inflect','getPluginLocalizationStatus','stemRussian','fuzzyMatchRu','humanizeError']
262
264
  ctx.effect(() => {
@@ -305,7 +307,7 @@ window.__ModuleLoader__.load({
305
307
  if (origProps[p] !== undefined) runtime[p] = origProps[p]
306
308
  else delete runtime[p]
307
309
  }
308
- if (typeof removeLang === 'function') { try { removeLang() } catch (_) { /* bestEffort */ } }
310
+ if (typeof removeLang === 'function') { try { removeLang() } catch (_) { /* bestEffort */ void _; } }
309
311
  }
310
312
  }, 'dsh-russian-lang: runtime-lifecycle')
311
313
 
@@ -349,7 +351,7 @@ window.__ModuleLoader__.load({
349
351
  try {
350
352
  const value = scope.getSnapshot().value
351
353
  if (legacyFlagMode && value && value.enabled === true) { booted = true; activate() }
352
- } catch (err) { /* ignore */ }
354
+ } catch (err) { /* ignore */ void err; }
353
355
  }
354
356
  ctx.effect(() => scope.subscribe(tryBoot), 'dsh-russian-lang: boot')
355
357
  tryBoot()
@@ -418,14 +420,14 @@ window.__ModuleLoader__.load({
418
420
  }
419
421
  })
420
422
  spellObserver.observe(document.body, { childList: true, subtree: true })
421
- } catch (err) { /* ignore */ }
423
+ } catch (err) { /* ignore */ void err; }
422
424
  }
423
425
  const unsubscribeSpell = runtime.subscribe(syncSpell)
424
426
  ctx.effect(() => {
425
427
  return () => {
426
428
  unsubscribeSpell()
427
429
  if (spellObserver) spellObserver.disconnect()
428
- try { document.querySelectorAll('[' + SPELL_ON + ']').forEach(spellOff) } catch (err) { /* ignore */ }
430
+ try { document.querySelectorAll('[' + SPELL_ON + ']').forEach(spellOff) } catch (err) { /* ignore */ void err; }
429
431
  }
430
432
  }, 'dsh-russian-lang: spellcheck')
431
433
  syncSpell()
@@ -795,11 +797,12 @@ window.__ModuleLoader__.load({
795
797
  node.nodeValue = val.replace(trimmed, curOverrides[trimmed])
796
798
  continue
797
799
  }
800
+ const p = node.parentElement
801
+ const isProtected = p && p.closest('code, pre, script, style, textarea, input, select, kbd, samp, [contenteditable="true"], [data-composer-input], [role="textbox"], .chat-message, .markdown-body')
798
802
  if (trimmed.length >= 1 && ZH_CJK.test(val)) {
799
- hits.push(node)
803
+ if (!isProtected) hits.push(node)
800
804
  } else if (trimmed.length >= 1 && DOM_EN_TEXT[trimmed]) {
801
- const p = node.parentElement
802
- if (p && !p.closest('code, pre, script, style, textarea, input, select, kbd, samp, [contenteditable="true"], [data-composer-input], [role="textbox"]')) {
805
+ if (!isProtected) {
803
806
  node.nodeValue = val.replace(trimmed, DOM_EN_TEXT[trimmed])
804
807
  }
805
808
  }
@@ -834,7 +837,7 @@ window.__ModuleLoader__.load({
834
837
  }
835
838
  }
836
839
  }
837
- } catch (err) { /* ignore */ }
840
+ } catch (err) { /* ignore */ void err; }
838
841
  }
839
842
 
840
843
  let zhObserver = null
@@ -886,7 +889,7 @@ window.__ModuleLoader__.load({
886
889
  document.addEventListener('click', onInteraction, { passive: true })
887
890
  }
888
891
  queueZhWalk()
889
- } catch (err) { /* ignore */ }
892
+ } catch (err) { /* ignore */ void err; }
890
893
  }
891
894
  const unsubscribeZh = runtime.subscribe(syncZhDom)
892
895
  ctx.effect(() => {
@@ -965,7 +968,7 @@ window.__ModuleLoader__.load({
965
968
  else typoWalk(root, conf)
966
969
  }
967
970
  typoPending.clear()
968
- } catch (err) { /* ignore */ }
971
+ } catch (err) { /* ignore */ void err; }
969
972
  }
970
973
  const typoPending = new Set()
971
974
  const queueTypo = (roots) => {
@@ -993,7 +996,7 @@ window.__ModuleLoader__.load({
993
996
  if (roots.length > 0) queueTypo(roots)
994
997
  })
995
998
  typoObserver.observe(document.body, { childList: true, subtree: true })
996
- } catch (err) { /* ignore */ }
999
+ } catch (err) { /* ignore */ void err; }
997
1000
  }
998
1001
  const unsubscribeTypo = runtime.subscribe(syncTypo)
999
1002
  ctx.effect(() => {
@@ -1274,7 +1277,7 @@ window.__ModuleLoader__.load({
1274
1277
  if (c) { layoutShowHint(el, c.converted, 'cmd'); return }
1275
1278
  }
1276
1279
  layoutDismiss()
1277
- } catch (err) { /* ignore */ }
1280
+ } catch (err) { /* ignore */ void err; }
1278
1281
  }
1279
1282
  const unsubscribeLayout = runtime.subscribe(layoutOnInput)
1280
1283
 
@@ -1438,7 +1441,7 @@ window.__ModuleLoader__.load({
1438
1441
  return hoverBoxEl
1439
1442
  }
1440
1443
 
1441
- const updateInspectorPill = () => {
1444
+ updateInspectorPill = () => {
1442
1445
  if (typeof document === 'undefined') return
1443
1446
  if (!pillEl) {
1444
1447
  pillEl = document.createElement('div')
@@ -1454,7 +1457,7 @@ window.__ModuleLoader__.load({
1454
1457
  document.body.appendChild(pillEl)
1455
1458
  }
1456
1459
  pillEl.style.display = isInspectorActive ? 'flex' : 'none'
1457
- if (isInspectorActive) pillEl.classList.add('rl-inspector-pill-active')
1460
+ if (isInspectorActive && pillEl.classList) pillEl.classList.add('rl-inspector-pill-active')
1458
1461
  }
1459
1462
 
1460
1463
  const openInspectorModal = (meta, rawText, targetElement) => {
@@ -1734,34 +1737,37 @@ window.__ModuleLoader__.load({
1734
1737
  // ядро (0.1.6-alpha.2) рендерит как страницу плагина с настройками. label —
1735
1738
  // статичная строка: он резолвится во время рендера страницы, и обращение к
1736
1739
  // локали там роняет весь клиентский батч. Прежние посадки сохранены фолбэками.
1737
- try {
1740
+ // Посадочные места карточки настроек плагина.
1741
+ // DSH 0.2.0-rc.1:
1742
+ // - plugins.item (#388): id = FORM_NS ('dsh-russian-lang'), монтируется через whileServed([FORM_NS])
1743
+ // - plugins.row.config (#387): key = '@goodandready/dsh-russian-lang#' + FORM_NS
1744
+ // - settings-plugin-item (#389): устаревший слот упразднен в DSH 0.2.0-rc.1, удален
1745
+ const registerPluginsItem = () => {
1738
1746
  ctx.slots.inject('plugins.item', () =>
1739
1747
  ctx.slots.register({
1740
1748
  name: 'plugins.item',
1741
- id: SETTINGS_NS_NAME,
1749
+ id: FORM_NS,
1742
1750
  order: 60,
1743
1751
  label: () => 'Russian language',
1744
1752
  locale: SETTINGS_NS_NAME,
1745
1753
  inject: () => ({ scope, runtime, toggleRu }),
1746
1754
  }, SettingsCard),
1747
1755
  )
1748
- ctx.slots.inject('plugins.row.config', () =>
1749
- ctx.slots.register({
1750
- name: 'plugins.row.config',
1751
- key: ROW_CONFIG_KEY,
1752
- locale: SETTINGS_NS_NAME,
1753
- inject: () => ({ scope, runtime, toggleRu }),
1754
- }, SettingsCard),
1755
- )
1756
- ctx.slots.inject('settings.plugin.item', () =>
1757
- ctx.slots.register({
1758
- name: 'settings.plugin.item',
1759
- key: SETTINGS_NS_NAME,
1760
- locale: SETTINGS_NS_NAME,
1761
- inject: () => ({ scope, runtime, toggleRu }),
1762
- }, SettingsCard),
1763
- )
1764
- } catch (err) { console.warn('dsh-russian-lang: settings slot unavailable', err) }
1756
+ }
1757
+ if (typeof configForms?.whileServed === 'function') {
1758
+ ctx.effect(() => configForms.whileServed([FORM_NS], registerPluginsItem), 'dsh-russian-lang: plugins.item')
1759
+ } else {
1760
+ registerPluginsItem()
1761
+ }
1762
+
1763
+ ctx.slots.inject('plugins.row.config', () =>
1764
+ ctx.slots.register({
1765
+ name: 'plugins.row.config',
1766
+ key: ROW_CONFIG_KEY,
1767
+ locale: SETTINGS_NS_NAME,
1768
+ inject: () => ({ scope, runtime, toggleRu }),
1769
+ }, SettingsCard),
1770
+ )
1765
1771
 
1766
1772
  // #158: Быстрый переключатель RU ⇄ EN в шапке сессии
1767
1773
  try {
@@ -1774,7 +1780,7 @@ window.__ModuleLoader__.load({
1774
1780
  inject: () => ({ runtime, toggleRu }),
1775
1781
  }, QuickLangSwitch),
1776
1782
  )
1777
- } catch (err) { /* ignore if slot not declared */ }
1783
+ } catch (err) { /* ignore if slot not declared */ void err; }
1778
1784
 
1779
1785
  // #158: Кнопка перевода реплики на русский в действиях ассистента
1780
1786
  try {
@@ -1787,7 +1793,7 @@ window.__ModuleLoader__.load({
1787
1793
  inject: () => ({ runtime }),
1788
1794
  }, TranslateTurnAction),
1789
1795
  )
1790
- } catch (err) { /* ignore if slot not declared */ }
1796
+ } catch (err) { /* ignore if slot not declared */ void err; }
1791
1797
 
1792
1798
  // #158: Экспорт сессии в Markdown
1793
1799
  try {
@@ -1800,7 +1806,7 @@ window.__ModuleLoader__.load({
1800
1806
  inject: () => ({ runtime }),
1801
1807
  }, ExportMarkdownButton),
1802
1808
  )
1803
- } catch (err) { /* ignore if slot not declared */ }
1809
+ } catch (err) { /* ignore if slot not declared */ void err; }
1804
1810
  }
1805
1811
 
1806
1812
  // Карточка настроек: React-компонент вне apply.
@@ -1820,7 +1826,7 @@ window.__ModuleLoader__.load({
1820
1826
  React.useEffect(() => {
1821
1827
  if (!runtime) return
1822
1828
  return runtime.subscribe(() => {
1823
- try { setLocaleState(runtime.getLocale().active || 'en') } catch (e) { /* ignore */ }
1829
+ try { setLocaleState(runtime.getLocale().active || 'en') } catch (e) { /* ignore */ void e; }
1824
1830
  })
1825
1831
  }, [runtime])
1826
1832
  const isRu = locale === 'ru'
@@ -2166,7 +2172,7 @@ window.__ModuleLoader__.load({
2166
2172
  React.useEffect(() => {
2167
2173
  try {
2168
2174
  const un = runtime.subscribe(() => {
2169
- try { setRuActive(runtime.getLocale().active === 'ru') } catch (e) { /* ignore */ }
2175
+ try { setRuActive(runtime.getLocale().active === 'ru') } catch (e) { /* ignore */ void e; }
2170
2176
  })
2171
2177
  return un
2172
2178
  } catch (e) { return undefined }
@@ -2586,7 +2592,7 @@ window.__ModuleLoader__.load({
2586
2592
  className: 'rl-btn',
2587
2593
  style: { fontSize: '11px' },
2588
2594
  onClick: () => {
2589
- const input = prompt('Вставьте JSON с оверрайдами:')
2595
+ const input = typeof window !== 'undefined' && typeof window.prompt === 'function' ? window.prompt('Вставьте JSON с оверрайдами:') : null
2590
2596
  if (!input) return
2591
2597
  try {
2592
2598
  const parsed = JSON.parse(input)
package/lib/locales.js CHANGED
@@ -79,7 +79,7 @@ export function getAllDictionaries() {
79
79
  export function getZhRuMap() {
80
80
  if (existsSync(ZH_RU_FILE)) {
81
81
  try {
82
- return JSON.parse(readFileSync(ZG_RU_FILE, "utf8"))
82
+ return JSON.parse(readFileSync(ZH_RU_FILE, "utf8"))
83
83
  } catch (_) { /* bestEffort */ void _; }
84
84
  }
85
85
  return {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@goodandready/dsh-russian-lang",
3
- "version": "0.3.15",
3
+ "version": "0.3.17",
4
4
  "description": "Russian localization for DeepSeek Harness (DSH v0.1.7-rc.1+) web UI: adds Русский as native language option. 100.0% coverage across 11,295 keys (127 namespaces). Features full DSH v0.1.7-rc.1 core support (terminal, archive, command palette, Auto review, trajectory, PTC/Creator presets) and complete GoodAndReady plugin catalog (subscriptions, tts, image-gen, voice, key-limits, notify, commandcode, plugin-console).",
5
5
  "type": "module",
6
6
  "main": "lib/index.js",
@@ -57,7 +57,7 @@
57
57
  },
58
58
  "peerDependencies": {
59
59
  "@deepseek-ai/cordis": "^4.0.1",
60
- "@deepseek-ai/dsh-settings": "^0.1.2-alpha.2"
60
+ "@deepseek-ai/dsh-settings": "^0.1.7-rc.2 || ^0.2.0-rc.1"
61
61
  },
62
62
  "repository": {
63
63
  "type": "git",