Repository navigation
Description
Steps to reproduce
- Run
flutter create --platforms web bugand replacelib/main.dartwith the code sample below. - Run
flutter build web, then serve it withpython3 -m http.server -d build/web. - Open http://localhost:8000 and run this in the DevTools console:
document.querySelector('flt-semantics[lang]').getAttribute('lang')
Expected results
"es-US". The HTML lang attribute must be a valid BCP 47 language tag, and BCP 47 separates subtags with hyphens.
Actual results
"es_US". In Chromium and WebKit, element.matches(':lang(es)') is then false for that node. Firefox accepts the underscore and returns true.
Measured on 3.47.7 stable with Playwright's Chromium 156, Firefox 157 and WebKit 27.2 builds. With Locale('es') the attribute is "es", which avoids the bug at the cost of the region. Localizations.override with Locale('es', 'US') produces the same "es_US", since it sets localeForSubtree too.
The web engine's _updateLocale builds the attribute from semanticsObject.locale?.toString(), which joins subtags with an underscore. This is still the code on master. #171196 used toString() for both web and native, and #173364 later switched the native path in dart:ui to toLanguageTag(). Making the same change in _updateLocale should fix web, since Locale('es', 'US').toLanguageTag() returns "es-US" there.
The web tests did not catch this because they construct Locale('es-MX'), which puts the whole tag in languageCode and leaves countryCode null.
Code sample
Code sample
import 'package:flutter/semantics.dart';
import 'package:flutter/widgets.dart';
void main() {
runApp(
Directionality(
textDirection: TextDirection.ltr,
child: Semantics(
localeForSubtree: const Locale('es', 'US'),
child: const Text('Hola'),
),
),
);
SemanticsBinding.instance.ensureSemantics();
}Screenshots or Video
No response
Logs
No response
Flutter Doctor output
Doctor output
[✓] Flutter (Channel stable, 3.47.7, on macOS 26.5.1 25F80 darwin-arm64, locale en-US) [1,606ms]
• Flutter version 3.47.7 on channel stable at ~/fvm/versions/3.47.7
• Upstream repository https://github.com/flutter/flutter.git
• Framework revision abaf9c5237 (10 days ago), 2026-10-08 09:51:21 -0700
• Engine revision deb287481e
• Dart version 3.13.5
• DevTools version 2.60.0
• Feature flags: enable-web, enable-linux-desktop, enable-macos-desktop, enable-windows-desktop, enable-android, enable-ios, cli-animations, enable-native-assets, enable-record-use, enable-swift-package-manager, omit-legacy-version-file, enable-lldb-debugging, enable-uiscene-migration
[✓] Android toolchain - develop for Android devices (Android SDK version 36.1.0) [2.8s]
• Android SDK at ~/Library/Android/sdk
• Emulator version 37.1.11.0 (build_id 15917651) (CL:N/A)
• Platform android-36.1, build-tools 36.1.0
• Java binary at: /Applications/Android Studio.app/Contents/jbr/Contents/Home/bin/java
This is the JDK bundled with the latest Android Studio installation on this machine.
To manually set the JDK path, use: `flutter config --jdk-dir="path/to/jdk"`.
• Java version OpenJDK Runtime Environment (build 25.0.3+-15898627-b508.16)
• All Android licenses accepted.
[✓] Xcode - develop for iOS and macOS (Xcode 26.3) [3.3s]
• Xcode at /Applications/Xcode.app/Contents/Developer
• Build 17C529
• CocoaPods version 1.16.2
[✓] Chrome - develop for the web [19ms]
• Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome
[✓] Connected device (4 available) [15.6s]
• Pixel 7 Pro (mobile) • <redacted> • android-arm64 • Android 17 (API 37)
• iPhone (mobile) • <redacted> • ios • iOS 26.7.1 23H30
• macOS (desktop) • macos • darwin-arm64 • macOS 26.5.1 25F80 darwin-arm64
• Chrome (web) • chrome • web-javascript • Google Chrome 155.0.8059.80
[✓] Network resources [782ms]
• All expected network resources are available.
• No issues found!
Activity
suryaKommana2662 commentedon Oct 20, 2026
@T-Davis Thanks for teh report. I was able to reproduce the issue. In Chrome DevTools Console, the following command returns
es_USinstead of the expectedes-US. Routing this to the accessibility team for further investigation.Flutter Doctor Output
flutter-zl commentedon Oct 21, 2026
flutter-demo-apps/working on/issue_194688_before/. ASemantics(localeForSubtree: Locale('es', 'US'))around aText. Semantics is on at startup.document.querySelector('flt-semantics[lang]').getAttribute('lang')in the console."es_US", andelement.matches(':lang(es)')is false in Chromium. Fixed:"es-US".