[Regression]: Locale silently ignored on Android — toString() emits "zh_TW" but native forLanguageTag() accepts BCP-47 only
Chưa có ai nhận issue này.
Đánh giá
- Độ khó
- 2/5
- Thời gian dự kiến
- 1-3 giờ
- Mức phù hợp với người mới
- 84/100
Hướng nghiên cứu
Bắt đầu tại geocoding_android-5.1.0/lib/src/geocoding_android.dart:164 và so sánh mã định danh locale với android/src/main/kotlin/com/baseflow/geocoding/proxies/LocaleProxyApi.kt:17. Kiểm tra các bài kiểm thử package hiện có, sau đó xác minh rằng các locale quốc gia và script được truyền đến native API dưới dạng các thẻ BCP-47 hợp lệ, đồng thời vẫn giữ nguyên khả năng bản địa hóa của Android mà không ảnh hưởng đến iOS.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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
- Ngôn ngữ chính
- Dart
- Star
- 153
- Fork
- 92
- Chỉ số merge pull request
- Không có pull request nào được merge trong 30 ngày
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của Baseflow/flutter-geocoding
-
Độ khó 1/5 1-3 giờ Mức phù hợp với người mới 84/100
Baseflow/flutter-geocoding#311 ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 38/100
Baseflow/flutter-geocoding#287 · 1 bình luận ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
Baseflow/flutter-geocoding#286 · 2 bình luận ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
Baseflow/flutter-geocoding#257 · 2 bình luận ·
-
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 25/100
Baseflow/flutter-geocoding#247 · 1 bình luận · 1 reaction ·
Tất cả issue của Baseflow/flutter-geocoding
Issue tương tự
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
code quality good first issue
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 90/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
Suwayomi/Suwayomi-Tsumiru#479 ·
-
Build Failure: agora_rtc_engine compiled against android-31 while dependencies require android-34+ Đang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 92/100
conceptadev/noir#95 ·