From 4e7c1909eee62d726ada073f65ab6d8ea4b2239a Mon Sep 17 00:00:00 2001 From: Sam Date: Mon, 2 Mar 2026 17:51:56 +0100 Subject: [PATCH] =?UTF-8?q?Fix=20country=20matching:=20English=E2=86=92ISO?= =?UTF-8?q?=20code=20lookup=20for=20geocoding?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "Rab,Croatia" now correctly matches Croatia (HR) instead of Rabat (Morocco). Added country code mapping for common English and German country names. Co-Authored-By: Claude Opus 4.6 --- server/services/weather_service.py | 65 +++++++++++++++++++++++++++++- 1 file changed, 63 insertions(+), 2 deletions(-) diff --git a/server/services/weather_service.py b/server/services/weather_service.py index 9552530..bf9cad9 100644 --- a/server/services/weather_service.py +++ b/server/services/weather_service.py @@ -67,6 +67,49 @@ def _wmo_description(code: int) -> str: _geocode_cache: Dict[str, Dict[str, Any]] = {} +# Common English country names → ISO 3166-1 alpha-2 codes +# (Open-Meteo returns German names, so we need this for English→code matching) +_COUNTRY_CODES: Dict[str, str] = { + "croatia": "hr", "kroatien": "hr", + "germany": "de", "deutschland": "de", + "austria": "at", "österreich": "at", + "switzerland": "ch", "schweiz": "ch", + "france": "fr", "frankreich": "fr", + "italy": "it", "italien": "it", + "spain": "es", "spanien": "es", + "portugal": "pt", + "greece": "gr", "griechenland": "gr", + "turkey": "tr", "türkei": "tr", + "netherlands": "nl", "niederlande": "nl", + "belgium": "be", "belgien": "be", + "poland": "pl", "polen": "pl", + "czech republic": "cz", "tschechien": "cz", + "hungary": "hu", "ungarn": "hu", + "romania": "ro", "rumänien": "ro", + "bulgaria": "bg", "bulgarien": "bg", + "sweden": "se", "schweden": "se", + "norway": "no", "norwegen": "no", + "denmark": "dk", "dänemark": "dk", + "finland": "fi", "finnland": "fi", + "uk": "gb", "united kingdom": "gb", "england": "gb", + "usa": "us", "united states": "us", + "canada": "ca", "kanada": "ca", + "australia": "au", "australien": "au", + "japan": "jp", + "china": "cn", + "india": "in", "indien": "in", + "brazil": "br", "brasilien": "br", + "mexico": "mx", "mexiko": "mx", + "morocco": "ma", "marokko": "ma", + "egypt": "eg", "ägypten": "eg", + "thailand": "th", + "indonesia": "id", "indonesien": "id", + "slovenia": "si", "slowenien": "si", + "serbia": "rs", "serbien": "rs", + "montenegro": "me", + "bosnia": "ba", "bosnien": "ba", +} + async def _geocode(location: str) -> Optional[Dict[str, Any]]: """Resolve a city name to lat/lon using Open-Meteo Geocoding API. @@ -108,13 +151,31 @@ async def _geocode(location: str) -> Optional[Dict[str, Any]]: # If country hint provided, try to find a matching result best = results[0] if country_hint: + hint = country_hint.lower() + # Resolve English country names to ISO codes for matching + hint_code = _COUNTRY_CODES.get(hint, hint[:2]) + + matched = False for r in results: country = (r.get("country", "") or "").lower() country_code = (r.get("country_code", "") or "").lower() - if country_hint in country or country_hint == country_code: + # Match: hint in DE name, DE name in hint, ISO code, or exact city name + if (hint in country or country in hint + or hint_code == country_code + or hint == country_code): best = r + matched = True break - else: + + if not matched: + # Prefer an exact city name match over the first result + for r in results: + if r.get("name", "").lower() == city_name.lower(): + best = r + matched = True + break + + if not matched: logger.warning("[WEATHER] Country '%s' not found in results for '%s', using first match", country_hint, city_name)