diff --git a/packages/blockly/core/block_aria_composer.ts b/packages/blockly/core/block_aria_composer.ts index aa9cb6db7..f884f315c 100644 --- a/packages/blockly/core/block_aria_composer.ts +++ b/packages/blockly/core/block_aria_composer.ts @@ -26,6 +26,7 @@ export enum ConnectionPreposition { AFTER, AROUND, INSIDE, + TO, } /** @@ -342,6 +343,55 @@ function getParentToolboxCategoryLabel(block: BlockSvg) { return undefined; } +/** + * Returns the appropriate translated announcement template based on the connection type. + * + * @param preposition The relationship between the local and neighbour connections. + * @returns A translated string template to use for announcing a block move. + */ +function getAnnouncementTemplate(preposition: ConnectionPreposition): string { + switch (preposition) { + case ConnectionPreposition.BEFORE: + return Msg['ANNOUNCE_MOVE_BEFORE']; + case ConnectionPreposition.AFTER: + return Msg['ANNOUNCE_MOVE_AFTER']; + case ConnectionPreposition.INSIDE: + return Msg['ANNOUNCE_MOVE_INSIDE']; + case ConnectionPreposition.AROUND: + return Msg['ANNOUNCE_MOVE_AROUND']; + default: + return Msg['ANNOUNCE_MOVE_TO']; + } +} + +/** + * Returns a label for a connection includes either a block label, input label or both. + * + * @param conn The connection to generate a label for. + * @param baseLabel An optional block label to include in the returned string. + * @returns A label describing the given connection + */ +function computeMoveConnectionLabel( + conn: RenderedConnection, + baseLabel: string, +): string { + const input = conn.getParentInput(); + if (!input) return baseLabel; + + const labels = getInputLabelsSubset( + conn.getSourceBlock(), + input, + Verbosity.TERSE, + ); + if (!labels.length) return baseLabel; + + const inputLabel = labels.join(', '); + + return baseLabel + ? Msg['ANNOUNCE_MOVE_OF'].replace('%1', inputLabel).replace('%2', baseLabel) + : inputLabel; +} + /** * Returns a translated string describing an in-progress move of a block to a new * connection, suitable for announcement on the ARIA live region. The returned string @@ -364,67 +414,32 @@ export function computeMoveLabel( isMoveStart = false, ): string { const preposition = getConnectionPreposition(local, neighbour); - const neighbourBlock = neighbour.getSourceBlock() as BlockSvg; - const neighbourBlockLabel = neighbourBlock.getAriaLabel(Verbosity.TERSE); - const blockLabel = isMoveStart + const template = getAnnouncementTemplate(preposition); + + const needsDisambiguation = ![ + ConnectionPreposition.BEFORE, + ConnectionPreposition.AFTER, + ].includes(preposition); + + const includeLocalContext = needsDisambiguation && disambiguationPolicy(true); + const includeNeighbourContext = + needsDisambiguation && disambiguationPolicy(false); + + let blockLabel = isMoveStart ? local.getSourceBlock().getStackBlocksCountLabel() : ''; + let neighbourLabel = (neighbour.getSourceBlock() as BlockSvg).getAriaLabel( + Verbosity.TERSE, + ); - let announcementTemplate; - // Message strings take a format like 'moving %1 %2 to %3 %4' where: - // "to" is replaced with a preposition based on the type of the connection candidate - // (e.g. "before", "after", "inside", "around", etc), and the placeholders are replaced with: - // %1 = optional label for the block being moved - // %2 = optional label for the local connection - // %3 = label for the neighbour block - // %4 = optional label for the neighbour connection - switch (preposition) { - case ConnectionPreposition.BEFORE: - announcementTemplate = Msg['ANNOUNCE_MOVE_BEFORE']; - break; - case ConnectionPreposition.AFTER: - announcementTemplate = Msg['ANNOUNCE_MOVE_AFTER']; - break; - case ConnectionPreposition.INSIDE: - announcementTemplate = Msg['ANNOUNCE_MOVE_INSIDE']; - break; - case ConnectionPreposition.AROUND: - announcementTemplate = Msg['ANNOUNCE_MOVE_AROUND']; - break; - case ConnectionPreposition.UNKNOWN: - announcementTemplate = Msg['ANNOUNCE_MOVE_UNKNOWN']; + if (includeLocalContext) { + blockLabel = computeMoveConnectionLabel(local, blockLabel); + } + if (includeNeighbourContext) { + neighbourLabel = computeMoveConnectionLabel(neighbour, neighbourLabel); } - // If multiple compatible candidate connections exist for either/both pairs of the - // current connection candidate, increase the verbosity of the announcement to help - // disambiguate them. - const requiresDisambiguation = [ - ConnectionPreposition.INSIDE, - ConnectionPreposition.AROUND, - ].includes(preposition); - const describeLocal = requiresDisambiguation && disambiguationPolicy(true); - const describeNeighbour = - requiresDisambiguation && disambiguationPolicy(false); - - const localInput = local.getParentInput(); - const neighbourInput = neighbour.getParentInput(); - - const localConnLabel = - (describeLocal && - localInput && - getInputLabelsSubset(local.getSourceBlock(), localInput).join(', ')) || - ''; - const neighbourConnLabel = - (describeNeighbour && - neighbourInput && - getInputLabelsSubset(neighbourBlock, neighbourInput).join(', ')) || - ''; - - return announcementTemplate - .replace('%1', blockLabel) - .replace('%2', localConnLabel) - .replace('%3', neighbourBlockLabel) - .replace('%4', neighbourConnLabel); + return template.replace('%1', blockLabel).replace('%2', neighbourLabel); } /** @@ -436,10 +451,9 @@ function getConnectionPreposition( neighbour: RenderedConnection, ): ConnectionPreposition { switch (local.type) { - case ConnectionType.OUTPUT_VALUE: - return ConnectionPreposition.INSIDE; case ConnectionType.INPUT_VALUE: - return ConnectionPreposition.AROUND; + case ConnectionType.OUTPUT_VALUE: + return ConnectionPreposition.TO; case ConnectionType.NEXT_STATEMENT: if (local === local.getSourceBlock().nextConnection) { return ConnectionPreposition.BEFORE; @@ -453,8 +467,8 @@ function getConnectionPreposition( return ConnectionPreposition.INSIDE; } } - // Not normally reachable since we should always have a connection candidate - // with valid connection types. Satisfies the return type. + // Not normally reachable since all valid connection types are covered. + // Satisfies the return type. return ConnectionPreposition.UNKNOWN; } diff --git a/packages/blockly/msg/json/en.json b/packages/blockly/msg/json/en.json index 79a6fb5d7..3513b2e8c 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-05-01 14:09:40.345417", + "lastupdated": "2026-05-06 14:12:59.060731", "locale": "en", "messagedocumentation" : "qqq" }, @@ -426,7 +426,7 @@ "CUT_SHORTCUT": "Cut", "COPY_SHORTCUT": "Copy", "PASTE_SHORTCUT": "Paste", - "HELP_PROMPT": "Press %1 for help on keyboard controls", + "HELP_PROMPT": "Press %1 for help on keyboard controls.", "SHORTCUTS_GENERAL": "General", "SHORTCUTS_EDITING": "Editing", "SHORTCUTS_CODE_NAVIGATION": "Code navigation", @@ -451,8 +451,8 @@ "SHORTCUTS_DUPLICATE": "Duplicate", "SHORTCUTS_CLEANUP": "Clean up workspace", "SHORTCUTS_SHOW_TOOLTIP": "Show tooltip", - "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_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.", "KEYBOARD_NAV_CUT_HINT": "Cut. Press %1 to paste.", "WORKSPACE_LABEL_1_STACK": "Blocks workspace. 1 stack of blocks", @@ -464,8 +464,8 @@ "WORKSPACE_CONTENTS_BLOCKS_ZERO": "No blocks%2 in workspace.", "WORKSPACE_CONTENTS_COMMENTS_MANY": " and %1 comments", "WORKSPACE_CONTENTS_COMMENTS_ONE": " and one comment", - "KEYBOARD_NAV_BLOCK_NAVIGATION_HINT": "Use the right arrow key to navigate inside of blocks", - "KEYBOARD_NAV_WORKSPACE_NAVIGATION_HINT": "Use the arrow keys to navigate", + "KEYBOARD_NAV_BLOCK_NAVIGATION_HINT": "Use the right arrow key to navigate inside of blocks.", + "KEYBOARD_NAV_WORKSPACE_NAVIGATION_HINT": "Use the arrow keys to navigate.", "BLOCK_LABEL_BEGIN_STACK": "Begin stack", "BLOCK_LABEL_BEGIN_PREFIX": "Begin %1", "BLOCK_LABEL_TOOLBOX_CATEGORY": "%1 category", @@ -479,13 +479,14 @@ "BLOCK_LABEL_VALUE": "value", "BLOCK_LABEL_STACK_BLOCKS": "%1 stack blocks", "INPUT_LABEL_INDEX": "input %1", - "ANNOUNCE_MOVE_WORKSPACE": "moving %1 on workspace", - "ANNOUNCE_MOVE_BEFORE": "moving %1 before %3", - "ANNOUNCE_MOVE_AFTER": "moving %1 after %3", - "ANNOUNCE_MOVE_INSIDE": "moving %1 inside %3 %4", - "ANNOUNCE_MOVE_AROUND": "moving %1 %2 around %3", - "ANNOUNCE_MOVE_TO": "moving %1 %2 to %3 %4", - "ANNOUNCE_MOVE_CANCELED": "Canceled movement", + "ANNOUNCE_MOVE_WORKSPACE": "Moving %1 on workspace.", + "ANNOUNCE_MOVE_BEFORE": "Moving %1 before %2.", + "ANNOUNCE_MOVE_AFTER": "Moving %1 after %2.", + "ANNOUNCE_MOVE_INSIDE": "Moving %1 inside %2.", + "ANNOUNCE_MOVE_AROUND": "Moving %1 around %2.", + "ANNOUNCE_MOVE_TO": "Moving %1 to %2.", + "ANNOUNCE_MOVE_OF": "%1 of %2", + "ANNOUNCE_MOVE_CANCELED": "Canceled movement.", "FIELD_LABEL_EMPTY": "empty", "ARIA_TYPE_FIELD_INPUT": "input", "ARIA_TYPE_FIELD_TEXT_INPUT": "text", diff --git a/packages/blockly/msg/json/qqq.json b/packages/blockly/msg/json/qqq.json index f8bfd7132..4fc7a0b53 100644 --- a/packages/blockly/msg/json/qqq.json +++ b/packages/blockly/msg/json/qqq.json @@ -488,11 +488,12 @@ "BLOCK_LABEL_STACK_BLOCKS": "Accessibility label for a block that indicates it is a stack of two or more blocks.", "INPUT_LABEL_INDEX": "Accessibility label for an unlabeled input that communicates its index on the block. \n\nParameters:\n* %1 - the index of the input, starting at 1", "ANNOUNCE_MOVE_WORKSPACE": "ARIA live region message announcing a block is being moved on the workspace, without specifying a target location or specific movement direction.", - "ANNOUNCE_MOVE_BEFORE": "ARIA live region message announcing a block is being moved before another block \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks\n* %3 - the label of the target (neighbour) block \n\nExamples:\n* 'moving before repeat 10, times, do'\n* 'moving 2 stack blocks before repeat 10, times, do'", - "ANNOUNCE_MOVE_AFTER": "ARIA live region message announcing a block is being moved after another block \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks\n* %3 - the label of the target (neighbour) block \n\nExamples:\n* 'moving after repeat 10, times, do'\n* 'moving 2 stack blocks after repeat 10, times, do' \n* 'moving block A after Function block output'", - "ANNOUNCE_MOVE_INSIDE": "ARIA live region message announcing a block is being moved inside another block, optionally including connection-specific label for disambiguation.", - "ANNOUNCE_MOVE_AROUND": "ARIA live region message announcing a block is being moved around another block, optionally including connection-specific label for disambiguation. \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks \n* %2 - optional phrase describing the local connection label \n* %3 - the label of the target (neighbour) block \n\nExamples:\n* 'moving around print abc'\n* 'moving if, do else statement around print abc'", - "ANNOUNCE_MOVE_TO": "ARIA live region message announcing a block is being moved to a workspace location where the relationship is not specifically known. \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks \n* %2 - optional phrase describing the local connection label \n* %3 - the label of the target (neighbour) block or location \n* %4 - optional phrase describing the target connection label \n\nExamples:\n* 'moving to repeat 10, times, do'\n* 'moving 2 stack blocks else statement to repeat 10, times, do previous connection'", + "ANNOUNCE_MOVE_BEFORE": "ARIA live region message announcing a block is being moved before another block \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks\n* %2 - the label of the target (neighbour) block \n\nExamples:\n* 'Moving before repeat, 10, times, do.'\n* 'Moving print before repeat, 10, times, do.'", + "ANNOUNCE_MOVE_AFTER": "ARIA live region message announcing a block is being moved after another block \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks\n* %2 - the label of the target (neighbour) block \n\nExamples:\n* 'Moving after repeat, 10, times, do.'\n* 'Moving 2 stack blocks after repeat, 10, times, do.'", + "ANNOUNCE_MOVE_INSIDE": "ARIA live region message announcing a block is being moved inside another block's statement connection, optionally including connection-specific label for disambiguation.", + "ANNOUNCE_MOVE_AROUND": "ARIA live region message announcing a block is being moved around another block (using its own statement connection), optionally including connection-specific label for disambiguation. \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks or a local connection label \n* %2 - the label of the target (neighbour) block \n\nExamples:\n* 'Moving around print.'\n* 'Moving else around print.'", + "ANNOUNCE_MOVE_TO": "ARIA live region message announcing a block is being moved to another block's value input connection, optionally including connection-specific label for disambiguation. \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks or a local connection label \n* %2 - the label of the target (neighbour) block or location \n\nExamples:\n* 'Moving to repeat, 10, times, do.'\n* 'Moving 2 stack blocks else statement to previous connection in repeat, 10, times, do.'", + "ANNOUNCE_MOVE_OF": "A label describing a specific connection of a block. Part of an ARIA live region message announcing a block is being moved. \n\nParameters:\n* %1 - connection label\n* %2 - block label of the block the connection belongs to \n\nExamples:\n* 'else statement of if, do''", "ANNOUNCE_MOVE_CANCELED": "ARIA live region message announcing a block movement has been canceled.", "FIELD_LABEL_EMPTY": "Label for an empty field, used by screen readers to identify fields that have no content.", "ARIA_TYPE_FIELD_INPUT": "ARIA type name for an input field, used by screen readers to identify the type of field.", diff --git a/packages/blockly/msg/messages.js b/packages/blockly/msg/messages.js index c88b166f6..82ccae166 100644 --- a/packages/blockly/msg/messages.js +++ b/packages/blockly/msg/messages.js @@ -1708,7 +1708,7 @@ Blockly.Msg.COPY_SHORTCUT = 'Copy'; Blockly.Msg.PASTE_SHORTCUT = 'Paste'; /** @type {string} */ /// Alert message shown to prompt users to review available keyboard shortcuts. -Blockly.Msg.HELP_PROMPT = 'Press %1 for help on keyboard controls'; +Blockly.Msg.HELP_PROMPT = 'Press %1 for help on keyboard controls.'; /** @type {string} */ /// shortcut list section header - Label for general purpose keyboard shortcuts. Blockly.Msg.SHORTCUTS_GENERAL = 'General'; @@ -1786,10 +1786,10 @@ Blockly.Msg.SHORTCUTS_SHOW_TOOLTIP = 'Show tooltip'; /** @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'; +Blockly.Msg.KEYBOARD_NAV_UNCONSTRAINED_MOVE_HINT = 'Hold %1 and use arrow keys to move freely, then %2 to accept the position.'; /** @type {string} */ /// Message shown to inform users how to move blocks with the keyboard. -Blockly.Msg.KEYBOARD_NAV_CONSTRAINED_MOVE_HINT = 'Use the arrow keys to move, then %1 to accept the position'; +Blockly.Msg.KEYBOARD_NAV_CONSTRAINED_MOVE_HINT = 'Use the arrow keys to move, then %1 to accept the position.'; /** @type {string} */ /// Message shown when an item is copied in keyboard navigation mode. Blockly.Msg.KEYBOARD_NAV_COPIED_HINT = 'Copied. Press %1 to paste.'; @@ -1839,10 +1839,10 @@ Blockly.Msg.WORKSPACE_CONTENTS_COMMENTS_MANY = ' and %1 comments'; Blockly.Msg.WORKSPACE_CONTENTS_COMMENTS_ONE = ' and one comment'; /** @type {string} */ /// Message shown when a user presses Enter with a navigable block focused. -Blockly.Msg.KEYBOARD_NAV_BLOCK_NAVIGATION_HINT = 'Use the right arrow key to navigate inside of blocks'; +Blockly.Msg.KEYBOARD_NAV_BLOCK_NAVIGATION_HINT = 'Use the right arrow key to navigate inside of blocks.'; /** @type {string} */ /// Message shown when a user presses Enter with the workspace focused. -Blockly.Msg.KEYBOARD_NAV_WORKSPACE_NAVIGATION_HINT = 'Use the arrow keys to navigate'; +Blockly.Msg.KEYBOARD_NAV_WORKSPACE_NAVIGATION_HINT = 'Use the arrow keys to navigate.'; /** @type {string} */ /// Part of an accessibility label for a block that indicates it is the first /// block in the stack. @@ -1902,44 +1902,44 @@ Blockly.Msg.INPUT_LABEL_INDEX = 'input %1'; /** @type {string} */ /// ARIA live region message announcing a block is being moved on the workspace, without specifying a target location or specific movement direction. // \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks -// \n\nExamples:\n* "moving block A on workspace"\n* "moving 2 stack blocks on workspace" -Blockly.Msg.ANNOUNCE_MOVE_WORKSPACE = 'moving %1 on workspace'; +// \n\nExamples:\n* "Moving if, do on workspace."\n* "Moving 2 stack blocks on workspace." +Blockly.Msg.ANNOUNCE_MOVE_WORKSPACE = 'Moving %1 on workspace.'; /** @type {string} */ /// ARIA live region message announcing a block is being moved before another block -/// \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks\n* %3 - the label of the target (neighbour) block -/// \n\nExamples:\n* "moving before repeat 10, times, do"\n* "moving 2 stack blocks before repeat 10, times, do" -Blockly.Msg.ANNOUNCE_MOVE_BEFORE = 'moving %1 before %3'; +/// \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks\n* %2 - the label of the target (neighbour) block +/// \n\nExamples:\n* "Moving before repeat, 10, times, do."\n* "Moving print before repeat, 10, times, do." +Blockly.Msg.ANNOUNCE_MOVE_BEFORE = 'Moving %1 before %2.'; /** @type {string} */ /// ARIA live region message announcing a block is being moved after another block -/// \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks\n* %3 - the label of the target (neighbour) block -/// \n\nExamples:\n* "moving after repeat 10, times, do"\n* "moving 2 stack blocks after repeat 10, times, do" -/// \n* "moving block A after Function block output" -Blockly.Msg.ANNOUNCE_MOVE_AFTER = 'moving %1 after %3'; +/// \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks\n* %2 - the label of the target (neighbour) block +/// \n\nExamples:\n* "Moving after repeat, 10, times, do."\n* "Moving 2 stack blocks after repeat, 10, times, do." +Blockly.Msg.ANNOUNCE_MOVE_AFTER = 'Moving %1 after %2.'; /** @type {string} */ -/// ARIA live region message announcing a block is being moved inside another block, optionally including connection-specific label for disambiguation. +/// ARIA live region message announcing a block is being moved inside another block's statement connection, optionally including connection-specific label for disambiguation. // \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks -// \n* %3 - the label of the target (neighbour) block -// \n* %4 - optional phrase describing the target connection label -// \n\nExamples:\n* "moving inside if, do"\n* "moving 2 stack blocks inside if, do else statement" -Blockly.Msg.ANNOUNCE_MOVE_INSIDE = 'moving %1 inside %3 %4'; +// \n* %2 - the label of the target (neighbour) block +// \n\nExamples:\n* "Moving inside if, do."\n* "Moving 3 stack blocks inside repeat, 10, times, do." +Blockly.Msg.ANNOUNCE_MOVE_INSIDE = 'Moving %1 inside %2.'; /** @type {string} */ -/// ARIA live region message announcing a block is being moved around another block, optionally including connection-specific label for disambiguation. -/// \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks -/// \n* %2 - optional phrase describing the local connection label -/// \n* %3 - the label of the target (neighbour) block -/// \n\nExamples:\n* "moving around print abc"\n* "moving if, do else statement around print abc" -Blockly.Msg.ANNOUNCE_MOVE_AROUND = 'moving %1 %2 around %3'; +/// ARIA live region message announcing a block is being moved around another block (using its own statement connection), optionally including connection-specific label for disambiguation. +/// \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks or a local connection label +/// \n* %2 - the label of the target (neighbour) block +/// \n\nExamples:\n* "Moving around print."\n* "Moving else around print." +Blockly.Msg.ANNOUNCE_MOVE_AROUND = 'Moving %1 around %2.'; /** @type {string} */ -/// ARIA live region message announcing a block is being moved to a workspace location where the relationship is not specifically known. -/// \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks -/// \n* %2 - optional phrase describing the local connection label -/// \n* %3 - the label of the target (neighbour) block or location -/// \n* %4 - optional phrase describing the target connection label -/// \n\nExamples:\n* "moving to repeat 10, times, do"\n* "moving 2 stack blocks else statement to repeat 10, times, do previous connection" -Blockly.Msg.ANNOUNCE_MOVE_TO = 'moving %1 %2 to %3 %4'; +/// ARIA live region message announcing a block is being moved to another block's value input connection, optionally including connection-specific label for disambiguation. +/// \n\nParameters:\n* %1 - optional phrase describing the moving stack of blocks or a local connection label +/// \n* %2 - the label of the target (neighbour) block or location +/// \n\nExamples:\n* "Moving to repeat, 10, times, do."\n* "Moving 2 stack blocks else statement to previous connection in repeat, 10, times, do." +Blockly.Msg.ANNOUNCE_MOVE_TO = 'Moving %1 to %2.'; +/** @type {string} */ +/// A label describing a specific connection of a block. Part of an ARIA live region message announcing a block is being moved. +/// \n\nParameters:\n* %1 - connection label\n* %2 - block label of the block the connection belongs to +/// \n\nExamples:\n* "else statement of if, do"" +Blockly.Msg.ANNOUNCE_MOVE_OF = '%1 of %2'; /** @type {string} */ /// ARIA live region message announcing a block movement has been canceled. -Blockly.Msg.ANNOUNCE_MOVE_CANCELED = 'Canceled movement'; +Blockly.Msg.ANNOUNCE_MOVE_CANCELED = 'Canceled movement.'; /** @type {string} */ /// Label for an empty field, used by screen readers to identify fields that have no content. Blockly.Msg.FIELD_LABEL_EMPTY = 'empty'; diff --git a/packages/blockly/tests/mocha/keyboard_movement_test.js b/packages/blockly/tests/mocha/keyboard_movement_test.js index 1bbb4b945..bb50d3a94 100644 --- a/packages/blockly/tests/mocha/keyboard_movement_test.js +++ b/packages/blockly/tests/mocha/keyboard_movement_test.js @@ -6,6 +6,7 @@ import {getInputLabelsSubset} from '../../build/src/core/block_aria_composer.js'; import * as Blockly from '../../build/src/core/blockly.js'; +import {Verbosity} from '../../build/src/core/utils/aria.js'; import {assert} from '../../node_modules/chai/index.js'; import { moveStatementTestBlocks, @@ -570,8 +571,8 @@ suite('Keyboard-driven movement', function () { assert.equal( toastSpy.args[0][1]['message'], Blockly.utils.userAgent.MAC - ? 'Hold ⌘ Command and use arrow keys to move freely, then Enter to accept the position' - : 'Hold Ctrl and use arrow keys to move freely, then Enter to accept the position', + ? 'Hold ⌘ Command and use arrow keys to move freely, then Enter to accept the position.' + : 'Hold Ctrl and use arrow keys to move freely, then Enter to accept the position.', ); sinon.assert.calledOnce(beepSpy); beepSpy.restore(); @@ -1142,6 +1143,12 @@ suite('Keyboard-driven movement', function () { }; this.getBlockLabel = (block) => block.getAriaLabel(Blockly.utils.aria.Verbosity.TERSE); + this.getInputLabel = (block, input) => + getInputLabelsSubset( + block, + block.getInput(input), + Verbosity.TERSE, + ).join(', '); this.block1 = this.workspace.newBlock('draw_emoji'); this.block1.initSvg(); this.block1.render(); @@ -1151,7 +1158,7 @@ suite('Keyboard-driven movement', function () { Blockly.getFocusManager().focusNode(this.block1); this.moveAndAssert( startMove, - ['moving', this.getBlockLabel(this.block1), 'on workspace'], + ['Moving', this.getBlockLabel(this.block1), 'on workspace.'], [], ); cancelMove(this.workspace); @@ -1166,9 +1173,9 @@ suite('Keyboard-driven movement', function () { Blockly.getFocusManager().focusNode(this.block1); this.moveAndAssert(startMoveStack, [ - 'moving', + 'Moving', '2 stack blocks', - 'on workspace', + 'on workspace.', ]); cancelMove(this.workspace); }); @@ -1181,10 +1188,9 @@ suite('Keyboard-driven movement', function () { Blockly.getFocusManager().focusNode(this.block1); startMove(this.workspace); - this.moveAndAssert( moveRight, - ['moving', 'before', this.getBlockLabel(block2)], + ['Moving', 'before', this.getBlockLabel(block2)], [this.getBlockLabel(this.block1)], ); @@ -1201,7 +1207,7 @@ suite('Keyboard-driven movement', function () { Blockly.getFocusManager().focusNode(block2); this.moveAndAssert(startMove, [ - 'moving', + 'Moving', this.getBlockLabel(block2), 'after', this.getBlockLabel(this.block1), @@ -1209,7 +1215,7 @@ suite('Keyboard-driven movement', function () { cancelMove(this.workspace); }); - test('announces "inside" for value connections', function () { + test('announces "to" for value connections', function () { const valueBlock = this.workspace.newBlock('text'); valueBlock.initSvg(); valueBlock.render(); @@ -1223,7 +1229,7 @@ suite('Keyboard-driven movement', function () { this.clock.tick(10); this.moveAndAssert( moveRight, - ['moving', 'inside', this.getBlockLabel(parent)], + ['Moving', 'to', this.getBlockLabel(parent)], [this.getBlockLabel(valueBlock)], ); @@ -1241,11 +1247,8 @@ suite('Keyboard-driven movement', function () { this.moveAndAssert( moveRight, - ['moving', 'around', this.getBlockLabel(this.block1)], - [ - this.getBlockLabel(loop), - getInputLabelsSubset(loop, loop.getInput('DO')).join(', '), - ], + ['Moving', 'around', this.getBlockLabel(this.block1)], + [this.getBlockLabel(loop), this.getInputLabel(loop, 'DO')], ); cancelMove(this.workspace); @@ -1266,8 +1269,8 @@ suite('Keyboard-driven movement', function () { this.moveAndAssert( moveRight, [ - 'moving', - getInputLabelsSubset(ifBlock, ifBlock.getInput('DO1')).join(', '), + 'Moving', + this.getInputLabel(ifBlock, 'DO1'), 'around', this.getBlockLabel(this.block1), ], @@ -1276,8 +1279,8 @@ suite('Keyboard-driven movement', function () { this.moveAndAssert( moveRight, [ - 'moving', - getInputLabelsSubset(ifBlock, ifBlock.getInput('DO0')).join(', '), + 'Moving', + this.getInputLabel(ifBlock, 'DO0'), 'around', this.getBlockLabel(this.block1), ], @@ -1297,23 +1300,24 @@ suite('Keyboard-driven movement', function () { Blockly.getFocusManager().focusNode(boolean); startMove(this.workspace); this.clock.tick(10); + console.log([this.getBlockLabel(compare), this.getBlockLabel(boolean)]); this.moveAndAssert( moveRight, [ - 'moving', - 'inside', + 'Moving', + 'to', this.getBlockLabel(compare), - getInputLabelsSubset(compare, compare.getInput('A')).join(', '), + this.getInputLabel(compare, 'A'), ], [this.getBlockLabel(boolean)], ); this.moveAndAssert( moveRight, [ - 'moving', - 'inside', + 'Moving', + 'to', this.getBlockLabel(compare), - getInputLabelsSubset(compare, compare.getInput('B')).join(', '), + this.getInputLabel(compare, 'B'), ], [this.getBlockLabel(boolean)], ); @@ -1336,12 +1340,12 @@ suite('Keyboard-driven movement', function () { this.clock.tick(10); this.moveAndAssert( moveRight, - ['moving', 'inside', this.getBlockLabel(textJoin), 'input 2'], + ['Moving', 'to', this.getBlockLabel(textJoin), 'input 2'], [this.getBlockLabel(text)], ); this.moveAndAssert( moveRight, - ['moving', 'inside', this.getBlockLabel(textJoin), 'input 3'], + ['Moving', 'to', this.getBlockLabel(textJoin), 'input 3'], [this.getBlockLabel(text)], );