[Regression]: Locale silently ignored on Android — toString() emits "zh_TW" but native forLanguageTag() accepts BCP-47 only
Nessuno ha ancora preso questa issue.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 84/100
Direzione di ricerca
Inizia da geocoding_android-5.1.0/lib/src/geocoding_android.dart:164 e confronta l’identificatore della locale con android/src/main/kotlin/com/baseflow/geocoding/proxies/LocaleProxyApi.kt:17. Controlla i test esistenti del package, quindi verifica che le locale di paese e di script raggiungano l’API nativa come tag BCP-47 validi e che la localizzazione Android venga preservata senza influire su iOS.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
Is there an existing issue for this?
- I have searched the existing issues — found none covering this.
Affected platform(s)
- Android
- iOS
Old behavior
On geocoding_android 4.x, passing a Locale with a country subtag worked: the returned placemarks were localized to that locale. The native side converted the identifier manually (LocaleConverter.java, splitting the string on _), which accepted the underscore form that the Dart side produces.
Current behavior
On geocoding_android 5.x the locale is silently ignored — results come back in the device's default language. The call succeeds, no exception, nothing observable at the call site.
Root cause is a mismatch between the producer and the consumer of the identifier string.
Dart side serializes with toString():
// geocoding_android-5.1.0/lib/src/geocoding_android.dart:164
final Locale? nativeLocale =
locale != null ? Locale(identifier: locale.toString()) : null;
Flutter's Locale.toString() joins subtags with an underscore — Locale('zh','TW').toString() == "zh_TW".
Native side parses with forLanguageTag():
// geocoding_android/android/src/main/kotlin/com/baseflow/geocoding/proxies/LocaleProxyApi.kt:17
return Locale.forLanguageTag(identifier);
Locale.forLanguageTag accepts BCP-47 only. Per the Javadoc: "If the specified language tag contains any ill-formed subtags, the first such subtag and all following subtags are ignored." zh_TW is a single ill-formed subtag, so the entire tag is dropped and an empty (und) Locale is returned.
Verified on JDK 21:
forLanguageTag("zh_TW") -> language="" country="" toLanguageTag="und"
forLanguageTag("zh-TW") -> language="zh" country="TW" toLanguageTag="zh-TW"
forLanguageTag("zh_Hant_TW") -> language="" country="" toLanguageTag="und"
forLanguageTag("en_US") -> language="" country="" toLanguageTag="und"
Note that GeocoderProxyApi passes this non-null but empty Locale straight to Geocoder(context, locale), so it does not fall back to the null-locale path — the request goes out with an undetermined locale.
This affects every locale carrying a country or script subtag (en_US, pt_BR, zh_Hant_TW, …). A language-only locale such as Locale('ja') happens to still work, since "ja" is already a well-formed tag.
Side note: the README still documents the identifier format as [languageCode]_[countryCode] (underscore) — which is now precisely the form that fails.
Steps to reproduce
- On Android, set the device language to something other than the locale you are about to request (e.g. device in English).
- Call
placemarkFromCoordinates(lat, lng, locale: const Locale('zh', 'TW'))— any locale with a country subtag reproduces it. - Observe the returned
Placemarkfields: they are in the device language, not the requested one. No error is raised. - Repeat with
const Locale('zh-TW')(single subtag, sotoString()already yields a hyphen) — the result is correctly localized.
Code sample
Code sample
// Ignored on Android (serializes to "zh_TW" -> forLanguageTag -> und):
final ignored = await Geocoding().placemarkFromCoordinates(
25.0330, 121.5654,
locale: const Locale('zh', 'TW'),
);
// Honored (serializes to "zh-TW"):
final honored = await Geocoding().placemarkFromCoordinates(
25.0330, 121.5654,
locale: const Locale('zh-TW'),
);
Suggested fix
Serialize with toLanguageTag() instead of toString() on the Dart side:
Locale(identifier: locale.toLanguageTag()) // "zh-TW"
toLanguageTag() emits exactly BCP-47, which is what forLanguageTag expects. One line, no native change required.
iOS is unaffected either way — geocoding_darwin uses Locale(identifier:), and Foundation parses "zh_TW" and "zh-TW" identically (verified on macOS: both yield language=zh region=TW). So switching to toLanguageTag() is safe for both platforms.
Workaround for users
Pass the tag as a single-subtag Dart Locale, so that toString() already produces the hyphenated form:
const Locale('zh-TW') // toString() == "zh-TW" -> honored
const Locale('zh', 'TW') // toString() == "zh_TW" -> silently ignored
Current version
geocoding: 5.0.0 / geocoding_android: 5.1.0 (latest at time of writing) / geocoding_platform_interface: 5.0.0. Still present on main.
Last version without regression
geocoding_android: 4.0.1
- Lingua principale
- Dart
- Stelle
- 153
- Fork
- 92
- Metriche di merge delle PR
- Nessuna PR unita negli ultimi 30g
Guida per i contributori
Apri la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di Baseflow/flutter-geocoding
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 84/100
Baseflow/flutter-geocoding#311 ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 38/100
Baseflow/flutter-geocoding#287 · 1 commento ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
Baseflow/flutter-geocoding#286 · 2 commenti ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 35/100
Baseflow/flutter-geocoding#257 · 2 commenti ·
-
Difficoltà 4/5 3-5 giorni Idoneità per principianti 25/100
Baseflow/flutter-geocoding#247 · 1 commento · 1 reazione ·
Tutte le issue di Baseflow/flutter-geocoding
Issue simili
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
code quality good first issue
Difficoltà 2/5 1-3 ore Idoneità per principianti 90/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
Suwayomi/Suwayomi-Tsumiru#479 ·
-
Build Failure: agora_rtc_engine compiled against android-31 while dependencies require android-34+ Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 72/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 92/100
conceptadev/noir#95 ·