[A11y] Add lang attribute to language options for screen reader pronunciation#84588
[A11y] Add lang attribute to language options for screen reader pronunciation#84588
Conversation
… pronunciation Non-English language options on the Language preferences page were being announced with English pronunciation by screen readers (JAWS + Chrome) because the HTML elements lacked the lang attribute. This adds a lang property to ListItem, threads it through BaseListItem to the pressable element, and sets it on each language option in LanguagePage using the locale code as the BCP 47 language tag. Co-authored-by: Rushat Gabhane <rushatgabhane@users.noreply.github.com>
|
@MelvinBot will this work on react native? https://reactnative.dev/docs/accessibility suggest a fix that works on native too |
|
Good catch — the For iOS, React Native supports Suggested fix — in lang={item.lang}
accessibilityLanguage={item.lang}The prop forwarding chain ( Platform coverage after this change:
|
|
@MelvinBot see what react native web needs? Also is our value passed to the prop correct? |
|
@MelvinBot mark ready for review |
|
Investigated both questions: 1. What does React Native Web need?RNW explicitly supports the const forwardPropsList = {
// ...
lang: true,
// ...
};It does two things with it:
So the current approach of passing 2. Are the values correct?The values come from
All values are valid BCP 47 language tags. Screen readers (JAWS, NVDA, VoiceOver on macOS) will correctly switch pronunciation based on these tags. One note on native platforms (from my earlier comment): on iOS, this prop has no effect — iOS needs |
|
Done — PR is now marked as ready for review. |
|
@ahmedGaber93 Please copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
@ahmedGaber93 all yours |
|
No product review needed |
|
reassigning to @mkhutornyi |
|
@mkhutornyi feel free to change this please, if something isn't working |
|
@MelvinBot please fix native too if not done |
The lang prop only works on web (React Native Web forwards it as the HTML lang attribute). On native iOS, VoiceOver uses the accessibilityLanguage prop to determine pronunciation language. This passes the same BCP 47 locale tag to accessibilityLanguage so iOS VoiceOver announces language options correctly. Co-authored-by: Rushat Gabhane <rushatgabhane@users.noreply.github.com>
|
@thesahindia @dangrous One of you needs to copy/paste the Reviewer Checklist from here into a new comment on this PR and complete it. If you have the K2 extension, you can simply click: [this button] |
|
Added
Both props receive the same BCP 47 locale tag (e.g., |
|
The failing check is unrelated to this PR. Analysis: The failure is in Evidence:
|
|
@MelvinBot merge main |
…eScreenReaderLang Co-authored-by: Rushat Gabhane <rushatgabhane@users.noreply.github.com>
|
Merged main into the PR branch. |
Reviewer Checklist
Screenshots/VideosAndroid: HybridAppAndroid: mWeb ChromeiOS: HybridAppiOS: mWeb Safari |
dangrous
left a comment
There was a problem hiding this comment.
Codewise seems great if it works!
|
There's regression on staging so web testing is blocked at the moment. Works fine on production Not able to select each menu item at all. I tested using VoiceOver. staging: reg.movproduction:
@rushatgabhane should we create new issue for this? I can investigate if you'd assign me. |
| {...bind} | ||
| ref={pressableRef} | ||
| lang={item.lang} | ||
| accessibilityLanguage={item.lang} |
There was a problem hiding this comment.
@MelvinBot accessibilityLanguage is iOS only prop. https://reactnative.dev/docs/view#accessibilitylanguage-ios
Does this work on android too?
|
@mkhutornyi this bug doesn't occur on Android btw, try it out And for web regression on staging I don't think we need to wait on it if DOM element looks good |
|
No — Current cross-platform coverage
Why Android doesn't workReact Native has no wiring for
The prop is silently ignored on Android — no crash, no error, just no effect. What Android offers (outside RN)
RecommendationThe current approach ( If you'd like, I can file an upstream issue on |
DOM element looks good. Btw the original bug report is from web platform. iOS works fine. For android, I am not sure if there's solution to support all devices. Should we not block on this? |
|
@dangrous all yours! 🙇 |
yep it works on modern android versions. so i don't think we should block on this. |
|
🚧 @dangrous has triggered a test Expensify/App build. You can view the workflow run here. |
|
🧪🧪 Use the links below to test this adhoc build on Android, iOS, and Web. Happy testing! 🧪🧪
|
|
🚀 Deployed to staging by https://github.com/dangrous in version: 9.3.39-0 🚀
|
|
✋ This PR was not deployed to staging yet because QA is ongoing. It will be automatically deployed to staging after the next production release. |
|
🚀 Deployed to production by https://github.com/cristipaval in version: 9.3.39-3 🚀
|


Explanation of Change
Non-English language options on the Language preferences page (Settings > Preferences > Language) were being announced with English pronunciation by screen readers (e.g., JAWS + Chrome) because the HTML elements lacked the
langattribute. Per WCAG 3.1.1, thelangattribute tells screen readers which language to use for pronunciation, so without it, text like "中文 (简体)" or "日本語" was either mispronounced or skipped entirely.This PR adds a
langproperty to theListItemtype, threads it throughBaseListItemto the pressable DOM element, and sets it on each language option inLanguagePageusing the locale code as the BCP 47 language tag. On web, React Native Web forwards thelangprop to the HTMLlangattribute on the rendered<div>. On native platforms, the prop is harmlessly ignored.Fixed Issues
$ #74881
Tests
Offline tests
N/A — These are accessibility attribute changes that don't affect offline behavior.
QA Steps
PR Author Checklist
### Fixed Issuessection aboveTestssectionOffline stepssectionQA stepssectiontoggleReportand notonIconClick)src/languages/*files and using the translation methodSTYLE.md) were followedAvatar, I verified the components usingAvatarare working as expected)StyleUtils.getBackgroundAndBorderStyle(theme.componentBG))npm run compress-svg)Avataris modified, I verified thatAvataris working as expected in all cases)Designlabel and/or tagged@Expensify/designso the design team can review the changes.ScrollViewcomponent to make it scrollable when more elements are added to the page.mainbranch was merged into this PR after a review, I tested again and verified the outcome was still expected according to theTeststeps.Screenshots/Videos
Web: Language Preferences Page with lang attributes
DOM verification showing each language option now has the correct
langattribute: