From 34ff9e976c2f1ae8c3ff93b06086a70d08d46049 Mon Sep 17 00:00:00 2001 From: Vincent Gao Date: Thu, 25 Jun 2026 14:08:30 +0200 Subject: [PATCH] Fix geocoder returning empty when longer prefix lacks requested language MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit _prefix_description_for_number immediately returned an empty string when a longer prefix was found in the geocoding data but did not carry an entry for the requested language. This prevented the loop from trying shorter (less specific) prefixes that do have the language data. For example, Finnish Helsinki-area numbers (+3589x…) were mapped to 'Finland' rather than 'Helsinki' when English or Finnish was requested, because the 5-digit prefix '35891' exists with only a Swedish ('se') entry while the 4-digit prefix '3589' carries 'en', 'fi', and 'sv' data. Fix: instead of returning U_EMPTY_STRING when _find_lang yields None, allow the loop to continue to shorter prefixes. Add a regression test that drives this path using synthetic test geodata so that the fix is verifiable without depending on the full production data files. --- python/phonenumbers/prefix.py | 3 +-- python/tests/geocodertest.py | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 2 deletions(-) diff --git a/python/phonenumbers/prefix.py b/python/phonenumbers/prefix.py index 0e3680efa..04a82dee4 100644 --- a/python/phonenumbers/prefix.py +++ b/python/phonenumbers/prefix.py @@ -85,6 +85,5 @@ def _prefix_description_for_number(data, longest_prefix, numobj, lang, script=No name = _find_lang(data[prefix], lang, script, region) if name is not None: return name - else: - return U_EMPTY_STRING + # Language not available for this prefix; try a less-specific (shorter) prefix. return U_EMPTY_STRING diff --git a/python/tests/geocodertest.py b/python/tests/geocodertest.py index 755d96e0e..c208827c4 100644 --- a/python/tests/geocodertest.py +++ b/python/tests/geocodertest.py @@ -178,6 +178,29 @@ def testGetDescriptionForNonGeographicalNumberWithGeocodingPrefix(self): # We have a geocoding prefix, but we shouldn't use it since this is not geographical. self.assertEqual("South Korea", description_for_number(KO_MOBILE, _ENGLISH)) + def testPrefixFallsBackToShorterPrefixWhenLanguageMissing(self): + # Python version extra test - this has no equivalent Java test. + # This can occur when only a subset of sub-prefixes carry alternative-language + # entries for a region. + # + # Simulate: '1212' has 'en', '12123' exists only for 'de'. + # Asking for 'fr' on a number whose digits start with 12123 should fall back + # to '1212' and return the English name (since French falls back to English), + # not the empty string from '12123'. + TEST_GEOCODE_DATA['12123'] = {'de': u("TestDistrict")} + try: + # US_NUMBER3 is +1 212-812-0000; its prefix digits start with '12128' so + # it won't hit '12123'. Use a fabricated number whose digits begin '12123'. + test_num = FrozenPhoneNumber(country_code=1, national_number=2123000000) + # '12123' has no 'fr', '1212' has 'en' -> French should fall back to 'NY' + self.assertEqual("NY", _prefix_description_for_number( + TEST_GEOCODE_DATA, TEST_GEOCODE_LONGEST_PREFIX, test_num, "fr")) + # 'de' is directly present in '12123', so German gets the detailed name + self.assertEqual("TestDistrict", _prefix_description_for_number( + TEST_GEOCODE_DATA, TEST_GEOCODE_LONGEST_PREFIX, test_num, "de")) + finally: + del TEST_GEOCODE_DATA['12123'] + def testCoverage(self): # Python version extra tests invalid_number = PhoneNumber(country_code=210, national_number=123456)