Skip to content

Commit e205e60

Browse files
authored
add translatable ariaLabel to block dropdown items (#11416)
* add translatable ariaLabel to enums * update docs
1 parent ea51008 commit e205e60

6 files changed

Lines changed: 43 additions & 6 deletions

File tree

docs/defining-blocks.md

Lines changed: 15 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ parameter = string
106106
* each `field` is mapped to a field name on the block.
107107
* the function parameters are mapped to the `$parameter` argument with an identical name. The loader automatically builds a mapping between the block field names and the function names.
108108
* the block will automatically switch to external inputs (wrapping) when there are four or more parameters.
109-
* the `|` indicates where to start a new line if the block is in external inputs mode.
109+
* the `|` indicates where to start a new line if the block is in external inputs mode.
110110

111111
## Custom block localization
112112

@@ -124,11 +124,12 @@ For example,
124124
export function square(x: number): number {}
125125
```
126126

127-
You can also override the ``jsdoc`` description and parameter info.
127+
You can also override the ``jsdoc`` description, parameter info, and ariaLabel (for dropdown values).
128128

129129
```
130130
jsdoc.loc.LOCALE = translated jsdoc
131131
PARAM.loc.LOCALE = parameter jsdoc
132+
ariaLabel.loc.LOCALE = translated aria label
132133
```
133134

134135
```typescript-ignore
@@ -141,6 +142,14 @@ PARAM.loc.LOCALE = parameter jsdoc
141142
//% jsdoc.loc.fr="Calcule le carré de x"
142143
//% x.loc.fr="le nombre"
143144
export function square(x: number): number {}
145+
146+
147+
export enum MyEnum {
148+
//% block="x"
149+
//% ariaLabel="x axis"
150+
//% ariaLabel.loc.fr="axe des x"
151+
X
152+
}
144153
```
145154

146155

@@ -339,14 +348,16 @@ Enum is supported and will automatically be represented by a dropdown in blocks.
339348
enum Button {
340349
A = 1,
341350
B = 2,
342-
//% blockId="ApB" block="A+B"
351+
//% block="A+B" ariaLabel="A and B"
343352
AB = 3,
344353
}
345354
```
346355

347356
* the initializer can be used to map the value
348-
* the `blockId` attribute can be used to override the block id
349357
* the `block` attribute can be used to override the rendered string
358+
* the `ariaLabel` attribute can be used to override the aria label on the dropdown value if the `block` value is not read correctly by screen readers
359+
360+
The `block` and `ariaLabel` values can both be localized, either by including a strings JSON file or locally in the comments (see custom block localization section above).
350361

351362
### Tip: dropdown for non-enum parameters
352363

localtypings/pxtarget.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -980,6 +980,7 @@ declare namespace ts.pxtc {
980980
enumIsHash?: boolean; // if true, the name of the enum is normalized, then hashed to generate the value
981981
enumPromptHint?: string; // The hint that will be displayed in the member creation prompt
982982
enumInitialMembers?: string[]; // The initial enum values which will be given the lowest values available
983+
ariaLabel?: string; // The aria label for the enum value if the screen reader text should differ from the block value in dropdown items
983984

984985
/* end enum-only attributes */
985986

@@ -1017,6 +1018,7 @@ declare namespace ts.pxtc {
10171018
_untranslatedBlock?: string; // The block definition before it was translated
10181019
_untranslatedJsDoc?: string // the jsDoc before it was translated
10191020
_untranslatedParamDefl?: pxt.Map<string>; // the parameter defaults before they were translated
1021+
_untranslatedAriaLabel?: string; // the aria label before it was translated
10201022
_translatedLanguageCode?: string // the language this block has been translated into
10211023
_shadowOverrides?: pxt.Map<string>;
10221024
jsDoc?: string;

pxtblocks/loader.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -538,7 +538,8 @@ function initBlock(block: Blockly.Block, info: pxtc.BlocksInfo, fn: pxtc.SymbolI
538538
height: 36,
539539
value: v.name
540540
} : k,
541-
v.namespace + "." + v.name
541+
v.namespace + "." + v.name,
542+
v.attributes.ariaLabel
542543
];
543544
});
544545
// if a value is provided, move it first

pxtcompiler/emitter/service.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,10 @@ namespace ts.pxtc {
366366
}
367367
}
368368
}
369+
370+
if (si.attributes.ariaLabel) {
371+
locStrings[`${si.qName}|ariaLabel`] = si.attributes.ariaLabel;
372+
}
369373
}
370374
const mapLocs = (m: pxt.Map<string>, name: string) => {
371375
if (!options.locs) return;
@@ -385,6 +389,7 @@ namespace ts.pxtc {
385389
if (options.locs)
386390
enumMembers.forEach(em => {
387391
if (em.attributes.block) locStrings[`${em.qName}|block`] = em.attributes.block;
392+
if (em.attributes.ariaLabel) locStrings[`${em.qName}|ariaLabel`] = em.attributes.ariaLabel;
388393
if (em.attributes.jsDoc) locStrings[em.qName] = em.attributes.jsDoc;
389394
});
390395
mapLocs(locStrings, "");

pxtlib/service.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -706,6 +706,7 @@ namespace ts.pxtc {
706706
const langLower = lang.toLowerCase();
707707
const attrJsLocsKey = langLower + "|jsdoc";
708708
const attrBlockLocsKey = langLower + "|block";
709+
const attrAriaLabelLocsKey = langLower + "|ariaLabel";
709710

710711
const loc = await mainPkg.localizationStringsAsync(lang);
711712
if (apiLocalizationStrings)
@@ -717,7 +718,8 @@ namespace ts.pxtc {
717718
const altLocSrcFn = altLocSrc && apis.byQName[altLocSrc];
718719

719720
if (fn.attributes._untranslatedJsDoc) fn.attributes.jsDoc = fn.attributes._untranslatedJsDoc;
720-
if (fn.attributes._untranslatedBlock) fn.attributes.jsDoc = fn.attributes._untranslatedBlock;
721+
if (fn.attributes._untranslatedBlock) fn.attributes.block = fn.attributes._untranslatedBlock;
722+
if (fn.attributes._untranslatedAriaLabel) fn.attributes.ariaLabel = fn.attributes._untranslatedAriaLabel;
721723
if (fn.attributes._untranslatedParamDefl) {
722724
fn.attributes.paramDefl = U.clone(fn.attributes._untranslatedParamDefl);
723725
syncParameterDefaults(fn);
@@ -747,6 +749,7 @@ namespace ts.pxtc {
747749

748750
const nsDoc = loc['{id:category}' + Util.capitalize(fn.qName)];
749751
let locBlock = loc[`${fn.qName}|block`] || fn.attributes.locs?.[attrBlockLocsKey];
752+
const locAriaLabel = loc[`${fn.qName}|ariaLabel`] || fn.attributes.locs?.[attrAriaLabelLocsKey];
750753

751754
if (fn.attributes.block) {
752755
const comp = pxt.blocks.compileInfo(fn);
@@ -848,6 +851,13 @@ namespace ts.pxtc {
848851
} else {
849852
updateBlockDef(fn.attributes);
850853
}
854+
855+
if (locAriaLabel) {
856+
if (!fn.attributes._untranslatedAriaLabel) {
857+
fn.attributes._untranslatedAriaLabel = fn.attributes.ariaLabel;
858+
}
859+
fn.attributes.ariaLabel = locAriaLabel;
860+
}
851861
fn.attributes._translatedLanguageCode = lang;
852862
});
853863

@@ -990,6 +1000,9 @@ namespace ts.pxtc {
9901000
} else if (U.startsWith(n, "jsdoc.loc.")) {
9911001
if (!res.locs) res.locs = {};
9921002
res.locs[n.slice("jsdoc.loc.".length).toLowerCase() + "|jsdoc"] = v;
1003+
} else if (U.startsWith(n, "ariaLabel.loc.")) {
1004+
if (!res.locs) res.locs = {};
1005+
res.locs[n.slice("ariaLabel.loc.".length).toLowerCase() + "|ariaLabel"] = v;
9931006
} else if (U.contains(n, ".loc.")) {
9941007
if (!res.locs) res.locs = {};
9951008
const p = n.slice(0, n.indexOf('.loc.'));

webapp/src/compiler.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -839,6 +839,11 @@ function cleanApiForCache(apiInfo: pxtc.SymbolInfo) {
839839
delete cachedAttrs._untranslatedJsDoc;
840840
defChanged = true;
841841
}
842+
if (cachedAttrs._untranslatedAriaLabel) {
843+
cachedAttrs.ariaLabel = cachedAttrs._untranslatedAriaLabel;
844+
delete cachedAttrs._untranslatedAriaLabel;
845+
defChanged = true;
846+
}
842847
if (defChanged) {
843848
ts.pxtc.updateBlockDef(cachedAttrs);
844849
}

0 commit comments

Comments
 (0)