diff --git a/plugins/block-plus-minus/README.md b/plugins/block-plus-minus/README.md index 026d446680..076a681ded 100644 --- a/plugins/block-plus-minus/README.md +++ b/plugins/block-plus-minus/README.md @@ -34,17 +34,15 @@ import Blockly from 'blockly'; import '@blockly/block-plus-minus'; ``` -### Blockly Languages +### Localization and text customization -We do not currently support translating the text in this plugin to different -languages. However, if you would like to support multiple languages the messages -can be translated by assigning the following properties of Blockly.Msg - -- `PROCEDURE_VARIABLE` (Default: "variable:"): The label which signals the text - input is a variable. +The plus and minus buttons have ARIA labels to communicate their purpose to +screenreaders. These are localizable; additionally, if you want to customize the +labels (for example, to use a different term that "input" for procedure blocks) +you can do so by adjusting the messages: ```javascript -Blockly.Msg['PROCEDURE_VARIABLE'] = 'variabele:'; // Dutch +Blockly.Msg['ARIA_LABEL_ADD_INPUT'] = 'Add parameter'; // Inject workspace, etc... ``` diff --git a/plugins/block-plus-minus/src/field_minus.js b/plugins/block-plus-minus/src/field_minus.js index 4ee1060a0a..040480b576 100644 --- a/plugins/block-plus-minus/src/field_minus.js +++ b/plugins/block-plus-minus/src/field_minus.js @@ -18,8 +18,8 @@ import {getExtraBlockState} from './serialization_helper'; * is clicked. * @returns {Blockly.FieldImage} The minus field. */ -export function createMinusField(args = undefined) { - const minus = new Blockly.FieldImage(minusImage, 15, 15, undefined, onClick_); +export function createMinusField(args = undefined, altText = '') { + const minus = new Blockly.FieldImage(minusImage, 15, 15, altText, onClick_); /** * Untyped args passed to block.minus when the field is clicked. * @type {?(Object|undefined)} diff --git a/plugins/block-plus-minus/src/field_plus.js b/plugins/block-plus-minus/src/field_plus.js index f6b1154fe0..05762eb3d9 100644 --- a/plugins/block-plus-minus/src/field_plus.js +++ b/plugins/block-plus-minus/src/field_plus.js @@ -18,8 +18,8 @@ import {getExtraBlockState} from './serialization_helper'; * is clicked. * @returns {Blockly.FieldImage} The Plus field. */ -export function createPlusField(args = undefined) { - const plus = new Blockly.FieldImage(plusImage, 15, 15, undefined, onClick_); +export function createPlusField(args = undefined, altText = '') { + const plus = new Blockly.FieldImage(plusImage, 15, 15, altText, onClick_); /** * Untyped args passed to block.plus when the field is clicked. * @type {?(Object|undefined)} diff --git a/plugins/block-plus-minus/src/if.js b/plugins/block-plus-minus/src/if.js index ee014cf3b8..09d3255d3b 100644 --- a/plugins/block-plus-minus/src/if.js +++ b/plugins/block-plus-minus/src/if.js @@ -143,7 +143,10 @@ const controlsIfMutator = { .setCheck('Boolean') .appendField(Blockly.Msg['CONTROLS_IF_MSG_ELSEIF']) .appendField( - createMinusField(this.elseIfCount_), + createMinusField( + this.elseIfCount_, + Blockly.Msg['ARIA_LABEL_REMOVE_ELSE_IF'], + ), 'MINUS' + this.elseIfCount_, ); this.appendStatementInput('DO' + this.elseIfCount_).appendField( @@ -209,7 +212,11 @@ const controlsIfMutator = { * @this {Blockly.Block} */ const controlsIfHelper = function () { - this.getInput('IF0').insertFieldAt(0, createPlusField(), 'PLUS'); + this.getInput('IF0').insertFieldAt( + 0, + createPlusField(undefined, Blockly.Msg['ARIA_LABEL_ADD_ELSE_IF']), + 'PLUS', + ); }; if (Blockly.Extensions.isRegistered('controls_if_mutator')) { diff --git a/plugins/block-plus-minus/src/list_create.js b/plugins/block-plus-minus/src/list_create.js index 6b413d15cc..9f75a93b80 100644 --- a/plugins/block-plus-minus/src/list_create.js +++ b/plugins/block-plus-minus/src/list_create.js @@ -130,7 +130,10 @@ const listCreateMutator = { if (this.itemCount_ == 0) { this.removeInput('EMPTY'); this.topInput_ = this.appendValueInput('ADD' + this.itemCount_) - .appendField(createPlusField(), 'PLUS') + .appendField( + createPlusField(undefined, Blockly.Msg['ARIA_LABEL_ADD_LIST_ITEM']), + 'PLUS', + ) .appendField(Blockly.Msg['LISTS_CREATE_WITH_INPUT_WITH']); } else { this.appendValueInput('ADD' + this.itemCount_); @@ -149,7 +152,10 @@ const listCreateMutator = { this.removeInput('ADD' + this.itemCount_); if (this.itemCount_ == 0) { this.topInput_ = this.appendDummyInput('EMPTY') - .appendField(createPlusField(), 'PLUS') + .appendField( + createPlusField(undefined, Blockly.Msg['ARIA_LABEL_ADD_LIST_ITEM']), + 'PLUS', + ) .appendField(Blockly.Msg['LISTS_CREATE_EMPTY_TITLE']); } }, @@ -161,7 +167,11 @@ const listCreateMutator = { updateMinus_: function () { const minusField = this.getField('MINUS'); if (!minusField && this.itemCount_ > 0) { - this.topInput_.insertFieldAt(1, createMinusField(), 'MINUS'); + this.topInput_.insertFieldAt( + 1, + createMinusField(undefined, Blockly.Msg['ARIA_LABEL_REMOVE_LIST_ITEM']), + 'MINUS', + ); } else if (minusField && this.itemCount_ < 1) { this.topInput_.removeField('MINUS'); } @@ -173,7 +183,11 @@ const listCreateMutator = { * @this {Blockly.Block} */ const listCreateHelper = function () { - this.getInput('EMPTY').insertFieldAt(0, createPlusField(), 'PLUS'); + this.getInput('EMPTY').insertFieldAt( + 0, + createPlusField(undefined, Blockly.Msg['ARIA_LABEL_ADD_LIST_ITEM']), + 'PLUS', + ); this.updateShape_(3); }; diff --git a/plugins/block-plus-minus/src/procedures.js b/plugins/block-plus-minus/src/procedures.js index 40f9390393..39d96dff12 100644 --- a/plugins/block-plus-minus/src/procedures.js +++ b/plugins/block-plus-minus/src/procedures.js @@ -452,7 +452,9 @@ const procedureDefMutator = { this.appendDummyInput(argId) .setAlign(Blockly.inputs.Align.RIGHT) - .appendField(createMinusField(argId)) + .appendField( + createMinusField(argId, Blockly.Msg['ARIA_LABEL_REMOVE_INPUT']), + ) .appendField(Blockly.Msg['PROCEDURE_VARIABLE']) // Untranslated! .appendField(nameField, argId); // The name of the field is the arg id. }, @@ -500,13 +502,15 @@ const procedureDefMutator = { * only used by this block, or callers of this procedure. */ const varOnlyUsedHere = () => { - return workspace.getVariableUsesById(currId).every((block) => { - return ( - block.id == sourceBlock.id || - (block.getProcedureCall && - block.getProcedureCall() == sourceBlock.getProcedureDef()[0]) - ); - }); + return Blockly.Variables.getVariableUsesById(workspace, currId).every( + (block) => { + return ( + block.id == sourceBlock.id || + (block.getProcedureCall && + block.getProcedureCall() == sourceBlock.getProcedureDef()[0]) + ); + }, + ); }; if (!newName || !argData.every(hasDifName)) { @@ -527,14 +531,17 @@ const procedureDefMutator = { // Create new vars instead of renaming the old ones, so users can't // accidentally rename/coalesce vars. - let model = workspace.getVariable(newName, ''); + let model = workspace.getVariableMap().getVariable(newName, ''); if (!model) { - model = workspace.createVariable(newName, ''); + model = workspace.getVariableMap().createVariable(newName, ''); this.varIdsToDelete_.push(model.getId()); } else if (model.name != newName) { // Blockly is case-insensitive so we have to update the var instead of // creating a new one. - workspace.renameVariableById(model.getId(), newName); + const variable = workspace + .getVariableMap() + .getVariableById(model.getId()); + workspace.getVariableMap().renameVariable(variable, newName); } if (model.getId() != currId) { argDatum.model = model; @@ -587,7 +594,11 @@ const procedureDefHelper = function () { */ this.hasStatements_ = true; - this.getInput('TOP').insertFieldAt(0, createPlusField(), 'PLUS'); + this.getInput('TOP').insertFieldAt( + 0, + createPlusField(undefined, Blockly.Msg['ARIA_LABEL_ADD_INPUT']), + 'PLUS', + ); }; Blockly.Extensions.registerMutator( @@ -647,7 +658,7 @@ const procedureVars = function () { return; // Not on this block. } - const newVar = this.workspace.getVariableById(newId); + const newVar = this.workspace.getVariableMap().getVariableById(newId); const newName = newVar.name; this.addVarInput_(newName, newId); this.moveInputBefore(newId, oldId); diff --git a/plugins/block-plus-minus/src/text_join.js b/plugins/block-plus-minus/src/text_join.js index f4267a9990..00acb0996b 100644 --- a/plugins/block-plus-minus/src/text_join.js +++ b/plugins/block-plus-minus/src/text_join.js @@ -109,7 +109,10 @@ const textJoinMutator = { this.removeInput('EMPTY'); } this.topInput_ = this.appendValueInput('ADD' + this.itemCount_) - .appendField(createPlusField(), 'PLUS') + .appendField( + createPlusField(undefined, Blockly.Msg['ARIA_LABEL_ADD_TEXT']), + 'PLUS', + ) .appendField(Blockly.Msg['TEXT_JOIN_TITLE_CREATEWITH']); } else { this.appendValueInput('ADD' + this.itemCount_); @@ -129,7 +132,10 @@ const textJoinMutator = { this.removeInput('ADD' + this.itemCount_); if (this.itemCount_ == 0) { this.topInput_ = this.appendDummyInput('EMPTY') - .appendField(createPlusField(), 'PLUS') + .appendField( + createPlusField(undefined, Blockly.Msg['ARIA_LABEL_ADD_TEXT']), + 'PLUS', + ) .appendField(this.newQuote_(true)) .appendField(this.newQuote_(false)); } @@ -142,7 +148,11 @@ const textJoinMutator = { updateMinus_: function () { const minusField = this.getField('MINUS'); if (!minusField && this.itemCount_ > 0) { - this.topInput_.insertFieldAt(1, createMinusField(), 'MINUS'); + this.topInput_.insertFieldAt( + 1, + createMinusField(undefined, Blockly.Msg['ARIA_LABEL_REMOVE_TEXT']), + 'MINUS', + ); } else if (minusField && this.itemCount_ < 1) { this.topInput_.removeField('MINUS'); } diff --git a/plugins/block-plus-minus/test/list_create.mocha.js b/plugins/block-plus-minus/test/list_create.mocha.js index e99a756eab..e17d3b852d 100644 --- a/plugins/block-plus-minus/test/list_create.mocha.js +++ b/plugins/block-plus-minus/test/list_create.mocha.js @@ -39,7 +39,7 @@ suite('List create block', function () { assert.equal(input.name, 'EMPTY'); assert.isNull(block.getField('MINUS')); // Easy way to test we're displaying empty instead of normal text. - assert.equal(block.toString(), 'create empty list'); + assert.equal(block.toString(), 'Add list item create empty list'); return; } @@ -49,7 +49,7 @@ suite('List create block', function () { } assert.isNotNull(block.getField('MINUS')); // Easy way to test we're displaying normal text instead of empty. - assert.notEqual(block.toString(), 'create empty list'); + assert.notEqual(block.toString(), 'Add list item create empty list'); } setup(function () { diff --git a/plugins/block-plus-minus/test/procedures.mocha.js b/plugins/block-plus-minus/test/procedures.mocha.js index d1481e460b..b415ec0658 100644 --- a/plugins/block-plus-minus/test/procedures.mocha.js +++ b/plugins/block-plus-minus/test/procedures.mocha.js @@ -604,6 +604,7 @@ suite('Procedure blocks', function () { setup(function () { this.assertVars = function (constsArray) { const constNames = this.workspace + .getVariableMap() .getVariablesOfType('') .map((model) => model.name); assert.sameMembers(constNames, constsArray); @@ -696,7 +697,7 @@ suite('Procedure blocks', function () { this.assertVars(['x', 'y']); }); test('Match Existing', function () { - this.workspace.createVariable('test', ''); + this.workspace.getVariableMap().createVariable('test', ''); this.def.plus(); const field = this.def.inputList[1].fieldRow[2]; field.setValue('test'); @@ -709,7 +710,7 @@ suite('Procedure blocks', function () { this.assertVars(['x', 'test']); assert.equal( this.def.argData_[0].model.getId(), - this.workspace.getVariable('test', '').getId(), + this.workspace.getVariableMap().getVariable('test', '').getId(), ); }); }); @@ -723,8 +724,10 @@ suite('Procedure blocks', function () { }); test('Simple Rename', function () { this.def.plus(); - const Variable = this.workspace.getVariable('x', ''); - this.workspace.renameVariableById(Variable.getId(), 'test'); + const Variable = this.workspace + .getVariableMap() + .getVariable('x', ''); + this.workspace.getVariableMap().renameVariable(Variable, 'test'); assertProcBlocksStructure( this.def, this.call, @@ -737,14 +740,18 @@ suite('Procedure blocks', function () { test.skip('Duplicate', function () { this.def.plus(); this.def.plus(); - const Variable = this.workspace.getVariable('x', ''); - this.workspace.renameVariableById(Variable.getId(), 'y'); + const Variable = this.workspace + .getVariableMap() + .getVariable('x', ''); + this.workspace.getVariableMap().renameVariable(Variable, 'y'); // Don't know what we want to have happen. }); test('Change Case', function () { this.def.plus(); - const Variable = this.workspace.getVariable('x', ''); - this.workspace.renameVariableById(Variable.getId(), 'X'); + const Variable = this.workspace + .getVariableMap() + .getVariable('x', ''); + this.workspace.getVariableMap().renameVariable(Variable, 'X'); assertProcBlocksStructure( this.def, this.call, @@ -754,9 +761,11 @@ suite('Procedure blocks', function () { this.assertVars(['X']); }); test('Coalesce Change Case', function () { - const variable = this.workspace.createVariable('test'); + const variable = this.workspace + .getVariableMap() + .createVariable('test'); this.def.plus(); - this.workspace.renameVariableById(variable.getId(), 'X'); + this.workspace.getVariableMap().renameVariable(variable, 'X'); assertProcBlocksStructure( this.def, this.call, diff --git a/plugins/block-plus-minus/test/text_join.mocha.js b/plugins/block-plus-minus/test/text_join.mocha.js index 3481b84b0a..acd96a43e0 100644 --- a/plugins/block-plus-minus/test/text_join.mocha.js +++ b/plugins/block-plus-minus/test/text_join.mocha.js @@ -39,7 +39,7 @@ suite('Text join block', function () { assert.equal(input.name, 'EMPTY'); assert.isNull(block.getField('MINUS')); // Easy way to test we're displaying quotes instead of normal text. - assert.equal(block.toString(), '“ ”'); + assert.equal(block.toString(), 'Add text “ ”'); return; } @@ -49,7 +49,7 @@ suite('Text join block', function () { } assert.isNotNull(block.getField('MINUS')); // Easy way to test we're displaying normal text instead of quotes. - assert.notEqual(block.toString(), '“ ”'); + assert.notEqual(block.toString(), 'Add text “ ”'); } setup(function () {