From 77eed91b8e4f6a915968bc076a4b43e6107e64e5 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 | 24 ++++++++++++++++++++++++ 2 files changed, 25 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..695979f4b 100644 --- a/python/tests/geocodertest.py +++ b/python/tests/geocodertest.py @@ -178,6 +178,30 @@ 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): + # When a longer prefix exists in the geocoding data but lacks the requested + # language, the lookup must continue to shorter prefixes rather than returning + # empty immediately. 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)