From cb8aaf500bd0c9ac615f68053ff73c511cbd709c Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Tue, 21 Apr 2026 12:44:54 -0400 Subject: [PATCH 1/2] feat: add display text to shortcuts --- packages/blockly/core/shortcut_items.ts | 29 ++++++++++ packages/blockly/core/shortcut_registry.ts | 7 +++ packages/blockly/msg/json/en.json | 23 +++++++- packages/blockly/msg/json/qqq.json | 23 +++++++- packages/blockly/msg/messages.js | 63 ++++++++++++++++++++++ 5 files changed, 143 insertions(+), 2 deletions(-) diff --git a/packages/blockly/core/shortcut_items.ts b/packages/blockly/core/shortcut_items.ts index af82248d4f5..2b8d00d97ea 100644 --- a/packages/blockly/core/shortcut_items.ts +++ b/packages/blockly/core/shortcut_items.ts @@ -80,6 +80,7 @@ export function registerEscape() { return true; }, keyCodes: [KeyCodes.ESC], + displayText: () => Msg['SHORTCUTS_ESCAPE'], }; ShortcutRegistry.registry.register(escapeAction); } @@ -119,6 +120,7 @@ export function registerDelete() { return true; }, keyCodes: [KeyCodes.DELETE, KeyCodes.BACKSPACE], + displayText: () => Msg['SHORTCUTS_DELETE'], }; ShortcutRegistry.registry.register(deleteShortcut); } @@ -208,6 +210,7 @@ export function registerCopy() { return !!clipboard.copy(focused, copyCoords); }, keyCodes: [ctrlC], + displayText: () => Msg['COPY_SHORTCUT'], }; ShortcutRegistry.registry.register(copyShortcut); } @@ -252,6 +255,7 @@ export function registerCut() { return !!copyData; }, keyCodes: [ctrlX], + displayText: () => Msg['CUT_SHORTCUT'], }; ShortcutRegistry.registry.register(cutShortcut); @@ -334,6 +338,7 @@ export function registerPaste() { return !!clipboard.paste(copyData, targetWorkspace, centerCoords); }, keyCodes: [ctrlV], + displayText: () => Msg['PASTE_SHORTCUT'], }; ShortcutRegistry.registry.register(pasteShortcut); @@ -364,6 +369,7 @@ export function registerUndo() { return true; }, keyCodes: [ctrlZ], + displayText: () => Msg['UNDO'], }; ShortcutRegistry.registry.register(undoShortcut); } @@ -400,6 +406,7 @@ export function registerRedo() { return true; }, keyCodes: [ctrlShiftZ, ctrlY], + displayText: () => Msg['REDO'], }; ShortcutRegistry.registry.register(redoShortcut); } @@ -445,6 +452,7 @@ export function registerMovementShortcuts() { ); }, keyCodes: [KeyCodes.M], + displayText: () => Msg['SHORTCUTS_START_MOVE'], }; const shortcuts: ShortcutRegistry.KeyboardShortcut[] = [ startMoveShortcut, @@ -452,6 +460,7 @@ export function registerMovementShortcuts() { ...startMoveShortcut, name: names.START_MOVE_STACK, keyCodes: [shiftM], + displayText: () => Msg['SHORTCUTS_START_MOVE_STACK'], }, { name: names.FINISH_MOVE, @@ -460,6 +469,7 @@ export function registerMovementShortcuts() { KeyboardMover.mover.finishMove(e as KeyboardEvent), keyCodes: [KeyCodes.ENTER, KeyCodes.SPACE], allowCollision: true, + displayText: () => Msg['SHORTCUTS_FINISH_MOVE'], }, { name: names.ABORT_MOVE, @@ -468,6 +478,7 @@ export function registerMovementShortcuts() { KeyboardMover.mover.abortMove(e as KeyboardEvent), keyCodes: [KeyCodes.ESC], allowCollision: true, + displayText: () => Msg['SHORTCUTS_ABORT_MOVE'], }, { name: names.MOVE_LEFT, @@ -483,6 +494,7 @@ export function registerMovementShortcuts() { ]), ], allowCollision: true, + displayText: () => Msg['SHORTCUTS_MOVE_LEFT'], }, { name: names.MOVE_RIGHT, @@ -498,6 +510,7 @@ export function registerMovementShortcuts() { ]), ], allowCollision: true, + displayText: () => Msg['SHORTCUTS_MOVE_RIGHT'], }, { name: names.MOVE_UP, @@ -513,6 +526,7 @@ export function registerMovementShortcuts() { ]), ], allowCollision: true, + displayText: () => Msg['SHORTCUTS_MOVE_UP'], }, { name: names.MOVE_DOWN, @@ -528,6 +542,7 @@ export function registerMovementShortcuts() { ]), ], allowCollision: true, + displayText: () => Msg['SHORTCUTS_MOVE_DOWN'], }, ]; @@ -562,6 +577,7 @@ export function registerShowContextMenu() { return false; }, keyCodes: [ctrlEnter], + displayText: () => Msg['SHORTCUTS_SHOW_CONTEXT_MENU'], }; ShortcutRegistry.registry.register(contextMenuShortcut); } @@ -592,6 +608,7 @@ export function registerArrowNavigation() { }, keyCodes: [KeyCodes.RIGHT], allowCollision: true, + displayText: () => Msg['SHORTCUTS_NAVIGATE_RIGHT'], }, /** Go to the next location to the left. */ @@ -613,6 +630,7 @@ export function registerArrowNavigation() { }, keyCodes: [KeyCodes.LEFT], allowCollision: true, + displayText: () => Msg['SHORTCUTS_NAVIGATE_LEFT'], }, /** Go down to the next location. */ @@ -635,6 +653,7 @@ export function registerArrowNavigation() { }, keyCodes: [KeyCodes.DOWN], allowCollision: true, + displayText: () => Msg['SHORTCUTS_NAVIGATE_DOWN'], }, /** Go up to the previous location. */ up: { @@ -656,6 +675,7 @@ export function registerArrowNavigation() { }, keyCodes: [KeyCodes.UP], allowCollision: true, + displayText: () => Msg['SHORTCUTS_NAVIGATE_UP'], }, }; @@ -687,6 +707,7 @@ export function registerFocusWorkspace() { return true; }, keyCodes: [KeyCodes.W], + displayText: () => Msg['SHORTCUTS_FOCUS_WORKSPACE'], }; ShortcutRegistry.registry.register(focusWorkspaceShortcut); } @@ -714,6 +735,7 @@ export function registerFocusToolbox() { } }, keyCodes: [KeyCodes.T], + displayText: () => Msg['SHORTCUTS_FOCUS_TOOLBOX'], }; ShortcutRegistry.registry.register(focusToolboxShortcut); } @@ -763,6 +785,7 @@ export function registerWorkspaceOverview() { return true; }, keyCodes: [KeyCodes.I], + displayText: () => Msg['SHORTCUTS_INFORMATION'], }; ShortcutRegistry.registry.register(shortcut); } @@ -790,6 +813,7 @@ export function registerDisconnectBlock() { return true; }, keyCodes: [KeyCodes.X, shiftX], + displayText: () => Msg['SHORTCUTS_DISCONNECT'], }; ShortcutRegistry.registry.register(disconnectShortcut); } @@ -838,6 +862,7 @@ export function registerStackNavigation() { return true; }, keyCodes: [KeyCodes.N], + displayText: () => Msg['SHORTCUTS_NEXT_STACK'], }; const previousStackShortcut: KeyboardShortcut = { @@ -863,6 +888,7 @@ export function registerStackNavigation() { return true; }, keyCodes: [KeyCodes.B], + displayText: () => Msg['SHORTCUTS_PREVIOUS_STACK'], }; ShortcutRegistry.registry.register(nextStackShortcut); @@ -891,6 +917,7 @@ export function registerPerformAction() { }, keyCodes: [KeyCodes.ENTER, KeyCodes.SPACE], allowCollision: true, + displayText: () => Msg['SHORTCUTS_PERFORM_ACTION'], }; ShortcutRegistry.registry.register(performActionShortcut); } @@ -919,6 +946,7 @@ export function registerDuplicate() { }, keyCodes: [KeyCodes.D], allowCollision: true, + displayText: () => Msg['SHORTCUTS_DUPLICATE'], }; ShortcutRegistry.registry.register(duplicateShortcut); } @@ -938,6 +966,7 @@ export function registerCleanup() { }, keyCodes: [KeyCodes.C], allowCollision: true, + displayText: () => Msg['SHORTCUTS_CLEANUP'], }; ShortcutRegistry.registry.register(cleanupShortcut); } diff --git a/packages/blockly/core/shortcut_registry.ts b/packages/blockly/core/shortcut_registry.ts index f40149db816..c5d820ff78b 100644 --- a/packages/blockly/core/shortcut_registry.ts +++ b/packages/blockly/core/shortcut_registry.ts @@ -434,6 +434,13 @@ export namespace ShortcutRegistry { * name. */ allowCollision?: boolean; + + /** + * Display text for the shortcut. This is not used in core but may + * be used by plugins or applications to provide a user-facing + * label for the shortcut. + */ + displayText?: string | (() => string); } /** Supported modifiers. */ diff --git a/packages/blockly/msg/json/en.json b/packages/blockly/msg/json/en.json index a1c94aae0ff..172b739d905 100644 --- a/packages/blockly/msg/json/en.json +++ b/packages/blockly/msg/json/en.json @@ -1,7 +1,7 @@ { "@metadata": { "author": "Ellen Spertus ", - "lastupdated": "2026-04-20 12:26:14.946401", + "lastupdated": "2026-04-21 12:36:42.927221", "locale": "en", "messagedocumentation" : "qqq" }, @@ -417,6 +417,27 @@ "SHORTCUTS_GENERAL": "General", "SHORTCUTS_EDITING": "Editing", "SHORTCUTS_CODE_NAVIGATION": "Code navigation", + "SHORTCUTS_ESCAPE": "Exit", + "SHORTCUTS_DELETE": "Delete", + "SHORTCUTS_DELETE": "Delete", + "SHORTCUTS_START_MOVE": "Start move", + "SHORTCUTS_START_MOVE_STACK": "Start move stack", + "SHORTCUTS_MOVE_LEFT": "Move left", + "SHORTCUTS_MOVE_RIGHT": "Move right", + "SHORTCUTS_MOVE_UP": "Move up", + "SHORTCUTS_MOVE_DOWN": "Move down", + "SHORTCUTS_FINISH_MOVE": "Finish move", + "SHORTCUTS_ABORT_MOVE": "Abort move", + "SHORTCUTS_SHOW_CONTEXT_MENU": "Show menu", + "SHORTCUTS_FOCUS_WORKSPACE": "Focus workspace", + "SHORTCUTS_FOCUS_TOOLBOX": "Focus toolbox", + "SHORTCUTS_INFORMATION": "Announce information", + "SHORTCUTS_DISCONNECT": "Disconnect block", + "SHORTCUTS_NEXT_STACK": "Next stack", + "SHORTCUTS_PREVIOUS_STACK": "Previous stack", + "SHORTCUTS_PERFORM_ACTION": "Edit or confirm", + "SHORTCUTS_DUPLICATE": "Duplicate", + "SHORTCUTS_CLEANUP": "Clean up workspace", "KEYBOARD_NAV_UNCONSTRAINED_MOVE_HINT": "Hold %1 and use arrow keys to move freely, then %2 to accept the position", "KEYBOARD_NAV_CONSTRAINED_MOVE_HINT": "Use the arrow keys to move, then %1 to accept the position", "KEYBOARD_NAV_COPIED_HINT": "Copied. Press %1 to paste.", diff --git a/packages/blockly/msg/json/qqq.json b/packages/blockly/msg/json/qqq.json index 0fa1a2cd6e1..436f8facab7 100644 --- a/packages/blockly/msg/json/qqq.json +++ b/packages/blockly/msg/json/qqq.json @@ -1,5 +1,5 @@ { - "@metadata": { + "@metadata": { "authors": [ "Ajeje Brazorf", "Amire80", @@ -424,6 +424,27 @@ "SHORTCUTS_GENERAL": "shortcut list section header - Label for general purpose keyboard shortcuts.", "SHORTCUTS_EDITING": "shortcut list section header - Label for keyboard shortcuts related to editing a workspace.", "SHORTCUTS_CODE_NAVIGATION": "shortcut list section header - Label for keyboard shortcuts related to moving around the workspace.", + "SHORTCUTS_ESCAPE": "shortcut display text for the escape shortcut, which is used in various contexts to exit or cancel an action.", + "SHORTCUTS_DELETE": "shortcut display text for the delete shortcut, which is used in various contexts to delete items.", + "SHORTCUTS_DELETE": "shortcut display text for the delete shortcut, which is used in various contexts to delete items.", + "SHORTCUTS_START_MOVE": "shortcut display text for the start move shortcut, which enters the keyboard navigation 'move mode'.", + "SHORTCUTS_START_MOVE_STACK": "shortcut display text for the start move stack shortcut, which enters the keyboard navigation 'move mode' for a stack of blocks.", + "SHORTCUTS_MOVE_LEFT": "shortcut display text for the move left shortcut, which moves a block left during keyboard navigation.", + "SHORTCUTS_MOVE_RIGHT": "shortcut display text for the move right shortcut, which moves a block right during keyboard navigation.", + "SHORTCUTS_MOVE_UP": "shortcut display text for the move up shortcut, which moves a block up during keyboard navigation.", + "SHORTCUTS_MOVE_DOWN": "shortcut display text for the move down shortcut, which moves a block down during keyboard navigation.", + "SHORTCUTS_FINISH_MOVE": "shortcut display text for the finish move shortcut, which exits the keyboard navigation 'move mode'.", + "SHORTCUTS_ABORT_MOVE": "shortcut display text for the abort move shortcut, which cancels the keyboard navigation 'move mode'.", + "SHORTCUTS_SHOW_CONTEXT_MENU": "shortcut display text for the shortcut that opens the context menu.", + "SHORTCUTS_FOCUS_WORKSPACE": "shortcut display text for the focus workspace shortcut, which moves focus to the workspace.", + "SHORTCUTS_FOCUS_TOOLBOX": "shortcut display text for the focus toolbox shortcut, which moves focus to the toolbox or flyout.", + "SHORTCUTS_INFORMATION": "shortcut display text for the information shortcut, which announces information about a focused element.", + "SHORTCUTS_DISCONNECT": "shortcut display text for the disconnect shortcut, which disconnects a block from its neighbor.", + "SHORTCUTS_NEXT_STACK": "shortcut display text for the next stack shortcut, which navigates to the next block stack.", + "SHORTCUTS_PREVIOUS_STACK": "shortcut display text for the previous stack shortcut, which navigates to the previous block stack.", + "SHORTCUTS_PERFORM_ACTION": "shortcut display text for the perform action shortcut, which triggers an action on the focused element.", + "SHORTCUTS_DUPLICATE": "shortcut display text for the duplicate shortcut, which duplicates the focused block or comment.", + "SHORTCUTS_CLEANUP": "shortcut display text for the cleanup shortcut, which organizes blocks on the workspace.", "KEYBOARD_NAV_UNCONSTRAINED_MOVE_HINT": "Message shown to inform users how to move blocks to arbitrary locations with the keyboard.", "KEYBOARD_NAV_CONSTRAINED_MOVE_HINT": "Message shown to inform users how to move blocks with the keyboard.", "KEYBOARD_NAV_COPIED_HINT": "Message shown when an item is copied in keyboard navigation mode.", diff --git a/packages/blockly/msg/messages.js b/packages/blockly/msg/messages.js index 9d6162eea74..255e175ac8c 100644 --- a/packages/blockly/msg/messages.js +++ b/packages/blockly/msg/messages.js @@ -1684,6 +1684,69 @@ Blockly.Msg.SHORTCUTS_EDITING = 'Editing' /// moving around the workspace. Blockly.Msg.SHORTCUTS_CODE_NAVIGATION = 'Code navigation'; /** @type {string} */ +/// shortcut display text for the escape shortcut, which is used in various contexts to exit or cancel an action. +Blockly.Msg.SHORTCUTS_ESCAPE = 'Exit'; +/** @type {string} */ +/// shortcut display text for the delete shortcut, which is used in various contexts to delete items. +Blockly.Msg.SHORTCUTS_DELETE = 'Delete'; +/** @type {string} */ +/// shortcut display text for the delete shortcut, which is used in various contexts to delete items. +Blockly.Msg.SHORTCUTS_DELETE = 'Delete'; +/** @type {string} */ +/// shortcut display text for the start move shortcut, which enters the keyboard navigation "move mode". +Blockly.Msg.SHORTCUTS_START_MOVE = 'Start move'; +/** @type {string} */ +/// shortcut display text for the start move stack shortcut, which enters the keyboard navigation "move mode" for a stack of blocks. +Blockly.Msg.SHORTCUTS_START_MOVE_STACK = 'Start move stack'; +/** @type {string} */ +/// shortcut display text for the move left shortcut, which moves a block left during keyboard navigation. +Blockly.Msg.SHORTCUTS_MOVE_LEFT = 'Move left'; +/** @type {string} */ +/// shortcut display text for the move right shortcut, which moves a block right during keyboard navigation. +Blockly.Msg.SHORTCUTS_MOVE_RIGHT = 'Move right'; +/** @type {string} */ +/// shortcut display text for the move up shortcut, which moves a block up during keyboard navigation. +Blockly.Msg.SHORTCUTS_MOVE_UP = 'Move up'; +/** @type {string} */ +/// shortcut display text for the move down shortcut, which moves a block down during keyboard navigation. +Blockly.Msg.SHORTCUTS_MOVE_DOWN = 'Move down'; +/** @type {string} */ +/// shortcut display text for the finish move shortcut, which exits the keyboard navigation "move mode". +Blockly.Msg.SHORTCUTS_FINISH_MOVE = 'Finish move'; +/** @type {string} */ +/// shortcut display text for the abort move shortcut, which cancels the keyboard navigation "move mode". +Blockly.Msg.SHORTCUTS_ABORT_MOVE = 'Abort move'; +/** @type {string} */ +/// shortcut display text for the shortcut that opens the context menu. +Blockly.Msg.SHORTCUTS_SHOW_CONTEXT_MENU = 'Show menu'; +/** @type {string} */ +/// shortcut display text for the focus workspace shortcut, which moves focus to the workspace. +Blockly.Msg.SHORTCUTS_FOCUS_WORKSPACE = 'Focus workspace'; +/** @type {string} */ +/// shortcut display text for the focus toolbox shortcut, which moves focus to the toolbox or flyout. +Blockly.Msg.SHORTCUTS_FOCUS_TOOLBOX = 'Focus toolbox'; +/** @type {string} */ +/// shortcut display text for the information shortcut, which announces information about a focused element. +Blockly.Msg.SHORTCUTS_INFORMATION = 'Announce information'; +/** @type {string} */ +/// shortcut display text for the disconnect shortcut, which disconnects a block from its neighbor. +Blockly.Msg.SHORTCUTS_DISCONNECT = 'Disconnect block'; +/** @type {string} */ +/// shortcut display text for the next stack shortcut, which navigates to the next block stack. +Blockly.Msg.SHORTCUTS_NEXT_STACK = 'Next stack'; +/** @type {string} */ +/// shortcut display text for the previous stack shortcut, which navigates to the previous block stack. +Blockly.Msg.SHORTCUTS_PREVIOUS_STACK = 'Previous stack'; +/** @type {string} */ +/// shortcut display text for the perform action shortcut, which triggers an action on the focused element. +Blockly.Msg.SHORTCUTS_PERFORM_ACTION = 'Edit or confirm'; +/** @type {string} */ +/// shortcut display text for the duplicate shortcut, which duplicates the focused block or comment. +Blockly.Msg.SHORTCUTS_DUPLICATE = 'Duplicate'; +/** @type {string} */ +/// shortcut display text for the cleanup shortcut, which organizes blocks on the workspace. +Blockly.Msg.SHORTCUTS_CLEANUP = 'Clean up workspace'; +/** @type {string} */ /// Message shown to inform users how to move blocks to arbitrary locations /// with the keyboard. Blockly.Msg.KEYBOARD_NAV_UNCONSTRAINED_MOVE_HINT = 'Hold %1 and use arrow keys to move freely, then %2 to accept the position'; From ac40fd34543a28a566b46fde2903369db02453dc Mon Sep 17 00:00:00 2001 From: Maribeth Moffatt Date: Tue, 21 Apr 2026 15:16:14 -0400 Subject: [PATCH 2/2] fix: remove duplicated message --- packages/blockly/msg/json/en.json | 1 - packages/blockly/msg/json/qqq.json | 1 - packages/blockly/msg/messages.js | 3 --- 3 files changed, 5 deletions(-) diff --git a/packages/blockly/msg/json/en.json b/packages/blockly/msg/json/en.json index 172b739d905..0812fa3d493 100644 --- a/packages/blockly/msg/json/en.json +++ b/packages/blockly/msg/json/en.json @@ -419,7 +419,6 @@ "SHORTCUTS_CODE_NAVIGATION": "Code navigation", "SHORTCUTS_ESCAPE": "Exit", "SHORTCUTS_DELETE": "Delete", - "SHORTCUTS_DELETE": "Delete", "SHORTCUTS_START_MOVE": "Start move", "SHORTCUTS_START_MOVE_STACK": "Start move stack", "SHORTCUTS_MOVE_LEFT": "Move left", diff --git a/packages/blockly/msg/json/qqq.json b/packages/blockly/msg/json/qqq.json index 436f8facab7..5a1472db20f 100644 --- a/packages/blockly/msg/json/qqq.json +++ b/packages/blockly/msg/json/qqq.json @@ -426,7 +426,6 @@ "SHORTCUTS_CODE_NAVIGATION": "shortcut list section header - Label for keyboard shortcuts related to moving around the workspace.", "SHORTCUTS_ESCAPE": "shortcut display text for the escape shortcut, which is used in various contexts to exit or cancel an action.", "SHORTCUTS_DELETE": "shortcut display text for the delete shortcut, which is used in various contexts to delete items.", - "SHORTCUTS_DELETE": "shortcut display text for the delete shortcut, which is used in various contexts to delete items.", "SHORTCUTS_START_MOVE": "shortcut display text for the start move shortcut, which enters the keyboard navigation 'move mode'.", "SHORTCUTS_START_MOVE_STACK": "shortcut display text for the start move stack shortcut, which enters the keyboard navigation 'move mode' for a stack of blocks.", "SHORTCUTS_MOVE_LEFT": "shortcut display text for the move left shortcut, which moves a block left during keyboard navigation.", diff --git a/packages/blockly/msg/messages.js b/packages/blockly/msg/messages.js index 255e175ac8c..8c8271033e1 100644 --- a/packages/blockly/msg/messages.js +++ b/packages/blockly/msg/messages.js @@ -1690,9 +1690,6 @@ Blockly.Msg.SHORTCUTS_ESCAPE = 'Exit'; /// shortcut display text for the delete shortcut, which is used in various contexts to delete items. Blockly.Msg.SHORTCUTS_DELETE = 'Delete'; /** @type {string} */ -/// shortcut display text for the delete shortcut, which is used in various contexts to delete items. -Blockly.Msg.SHORTCUTS_DELETE = 'Delete'; -/** @type {string} */ /// shortcut display text for the start move shortcut, which enters the keyboard navigation "move mode". Blockly.Msg.SHORTCUTS_START_MOVE = 'Start move'; /** @type {string} */