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)