From 47deb5a983218182e999aedb60d3522fb9fb1876 Mon Sep 17 00:00:00 2001 From: Emre Sokullu Date: Mon, 2 Nov 2026 21:20:55 +0300 Subject: [PATCH] Number the answers on clarify cards and answer them with a digit Every answer on a clarify, permission or confirmation card now carries its number in a small square at the button's right edge, and typing that digit picks it. These cards interrupt a run and are usually settled with one click, so the keyboard is the faster path. The number lives in a data attribute that the stylesheet draws through ::after, not in the button's text. A card restored from saved chat HTML sends its own label back as the answer, so a digit inside that text would change what WebBrain receives. The empty alt text after the slash keeps the digit out of the button's accessible name, and aria-keyshortcuts announces the shortcut instead. A digit only counts as a shortcut where nothing else claims the keyboard: no focus, the composer, or the card itself, and only while that field is empty. Someone typing "2 pages please" into the composer keeps the character, and so does an answer that starts with a digit in the card's own field. The handler clicks the button instead of answering directly, so a permission card's label bookkeeping and a scheduled card's tab still go through one path. The skip-all-prompts button is not an answer and gets no number. The help panel's shortcut list gained the line in all 23 languages, and the lists that had drifted are back in step with en.js. Fifteen locales advertised Ctrl/Cmd+M for voice input, which neither build has a handler for, and left out Escape, which both of them do. Dutch held a "..." placeholder where the list belongs, and the Firefox German list claimed a second Escape stops a recording, which only Chrome can do. test/clarify-option-shortcuts.mjs runs the real card renderer, the real submit path and the keydown handler in Chromium and Firefox: the numbering, the square drawn from the attribute, the answer a digit sends, and the two cases where the digit stays text. Co-Authored-By: Claude Opus 5 --- package.json | 2 +- src/chrome/src/ui/locales/ar.js | 2 +- src/chrome/src/ui/locales/bn.js | 2 +- src/chrome/src/ui/locales/de.js | 2 +- src/chrome/src/ui/locales/en.js | 2 +- src/chrome/src/ui/locales/es.js | 2 +- src/chrome/src/ui/locales/fa.js | 2 +- src/chrome/src/ui/locales/fr.js | 2 +- src/chrome/src/ui/locales/he.js | 2 +- src/chrome/src/ui/locales/hi.js | 2 +- src/chrome/src/ui/locales/id.js | 2 +- src/chrome/src/ui/locales/ja.js | 2 +- src/chrome/src/ui/locales/ko.js | 2 +- src/chrome/src/ui/locales/ms.js | 2 +- src/chrome/src/ui/locales/nl.js | 2 +- src/chrome/src/ui/locales/pl.js | 2 +- src/chrome/src/ui/locales/pt.js | 2 +- src/chrome/src/ui/locales/ru.js | 2 +- src/chrome/src/ui/locales/th.js | 2 +- src/chrome/src/ui/locales/tl.js | 2 +- src/chrome/src/ui/locales/tr.js | 2 +- src/chrome/src/ui/locales/uk.js | 2 +- src/chrome/src/ui/locales/vi.js | 2 +- src/chrome/src/ui/locales/zh.js | 2 +- src/chrome/src/ui/sidepanel.js | 70 ++++++++++++ src/chrome/styles/sidepanel.css | 30 +++++ src/firefox/src/ui/locales/ar.js | 2 +- src/firefox/src/ui/locales/bn.js | 2 +- src/firefox/src/ui/locales/de.js | 2 +- src/firefox/src/ui/locales/en.js | 2 +- src/firefox/src/ui/locales/es.js | 2 +- src/firefox/src/ui/locales/fa.js | 2 +- src/firefox/src/ui/locales/fr.js | 2 +- src/firefox/src/ui/locales/he.js | 2 +- src/firefox/src/ui/locales/hi.js | 2 +- src/firefox/src/ui/locales/id.js | 2 +- src/firefox/src/ui/locales/ja.js | 2 +- src/firefox/src/ui/locales/ko.js | 2 +- src/firefox/src/ui/locales/ms.js | 2 +- src/firefox/src/ui/locales/nl.js | 2 +- src/firefox/src/ui/locales/pl.js | 2 +- src/firefox/src/ui/locales/pt.js | 2 +- src/firefox/src/ui/locales/ru.js | 2 +- src/firefox/src/ui/locales/th.js | 2 +- src/firefox/src/ui/locales/tl.js | 2 +- src/firefox/src/ui/locales/tr.js | 2 +- src/firefox/src/ui/locales/uk.js | 2 +- src/firefox/src/ui/locales/vi.js | 2 +- src/firefox/src/ui/locales/zh.js | 2 +- src/firefox/src/ui/sidepanel.js | 70 ++++++++++++ src/firefox/styles/sidepanel.css | 30 +++++ test/clarify-option-shortcuts.mjs | 175 ++++++++++++++++++++++++++++++ 52 files changed, 422 insertions(+), 47 deletions(-) create mode 100644 test/clarify-option-shortcuts.mjs diff --git a/package.json b/package.json index cba55e270..07e09f51c 100644 --- a/package.json +++ b/package.json @@ -107,7 +107,7 @@ "test:upload-owner": "node --test test/page-monitor-upload-owner.mjs test/page-monitor-upload-release.mjs", "test:shard:quick": "npm run test:cms && npm run test:markdown && npm run test:generative-media && npm run test:systemone && npm run test:systemone:fast && node --test test/guard-policy.mjs test/browser-dialogs.mjs test/capsolver-cloud-broker.mjs test/captcha-providers.mjs test/captcha-weighted-fallback.mjs test/captcha-hcaptcha-providers.mjs test/captcha-native-providers.mjs test/captcha-runtime-policy.mjs test/captcha-callback-bridge.mjs test/captcha-bridge-registration.mjs test/cookie-banner-host.mjs test/captcha-aws-recovery.mjs test/captcha-documented-contracts.mjs test/huggingface-signup-recovery.mjs test/trace-full-export.mjs test/slash-command-tab-ownership.mjs test/feedback-traces.mjs && npm run test:firefox-bidi && npm run test:billing-notice && npm run test:compass-quota && npm run test:provider-limits && npm run test:provider-catalog && npm run test:provider-instances:ui && npm run test:settings-pages:ui && npm run test:openrouter-capabilities && npm run test:anthropic && npm run test:browser-batch && npm run test:accessibility-tree-benchmark && npm run test:toolbar-guard && npm run test:cloud-bridge-approval && npm run test:discord && npm run test:pdf-read && npm run test:pdf-selection && npm run test:social-contract && npm run test:safesocial && npm run test:build-unpacked && npm run test:attachment-drop && npm run test:workflow-editor && node --test test/profile-sync-stats.mjs && node --test test/memcode-recall.mjs", "test:shard:runtime-unit": "node --test test/skill-download-wait.mjs && node --test test/agent-lifecycle.mjs test/runtime-startup.mjs test/run-ui-scheduled-lifecycle.mjs test/transport-deadlines.mjs test/cdp-worker-restart.mjs test/bot-memory.mjs test/bot-memory-click-guard.mjs test/bot-memory-registries.mjs test/bot-memory-cloud-controller.mjs test/cdp-clear-receipt.mjs test/cdp-field-submit-recovery.mjs test/conversation-persistence.mjs test/context-live-tool-group.mjs test/integration-races.mjs test/watch-completion-checkpoint.mjs test/runtime-model-identity.mjs test/provider-message-privacy.mjs test/runtime-task-authority.mjs test/planner-repair-authority.mjs test/runtime-progress-continuation.mjs test/chat-resume-chain.mjs test/chat-resume-completion.mjs test/native-chat-execution-ledger.mjs test/chat-send-dispatch-result.mjs test/chat-pre-enter-veto.mjs test/chat-reply-dedup-race.mjs test/memcode-lifecycle.mjs test/runtime-peer-review.mjs test/read-continuation-schema.mjs test/completion-submit-acknowledgement.mjs test/completion-live-status.mjs test/completion-iframe-submit.mjs test/form-validation-alert-readings.mjs test/control-effect-readings.mjs test/guard-reading-carry-over.mjs test/trusted-retry-readings.mjs test/completion-semantic-commit.mjs test/completion-diagnostics.mjs test/mastodon-publication.mjs test/calculator.mjs test/chat-recovery-protocol.mjs test/chat-pending-reconciliation.mjs test/semantic-page-retry.mjs test/pdf-detection.mjs test/runtime-lifecycle.mjs test/collection-read-progress.mjs test/document-read-progress.mjs test/network-lifecycle.mjs test/text-write-cancellation.mjs test/guard-advisory-writes.mjs test/trusted-field-preparation.mjs test/draftjs-text.mjs test/codemirror-text.mjs test/rich-text-frameworks.mjs test/cdp-managed-text-selection.mjs test/firefox-rich-text-readback.mjs test/contenteditable-beforeinput.mjs test/trusted-field-preparation-ownership.mjs test/typing-preparation-geometry.mjs test/chat-steering.mjs test/resource-mutation-guards.mjs test/action-guard-user-override.mjs test/guard-direct-override.mjs test/guard-override-persistence.mjs test/publication-user-override.mjs test/resource-mutation-clarification.mjs test/publication-override-target.mjs test/completion-steering-receipt-authority.mjs test/steering-revision-recovery.mjs test/pending-clarification-hydration.mjs test/run-ui-hidden-panel.mjs test/clarify-timeout-policy.mjs test/guard-ask-cards.mjs test/permission-steering-wakeup.mjs test/pure-calculation-reply.mjs test/pure-calculation-tools.mjs test/page-feedback.mjs test/page-feedback-progress.mjs test/page-feedback-unbindable-target.mjs test/guard-advisory-actions.mjs test/rich-text-preflight-page-change.mjs test/keyboard-receiver-frame.mjs test/input-receiving-frame.mjs test/ask-response-scope.mjs test/auto-mode.mjs test/plan-when-needed.mjs test/planner-prompt-trim.mjs test/model-picker-icon.mjs test/ask-completion-churn.mjs test/page-feedback-policy.mjs test/research-escalation-page-feedback.mjs test/page-feedback-transport-races.mjs test/page-feedback-recovery.mjs test/telegram-read-preparation-agent.mjs test/media-download-agent-handler.mjs test/code-scanning-url-recipient.mjs test/apocalypse-comm-parsing.mjs test/apocalypse-scalar-decoding.mjs test/bitgpu-chat-security.mjs test/social-media-url-upgrades.mjs test/downloaded-file-saved-bytes.mjs test/download-conversation-scope.mjs test/downloaded-file-local-probe.mjs test/formless-verification-recovery.mjs test/file-upload-accept.mjs test/file-upload-accept-agent.mjs test/workflow-route-generic-completion.mjs test/release-publication-completion.mjs test/workflow-implicit-metadata.mjs test/workflow-field-readings.mjs test/workflow-field-anchors.mjs test/user-turn-kind.mjs test/follow-up-task-context.mjs test/completion-current-execution-evidence.mjs test/video-upload-attachment.mjs test/feedback-automatic-churn.mjs test/feedback-navigation-idle.mjs test/feedback-run-boundaries.mjs test/feedback-ask-viewing.mjs test/lifecycle-terminal-done.mjs test/incomplete-completion-recovery.mjs test/guard-advisory-completion.mjs test/lean-mode.mjs test/prompt-unverified-pages.mjs test/prompt-missing-values.mjs test/lifecycle-planner-digest.mjs test/planner-clarify-loop.mjs test/lifecycle-steering-latency.mjs test/lifecycle-steering-restart.mjs test/lifecycle-vision-fallback.mjs test/delivery-click-locks.mjs test/guards-steering-receipts.mjs test/terminal-user-messages.mjs test/improver-providers.mjs test/improver-providers-agent.mjs test/improver-guards-ledger.mjs test/improver-guards-tools.mjs test/improver-clarify.mjs test/improver-clarify-scheduler.mjs test/improver-misc.mjs test/improver-forms.mjs test/improver-forms-strict-secrets.mjs test/improver-content-press-keys-hint.mjs && npm run test:plan-notifications", - "test:shard:browser-a": "node --test test/captcha-draft-content.mjs test/captcha-challenge-surfaces.mjs && node test/bot-memory-dom.mjs && node test/bot-memory-click-dom.mjs && node test/ui-content-lifecycle.mjs && node --test test/native-telegram-chat.mjs test/native-telegram-recipient.mjs test/telegram-native-baseline.mjs test/telegram-native-latest.mjs test/native-chat-pre-enter-draft.mjs test/chat-draft-dispatch-ownership.mjs test/native-telegram-alias-preparation.mjs test/telegram-read-preparation-content.mjs test/queued-composer-ownership.mjs test/queued-composer-landing.mjs test/onboarding-provider-ready.mjs test/sidepanel-permission-gate-ui.mjs test/permission-skip-dialog-ui.mjs test/permission-skip-session.mjs test/model-picker-status-ui.mjs test/workflow-native-targets.mjs test/native-whatsapp-chat.mjs test/native-chat-context-identity.mjs test/native-whatsapp-contact.mjs test/whatsapp-chat-selection.mjs test/whatsapp-native-bootstrap.mjs test/whatsapp-drawer-identity.mjs test/whatsapp-read-latest.mjs test/whatsapp-read-preparation.mjs test/whatsapp-chat-completion.mjs test/whatsapp-chat-restart.mjs test/chat-goal-lifecycle.mjs test/chat-completion.mjs test/chat-generic-dispatch.mjs test/completion-live-status-browser.mjs test/native-confirmation-visibility.mjs test/native-button-preparation.mjs test/read-continuation-browser.mjs test/iframe-preparation-focus.mjs test/contenteditable-literal.mjs test/native-chat-empty-editor.mjs test/native-chat-trusted-clear.mjs test/chat-steering-ui.mjs test/activity-brain-ui.mjs test/recipient-confirmation-ui.mjs test/assistant-message-visibility-ui.mjs test/slash-command-timeline-ui.mjs test/page-monitor-ui.mjs test/x-compose-trusted-typing.mjs test/page-monitor-dialog.mjs test/page-monitor-dialog-native.mjs test/page-monitor-inline-post.mjs test/bluesky-composer-context.mjs test/page-monitor-anchored.mjs test/page-monitor-upload-owner.mjs test/page-monitor-upload-release.mjs test/page-monitor-native-controls.mjs test/page-monitor-native-preparation.mjs test/native-preparation-cold.mjs test/page-monitor-navigation.mjs test/page-monitor-main-owner.mjs test/page-monitor-capture-cost.mjs test/page-monitor-collateral-controls.mjs test/accessibility-tree-scoped-budget.mjs test/ax-reference-origin.mjs test/page-monitor-decorative-hit.mjs test/social-ui-navigation.mjs test/native-resource-deletion-binding.mjs test/native-mastodon-confirmation.mjs test/dropdown-menu-inventory.mjs test/page-monitor-passive-progress.mjs test/page-monitor-feed-items.mjs test/media-download-binding.mjs test/media-download-capture-integration.mjs test/social-media-downloader-reinjection.mjs test/upload-file-local-state-guidance.mjs test/upload-file-source-approval.mjs test/monitor-intervention-contract.mjs test/monitor-owned-geometry.mjs test/monitor-viewport-remainder.mjs test/monitor-scroll-churn.mjs test/monitor-local-attribution.mjs test/monitor-lifecycle-leaks.mjs test/lifecycle-run-ui.mjs test/lifecycle-menu-prompts-held.mjs test/delivery-cdp-input.mjs test/delivery-click-ax-response-loss.mjs test/delivery-native-button-geometry.mjs test/delivery-hover-transition.mjs test/delivery-native-button-route.mjs test/delivery-dispatch-boundary.mjs test/delivery-stop-compound.mjs test/guards-control-classification.mjs test/guards-unbound-deletion.mjs test/submit-probe-readings.mjs test/declined-submission-identity.mjs test/improver-content-account-chrome.mjs test/improver-content-recipient.mjs test/improver-content-truncated-replacement.mjs test/improver-forms-probe.mjs test/improver-misc-trace-browser.mjs test/page-feedback-held-time.mjs test/page-monitor-held-observation.mjs", + "test:shard:browser-a": "node --test test/captcha-draft-content.mjs test/captcha-challenge-surfaces.mjs && node test/bot-memory-dom.mjs && node test/bot-memory-click-dom.mjs && node test/ui-content-lifecycle.mjs && node --test test/native-telegram-chat.mjs test/native-telegram-recipient.mjs test/telegram-native-baseline.mjs test/telegram-native-latest.mjs test/native-chat-pre-enter-draft.mjs test/chat-draft-dispatch-ownership.mjs test/native-telegram-alias-preparation.mjs test/telegram-read-preparation-content.mjs test/queued-composer-ownership.mjs test/queued-composer-landing.mjs test/onboarding-provider-ready.mjs test/sidepanel-permission-gate-ui.mjs test/permission-skip-dialog-ui.mjs test/permission-skip-session.mjs test/model-picker-status-ui.mjs test/workflow-native-targets.mjs test/native-whatsapp-chat.mjs test/native-chat-context-identity.mjs test/native-whatsapp-contact.mjs test/whatsapp-chat-selection.mjs test/whatsapp-native-bootstrap.mjs test/whatsapp-drawer-identity.mjs test/whatsapp-read-latest.mjs test/whatsapp-read-preparation.mjs test/whatsapp-chat-completion.mjs test/whatsapp-chat-restart.mjs test/chat-goal-lifecycle.mjs test/chat-completion.mjs test/chat-generic-dispatch.mjs test/completion-live-status-browser.mjs test/native-confirmation-visibility.mjs test/native-button-preparation.mjs test/read-continuation-browser.mjs test/iframe-preparation-focus.mjs test/contenteditable-literal.mjs test/native-chat-empty-editor.mjs test/native-chat-trusted-clear.mjs test/chat-steering-ui.mjs test/activity-brain-ui.mjs test/recipient-confirmation-ui.mjs test/clarify-option-shortcuts.mjs test/assistant-message-visibility-ui.mjs test/slash-command-timeline-ui.mjs test/page-monitor-ui.mjs test/x-compose-trusted-typing.mjs test/page-monitor-dialog.mjs test/page-monitor-dialog-native.mjs test/page-monitor-inline-post.mjs test/bluesky-composer-context.mjs test/page-monitor-anchored.mjs test/page-monitor-upload-owner.mjs test/page-monitor-upload-release.mjs test/page-monitor-native-controls.mjs test/page-monitor-native-preparation.mjs test/native-preparation-cold.mjs test/page-monitor-navigation.mjs test/page-monitor-main-owner.mjs test/page-monitor-capture-cost.mjs test/page-monitor-collateral-controls.mjs test/accessibility-tree-scoped-budget.mjs test/ax-reference-origin.mjs test/page-monitor-decorative-hit.mjs test/social-ui-navigation.mjs test/native-resource-deletion-binding.mjs test/native-mastodon-confirmation.mjs test/dropdown-menu-inventory.mjs test/page-monitor-passive-progress.mjs test/page-monitor-feed-items.mjs test/media-download-binding.mjs test/media-download-capture-integration.mjs test/social-media-downloader-reinjection.mjs test/upload-file-local-state-guidance.mjs test/upload-file-source-approval.mjs test/monitor-intervention-contract.mjs test/monitor-owned-geometry.mjs test/monitor-viewport-remainder.mjs test/monitor-scroll-churn.mjs test/monitor-local-attribution.mjs test/monitor-lifecycle-leaks.mjs test/lifecycle-run-ui.mjs test/lifecycle-menu-prompts-held.mjs test/delivery-cdp-input.mjs test/delivery-click-ax-response-loss.mjs test/delivery-native-button-geometry.mjs test/delivery-hover-transition.mjs test/delivery-native-button-route.mjs test/delivery-dispatch-boundary.mjs test/delivery-stop-compound.mjs test/guards-control-classification.mjs test/guards-unbound-deletion.mjs test/submit-probe-readings.mjs test/declined-submission-identity.mjs test/improver-content-account-chrome.mjs test/improver-content-recipient.mjs test/improver-content-truncated-replacement.mjs test/improver-forms-probe.mjs test/improver-misc-trace-browser.mjs test/page-feedback-held-time.mjs test/page-monitor-held-observation.mjs", "test:shard:browser-b1": "node test/message-recipient-upload.mjs && node test/message-recipient-clarify-binding.mjs && node --test test/message-recipient-whatsapp.mjs test/message-control-readings.mjs && node test/quality/integration-mv3.mjs --full-form && node test/quality/integration-mv3.mjs --batch && node test/quality/literal-calculate-midrun-mv3.mjs && node test/quality/ask-completion-churn-mv3.mjs && node test/quality/ask-person-activity-mv3.mjs && node test/quality/telegram-cold-preparation-mv3.mjs && node test/quality/native-chat-mv3.mjs && node test/quality/native-chat-presubmit-mv3.mjs && node test/quality/cloud-bot-memory-mv3.mjs", "test:shard:browser-b2": "node test/quality/whatsapp-contact-matrix.mjs && node test/quality/pdf-detection-mv3.mjs && node test/quality/download-upload-mv3.mjs && node test/quality/upload-release-binding-mv3.mjs && node test/quality/upload-release-binding-mv3.mjs --selector-recovery && node test/quality/upload-release-binding-mv3.mjs --sequential-assets && node test/quality/release-review-world-mv3.mjs && node test/quality/downloaded-file-saved-bytes-mv3.mjs && npm run test:quality:resolved-address && node test/quality/file-upload-accept-mv3.mjs && node test/quality/bulk-resume-mv3.mjs && node test/quality/shared-action-guards-mv3.mjs && node test/quality/video-upload-attachment-mv3.mjs && node --test test/iframe-probe-match-index.mjs", "test:shard:browser-c": "node test/quality/literal-frame-mv3.mjs && node test/quality/mastodon-publication-mv3.mjs && node test/quality/mastodon-reply-route-mv3.mjs && node test/quality/mastodon-deletion-mv3.mjs && node test/quality/mastodon-delete-confirmation-mv3.mjs && node test/quality/mastodon-delete-confirmation-mv3.mjs --menu-read && node test/quality/mastodon-delete-confirmation-mv3.mjs --vague && node test/quality/mastodon-delete-after-correction-mv3.mjs && node test/quality/unbound-deletion-mv3.mjs && node test/quality/recipient-clarify-mv3.mjs && node test/quality/open-chat-recipients-mv3.mjs && node test/quality/correction-cross-site-mv3.mjs && node test/quality/anchored-action-mv3.mjs && node test/quality/inline-social-composer-mv3.mjs && node test/quality/x-compose-dialog-mv3.mjs && node test/quality/bluesky-composer-mv3.mjs && node test/quality/dropdown-menu-matrix.mjs && node test/quality/mastodon-deletion-navigation-mv3.mjs && node test/quality/semantic-navigation-matrix.mjs && node test/quality/workflow-replay-mv3.mjs && node test/quality/generative-media-mv3.mjs && node test/quality/cdp-worker-restart-mv3.mjs && node test/quality/steering-worker-restart-mv3.mjs && node --test test/viewport-capture-browser.mjs && npm run test:vision-mode", diff --git a/src/chrome/src/ui/locales/ar.js b/src/chrome/src/ui/locales/ar.js index 956152265..2a2ac6cd1 100644 --- a/src/chrome/src/ui/locales/ar.js +++ b/src/chrome/src/ui/locales/ar.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "يُنزّل ملفات من", "sp.perm.verb.upload": "يرفع ملفًا إلى", "sp.perm.verb.record": "يُسجّل علامة التبويب (والميكروفون) على", - "sp.help.shortcuts_html": "اختصارات لوحة المفاتيح
Ctrl/Cmd+/ — التركيز على حقل الإدخال
Ctrl/Cmd+Shift+A — التبديل إلى وضع السؤال
Ctrl/Cmd+Shift+X — التبديل إلى وضع التنفيذ
Ctrl/Cmd+Shift+D — التبديل إلى وضع التطوير
Ctrl/Cmd+M — تبديل الإدخال الصوتي", + "sp.help.shortcuts_html": "اختصارات لوحة المفاتيح
Ctrl/Cmd+/ — التركيز على حقل الإدخال
Ctrl/Cmd+Shift+A — التبديل إلى وضع السؤال
Ctrl/Cmd+Shift+X — التبديل إلى وضع التنفيذ
Ctrl/Cmd+Shift+D — التبديل إلى وضع التطوير
Escape — إيقاف التشغيل النشط
Escape مرتين — إيقاف تسجيل نشط
1–9 — اختيار الإجابة التي تحمل هذا الرقم", "sp.slash.record_transcribe": "التسجيل وحفظ نص Whisper بعد الإيقاف", "sp.slash.unknown_command": "أمر شرطة مائلة غير معروف {command}. استخدم /help لعرض الأوامر المتاحة.", "sp.slash.invalid_usage": "بنية أمر الشرطة المائلة غير صالحة. الاستخدام: {usage}", diff --git a/src/chrome/src/ui/locales/bn.js b/src/chrome/src/ui/locales/bn.js index d446abf60..ae2bf9a26 100644 --- a/src/chrome/src/ui/locales/bn.js +++ b/src/chrome/src/ui/locales/bn.js @@ -527,7 +527,7 @@ export default { 'sp.permissions.gate_off': 'বন্ধ: WebBrain জিজ্ঞাসা না করেই প্রতিটি সাইটে কাজ করে।', 'sp.permissions.manage': 'সাইটের অনুমতি পরিচালনা করুন', 'sp.permissions.enabled': 'অনুমতি প্রম্পট আবার চালু হয়েছে।', - "sp.help.shortcuts_html": "কীবোর্ড শর্টকাট
Ctrl/Cmd+/ - ইনপুট ফোকাস করুন
Ctrl/Cmd+Shift+A — আস্ক মোডে স্যুইচ করুন
Ctrl/Cmd+Shift+X — অ্যাক্ট মোডে স্যুইচ করুন
Ctrl/Cmd+Shift+D — ডেভ মোডে স্যুইচ করুন
Escape - সক্রিয় রান বন্ধ করুন
Escape দুবার - একটি সক্রিয় রেকর্ডিং বন্ধ করুন", + "sp.help.shortcuts_html": "কীবোর্ড শর্টকাট
Ctrl/Cmd+/ - ইনপুট ফোকাস করুন
Ctrl/Cmd+Shift+A — আস্ক মোডে স্যুইচ করুন
Ctrl/Cmd+Shift+X — অ্যাক্ট মোডে স্যুইচ করুন
Ctrl/Cmd+Shift+D — ডেভ মোডে স্যুইচ করুন
Escape - সক্রিয় রান বন্ধ করুন
Escape দুবার - একটি সক্রিয় রেকর্ডিং বন্ধ করুন
1–9 — সেই নম্বরের উত্তরটি বেছে নিন", "sp.slash.record_transcribe": "থামার পরে একটি হুইস্পার প্রতিলিপি রেকর্ড করুন এবং সংরক্ষণ করুন", "sp.slash.unknown_command": "অজানা স্ল্যাশ কমান্ড {command}। উপলব্ধ কমান্ড দেখতে /help ব্যবহার করুন।", "sp.slash.invalid_usage": "অবৈধ স্ল্যাশ কমান্ড সিনট্যাক্স। ব্যবহার: {usage}", diff --git a/src/chrome/src/ui/locales/de.js b/src/chrome/src/ui/locales/de.js index d28d3f541..c99b8291c 100644 --- a/src/chrome/src/ui/locales/de.js +++ b/src/chrome/src/ui/locales/de.js @@ -532,7 +532,7 @@ export default { 'sp.perm.verb.record': 'Tab (und Mikrofon) aufnehmen auf', 'sp.perm.verb.schedule': 'zukünftige Aufgaben planen für', 'sp.perm.verb.window': 'die Größe des Browserfensters ändern auf', - 'sp.help.shortcuts_html': 'Tastenkürzel
Ctrl/Cmd+/ — Eingabefeld fokussieren
Ctrl/Cmd+Shift+A — Zum Fragen-Modus wechseln
Ctrl/Cmd+Shift+X — Zum Handeln-Modus wechseln
Ctrl/Cmd+Shift+D — Zum Dev-Modus wechseln
Escape — Aktiven Durchlauf stoppen
Escape zweimal — Aktive Aufnahme stoppen', + 'sp.help.shortcuts_html': 'Tastenkürzel
Ctrl/Cmd+/ — Eingabefeld fokussieren
Ctrl/Cmd+Shift+A — Zum Fragen-Modus wechseln
Ctrl/Cmd+Shift+X — Zum Handeln-Modus wechseln
Ctrl/Cmd+Shift+D — Zum Dev-Modus wechseln
Escape — Aktiven Durchlauf stoppen
Escape zweimal — Aktive Aufnahme stoppen
1–9 — Antwort mit dieser Nummer wählen', 'sp.compact.nothing_to_compact': 'Noch nichts zu kompaktieren — es gibt nicht genügend älteren Kontext.', 'sp.compact.busy': 'Kompaktierung nicht möglich, während ein Durchlauf läuft — warten Sie auf dessen Abschluss.', 'sp.compact.failed': 'Kontext-Kompaktierung fehlgeschlagen: {error}', diff --git a/src/chrome/src/ui/locales/en.js b/src/chrome/src/ui/locales/en.js index 9699d582f..e65abbb36 100644 --- a/src/chrome/src/ui/locales/en.js +++ b/src/chrome/src/ui/locales/en.js @@ -541,7 +541,7 @@ export default { 'sp.permissions.gate_off': 'Off: WebBrain acts on every site without asking.', 'sp.permissions.manage': 'Manage site permissions', 'sp.permissions.enabled': 'Permission prompts are on again.', - "sp.help.shortcuts_html": "Keyboard Shortcuts
Ctrl/Cmd+/ — Focus the input
Ctrl/Cmd+Shift+A — Switch to Ask mode
Ctrl/Cmd+Shift+X — Switch to Act mode
Ctrl/Cmd+Shift+D — Switch to Dev mode
Escape — Stop the active run
Escape twice — Stop an active recording", + "sp.help.shortcuts_html": "Keyboard Shortcuts
Ctrl/Cmd+/ — Focus the input
Ctrl/Cmd+Shift+A — Switch to Ask mode
Ctrl/Cmd+Shift+X — Switch to Act mode
Ctrl/Cmd+Shift+D — Switch to Dev mode
Escape — Stop the active run
Escape twice — Stop an active recording
1–9 — Pick that answer when WebBrain asks", "sp.slash.record_transcribe": "Record and save a Whisper transcript after stop", "sp.slash.unknown_command": "Unknown slash command {command}. Use /help to see available commands.", "sp.slash.invalid_usage": "Invalid slash command syntax. Usage: {usage}", diff --git a/src/chrome/src/ui/locales/es.js b/src/chrome/src/ui/locales/es.js index 2c4b33d2c..5fff8c5c6 100644 --- a/src/chrome/src/ui/locales/es.js +++ b/src/chrome/src/ui/locales/es.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "descargar archivos de", "sp.perm.verb.upload": "subir un archivo a", "sp.perm.verb.record": "grabar la pestaña (y el micrófono) en", - "sp.help.shortcuts_html": "Atajos de teclado
Ctrl/Cmd+/ — Enfocar la entrada
Ctrl/Cmd+Shift+A — Cambiar al modo Preguntar
Ctrl/Cmd+Shift+X — Cambiar al modo Actuar
Ctrl/Cmd+Shift+D — Cambiar al modo Desarrollo
Ctrl/Cmd+M — Alternar entrada de voz", + "sp.help.shortcuts_html": "Atajos de teclado
Ctrl/Cmd+/ — Enfocar la entrada
Ctrl/Cmd+Shift+A — Cambiar al modo Preguntar
Ctrl/Cmd+Shift+X — Cambiar al modo Actuar
Ctrl/Cmd+Shift+D — Cambiar al modo Desarrollo
Escape — Detener la ejecución activa
Escape dos veces — Detener una grabación activa
1–9 — Elegir la respuesta con ese número", "sp.slash.record_transcribe": "Grabar y guardar una transcripción de Whisper al detener", "sp.slash.unknown_command": "Comando de barra desconocido {command}. Usa /help para ver los comandos disponibles.", "sp.slash.invalid_usage": "Sintaxis de comando de barra no válida. Uso: {usage}", diff --git a/src/chrome/src/ui/locales/fa.js b/src/chrome/src/ui/locales/fa.js index 2548fc563..8744760de 100644 --- a/src/chrome/src/ui/locales/fa.js +++ b/src/chrome/src/ui/locales/fa.js @@ -527,7 +527,7 @@ export default { 'sp.permissions.gate_off': 'خاموش: WebBrain بدون پرسیدن در همهٔ سایت‌ها اقدام می‌کند.', 'sp.permissions.manage': 'مدیریت مجوزهای سایت', 'sp.permissions.enabled': 'درخواست‌های مجوز دوباره روشن شدند.', - "sp.help.shortcuts_html": "میانبرهای صفحه کلید
Ctrl/Cmd+/ - روی ورودی تمرکز کنید
Ctrl/Cmd+Shift+A - به حالت سؤال بروید
Ctrl/Cmd+Shift+X - به حالت Act تغییر دهید
Ctrl/Cmd+Shift+D - به حالت Dev بروید
Escape - اجرای فعال را متوقف کنید
Escape دو بار — یک ضبط فعال را متوقف کنید", + "sp.help.shortcuts_html": "میانبرهای صفحه کلید
Ctrl/Cmd+/ - روی ورودی تمرکز کنید
Ctrl/Cmd+Shift+A - به حالت سؤال بروید
Ctrl/Cmd+Shift+X - به حالت Act تغییر دهید
Ctrl/Cmd+Shift+D - به حالت Dev بروید
Escape - اجرای فعال را متوقف کنید
Escape دو بار — یک ضبط فعال را متوقف کنید
1–9 - انتخاب پاسخی که آن شماره را دارد", "sp.slash.record_transcribe": "پس از توقف، رونوشت Whisper را ضبط و ذخیره کنید", "sp.slash.unknown_command": "دستور اسلش نامشخص {command}. از /help برای دیدن دستورات موجود استفاده کنید.", "sp.slash.invalid_usage": "دستور دستور اسلش نامعتبر است. استفاده: {usage}", diff --git a/src/chrome/src/ui/locales/fr.js b/src/chrome/src/ui/locales/fr.js index 558c189bd..98cd8afa1 100644 --- a/src/chrome/src/ui/locales/fr.js +++ b/src/chrome/src/ui/locales/fr.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "télécharger des fichiers depuis", "sp.perm.verb.upload": "téléverser un fichier vers", "sp.perm.verb.record": "enregistrer l'onglet (et le microphone) sur", - "sp.help.shortcuts_html": "Raccourcis clavier
Ctrl/Cmd+/ — Focus sur la zone de saisie
Ctrl/Cmd+Shift+A — Passer en mode Demander
Ctrl/Cmd+Shift+X — Passer en mode Agir
Ctrl/Cmd+Shift+D — Passer en mode Développement
Ctrl/Cmd+M — Basculer la saisie vocale", + "sp.help.shortcuts_html": "Raccourcis clavier
Ctrl/Cmd+/ — Focus sur la zone de saisie
Ctrl/Cmd+Shift+A — Passer en mode Demander
Ctrl/Cmd+Shift+X — Passer en mode Agir
Ctrl/Cmd+Shift+D — Passer en mode Développement
Escape — Arrêter l’exécution en cours
Escape deux fois — Arrêter un enregistrement en cours
1–9 — Choisir la réponse portant ce numéro", "sp.slash.record_transcribe": "Enregistrer et sauvegarder une transcription Whisper à l'arrêt", "sp.slash.unknown_command": "Commande slash inconnue {command}. Utilisez /help pour voir les commandes disponibles.", "sp.slash.invalid_usage": "Syntaxe de commande slash invalide. Utilisation : {usage}", diff --git a/src/chrome/src/ui/locales/he.js b/src/chrome/src/ui/locales/he.js index 98cc3789a..e1223386b 100644 --- a/src/chrome/src/ui/locales/he.js +++ b/src/chrome/src/ui/locales/he.js @@ -512,7 +512,7 @@ export default { "sp.permissions.gate_off": "כבוי: WebBrain פועל בכל אתר בלי לשאול.", "sp.permissions.manage": "ניהול הרשאות אתרים", "sp.permissions.enabled": "בקשות ההרשאה הופעלו שוב.", - "sp.help.shortcuts_html": "קיצורי מקלדת
Ctrl/Cmd+/ — מקד את שדה הקלט
Ctrl/Cmd+Shift+A — עבור למצב שאל
Ctrl/Cmd+Shift+X — עבור למצב פעולה
Ctrl/Cmd+Shift+D — עבור למצב Dev
Ctrl/Cmd+M — הפעל או השבת קלט קולי", + "sp.help.shortcuts_html": "קיצורי מקלדת
Ctrl/Cmd+/ — מקד את שדה הקלט
Ctrl/Cmd+Shift+A — עבור למצב שאל
Ctrl/Cmd+Shift+X — עבור למצב פעולה
Ctrl/Cmd+Shift+D — עבור למצב Dev
Escape — עצירת ההרצה הפעילה
Escape פעמיים — עצירת הקלטה פעילה
1–9 — בחירת התשובה שמספרה זה", "sp.slash.record_transcribe": "הקלט ושמור תמלול Whisper לאחר העצירה", "sp.slash.unknown_command": "פקודת לוכסן לא מוכרת {command}. השתמשו ב-/help כדי לראות את הפקודות הזמינות.", "sp.slash.invalid_usage": "תחביר פקודת לוכסן לא תקין. שימוש: {usage}", diff --git a/src/chrome/src/ui/locales/hi.js b/src/chrome/src/ui/locales/hi.js index 37fa9184f..0bb64e487 100644 --- a/src/chrome/src/ui/locales/hi.js +++ b/src/chrome/src/ui/locales/hi.js @@ -527,7 +527,7 @@ export default { 'sp.permissions.gate_off': 'बंद: WebBrain बिना पूछे हर साइट पर कार्रवाई करता है।', 'sp.permissions.manage': 'साइट अनुमतियां प्रबंधित करें', 'sp.permissions.enabled': 'अनुमति संकेत फिर से चालू हैं।', - "sp.help.shortcuts_html": "कीबोर्ड शॉर्टकट
Ctrl/Cmd+/ - इनपुट पर फोकस करें
Ctrl/Cmd+Shift+A - आस्क मोड पर स्विच करें
Ctrl/Cmd+Shift+X - एक्ट मोड पर स्विच करें
Ctrl/Cmd+Shift+D - डेव मोड पर स्विच करें
Escape - सक्रिय रन बंद करें
Escape दो बार - सक्रिय रिकॉर्डिंग बंद करें", + "sp.help.shortcuts_html": "कीबोर्ड शॉर्टकट
Ctrl/Cmd+/ - इनपुट पर फोकस करें
Ctrl/Cmd+Shift+A - आस्क मोड पर स्विच करें
Ctrl/Cmd+Shift+X - एक्ट मोड पर स्विच करें
Ctrl/Cmd+Shift+D - डेव मोड पर स्विच करें
Escape - सक्रिय रन बंद करें
Escape दो बार - सक्रिय रिकॉर्डिंग बंद करें
1–9 - उस नंबर वाला उत्तर चुनें", "sp.slash.record_transcribe": "रुकने के बाद व्हिस्पर प्रतिलेख को रिकॉर्ड करें और सहेजें", "sp.slash.unknown_command": "अज्ञात स्लैश कमांड {command}। उपलब्ध कमांड देखने के लिए /help का उपयोग करें।", "sp.slash.invalid_usage": "अमान्य स्लैश कमांड सिंटैक्स. उपयोग: {usage}", diff --git a/src/chrome/src/ui/locales/id.js b/src/chrome/src/ui/locales/id.js index 7db0f2b51..655df6f0d 100644 --- a/src/chrome/src/ui/locales/id.js +++ b/src/chrome/src/ui/locales/id.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "mengunduh berkas dari", "sp.perm.verb.upload": "mengunggah berkas ke", "sp.perm.verb.record": "merekam tab (dan mikrofon) pada", - "sp.help.shortcuts_html": "Pintasan Keyboard
Ctrl/Cmd+/ — Fokus ke input
Ctrl/Cmd+Shift+A — Beralih ke mode Tanya
Ctrl/Cmd+Shift+X — Beralih ke mode Aksi
Ctrl/Cmd+Shift+D — Beralih ke mode Dev
Ctrl/Cmd+M — Alihkan input suara", + "sp.help.shortcuts_html": "Pintasan Keyboard
Ctrl/Cmd+/ — Fokus ke input
Ctrl/Cmd+Shift+A — Beralih ke mode Tanya
Ctrl/Cmd+Shift+X — Beralih ke mode Aksi
Ctrl/Cmd+Shift+D — Beralih ke mode Dev
Escape — Hentikan proses yang berjalan
Escape dua kali — Hentikan perekaman yang berjalan
1–9 — Pilih jawaban bernomor itu", "sp.slash.record_transcribe": "Rekam dan simpan transkrip Whisper setelah berhenti", "sp.slash.unknown_command": "Perintah garis miring tidak dikenal {command}. Gunakan /help untuk melihat perintah yang tersedia.", "sp.slash.invalid_usage": "Sintaks perintah garis miring tidak valid. Penggunaan: {usage}", diff --git a/src/chrome/src/ui/locales/ja.js b/src/chrome/src/ui/locales/ja.js index 8b4497e15..99a40fb2e 100644 --- a/src/chrome/src/ui/locales/ja.js +++ b/src/chrome/src/ui/locales/ja.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "からのファイルのダウンロードを", "sp.perm.verb.upload": "へのファイルのアップロードを", "sp.perm.verb.record": "でのタブ(およびマイク)の録画を", - "sp.help.shortcuts_html": "キーボードショートカット
Ctrl/Cmd+/ — 入力にフォーカス
Ctrl/Cmd+Shift+A — 質問モードに切り替え
Ctrl/Cmd+Shift+X — 操作モードに切り替え
Ctrl/Cmd+Shift+D — 開発モードに切り替え
Ctrl/Cmd+M — 音声入力を切り替え", + "sp.help.shortcuts_html": "キーボードショートカット
Ctrl/Cmd+/ — 入力にフォーカス
Ctrl/Cmd+Shift+A — 質問モードに切り替え
Ctrl/Cmd+Shift+X — 操作モードに切り替え
Ctrl/Cmd+Shift+D — 開発モードに切り替え
Escape — 実行中のタスクを停止
Escape 2回 — 録音を停止
1–9 — その番号の回答を選択", "sp.slash.record_transcribe": "録画停止後に Whisper の文字起こしを保存", "sp.slash.unknown_command": "不明なスラッシュコマンドです: {command}。利用可能なコマンドは /help で確認できます。", "sp.slash.invalid_usage": "スラッシュコマンドの構文が正しくありません。使用法: {usage}", diff --git a/src/chrome/src/ui/locales/ko.js b/src/chrome/src/ui/locales/ko.js index 6889873f3..2acf5f9b5 100644 --- a/src/chrome/src/ui/locales/ko.js +++ b/src/chrome/src/ui/locales/ko.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "파일 다운로드", "sp.perm.verb.upload": "파일 업로드", "sp.perm.verb.record": "탭(및 마이크) 녹화", - "sp.help.shortcuts_html": "키보드 단축키
Ctrl/Cmd+/ — 입력에 포커스
Ctrl/Cmd+Shift+A — 질문 모드로 전환
Ctrl/Cmd+Shift+X — 실행 모드로 전환
Ctrl/Cmd+Shift+D — 개발 모드로 전환
Ctrl/Cmd+M — 음성 입력 전환", + "sp.help.shortcuts_html": "키보드 단축키
Ctrl/Cmd+/ — 입력에 포커스
Ctrl/Cmd+Shift+A — 질문 모드로 전환
Ctrl/Cmd+Shift+X — 실행 모드로 전환
Ctrl/Cmd+Shift+D — 개발 모드로 전환
Escape — 실행 중인 작업 중지
Escape 두 번 — 진행 중인 녹음 중지
1–9 — 해당 번호의 답변 선택", "sp.slash.record_transcribe": "녹화 후 Whisper 전사본 저장", "sp.slash.unknown_command": "알 수 없는 슬래시 명령어입니다: {command}. 사용 가능한 명령어는 /help에서 확인하세요.", "sp.slash.invalid_usage": "슬래시 명령어 구문이 올바르지 않습니다. 사용법: {usage}", diff --git a/src/chrome/src/ui/locales/ms.js b/src/chrome/src/ui/locales/ms.js index d2d11ff0f..72d7e6e05 100644 --- a/src/chrome/src/ui/locales/ms.js +++ b/src/chrome/src/ui/locales/ms.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "memuat turun fail dari", "sp.perm.verb.upload": "memuat naik fail ke", "sp.perm.verb.record": "merakam tab (dan mikrofon) pada", - "sp.help.shortcuts_html": "Pintasan Papan Kekunci
Ctrl/Cmd+/ — Fokus pada medan input
Ctrl/Cmd+Shift+A — Beralih ke mod Tanya
Ctrl/Cmd+Shift+X — Beralih ke mod Lakukan
Ctrl/Cmd+Shift+D — Beralih ke mod Dev
Ctrl/Cmd+M — Togol input suara", + "sp.help.shortcuts_html": "Pintasan Papan Kekunci
Ctrl/Cmd+/ — Fokus pada medan input
Ctrl/Cmd+Shift+A — Beralih ke mod Tanya
Ctrl/Cmd+Shift+X — Beralih ke mod Lakukan
Ctrl/Cmd+Shift+D — Beralih ke mod Dev
Escape — Hentikan larian aktif
Escape dua kali — Hentikan rakaman aktif
1–9 — Pilih jawapan bernombor itu", "sp.slash.record_transcribe": "Rakam dan simpan transkrip Whisper selepas berhenti", "sp.slash.unknown_command": "Arahan slash tidak diketahui {command}. Gunakan /help untuk melihat arahan yang tersedia.", "sp.slash.invalid_usage": "Sintaks arahan slash tidak sah. Penggunaan: {usage}", diff --git a/src/chrome/src/ui/locales/nl.js b/src/chrome/src/ui/locales/nl.js index 1dfd1923c..017af8675 100644 --- a/src/chrome/src/ui/locales/nl.js +++ b/src/chrome/src/ui/locales/nl.js @@ -513,7 +513,7 @@ export default { 'sp.permissions.gate_off': 'Uit: WebBrain handelt op elke site zonder te vragen.', 'sp.permissions.manage': 'Sitemachtigingen beheren', 'sp.permissions.enabled': 'Machtigingsvragen staan weer aan.', - "sp.help.shortcuts_html": "Sneltoetsen
...", + "sp.help.shortcuts_html": "Sneltoetsen
Ctrl/Cmd+/ — Het invoerveld focussen
Ctrl/Cmd+Shift+A — Naar de modus Vragen schakelen
Ctrl/Cmd+Shift+X — Naar de modus Handelen schakelen
Ctrl/Cmd+Shift+D — Naar de modus Dev schakelen
Escape — De actieve run stoppen
Escape tweemaal — Een actieve opname stoppen
1–9 — Het antwoord met dat nummer kiezen", "sp.slash.record_transcribe": "Opnemen en Whisper-transcriptie opslaan na stop", "sp.slash.unknown_command": "Onbekend slashcommando {command}. Gebruik /help om beschikbare commando's te zien.", "sp.slash.invalid_usage": "Ongeldige slashcommandosyntaxis. Gebruik: {usage}", diff --git a/src/chrome/src/ui/locales/pl.js b/src/chrome/src/ui/locales/pl.js index 9514848cc..5ddf674ff 100644 --- a/src/chrome/src/ui/locales/pl.js +++ b/src/chrome/src/ui/locales/pl.js @@ -411,7 +411,7 @@ export default { 'sp.permissions.gate_off': 'Wyłączone: WebBrain działa na każdej stronie bez pytania.', 'sp.permissions.manage': 'Zarządzaj uprawnieniami stron', 'sp.permissions.enabled': 'Pytania o uprawnienia są ponownie włączone.', - "sp.help.shortcuts_html": "Skróty klawiszowe
Ctrl/Cmd+/ — Ustaw fokus na polu wprowadzania
Ctrl/Cmd+Shift+A — Przełącz na tryb Pytaj
Ctrl/Cmd+Shift+X — Przełącz na tryb Działaj
Ctrl/Cmd+Shift+D — Przełącz na tryb Dev
Ctrl/Cmd+M — Togol wprowadzanie głosowe", + "sp.help.shortcuts_html": "Skróty klawiszowe
Ctrl/Cmd+/ — Ustaw fokus na polu wprowadzania
Ctrl/Cmd+Shift+A — Przełącz na tryb Pytaj
Ctrl/Cmd+Shift+X — Przełącz na tryb Działaj
Ctrl/Cmd+Shift+D — Przełącz na tryb Dev
Escape — Zatrzymaj aktywne uruchomienie
Escape dwukrotnie — Zatrzymaj aktywne nagrywanie
1–9 — Wybierz odpowiedź z tym numerem", "sp.slash.record_transcribe": "Nagraj i zapisz transkrypcję Whisper po zatrzymaniu", "sp.slash.unknown_command": "Nieznane polecenie ukośnikowe {command}. Użyj /help, aby zobaczyć dostępne polecenia.", "sp.slash.invalid_usage": "Nieprawidłowa składnia polecenia ukośnikowego. Użycie: {usage}", diff --git a/src/chrome/src/ui/locales/pt.js b/src/chrome/src/ui/locales/pt.js index bc62673af..a4d297066 100644 --- a/src/chrome/src/ui/locales/pt.js +++ b/src/chrome/src/ui/locales/pt.js @@ -527,7 +527,7 @@ export default { 'sp.permissions.gate_off': 'Desativado: o WebBrain age em qualquer site sem perguntar.', 'sp.permissions.manage': 'Gerenciar permissões de sites', 'sp.permissions.enabled': 'Os prompts de permissão estão ativados novamente.', - "sp.help.shortcuts_html": "Atalhos de teclado
Ctrl/Cmd+/ - Concentre a entrada
Ctrl/Cmd+Shift+A — Mudar para o modo Perguntar
Ctrl/Cmd+Shift+X — Mudar para o modo Agir
Ctrl/Cmd+Shift+D — Mudar para o modo Dev
Escape — Pare a execução ativa
Escape duas vezes — Interrompa uma gravação ativa", + "sp.help.shortcuts_html": "Atalhos de teclado
Ctrl/Cmd+/ - Concentre a entrada
Ctrl/Cmd+Shift+A — Mudar para o modo Perguntar
Ctrl/Cmd+Shift+X — Mudar para o modo Agir
Ctrl/Cmd+Shift+D — Mudar para o modo Dev
Escape — Pare a execução ativa
Escape duas vezes — Interrompa uma gravação ativa
1–9 — Escolher a resposta com esse número", "sp.slash.record_transcribe": "Grave e salve uma transcrição do Whisper após parar", "sp.slash.unknown_command": "Comando de barra desconhecido {command}. Use /help para ver os comandos disponíveis.", "sp.slash.invalid_usage": "Sintaxe de comando de barra inválida. Uso: {usage}", diff --git a/src/chrome/src/ui/locales/ru.js b/src/chrome/src/ui/locales/ru.js index 7e7008693..5bccb91b3 100644 --- a/src/chrome/src/ui/locales/ru.js +++ b/src/chrome/src/ui/locales/ru.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "скачивать файлы с", "sp.perm.verb.upload": "загрузить файл на", "sp.perm.verb.record": "записывать вкладку (и микрофон) на", - "sp.help.shortcuts_html": "Горячие клавиши
Ctrl/Cmd+/ — Переключить фокус на ввод
Ctrl/Cmd+Shift+A — Переключиться в режим «Вопрос»
Ctrl/Cmd+Shift+X — Переключиться в режим «Действие»
Ctrl/Cmd+Shift+D — Переключиться в режим «Разработка»
Ctrl/Cmd+M — Переключить голосовой ввод", + "sp.help.shortcuts_html": "Горячие клавиши
Ctrl/Cmd+/ — Переключить фокус на ввод
Ctrl/Cmd+Shift+A — Переключиться в режим «Вопрос»
Ctrl/Cmd+Shift+X — Переключиться в режим «Действие»
Ctrl/Cmd+Shift+D — Переключиться в режим «Разработка»
Escape — Остановить активный запуск
Escape дважды — Остановить активную запись
1–9 — Выбрать ответ с этим номером", "sp.slash.record_transcribe": "Записать и сохранить расшифровку Whisper после остановки", "sp.slash.unknown_command": "Неизвестная slash-команда {command}. Используйте /help, чтобы увидеть доступные команды.", "sp.slash.invalid_usage": "Неверный синтаксис slash-команды. Использование: {usage}", diff --git a/src/chrome/src/ui/locales/th.js b/src/chrome/src/ui/locales/th.js index 49c34462d..a89eede7a 100644 --- a/src/chrome/src/ui/locales/th.js +++ b/src/chrome/src/ui/locales/th.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "ดาวน์โหลดไฟล์จาก", "sp.perm.verb.upload": "อัปโหลดไฟล์ไปยัง", "sp.perm.verb.record": "บันทึกแท็บ (และไมโครโฟน) บน", - "sp.help.shortcuts_html": "แป้นพิมพ์ลัด
Ctrl/Cmd+/ — โฟกัสช่องป้อนข้อความ
Ctrl/Cmd+Shift+A — เปลี่ยนไปโหมดถาม
Ctrl/Cmd+Shift+X — เปลี่ยนไปโหมดทำ
Ctrl/Cmd+Shift+D — เปลี่ยนไปโหมดนักพัฒนา
Ctrl/Cmd+M — สลับการป้อนด้วยเสียง", + "sp.help.shortcuts_html": "แป้นพิมพ์ลัด
Ctrl/Cmd+/ — โฟกัสช่องป้อนข้อความ
Ctrl/Cmd+Shift+A — เปลี่ยนไปโหมดถาม
Ctrl/Cmd+Shift+X — เปลี่ยนไปโหมดทำ
Ctrl/Cmd+Shift+D — เปลี่ยนไปโหมดนักพัฒนา
Escape — หยุดการทำงานที่กำลังทำอยู่
Escape สองครั้ง — หยุดการบันทึกที่กำลังทำอยู่
1–9 — เลือกคำตอบที่มีหมายเลขนั้น", "sp.slash.record_transcribe": "บันทึกและบันทึกบทถอดเสียง Whisper หลังหยุด", "sp.slash.unknown_command": "ไม่รู้จักคำสั่งสแลช {command} ใช้ /help เพื่อดูคำสั่งที่ใช้ได้", "sp.slash.invalid_usage": "ไวยากรณ์คำสั่งสแลชไม่ถูกต้อง วิธีใช้: {usage}", diff --git a/src/chrome/src/ui/locales/tl.js b/src/chrome/src/ui/locales/tl.js index cffd8eef4..20659efc6 100644 --- a/src/chrome/src/ui/locales/tl.js +++ b/src/chrome/src/ui/locales/tl.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "mag-download ng files mula sa", "sp.perm.verb.upload": "mag-upload ng file sa", "sp.perm.verb.record": "i-record ang tab (at mikropono) sa", - "sp.help.shortcuts_html": "Mga Keyboard Shortcut
Ctrl/Cmd+/ — I-focus ang input
Ctrl/Cmd+Shift+A — Lumipat sa Ask mode
Ctrl/Cmd+Shift+X — Lumipat sa Act mode
Ctrl/Cmd+Shift+D — Lumipat sa Dev mode
Ctrl/Cmd+M — I-toggle ang voice input", + "sp.help.shortcuts_html": "Mga Keyboard Shortcut
Ctrl/Cmd+/ — I-focus ang input
Ctrl/Cmd+Shift+A — Lumipat sa Ask mode
Ctrl/Cmd+Shift+X — Lumipat sa Act mode
Ctrl/Cmd+Shift+D — Lumipat sa Dev mode
Escape — Ihinto ang aktibong run
Escape nang dalawang beses — Ihinto ang aktibong pag-record
1–9 — Piliin ang sagot na may ganoong numero", "sp.slash.record_transcribe": "I-record at i-save ang Whisper transcript pagkatapos huminto", "sp.slash.unknown_command": "Hindi kilalang slash command {command}. Gamitin ang /help upang makita ang mga available na command.", "sp.slash.invalid_usage": "Hindi wastong syntax ng slash command. Paggamit: {usage}", diff --git a/src/chrome/src/ui/locales/tr.js b/src/chrome/src/ui/locales/tr.js index 387acb1aa..abb170750 100644 --- a/src/chrome/src/ui/locales/tr.js +++ b/src/chrome/src/ui/locales/tr.js @@ -725,7 +725,7 @@ export default { "sp.perm.verb.download": "dosya indirmek", "sp.perm.verb.upload": "dosya yüklemek", "sp.perm.verb.record": "sekmeyi (ve mikrofonu) kaydetmek", - "sp.help.shortcuts_html": "Klavye Kısayolları
Ctrl/Cmd+/ — Giriş alanına odaklan
Ctrl/Cmd+Shift+A — Sor moduna geç
Ctrl/Cmd+Shift+X — Uygula moduna geç
Ctrl/Cmd+Shift+D — Dev moduna geç
Ctrl/Cmd+M — Ses girişini aç/kapat", + "sp.help.shortcuts_html": "Klavye Kısayolları
Ctrl/Cmd+/ — Giriş alanına odaklan
Ctrl/Cmd+Shift+A — Sor moduna geç
Ctrl/Cmd+Shift+X — Uygula moduna geç
Ctrl/Cmd+Shift+D — Dev moduna geç
Escape — Aktif çalışmayı durdur
Escape iki kez — Aktif kaydı durdur
1–9 — O numaralı yanıtı seç", "sp.slash.record_transcribe": "Kaydet ve durdurduktan sonra Whisper dökümü kaydet", "sp.slash.unknown_command": "Bilinmeyen slash komutu {command}. Kullanılabilir komutları görmek için /help kullanın.", "sp.slash.invalid_usage": "Geçersiz slash komutu sözdizimi. Kullanım: {usage}", diff --git a/src/chrome/src/ui/locales/uk.js b/src/chrome/src/ui/locales/uk.js index 40802341a..5caf90a09 100644 --- a/src/chrome/src/ui/locales/uk.js +++ b/src/chrome/src/ui/locales/uk.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "завантажити файли з", "sp.perm.verb.upload": "вивантажити файл на", "sp.perm.verb.record": "записати вкладку (і мікрофон) на", - "sp.help.shortcuts_html": "Гарячі клавіші
Ctrl/Cmd+/ — Фокус на полі введення
Ctrl/Cmd+Shift+A — Перейти в режим запитань
Ctrl/Cmd+Shift+X — Перейти в режим дій
Ctrl/Cmd+Shift+D — Перейти в режим розробки
Ctrl/Cmd+M — Перемкнути голосове введення", + "sp.help.shortcuts_html": "Гарячі клавіші
Ctrl/Cmd+/ — Фокус на полі введення
Ctrl/Cmd+Shift+A — Перейти в режим запитань
Ctrl/Cmd+Shift+X — Перейти в режим дій
Ctrl/Cmd+Shift+D — Перейти в режим розробки
Escape — Зупинити активний запуск
Escape двічі — Зупинити активний запис
1–9 — Вибрати відповідь із цим номером", "sp.slash.record_transcribe": "Записати та зберегти транскрипт Whisper після зупинки", "sp.slash.unknown_command": "Невідома slash-команда {command}. Скористайтеся /help, щоб переглянути доступні команди.", "sp.slash.invalid_usage": "Неправильний синтаксис slash-команди. Використання: {usage}", diff --git a/src/chrome/src/ui/locales/vi.js b/src/chrome/src/ui/locales/vi.js index cb98ed256..8103501f5 100644 --- a/src/chrome/src/ui/locales/vi.js +++ b/src/chrome/src/ui/locales/vi.js @@ -527,7 +527,7 @@ export default { 'sp.permissions.gate_off': 'Tắt: WebBrain hành động trên mọi trang web mà không hỏi.', 'sp.permissions.manage': 'Quản lý quyền của trang web', 'sp.permissions.enabled': 'Lời nhắc về quyền đã được bật lại.', - "sp.help.shortcuts_html": "Phím tắt
Ctrl/Cmd+/ - Tập trung đầu vào
Ctrl/Cmd+Shift+A - Chuyển sang chế độ Hỏi
Ctrl/Cmd+Shift+X - Chuyển sang chế độ Act
Ctrl/Cmd+Shift+D - Chuyển sang chế độ Dev
Escape - Dừng quá trình chạy đang hoạt động
Escape hai lần - Dừng quá trình ghi đang hoạt động", + "sp.help.shortcuts_html": "Phím tắt
Ctrl/Cmd+/ - Tập trung đầu vào
Ctrl/Cmd+Shift+A - Chuyển sang chế độ Hỏi
Ctrl/Cmd+Shift+X - Chuyển sang chế độ Act
Ctrl/Cmd+Shift+D - Chuyển sang chế độ Dev
Escape - Dừng quá trình chạy đang hoạt động
Escape hai lần - Dừng quá trình ghi đang hoạt động
1–9 - Chọn câu trả lời có số đó", "sp.slash.record_transcribe": "Ghi và lưu bản ghi Whisper sau khi dừng", "sp.slash.unknown_command": "Lệnh gạch chéo không xác định {command}. Sử dụng /help để xem các lệnh có sẵn.", "sp.slash.invalid_usage": "Cú pháp lệnh gạch chéo không hợp lệ. Cách sử dụng: {usage}", diff --git a/src/chrome/src/ui/locales/zh.js b/src/chrome/src/ui/locales/zh.js index 7e3304422..a81117bcd 100644 --- a/src/chrome/src/ui/locales/zh.js +++ b/src/chrome/src/ui/locales/zh.js @@ -679,7 +679,7 @@ export default { "sp.perm.verb.download": "下载文件自", "sp.perm.verb.upload": "上传文件到", "sp.perm.verb.record": "录制标签页(及麦克风)于", - "sp.help.shortcuts_html": "键盘快捷键
Ctrl/Cmd+/ —— 聚焦输入框
Ctrl/Cmd+Shift+A —— 切换到提问模式
Ctrl/Cmd+Shift+X —— 切换到执行模式
Ctrl/Cmd+Shift+D —— 切换到开发模式
Ctrl/Cmd+M —— 切换语音输入", + "sp.help.shortcuts_html": "键盘快捷键
Ctrl/Cmd+/ —— 聚焦输入框
Ctrl/Cmd+Shift+A —— 切换到提问模式
Ctrl/Cmd+Shift+X —— 切换到执行模式
Ctrl/Cmd+Shift+D —— 切换到开发模式
Escape —— 停止当前运行
Escape 两次 —— 停止当前录制
1–9 —— 选择对应编号的答案", "sp.slash.record_transcribe": "停止录制后保存 Whisper 转录", "sp.slash.unknown_command": "未知斜杠命令 {command}。使用 /help 查看可用命令。", "sp.slash.invalid_usage": "斜杠命令语法无效。用法:{usage}", diff --git a/src/chrome/src/ui/sidepanel.js b/src/chrome/src/ui/sidepanel.js index 7444b40e4..81e104250 100644 --- a/src/chrome/src/ui/sidepanel.js +++ b/src/chrome/src/ui/sidepanel.js @@ -6890,7 +6890,14 @@ function rebindClarifyCards() { card.querySelectorAll('.permission-education-action').forEach(bindPermissionEducationAction); card.querySelectorAll('.clarify-skip-permissions').forEach(btn => bindPermissionSkipButton(btn, card, tabId, clarifyId)); + // Number the answers again: a card whose HTML was saved before the numbers + // existed gets them now, so every live card answers to its digits. + let shortcut = 0; card.querySelectorAll('.clarify-option').forEach(btn => { + if (++shortcut <= 9) { + btn.dataset.shortcut = String(shortcut); + btn.setAttribute('aria-keyshortcuts', String(shortcut)); + } if (btn.dataset.bound) return; btn.dataset.bound = 'true'; btn.addEventListener('click', () => { @@ -11987,6 +11994,21 @@ function renderClarifyCard(data) { card.dataset.deadlineTs = String(Math.floor(deadlineTs)); } + // Every answer carries its own number, shown in a small square at the right + // edge of the button, and typing that digit answers the card + // (handleClarifyShortcutKeydown). The number lives in a data attribute the + // CSS draws rather than in the button's text, because a card restored from + // saved chat HTML sends that text back as the answer. Inlined, like the text + // repair above, so function-extraction test harnesses keep working. + const numberClarifyOptions = (optionsEl) => { + let shortcut = 0; + for (const button of optionsEl.querySelectorAll('.clarify-option')) { + if (++shortcut > 9) break; + button.dataset.shortcut = String(shortcut); + button.setAttribute('aria-keyshortcuts', String(shortcut)); + } + }; + const qEl = document.createElement('div'); qEl.className = 'clarify-question'; if (data.pendingReconciliation === true) qEl.style.whiteSpace = 'pre-wrap'; @@ -12030,6 +12052,7 @@ function renderClarifyCard(data) { deny.dataset.value = 'deny'; deny.addEventListener('click', () => submitClarify(card, tabId, clarifyId, 'deny', 'option')); optionsEl.appendChild(deny); + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -12073,6 +12096,7 @@ function renderClarifyCard(data) { b.addEventListener('click', () => submitClarify(card, tabId, clarifyId, value, 'option')); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -12133,6 +12157,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -12183,6 +12208,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -12221,6 +12247,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -12259,6 +12286,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -12310,6 +12338,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); // The agent's timer decides; this countdown shows it and backs it up. const stepTimeoutAnswer = ['once', 'deny'].includes(data.timeoutAnswer) ? data.timeoutAnswer : ''; @@ -12408,6 +12437,7 @@ function renderClarifyCard(data) { bindPermissionSkipButton(skip, card, tabId, clarifyId); optionsEl.appendChild(skip); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); // The hint offers "Always allow", which an upload card does not have. @@ -12444,6 +12474,7 @@ function renderClarifyCard(data) { b.addEventListener('click', () => submitClarify(card, tabId, clarifyId, b.textContent, 'option')); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); } @@ -12976,6 +13007,45 @@ function submitClarify(card, tabId, clarifyId, answer, source) { } +/** + * The numbered answer a digit picks on the live clarify card, or null. + * + * The digit only counts where nothing else claims the keyboard: no focus, the + * composer, or the card itself. A field with text in it keeps the digit as + * text, so an answer the user is typing is never cut short; an empty field + * gives it up, which is what makes "1" work while the card's own input holds + * the caret. The lowest card is the live one — an older unanswered card sits + * above it, already invalidated or abandoned. + */ +function clarifyShortcutOption(event) { + if (event.defaultPrevented || event.isComposing) return null; + if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return null; + if (!/^[1-9]$/.test(event.key)) return null; + const cards = document.querySelectorAll('.clarify-card:not(.clarify-answered):not(.clarify-obsolete)'); + const card = cards[cards.length - 1]; + if (!card) return null; + const active = document.activeElement; + if (active && active !== document.body && active !== inputEl && !card.contains(active)) return null; + const tag = active?.tagName; + if (tag === 'SELECT' || active?.isContentEditable) return null; + if ((tag === 'INPUT' || tag === 'TEXTAREA') && String(active.value || '')) return null; + const option = card.querySelector(`.clarify-option[data-shortcut="${event.key}"]`); + return option && !option.disabled ? option : null; +} + +function handleClarifyShortcutKeydown(event) { + const option = clarifyShortcutOption(event); + if (!option) return; + // preventDefault keeps the digit out of the composer it was typed into. + event.preventDefault(); + event.stopPropagation(); + // Click the button rather than answering here, so a permission card's own + // label bookkeeping and a scheduled card's tab still go through one path. + option.click(); +} + +document.addEventListener('keydown', handleClarifyShortcutKeydown, true); + // ========================================================================== // ACTIVITY HISTORY — retained in every mode, revealed by verbose mode // ========================================================================== diff --git a/src/chrome/styles/sidepanel.css b/src/chrome/styles/sidepanel.css index 645120f1e..6458054a5 100644 --- a/src/chrome/styles/sidepanel.css +++ b/src/chrome/styles/sidepanel.css @@ -4855,6 +4855,9 @@ html[data-ui-scale="175"] .composer-toolbar { } .clarify-option { + display: flex; + align-items: center; + gap: 8px; text-align: left; padding: 8px 10px; background: var(--bg-input); @@ -4876,6 +4879,33 @@ html[data-ui-scale="175"] .composer-toolbar { cursor: default; } +/* The answer's number, drawn from the data attribute so the button's own text + stays the answer WebBrain sends back. The empty alt text after the slash + keeps the digit out of the accessible name; aria-keyshortcuts announces the + shortcut instead. */ +.clarify-option[data-shortcut]::after { + content: attr(data-shortcut) / ""; + box-sizing: border-box; + flex: none; + margin-left: auto; + min-width: 16px; + height: 16px; + border: 1px solid color-mix(in srgb, var(--text-secondary) 40%, transparent); + border-radius: 3px; + background: var(--tint-soft); + color: var(--text-secondary); + font-size: 10px; + font-weight: 600; + line-height: 14px; + text-align: center; + font-variant-numeric: tabular-nums; +} + +.clarify-option:hover:not(:disabled)::after { + border-color: var(--accent); + color: var(--text-primary); +} + /* The permission card's way to the skip dialog: set apart from the answers above it and marked as risky. */ .clarify-skip-permissions { diff --git a/src/firefox/src/ui/locales/ar.js b/src/firefox/src/ui/locales/ar.js index b96d89385..35436abbd 100644 --- a/src/firefox/src/ui/locales/ar.js +++ b/src/firefox/src/ui/locales/ar.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "يُنزّل ملفات من", "sp.perm.verb.upload": "يرفع ملفًا إلى", "sp.perm.verb.record": "يُسجّل علامة التبويب (والميكروفون) على", - "sp.help.shortcuts_html": "اختصارات لوحة المفاتيح
Ctrl/Cmd+/ — التركيز على حقل الإدخال
Ctrl/Cmd+Shift+A — التبديل إلى وضع السؤال
Ctrl/Cmd+Shift+X — التبديل إلى وضع التنفيذ
Ctrl/Cmd+Shift+D — التبديل إلى وضع التطوير
Ctrl/Cmd+M — تبديل الإدخال الصوتي", + "sp.help.shortcuts_html": "اختصارات لوحة المفاتيح
Ctrl/Cmd+/ — التركيز على حقل الإدخال
Ctrl/Cmd+Shift+A — التبديل إلى وضع السؤال
Ctrl/Cmd+Shift+X — التبديل إلى وضع التنفيذ
Ctrl/Cmd+Shift+D — التبديل إلى وضع التطوير
Escape — إيقاف التشغيل النشط
1–9 — اختيار الإجابة التي تحمل هذا الرقم", "sp.slash.record_transcribe": "التسجيل وحفظ نص Whisper بعد الإيقاف", "sp.slash.unknown_command": "أمر شرطة مائلة غير معروف {command}. استخدم /help لعرض الأوامر المتاحة.", "sp.slash.invalid_usage": "بنية أمر الشرطة المائلة غير صالحة. الاستخدام: {usage}", diff --git a/src/firefox/src/ui/locales/bn.js b/src/firefox/src/ui/locales/bn.js index fa6593301..dedf77f52 100644 --- a/src/firefox/src/ui/locales/bn.js +++ b/src/firefox/src/ui/locales/bn.js @@ -524,7 +524,7 @@ export default { 'sp.permissions.gate_off': 'বন্ধ: WebBrain জিজ্ঞাসা না করেই প্রতিটি সাইটে কাজ করে।', 'sp.permissions.manage': 'সাইটের অনুমতি পরিচালনা করুন', 'sp.permissions.enabled': 'অনুমতি প্রম্পট আবার চালু হয়েছে।', - "sp.help.shortcuts_html": "কীবোর্ড শর্টকাট
Ctrl/Cmd+/ - ইনপুট ফোকাস করুন
Ctrl/Cmd+Shift+A — আস্ক মোডে স্যুইচ করুন
Ctrl/Cmd+Shift+X — অ্যাক্ট মোডে স্যুইচ করুন
Ctrl/Cmd+Shift+D — ডেভ মোডে স্যুইচ করুন
Escape - সক্রিয় রান বন্ধ করুন", + "sp.help.shortcuts_html": "কীবোর্ড শর্টকাট
Ctrl/Cmd+/ - ইনপুট ফোকাস করুন
Ctrl/Cmd+Shift+A — আস্ক মোডে স্যুইচ করুন
Ctrl/Cmd+Shift+X — অ্যাক্ট মোডে স্যুইচ করুন
Ctrl/Cmd+Shift+D — ডেভ মোডে স্যুইচ করুন
Escape - সক্রিয় রান বন্ধ করুন
1–9 — সেই নম্বরের উত্তরটি বেছে নিন", "sp.slash.record_transcribe": "থামার পরে একটি হুইস্পার প্রতিলিপি রেকর্ড করুন এবং সংরক্ষণ করুন", "sp.slash.unknown_command": "অজানা স্ল্যাশ কমান্ড {command}। উপলব্ধ কমান্ড দেখতে /help ব্যবহার করুন।", "sp.slash.invalid_usage": "অবৈধ স্ল্যাশ কমান্ড সিনট্যাক্স। ব্যবহার: {usage}", diff --git a/src/firefox/src/ui/locales/de.js b/src/firefox/src/ui/locales/de.js index f666c6eb2..7e59f1a78 100644 --- a/src/firefox/src/ui/locales/de.js +++ b/src/firefox/src/ui/locales/de.js @@ -529,7 +529,7 @@ export default { 'sp.perm.verb.record': 'Tab (und Mikrofon) aufnehmen auf', 'sp.perm.verb.schedule': 'zukünftige Aufgaben planen für', 'sp.perm.verb.window': 'die Größe des Browserfensters ändern auf', - 'sp.help.shortcuts_html': 'Tastenkürzel
Ctrl/Cmd+/ — Eingabefeld fokussieren
Ctrl/Cmd+Shift+A — Zum Fragen-Modus wechseln
Ctrl/Cmd+Shift+X — Zum Handeln-Modus wechseln
Ctrl/Cmd+Shift+D — Zum Dev-Modus wechseln
Escape — Aktiven Durchlauf stoppen
Escape zweimal — Aktive Aufnahme stoppen', + 'sp.help.shortcuts_html': 'Tastenkürzel
Ctrl/Cmd+/ — Eingabefeld fokussieren
Ctrl/Cmd+Shift+A — Zum Fragen-Modus wechseln
Ctrl/Cmd+Shift+X — Zum Handeln-Modus wechseln
Ctrl/Cmd+Shift+D — Zum Dev-Modus wechseln
Escape — Aktiven Durchlauf stoppen
1–9 — Antwort mit dieser Nummer wählen', 'sp.compact.nothing_to_compact': 'Noch nichts zu kompaktieren — es gibt nicht genügend älteren Kontext.', 'sp.compact.busy': 'Kompaktierung nicht möglich, während ein Durchlauf läuft — warten Sie auf dessen Abschluss.', 'sp.compact.failed': 'Kontext-Kompaktierung fehlgeschlagen: {error}', diff --git a/src/firefox/src/ui/locales/en.js b/src/firefox/src/ui/locales/en.js index 909e6165f..6bbe9e126 100644 --- a/src/firefox/src/ui/locales/en.js +++ b/src/firefox/src/ui/locales/en.js @@ -538,7 +538,7 @@ export default { 'sp.permissions.gate_off': 'Off: WebBrain acts on every site without asking.', 'sp.permissions.manage': 'Manage site permissions', 'sp.permissions.enabled': 'Permission prompts are on again.', - "sp.help.shortcuts_html": "Keyboard Shortcuts
Ctrl/Cmd+/ — Focus the input
Ctrl/Cmd+Shift+A — Switch to Ask mode
Ctrl/Cmd+Shift+X — Switch to Act mode
Ctrl/Cmd+Shift+D — Switch to Dev mode
Escape — Stop the active run", + "sp.help.shortcuts_html": "Keyboard Shortcuts
Ctrl/Cmd+/ — Focus the input
Ctrl/Cmd+Shift+A — Switch to Ask mode
Ctrl/Cmd+Shift+X — Switch to Act mode
Ctrl/Cmd+Shift+D — Switch to Dev mode
Escape — Stop the active run
1–9 — Pick that answer when WebBrain asks", "sp.slash.record_transcribe": "Record and save a Whisper transcript after stop", "sp.slash.unknown_command": "Unknown slash command {command}. Use /help to see available commands.", "sp.slash.invalid_usage": "Invalid slash command syntax. Usage: {usage}", diff --git a/src/firefox/src/ui/locales/es.js b/src/firefox/src/ui/locales/es.js index 6c0c817c1..bb12c1077 100644 --- a/src/firefox/src/ui/locales/es.js +++ b/src/firefox/src/ui/locales/es.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "descargar archivos de", "sp.perm.verb.upload": "subir un archivo a", "sp.perm.verb.record": "grabar la pestaña (y el micrófono) en", - "sp.help.shortcuts_html": "Atajos de teclado
Ctrl/Cmd+/ — Enfocar la entrada
Ctrl/Cmd+Shift+A — Cambiar al modo Preguntar
Ctrl/Cmd+Shift+X — Cambiar al modo Actuar
Ctrl/Cmd+Shift+D — Cambiar al modo Desarrollo
Ctrl/Cmd+M — Alternar entrada de voz", + "sp.help.shortcuts_html": "Atajos de teclado
Ctrl/Cmd+/ — Enfocar la entrada
Ctrl/Cmd+Shift+A — Cambiar al modo Preguntar
Ctrl/Cmd+Shift+X — Cambiar al modo Actuar
Ctrl/Cmd+Shift+D — Cambiar al modo Desarrollo
Escape — Detener la ejecución activa
1–9 — Elegir la respuesta con ese número", "sp.slash.record_transcribe": "Grabar y guardar una transcripción de Whisper al detener", "sp.slash.unknown_command": "Comando de barra desconocido {command}. Usa /help para ver los comandos disponibles.", "sp.slash.invalid_usage": "Sintaxis de comando de barra no válida. Uso: {usage}", diff --git a/src/firefox/src/ui/locales/fa.js b/src/firefox/src/ui/locales/fa.js index bd9409c93..8dd61b0aa 100644 --- a/src/firefox/src/ui/locales/fa.js +++ b/src/firefox/src/ui/locales/fa.js @@ -524,7 +524,7 @@ export default { 'sp.permissions.gate_off': 'خاموش: WebBrain بدون پرسیدن در همهٔ سایت‌ها اقدام می‌کند.', 'sp.permissions.manage': 'مدیریت مجوزهای سایت', 'sp.permissions.enabled': 'درخواست‌های مجوز دوباره روشن شدند.', - "sp.help.shortcuts_html": "میانبرهای صفحه کلید
Ctrl/Cmd+/ - روی ورودی تمرکز کنید
Ctrl/Cmd+Shift+A - به حالت سؤال بروید
Ctrl/Cmd+Shift+X - به حالت Act تغییر دهید
Ctrl/Cmd+Shift+D - به حالت Dev بروید
Escape - اجرای فعال را متوقف کنید", + "sp.help.shortcuts_html": "میانبرهای صفحه کلید
Ctrl/Cmd+/ - روی ورودی تمرکز کنید
Ctrl/Cmd+Shift+A - به حالت سؤال بروید
Ctrl/Cmd+Shift+X - به حالت Act تغییر دهید
Ctrl/Cmd+Shift+D - به حالت Dev بروید
Escape - اجرای فعال را متوقف کنید
1–9 - انتخاب پاسخی که آن شماره را دارد", "sp.slash.record_transcribe": "پس از توقف، رونوشت Whisper را ضبط و ذخیره کنید", "sp.slash.unknown_command": "دستور اسلش نامشخص {command}. از /help برای دیدن دستورات موجود استفاده کنید.", "sp.slash.invalid_usage": "دستور دستور اسلش نامعتبر است. استفاده: {usage}", diff --git a/src/firefox/src/ui/locales/fr.js b/src/firefox/src/ui/locales/fr.js index afe6696c6..a3a99764b 100644 --- a/src/firefox/src/ui/locales/fr.js +++ b/src/firefox/src/ui/locales/fr.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "télécharger des fichiers depuis", "sp.perm.verb.upload": "téléverser un fichier vers", "sp.perm.verb.record": "enregistrer l'onglet (et le microphone) sur", - "sp.help.shortcuts_html": "Raccourcis clavier
Ctrl/Cmd+/ — Focus sur la zone de saisie
Ctrl/Cmd+Shift+A — Passer en mode Demander
Ctrl/Cmd+Shift+X — Passer en mode Agir
Ctrl/Cmd+Shift+D — Passer en mode Développement
Ctrl/Cmd+M — Basculer la saisie vocale", + "sp.help.shortcuts_html": "Raccourcis clavier
Ctrl/Cmd+/ — Focus sur la zone de saisie
Ctrl/Cmd+Shift+A — Passer en mode Demander
Ctrl/Cmd+Shift+X — Passer en mode Agir
Ctrl/Cmd+Shift+D — Passer en mode Développement
Escape — Arrêter l’exécution en cours
1–9 — Choisir la réponse portant ce numéro", "sp.slash.record_transcribe": "Enregistrer et sauvegarder une transcription Whisper à l'arrêt", "sp.slash.unknown_command": "Commande slash inconnue {command}. Utilisez /help pour voir les commandes disponibles.", "sp.slash.invalid_usage": "Syntaxe de commande slash invalide. Utilisation : {usage}", diff --git a/src/firefox/src/ui/locales/he.js b/src/firefox/src/ui/locales/he.js index 749c82b4b..40a3ea9ff 100644 --- a/src/firefox/src/ui/locales/he.js +++ b/src/firefox/src/ui/locales/he.js @@ -509,7 +509,7 @@ export default { "sp.permissions.gate_off": "כבוי: WebBrain פועל בכל אתר בלי לשאול.", "sp.permissions.manage": "ניהול הרשאות אתרים", "sp.permissions.enabled": "בקשות ההרשאה הופעלו שוב.", - "sp.help.shortcuts_html": "קיצורי מקלדת
Ctrl/Cmd+/ — מקד את שדה הקלט
Ctrl/Cmd+Shift+A — עבור למצב שאל
Ctrl/Cmd+Shift+X — עבור למצב פעולה
Ctrl/Cmd+Shift+D — עבור למצב Dev
Ctrl/Cmd+M — הפעל או השבת קלט קולי", + "sp.help.shortcuts_html": "קיצורי מקלדת
Ctrl/Cmd+/ — מקד את שדה הקלט
Ctrl/Cmd+Shift+A — עבור למצב שאל
Ctrl/Cmd+Shift+X — עבור למצב פעולה
Ctrl/Cmd+Shift+D — עבור למצב Dev
Escape — עצירת ההרצה הפעילה
1–9 — בחירת התשובה שמספרה זה", "sp.slash.record_transcribe": "הקלט ושמור תמלול Whisper לאחר העצירה", "sp.slash.unknown_command": "פקודת לוכסן לא מוכרת {command}. השתמשו ב-/help כדי לראות את הפקודות הזמינות.", "sp.slash.invalid_usage": "תחביר פקודת לוכסן לא תקין. שימוש: {usage}", diff --git a/src/firefox/src/ui/locales/hi.js b/src/firefox/src/ui/locales/hi.js index 2bfba600a..e5dc16b77 100644 --- a/src/firefox/src/ui/locales/hi.js +++ b/src/firefox/src/ui/locales/hi.js @@ -524,7 +524,7 @@ export default { 'sp.permissions.gate_off': 'बंद: WebBrain बिना पूछे हर साइट पर कार्रवाई करता है।', 'sp.permissions.manage': 'साइट अनुमतियां प्रबंधित करें', 'sp.permissions.enabled': 'अनुमति संकेत फिर से चालू हैं।', - "sp.help.shortcuts_html": "कीबोर्ड शॉर्टकट
Ctrl/Cmd+/ - इनपुट पर फोकस करें
Ctrl/Cmd+Shift+A - आस्क मोड पर स्विच करें
Ctrl/Cmd+Shift+X - एक्ट मोड पर स्विच करें
Ctrl/Cmd+Shift+D - डेव मोड पर स्विच करें
Escape - सक्रिय रन बंद करें", + "sp.help.shortcuts_html": "कीबोर्ड शॉर्टकट
Ctrl/Cmd+/ - इनपुट पर फोकस करें
Ctrl/Cmd+Shift+A - आस्क मोड पर स्विच करें
Ctrl/Cmd+Shift+X - एक्ट मोड पर स्विच करें
Ctrl/Cmd+Shift+D - डेव मोड पर स्विच करें
Escape - सक्रिय रन बंद करें
1–9 - उस नंबर वाला उत्तर चुनें", "sp.slash.record_transcribe": "रुकने के बाद व्हिस्पर प्रतिलेख को रिकॉर्ड करें और सहेजें", "sp.slash.unknown_command": "अज्ञात स्लैश कमांड {command}। उपलब्ध कमांड देखने के लिए /help का उपयोग करें।", "sp.slash.invalid_usage": "अमान्य स्लैश कमांड सिंटैक्स. उपयोग: {usage}", diff --git a/src/firefox/src/ui/locales/id.js b/src/firefox/src/ui/locales/id.js index 00e076dcc..5aa584a5b 100644 --- a/src/firefox/src/ui/locales/id.js +++ b/src/firefox/src/ui/locales/id.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "mengunduh berkas dari", "sp.perm.verb.upload": "mengunggah berkas ke", "sp.perm.verb.record": "merekam tab (dan mikrofon) pada", - "sp.help.shortcuts_html": "Pintasan Keyboard
Ctrl/Cmd+/ — Fokus ke input
Ctrl/Cmd+Shift+A — Beralih ke mode Tanya
Ctrl/Cmd+Shift+X — Beralih ke mode Aksi
Ctrl/Cmd+Shift+D — Beralih ke mode Dev
Ctrl/Cmd+M — Alihkan input suara", + "sp.help.shortcuts_html": "Pintasan Keyboard
Ctrl/Cmd+/ — Fokus ke input
Ctrl/Cmd+Shift+A — Beralih ke mode Tanya
Ctrl/Cmd+Shift+X — Beralih ke mode Aksi
Ctrl/Cmd+Shift+D — Beralih ke mode Dev
Escape — Hentikan proses yang berjalan
1–9 — Pilih jawaban bernomor itu", "sp.slash.record_transcribe": "Rekam dan simpan transkrip Whisper setelah berhenti", "sp.slash.unknown_command": "Perintah garis miring tidak dikenal {command}. Gunakan /help untuk melihat perintah yang tersedia.", "sp.slash.invalid_usage": "Sintaks perintah garis miring tidak valid. Penggunaan: {usage}", diff --git a/src/firefox/src/ui/locales/ja.js b/src/firefox/src/ui/locales/ja.js index b10097cea..60bdec254 100644 --- a/src/firefox/src/ui/locales/ja.js +++ b/src/firefox/src/ui/locales/ja.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "からのファイルのダウンロードを", "sp.perm.verb.upload": "へのファイルのアップロードを", "sp.perm.verb.record": "でのタブ(およびマイク)の録画を", - "sp.help.shortcuts_html": "キーボードショートカット
Ctrl/Cmd+/ — 入力にフォーカス
Ctrl/Cmd+Shift+A — 質問モードに切り替え
Ctrl/Cmd+Shift+X — 操作モードに切り替え
Ctrl/Cmd+Shift+D — 開発モードに切り替え
Ctrl/Cmd+M — 音声入力を切り替え", + "sp.help.shortcuts_html": "キーボードショートカット
Ctrl/Cmd+/ — 入力にフォーカス
Ctrl/Cmd+Shift+A — 質問モードに切り替え
Ctrl/Cmd+Shift+X — 操作モードに切り替え
Ctrl/Cmd+Shift+D — 開発モードに切り替え
Escape — 実行中のタスクを停止
1–9 — その番号の回答を選択", "sp.slash.record_transcribe": "録画停止後に Whisper の文字起こしを保存", "sp.slash.unknown_command": "不明なスラッシュコマンドです: {command}。利用可能なコマンドは /help で確認できます。", "sp.slash.invalid_usage": "スラッシュコマンドの構文が正しくありません。使用法: {usage}", diff --git a/src/firefox/src/ui/locales/ko.js b/src/firefox/src/ui/locales/ko.js index 01af25fcd..a747f1e51 100644 --- a/src/firefox/src/ui/locales/ko.js +++ b/src/firefox/src/ui/locales/ko.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "파일 다운로드", "sp.perm.verb.upload": "파일 업로드", "sp.perm.verb.record": "탭(및 마이크) 녹화", - "sp.help.shortcuts_html": "키보드 단축키
Ctrl/Cmd+/ — 입력에 포커스
Ctrl/Cmd+Shift+A — 질문 모드로 전환
Ctrl/Cmd+Shift+X — 실행 모드로 전환
Ctrl/Cmd+Shift+D — 개발 모드로 전환
Ctrl/Cmd+M — 음성 입력 전환", + "sp.help.shortcuts_html": "키보드 단축키
Ctrl/Cmd+/ — 입력에 포커스
Ctrl/Cmd+Shift+A — 질문 모드로 전환
Ctrl/Cmd+Shift+X — 실행 모드로 전환
Ctrl/Cmd+Shift+D — 개발 모드로 전환
Escape — 실행 중인 작업 중지
1–9 — 해당 번호의 답변 선택", "sp.slash.record_transcribe": "녹화 후 Whisper 전사본 저장", "sp.slash.unknown_command": "알 수 없는 슬래시 명령어입니다: {command}. 사용 가능한 명령어는 /help에서 확인하세요.", "sp.slash.invalid_usage": "슬래시 명령어 구문이 올바르지 않습니다. 사용법: {usage}", diff --git a/src/firefox/src/ui/locales/ms.js b/src/firefox/src/ui/locales/ms.js index 2c5540cdf..de2b9278d 100644 --- a/src/firefox/src/ui/locales/ms.js +++ b/src/firefox/src/ui/locales/ms.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "memuat turun fail dari", "sp.perm.verb.upload": "memuat naik fail ke", "sp.perm.verb.record": "merakam tab (dan mikrofon) pada", - "sp.help.shortcuts_html": "Pintasan Papan Kekunci
Ctrl/Cmd+/ — Fokus pada medan input
Ctrl/Cmd+Shift+A — Beralih ke mod Tanya
Ctrl/Cmd+Shift+X — Beralih ke mod Lakukan
Ctrl/Cmd+Shift+D — Beralih ke mod Dev
Ctrl/Cmd+M — Togol input suara", + "sp.help.shortcuts_html": "Pintasan Papan Kekunci
Ctrl/Cmd+/ — Fokus pada medan input
Ctrl/Cmd+Shift+A — Beralih ke mod Tanya
Ctrl/Cmd+Shift+X — Beralih ke mod Lakukan
Ctrl/Cmd+Shift+D — Beralih ke mod Dev
Escape — Hentikan larian aktif
1–9 — Pilih jawapan bernombor itu", "sp.slash.record_transcribe": "Rakam dan simpan transkrip Whisper selepas berhenti", "sp.slash.unknown_command": "Arahan slash tidak diketahui {command}. Gunakan /help untuk melihat arahan yang tersedia.", "sp.slash.invalid_usage": "Sintaks arahan slash tidak sah. Penggunaan: {usage}", diff --git a/src/firefox/src/ui/locales/nl.js b/src/firefox/src/ui/locales/nl.js index ab052e3e3..e79b7f748 100644 --- a/src/firefox/src/ui/locales/nl.js +++ b/src/firefox/src/ui/locales/nl.js @@ -510,7 +510,7 @@ export default { 'sp.permissions.gate_off': 'Uit: WebBrain handelt op elke site zonder te vragen.', 'sp.permissions.manage': 'Sitemachtigingen beheren', 'sp.permissions.enabled': 'Machtigingsvragen staan weer aan.', - "sp.help.shortcuts_html": "Sneltoetsen
...", + "sp.help.shortcuts_html": "Sneltoetsen
Ctrl/Cmd+/ — Het invoerveld focussen
Ctrl/Cmd+Shift+A — Naar de modus Vragen schakelen
Ctrl/Cmd+Shift+X — Naar de modus Handelen schakelen
Ctrl/Cmd+Shift+D — Naar de modus Dev schakelen
Escape — De actieve run stoppen
1–9 — Het antwoord met dat nummer kiezen", "sp.slash.record_transcribe": "Opnemen en Whisper-transcriptie opslaan na stop", "sp.slash.unknown_command": "Onbekend slashcommando {command}. Gebruik /help om beschikbare commando's te zien.", "sp.slash.invalid_usage": "Ongeldige slashcommandosyntaxis. Gebruik: {usage}", diff --git a/src/firefox/src/ui/locales/pl.js b/src/firefox/src/ui/locales/pl.js index 83a547af4..0e7fb1a3f 100644 --- a/src/firefox/src/ui/locales/pl.js +++ b/src/firefox/src/ui/locales/pl.js @@ -410,7 +410,7 @@ export default { 'sp.permissions.gate_off': 'Wyłączone: WebBrain działa na każdej stronie bez pytania.', 'sp.permissions.manage': 'Zarządzaj uprawnieniami stron', 'sp.permissions.enabled': 'Pytania o uprawnienia są ponownie włączone.', - "sp.help.shortcuts_html": "Skróty klawiszowe
Ctrl/Cmd+/ — Ustaw fokus na polu wprowadzania
Ctrl/Cmd+Shift+A — Przełącz na tryb Pytaj
Ctrl/Cmd+Shift+X — Przełącz na tryb Działaj
Ctrl/Cmd+Shift+D — Przełącz na tryb Dev
Ctrl/Cmd+M — Togol wprowadzanie głosowe", + "sp.help.shortcuts_html": "Skróty klawiszowe
Ctrl/Cmd+/ — Ustaw fokus na polu wprowadzania
Ctrl/Cmd+Shift+A — Przełącz na tryb Pytaj
Ctrl/Cmd+Shift+X — Przełącz na tryb Działaj
Ctrl/Cmd+Shift+D — Przełącz na tryb Dev
Escape — Zatrzymaj aktywne uruchomienie
1–9 — Wybierz odpowiedź z tym numerem", "sp.slash.record_transcribe": "Nagraj i zapisz transkrypcję Whisper po zatrzymaniu", "sp.slash.unknown_command": "Nieznane polecenie ukośnikowe {command}. Użyj /help, aby zobaczyć dostępne polecenia.", "sp.slash.invalid_usage": "Nieprawidłowa składnia polecenia ukośnikowego. Użycie: {usage}", diff --git a/src/firefox/src/ui/locales/pt.js b/src/firefox/src/ui/locales/pt.js index 2ed0d68ca..ee600debd 100644 --- a/src/firefox/src/ui/locales/pt.js +++ b/src/firefox/src/ui/locales/pt.js @@ -524,7 +524,7 @@ export default { 'sp.permissions.gate_off': 'Desativado: o WebBrain age em qualquer site sem perguntar.', 'sp.permissions.manage': 'Gerenciar permissões de sites', 'sp.permissions.enabled': 'Os prompts de permissão estão ativados novamente.', - "sp.help.shortcuts_html": "Atalhos de teclado
Ctrl/Cmd+/ - Concentre a entrada
Ctrl/Cmd+Shift+A — Mudar para o modo Perguntar
Ctrl/Cmd+Shift+X — Mudar para o modo Agir
Ctrl/Cmd+Shift+D — Mudar para o modo Dev
Escape — Pare a execução ativa", + "sp.help.shortcuts_html": "Atalhos de teclado
Ctrl/Cmd+/ - Concentre a entrada
Ctrl/Cmd+Shift+A — Mudar para o modo Perguntar
Ctrl/Cmd+Shift+X — Mudar para o modo Agir
Ctrl/Cmd+Shift+D — Mudar para o modo Dev
Escape — Pare a execução ativa
1–9 — Escolher a resposta com esse número", "sp.slash.record_transcribe": "Grave e salve uma transcrição do Whisper após parar", "sp.slash.unknown_command": "Comando de barra desconhecido {command}. Use /help para ver os comandos disponíveis.", "sp.slash.invalid_usage": "Sintaxe de comando de barra inválida. Uso: {usage}", diff --git a/src/firefox/src/ui/locales/ru.js b/src/firefox/src/ui/locales/ru.js index bf38fd7d6..baff36bd7 100644 --- a/src/firefox/src/ui/locales/ru.js +++ b/src/firefox/src/ui/locales/ru.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "скачивать файлы с", "sp.perm.verb.upload": "загрузить файл на", "sp.perm.verb.record": "записывать вкладку (и микрофон) на", - "sp.help.shortcuts_html": "Горячие клавиши
Ctrl/Cmd+/ — Переключить фокус на ввод
Ctrl/Cmd+Shift+A — Переключиться в режим «Вопрос»
Ctrl/Cmd+Shift+X — Переключиться в режим «Действие»
Ctrl/Cmd+Shift+D — Переключиться в режим «Разработка»
Ctrl/Cmd+M — Переключить голосовой ввод", + "sp.help.shortcuts_html": "Горячие клавиши
Ctrl/Cmd+/ — Переключить фокус на ввод
Ctrl/Cmd+Shift+A — Переключиться в режим «Вопрос»
Ctrl/Cmd+Shift+X — Переключиться в режим «Действие»
Ctrl/Cmd+Shift+D — Переключиться в режим «Разработка»
Escape — Остановить активный запуск
1–9 — Выбрать ответ с этим номером", "sp.slash.record_transcribe": "Записать и сохранить расшифровку Whisper после остановки", "sp.slash.unknown_command": "Неизвестная slash-команда {command}. Используйте /help, чтобы увидеть доступные команды.", "sp.slash.invalid_usage": "Неверный синтаксис slash-команды. Использование: {usage}", diff --git a/src/firefox/src/ui/locales/th.js b/src/firefox/src/ui/locales/th.js index 24c0d1142..8b368e7cd 100644 --- a/src/firefox/src/ui/locales/th.js +++ b/src/firefox/src/ui/locales/th.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "ดาวน์โหลดไฟล์จาก", "sp.perm.verb.upload": "อัปโหลดไฟล์ไปยัง", "sp.perm.verb.record": "บันทึกแท็บ (และไมโครโฟน) บน", - "sp.help.shortcuts_html": "แป้นพิมพ์ลัด
Ctrl/Cmd+/ — โฟกัสช่องป้อนข้อความ
Ctrl/Cmd+Shift+A — เปลี่ยนไปโหมดถาม
Ctrl/Cmd+Shift+X — เปลี่ยนไปโหมดทำ
Ctrl/Cmd+Shift+D — เปลี่ยนไปโหมดนักพัฒนา
Ctrl/Cmd+M — สลับการป้อนด้วยเสียง", + "sp.help.shortcuts_html": "แป้นพิมพ์ลัด
Ctrl/Cmd+/ — โฟกัสช่องป้อนข้อความ
Ctrl/Cmd+Shift+A — เปลี่ยนไปโหมดถาม
Ctrl/Cmd+Shift+X — เปลี่ยนไปโหมดทำ
Ctrl/Cmd+Shift+D — เปลี่ยนไปโหมดนักพัฒนา
Escape — หยุดการทำงานที่กำลังทำอยู่
1–9 — เลือกคำตอบที่มีหมายเลขนั้น", "sp.slash.record_transcribe": "บันทึกและบันทึกบทถอดเสียง Whisper หลังหยุด", "sp.slash.unknown_command": "ไม่รู้จักคำสั่งสแลช {command} ใช้ /help เพื่อดูคำสั่งที่ใช้ได้", "sp.slash.invalid_usage": "ไวยากรณ์คำสั่งสแลชไม่ถูกต้อง วิธีใช้: {usage}", diff --git a/src/firefox/src/ui/locales/tl.js b/src/firefox/src/ui/locales/tl.js index a96e79793..149da3ee2 100644 --- a/src/firefox/src/ui/locales/tl.js +++ b/src/firefox/src/ui/locales/tl.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "mag-download ng files mula sa", "sp.perm.verb.upload": "mag-upload ng file sa", "sp.perm.verb.record": "i-record ang tab (at mikropono) sa", - "sp.help.shortcuts_html": "Mga Keyboard Shortcut
Ctrl/Cmd+/ — I-focus ang input
Ctrl/Cmd+Shift+A — Lumipat sa Ask mode
Ctrl/Cmd+Shift+X — Lumipat sa Act mode
Ctrl/Cmd+Shift+D — Lumipat sa Dev mode
Ctrl/Cmd+M — I-toggle ang voice input", + "sp.help.shortcuts_html": "Mga Keyboard Shortcut
Ctrl/Cmd+/ — I-focus ang input
Ctrl/Cmd+Shift+A — Lumipat sa Ask mode
Ctrl/Cmd+Shift+X — Lumipat sa Act mode
Ctrl/Cmd+Shift+D — Lumipat sa Dev mode
Escape — Ihinto ang aktibong run
1–9 — Piliin ang sagot na may ganoong numero", "sp.slash.record_transcribe": "I-record at i-save ang Whisper transcript pagkatapos huminto", "sp.slash.unknown_command": "Hindi kilalang slash command {command}. Gamitin ang /help upang makita ang mga available na command.", "sp.slash.invalid_usage": "Hindi wastong syntax ng slash command. Paggamit: {usage}", diff --git a/src/firefox/src/ui/locales/tr.js b/src/firefox/src/ui/locales/tr.js index 1f02654e8..dc743eee0 100644 --- a/src/firefox/src/ui/locales/tr.js +++ b/src/firefox/src/ui/locales/tr.js @@ -698,7 +698,7 @@ export default { "sp.perm.verb.download": "dosya indirmek", "sp.perm.verb.upload": "dosya yüklemek", "sp.perm.verb.record": "sekmeyi (ve mikrofonu) kaydetmek", - "sp.help.shortcuts_html": "Klavye Kısayolları
Ctrl/Cmd+/ — Giriş alanına odaklan
Ctrl/Cmd+Shift+A — Sor moduna geç
Ctrl/Cmd+Shift+X — Uygula moduna geç
Ctrl/Cmd+Shift+D — Dev moduna geç
Ctrl/Cmd+M — Ses girişini aç/kapat", + "sp.help.shortcuts_html": "Klavye Kısayolları
Ctrl/Cmd+/ — Giriş alanına odaklan
Ctrl/Cmd+Shift+A — Sor moduna geç
Ctrl/Cmd+Shift+X — Uygula moduna geç
Ctrl/Cmd+Shift+D — Dev moduna geç
Escape — Aktif çalışmayı durdur
1–9 — O numaralı yanıtı seç", "sp.slash.record_transcribe": "Kaydet ve durdurduktan sonra Whisper dökümü kaydet", "sp.slash.unknown_command": "Bilinmeyen slash komutu {command}. Kullanılabilir komutları görmek için /help kullanın.", "sp.slash.invalid_usage": "Geçersiz slash komutu sözdizimi. Kullanım: {usage}", diff --git a/src/firefox/src/ui/locales/uk.js b/src/firefox/src/ui/locales/uk.js index 25fcd7741..e31f95002 100644 --- a/src/firefox/src/ui/locales/uk.js +++ b/src/firefox/src/ui/locales/uk.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "завантажити файли з", "sp.perm.verb.upload": "вивантажити файл на", "sp.perm.verb.record": "записати вкладку (і мікрофон) на", - "sp.help.shortcuts_html": "Гарячі клавіші
Ctrl/Cmd+/ — Фокус на полі введення
Ctrl/Cmd+Shift+A — Перейти в режим запитань
Ctrl/Cmd+Shift+X — Перейти в режим дій
Ctrl/Cmd+Shift+D — Перейти в режим розробки
Ctrl/Cmd+M — Перемкнути голосове введення", + "sp.help.shortcuts_html": "Гарячі клавіші
Ctrl/Cmd+/ — Фокус на полі введення
Ctrl/Cmd+Shift+A — Перейти в режим запитань
Ctrl/Cmd+Shift+X — Перейти в режим дій
Ctrl/Cmd+Shift+D — Перейти в режим розробки
Escape — Зупинити активний запуск
1–9 — Вибрати відповідь із цим номером", "sp.slash.record_transcribe": "Записати та зберегти транскрипт Whisper після зупинки", "sp.slash.unknown_command": "Невідома slash-команда {command}. Скористайтеся /help, щоб переглянути доступні команди.", "sp.slash.invalid_usage": "Неправильний синтаксис slash-команди. Використання: {usage}", diff --git a/src/firefox/src/ui/locales/vi.js b/src/firefox/src/ui/locales/vi.js index f4b159c22..623465d7c 100644 --- a/src/firefox/src/ui/locales/vi.js +++ b/src/firefox/src/ui/locales/vi.js @@ -524,7 +524,7 @@ export default { 'sp.permissions.gate_off': 'Tắt: WebBrain hành động trên mọi trang web mà không hỏi.', 'sp.permissions.manage': 'Quản lý quyền của trang web', 'sp.permissions.enabled': 'Lời nhắc về quyền đã được bật lại.', - "sp.help.shortcuts_html": "Phím tắt
Ctrl/Cmd+/ - Tập trung đầu vào
Ctrl/Cmd+Shift+A - Chuyển sang chế độ Hỏi
Ctrl/Cmd+Shift+X - Chuyển sang chế độ Act
Ctrl/Cmd+Shift+D - Chuyển sang chế độ Dev
Escape - Dừng quá trình chạy đang hoạt động", + "sp.help.shortcuts_html": "Phím tắt
Ctrl/Cmd+/ - Tập trung đầu vào
Ctrl/Cmd+Shift+A - Chuyển sang chế độ Hỏi
Ctrl/Cmd+Shift+X - Chuyển sang chế độ Act
Ctrl/Cmd+Shift+D - Chuyển sang chế độ Dev
Escape - Dừng quá trình chạy đang hoạt động
1–9 - Chọn câu trả lời có số đó", "sp.slash.record_transcribe": "Ghi và lưu bản ghi Whisper sau khi dừng", "sp.slash.unknown_command": "Lệnh gạch chéo không xác định {command}. Sử dụng /help để xem các lệnh có sẵn.", "sp.slash.invalid_usage": "Cú pháp lệnh gạch chéo không hợp lệ. Cách sử dụng: {usage}", diff --git a/src/firefox/src/ui/locales/zh.js b/src/firefox/src/ui/locales/zh.js index bc68570ae..1afdf4eeb 100644 --- a/src/firefox/src/ui/locales/zh.js +++ b/src/firefox/src/ui/locales/zh.js @@ -652,7 +652,7 @@ export default { "sp.perm.verb.download": "下载文件自", "sp.perm.verb.upload": "上传文件到", "sp.perm.verb.record": "录制标签页(及麦克风)于", - "sp.help.shortcuts_html": "键盘快捷键
Ctrl/Cmd+/ —— 聚焦输入框
Ctrl/Cmd+Shift+A —— 切换到提问模式
Ctrl/Cmd+Shift+X —— 切换到执行模式
Ctrl/Cmd+Shift+D —— 切换到开发模式
Ctrl/Cmd+M —— 切换语音输入", + "sp.help.shortcuts_html": "键盘快捷键
Ctrl/Cmd+/ —— 聚焦输入框
Ctrl/Cmd+Shift+A —— 切换到提问模式
Ctrl/Cmd+Shift+X —— 切换到执行模式
Ctrl/Cmd+Shift+D —— 切换到开发模式
Escape —— 停止当前运行
1–9 —— 选择对应编号的答案", "sp.slash.record_transcribe": "停止录制后保存 Whisper 转录", "sp.slash.unknown_command": "未知斜杠命令 {command}。使用 /help 查看可用命令。", "sp.slash.invalid_usage": "斜杠命令语法无效。用法:{usage}", diff --git a/src/firefox/src/ui/sidepanel.js b/src/firefox/src/ui/sidepanel.js index 0f231f6d0..f33f51c4f 100644 --- a/src/firefox/src/ui/sidepanel.js +++ b/src/firefox/src/ui/sidepanel.js @@ -6720,7 +6720,14 @@ function rebindClarifyCards() { card.querySelectorAll('.permission-education-action').forEach(bindPermissionEducationAction); card.querySelectorAll('.clarify-skip-permissions').forEach(btn => bindPermissionSkipButton(btn, card, tabId, clarifyId)); + // Number the answers again: a card whose HTML was saved before the numbers + // existed gets them now, so every live card answers to its digits. + let shortcut = 0; card.querySelectorAll('.clarify-option').forEach(btn => { + if (++shortcut <= 9) { + btn.dataset.shortcut = String(shortcut); + btn.setAttribute('aria-keyshortcuts', String(shortcut)); + } if (btn.dataset.bound) return; btn.dataset.bound = 'true'; btn.addEventListener('click', () => { @@ -11480,6 +11487,21 @@ function renderClarifyCard(data) { card.dataset.deadlineTs = String(Math.floor(deadlineTs)); } + // Every answer carries its own number, shown in a small square at the right + // edge of the button, and typing that digit answers the card + // (handleClarifyShortcutKeydown). The number lives in a data attribute the + // CSS draws rather than in the button's text, because a card restored from + // saved chat HTML sends that text back as the answer. Inlined, like the text + // repair above, so function-extraction test harnesses keep working. + const numberClarifyOptions = (optionsEl) => { + let shortcut = 0; + for (const button of optionsEl.querySelectorAll('.clarify-option')) { + if (++shortcut > 9) break; + button.dataset.shortcut = String(shortcut); + button.setAttribute('aria-keyshortcuts', String(shortcut)); + } + }; + const qEl = document.createElement('div'); qEl.className = 'clarify-question'; if (data.pendingReconciliation === true) qEl.style.whiteSpace = 'pre-wrap'; @@ -11523,6 +11545,7 @@ function renderClarifyCard(data) { deny.dataset.value = 'deny'; deny.addEventListener('click', () => submitClarify(card, tabId, clarifyId, 'deny', 'option')); optionsEl.appendChild(deny); + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -11566,6 +11589,7 @@ function renderClarifyCard(data) { b.addEventListener('click', () => submitClarify(card, tabId, clarifyId, value, 'option')); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -11626,6 +11650,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -11676,6 +11701,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -11714,6 +11740,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -11752,6 +11779,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); scrollToBottom({ force: true }); @@ -11803,6 +11831,7 @@ function renderClarifyCard(data) { }); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); // The agent's timer decides; this countdown shows it and backs it up. const stepTimeoutAnswer = ['once', 'deny'].includes(data.timeoutAnswer) ? data.timeoutAnswer : ''; @@ -11901,6 +11930,7 @@ function renderClarifyCard(data) { bindPermissionSkipButton(skip, card, tabId, clarifyId); optionsEl.appendChild(skip); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); content.appendChild(card); // The hint offers "Always allow", which an upload card does not have. @@ -11937,6 +11967,7 @@ function renderClarifyCard(data) { b.addEventListener('click', () => submitClarify(card, tabId, clarifyId, b.textContent, 'option')); optionsEl.appendChild(b); } + numberClarifyOptions(optionsEl); card.appendChild(optionsEl); } @@ -12604,6 +12635,45 @@ function submitClarify(card, tabId, clarifyId, answer, source) { } +/** + * The numbered answer a digit picks on the live clarify card, or null. + * + * The digit only counts where nothing else claims the keyboard: no focus, the + * composer, or the card itself. A field with text in it keeps the digit as + * text, so an answer the user is typing is never cut short; an empty field + * gives it up, which is what makes "1" work while the card's own input holds + * the caret. The lowest card is the live one — an older unanswered card sits + * above it, already invalidated or abandoned. + */ +function clarifyShortcutOption(event) { + if (event.defaultPrevented || event.isComposing) return null; + if (event.ctrlKey || event.metaKey || event.altKey || event.shiftKey) return null; + if (!/^[1-9]$/.test(event.key)) return null; + const cards = document.querySelectorAll('.clarify-card:not(.clarify-answered):not(.clarify-obsolete)'); + const card = cards[cards.length - 1]; + if (!card) return null; + const active = document.activeElement; + if (active && active !== document.body && active !== inputEl && !card.contains(active)) return null; + const tag = active?.tagName; + if (tag === 'SELECT' || active?.isContentEditable) return null; + if ((tag === 'INPUT' || tag === 'TEXTAREA') && String(active.value || '')) return null; + const option = card.querySelector(`.clarify-option[data-shortcut="${event.key}"]`); + return option && !option.disabled ? option : null; +} + +function handleClarifyShortcutKeydown(event) { + const option = clarifyShortcutOption(event); + if (!option) return; + // preventDefault keeps the digit out of the composer it was typed into. + event.preventDefault(); + event.stopPropagation(); + // Click the button rather than answering here, so a permission card's own + // label bookkeeping and a scheduled card's tab still go through one path. + option.click(); +} + +document.addEventListener('keydown', handleClarifyShortcutKeydown, true); + // ========================================================================== // ACTIVITY HISTORY — retained in every mode, revealed by verbose mode // ========================================================================== diff --git a/src/firefox/styles/sidepanel.css b/src/firefox/styles/sidepanel.css index dc7763ae9..7b20884f3 100644 --- a/src/firefox/styles/sidepanel.css +++ b/src/firefox/styles/sidepanel.css @@ -4695,6 +4695,9 @@ html[data-ui-scale="175"] .composer-toolbar { } .clarify-option { + display: flex; + align-items: center; + gap: 8px; text-align: left; padding: 8px 10px; background: var(--bg-input); @@ -4716,6 +4719,33 @@ html[data-ui-scale="175"] .composer-toolbar { cursor: default; } +/* The answer's number, drawn from the data attribute so the button's own text + stays the answer WebBrain sends back. The empty alt text after the slash + keeps the digit out of the accessible name; aria-keyshortcuts announces the + shortcut instead. */ +.clarify-option[data-shortcut]::after { + content: attr(data-shortcut) / ""; + box-sizing: border-box; + flex: none; + margin-left: auto; + min-width: 16px; + height: 16px; + border: 1px solid color-mix(in srgb, var(--text-secondary) 40%, transparent); + border-radius: 3px; + background: var(--tint-soft); + color: var(--text-secondary); + font-size: 10px; + font-weight: 600; + line-height: 14px; + text-align: center; + font-variant-numeric: tabular-nums; +} + +.clarify-option:hover:not(:disabled)::after { + border-color: var(--accent); + color: var(--text-primary); +} + /* The permission card's way to the skip dialog: set apart from the answers above it and marked as risky. */ .clarify-skip-permissions { diff --git a/test/clarify-option-shortcuts.mjs b/test/clarify-option-shortcuts.mjs new file mode 100644 index 000000000..5ccf8b96c --- /dev/null +++ b/test/clarify-option-shortcuts.mjs @@ -0,0 +1,175 @@ +// Numbered answers on WebBrain's clarify cards: the real renderClarifyCard, +// submitClarify and the keydown handler run in Chromium and Firefox with the +// real stylesheet and locale strings. Each answer shows its number in a small +// square at its right edge, drawn from a data attribute so the button's own +// text stays the answer the card sends back, and typing that digit answers the +// card. A field the user is writing in keeps the digit as text. +import assert from 'node:assert/strict'; +import fs from 'node:fs'; +import { test } from 'node:test'; +import { chromium, firefox } from 'playwright'; + +const read = (build, file) => fs.readFileSync(new URL(`../src/${build}/${file}`, import.meta.url), 'utf8').replace(/\r\n/g, '\n'); +function extract(source, name) { + const start = source.search(new RegExp(`^(?:async )?function ${name}\\(`, 'm')); + assert.ok(start >= 0, `Missing function: ${name}`); + return source.slice(start, source.indexOf('\n}', start) + 2); +} + +async function panel(build, engine) { + const source = read(build, 'src/ui/sidepanel.js'); + const english = (await import(`../src/${build}/src/ui/locales/en.js`)).default; + const browser = await engine.launch({ headless: true }); + const page = await browser.newPage({ viewport: { width: 380, height: 700 } }); + await page.setContent(` +
+ `); + await page.addScriptTag({ content: `(() => { + const STRINGS = ${JSON.stringify(english)}; + const t = (key, params) => String(STRINGS[key] ?? key).replace(/\\{(\\w+)\\}/g, (_, name) => params?.[name] ?? '{' + name + '}'); + let currentTabId = 9; + let currentAssistantEl = document.querySelector('.message.assistant'); + const inputEl = document.querySelector('#composer'); + const submittedClarificationIds = new Set(); + const sent = []; + function clarificationSubmissionKey(tabId, requestId, clarifyId) { return JSON.stringify([Number(tabId), String(requestId || ''), String(clarifyId || '')]); } + function hideActivity() {} function playClarifySound() {} function scrollToBottom() {} function hideRecommendedActions() {} + function resetChatNavigation() {} function addMessage() { return currentAssistantEl; } function applyClarifyTimeoutExtension() {} + function clearClarifyCountdown() {} function placeAnsweredClarifyCardInTimeline() {} function startClarifyCountdown() {} + function maybeShowPermissionEducationHint() {} function workflowHealingTargetLabel(value) { return String(value || ''); } + function sameTabId(a, b) { return Number(a) === Number(b); } function restoreActiveRunState() {} + function bindPermissionSkipButton() {} function uploadApprovalCard() { return null; } + function keepClarifyAliveWhileTyping() {} + const CAPABILITY_LABEL = {}; + async function sendToBackground(action, payload) { sent.push([action, payload]); return { matched: true }; } + ${extract(source, 'renderClarifyCard')} + ${extract(source, 'submitClarify')} + ${extract(source, 'clarifyShortcutOption')} + ${extract(source, 'handleClarifyShortcutKeydown')} + document.addEventListener('keydown', handleClarifyShortcutKeydown, true); + window.panel = { render: renderClarifyCard, sent, composer: inputEl }; + })();` }); + return { browser, page }; +} + +// What the user sees on each answer: its number, its unchanged label, and the +// square the stylesheet draws from the attribute. Chromium resolves attr() in +// the computed content, Firefox keeps the function — so the digit is also +// measured: a wider value widens the square only if the attribute is drawn. +const view = () => ({ + answers: [...document.querySelectorAll('.clarify-option')] + .map(button => [button.dataset.shortcut, button.textContent, button.getAttribute('aria-keyshortcuts')]), + badges: [...document.querySelectorAll('.clarify-option')].map(button => { + const after = getComputedStyle(button, '::after'); + return [after.content, Math.round(parseFloat(after.width)), Math.round(parseFloat(after.height))]; + }), + widened: (() => { + const button = document.querySelector('.clarify-option'); + const width = () => parseFloat(getComputedStyle(button, '::after').width); + const square = width(); + button.dataset.shortcut = '88888'; + const wide = width(); + button.dataset.shortcut = '1'; + return wide > square + 10 && Math.round(width()) === Math.round(square); + })(), + skipNumbered: !!document.querySelector('.clarify-skip-permissions')?.dataset?.shortcut, +}); + +for (const [build, engine] of [['chrome', chromium], ['firefox', firefox]]) { + test(`${build}: a permission card numbers its answers and a digit answers it`, async () => { + const { browser, page } = await panel(build, engine); + try { + await page.evaluate(data => window.panel.render(data), { + clarifyId: 'perm_1', tabId: 9, question: 'q', + permission: { capability: 'downloads', host: 'example.com' }, + }); + const shown = await page.evaluate(view); + assert.deepEqual(shown.answers.map(answer => answer[0]), ['1', '2', '3'], 'numbered in the order shown'); + assert.deepEqual(shown.answers.map(answer => answer[2]), ['1', '2', '3'], 'aria-keyshortcuts names the digit'); + assert.deepEqual(shown.answers.map(answer => answer[1]), + ['Allow once', 'Always allow on example.com', 'Don\'t allow'], 'the number is not in the label'); + // The slash and empty string are the alt text: the digit is drawn but + // stays out of the button's accessible name. + for (const [content, width, height] of shown.badges) { + assert.match(content, /^(attr\(data-shortcut\)|"[1-9]") \/ ""$/, 'the square takes the digit from the attribute'); + assert.deepEqual([width, height], [16, 16], 'a 16px square per answer'); + } + assert.equal(shown.widened, true, 'the attribute is what the square draws'); + assert.equal(shown.skipNumbered, false, 'the skip-all-prompts button is not an answer and gets no number'); + + await page.keyboard.press('2'); + assert.deepEqual(await page.evaluate(() => window.panel.sent), + [['clarify_response', { tabId: 9, clarifyId: 'perm_1', answer: 'always', source: 'option', memorySource: 'permission' }]], + 'pressing 2 sent the second answer'); + } finally { await browser.close(); } + }); + + test(`${build}: a question's options answer to digits, a typed answer does not`, async () => { + const { browser, page } = await panel(build, engine); + try { + await page.evaluate(data => window.panel.render(data), { + clarifyId: 'ask_1', tabId: 9, question: 'Which one?', options: ['Blue', 'Red', 'Green'], + }); + assert.deepEqual((await page.evaluate(view)).answers, + [['1', 'Blue', '1'], ['2', 'Red', '2'], ['3', 'Green', '3']]); + + // The card's own field has the caret. A digit after other text is text. + assert.equal(await page.evaluate(() => document.activeElement.className), 'clarify-input'); + await page.keyboard.type('abc'); + await page.keyboard.press('3'); + assert.deepEqual(await page.evaluate(() => window.panel.sent), [], 'the field was not empty'); + assert.equal(await page.evaluate(() => document.querySelector('.clarify-input').value), 'abc3'); + + await page.evaluate(() => { document.querySelector('.clarify-input').value = ''; }); + await page.keyboard.press('3'); + assert.deepEqual(await page.evaluate(() => window.panel.sent), + [['clarify_response', { tabId: 9, clarifyId: 'ask_1', answer: 'Green', source: 'option', + memorySource: 'clarification_response', question: 'Which one?' }]], + 'an empty field gives the digit up to the third option'); + assert.equal(await page.evaluate(() => document.querySelector('.clarify-input').value), '', + 'the digit was not typed as well'); + assert.equal(await page.evaluate(() => document.querySelector('.clarify-your-answer').textContent), + 'Your answer: Green'); + } finally { await browser.close(); } + }); + + test(`${build}: a draft in the composer and an answered card keep their digits`, async () => { + const { browser, page } = await panel(build, engine); + try { + await page.evaluate(data => window.panel.render(data), { + clarifyId: 'ask_2', tabId: 9, question: 'Which one?', options: ['Blue', 'Red'], + }); + await page.evaluate(() => { window.panel.composer.value = '2 pages please'; window.panel.composer.focus(); }); + await page.keyboard.press('1'); + assert.deepEqual(await page.evaluate(() => window.panel.sent), [], 'a draft in the composer keeps the digit'); + + await page.evaluate(() => { window.panel.composer.value = ''; }); + await page.keyboard.press('1'); + assert.deepEqual(await page.evaluate(() => window.panel.sent), + [['clarify_response', { tabId: 9, clarifyId: 'ask_2', answer: 'Blue', source: 'option', + memorySource: 'clarification_response', question: 'Which one?' }]], + 'an empty composer answers the card without the mouse'); + await page.keyboard.press('2'); + assert.equal(await page.evaluate(() => window.panel.sent.length), 1, 'an answered card takes no more digits'); + } finally { await browser.close(); } + }); +} + +test('both builds number and bind the answers the same way', async () => { + const [chrome, fox] = ['chrome', 'firefox'].map(build => read(build, 'src/ui/sidepanel.js')); + for (const name of ['clarifyShortcutOption', 'handleClarifyShortcutKeydown']) { + assert.equal(extract(chrome, name), extract(fox, name), `${name} is identical in both builds`); + } + for (const build of [chrome, fox]) { + // Every answer list is numbered: a branch that forgets it shows no numbers + // and answers to no digit. + assert.equal((build.match(/^ {4}card\.appendChild\(optionsEl\);$/gm) || []).length, + (build.match(/^ {4}numberClarifyOptions\(optionsEl\);$/gm) || []).length, + 'each clarify-options list is numbered before it is added to the card'); + } + for (const build of ['chrome', 'firefox']) { + const css = read(build, 'styles/sidepanel.css'); + assert.match(css, /\.clarify-option\[data-shortcut\]::after \{\n {2}content: attr\(data-shortcut\) \/ "";/, + 'the square is drawn from the attribute, with empty alt text'); + } +});