mirror of
https://github.com/agessaman/meshcore-bot.git
synced 2026-09-13 11:25:55 +00:00
feat(i18n): localize gwx output (wind, humidity, dew point, visibility, pressure, day names)
This commit is contained in:
@@ -1055,16 +1055,19 @@ class GlobalWxCommand(BaseCommand):
|
||||
|
||||
# Add feels like if significantly different
|
||||
if abs(feels_like - temp) >= 5:
|
||||
weather += f" (feels {feels_like}{temp_symbol})"
|
||||
feels_str = self.translate('commands.gwx.feels_like', value=feels_like, unit=temp_symbol)
|
||||
weather += f" {feels_str}"
|
||||
|
||||
# Add wind info (always show if >= 3 mph, show gusts if significant)
|
||||
if wind_speed >= 3:
|
||||
weather += f" {wind_direction}{wind_speed}"
|
||||
if wind_gusts > wind_speed + 3:
|
||||
weather += f"G{wind_gusts}"
|
||||
gust_str = self.translate('commands.gwx.gust', value=wind_gusts)
|
||||
weather += gust_str
|
||||
|
||||
# Add humidity
|
||||
weather += f" {humidity}%RH"
|
||||
humidity_str = self.translate('commands.gwx.humidity', value=humidity)
|
||||
weather += f" {humidity_str}"
|
||||
|
||||
# Add additional conditions if space allows
|
||||
conditions = []
|
||||
@@ -1072,7 +1075,8 @@ class GlobalWxCommand(BaseCommand):
|
||||
# Add dew point
|
||||
if dewpoint is not None:
|
||||
dewpoint_val = int(dewpoint)
|
||||
conditions.append(f"💧{dewpoint_val}{temp_symbol}")
|
||||
dew_str = self.translate('commands.gwx.dew_point', value=dewpoint_val, unit=temp_symbol)
|
||||
conditions.append(dew_str)
|
||||
|
||||
# Add visibility (already converted to miles above)
|
||||
if visibility_mi is not None and visibility_mi > 0:
|
||||
@@ -1080,12 +1084,14 @@ class GlobalWxCommand(BaseCommand):
|
||||
visibility_display = int(visibility_mi)
|
||||
if visibility_display > 20:
|
||||
visibility_display = 20
|
||||
conditions.append(f"👁️{visibility_display}mi")
|
||||
vis_str = self.translate('commands.gwx.visibility', value=visibility_display)
|
||||
conditions.append(vis_str)
|
||||
|
||||
# Add pressure (convert from hPa to display format)
|
||||
if pressure is not None:
|
||||
pressure_hpa = int(pressure)
|
||||
conditions.append(f"📊{pressure_hpa}hPa")
|
||||
press_str = self.translate('commands.gwx.pressure', value=pressure_hpa)
|
||||
conditions.append(press_str)
|
||||
|
||||
# Add conditions to weather string if space allows
|
||||
# Reserve space for forecast data (high/low and tomorrow)
|
||||
@@ -1177,7 +1183,8 @@ class GlobalWxCommand(BaseCommand):
|
||||
if len(daily.get('wind_gusts_10m_max', [])) > 1:
|
||||
wind_gusts = int(daily['wind_gusts_10m_max'][1])
|
||||
if wind_gusts > wind_speed + 3:
|
||||
wind_info += f"G{wind_gusts}"
|
||||
gust_str = self.translate('commands.gwx.gust', value=wind_gusts)
|
||||
wind_info += gust_str
|
||||
|
||||
# Get precipitation probability and amount
|
||||
precip_info = ""
|
||||
@@ -1231,13 +1238,13 @@ class GlobalWxCommand(BaseCommand):
|
||||
|
||||
# Map day names to 1-2 letter abbreviations
|
||||
day_abbrev_map = {
|
||||
'Monday': 'M',
|
||||
'Tuesday': 'T',
|
||||
'Wednesday': 'W',
|
||||
'Thursday': 'Th',
|
||||
'Friday': 'F',
|
||||
'Saturday': 'Sa',
|
||||
'Sunday': 'Su'
|
||||
'Monday': self.translate('commands.gwx.day_abbrev.Monday'),
|
||||
'Tuesday': self.translate('commands.gwx.day_abbrev.Tuesday'),
|
||||
'Wednesday': self.translate('commands.gwx.day_abbrev.Wednesday'),
|
||||
'Thursday': self.translate('commands.gwx.day_abbrev.Thursday'),
|
||||
'Friday': self.translate('commands.gwx.day_abbrev.Friday'),
|
||||
'Saturday': self.translate('commands.gwx.day_abbrev.Saturday'),
|
||||
'Sunday': self.translate('commands.gwx.day_abbrev.Sunday')
|
||||
}
|
||||
|
||||
parts = []
|
||||
@@ -1360,20 +1367,24 @@ class GlobalWxCommand(BaseCommand):
|
||||
if degrees is None:
|
||||
return ""
|
||||
|
||||
directions = [
|
||||
(0, "⬆️N"), (22.5, "↗️NE"), (45, "↗️NE"), (67.5, "➡️E"),
|
||||
(90, "➡️E"), (112.5, "↘️SE"), (135, "↘️SE"), (157.5, "⬇️S"),
|
||||
(180, "⬇️S"), (202.5, "↙️SW"), (225, "↙️SW"), (247.5, "⬅️W"),
|
||||
(270, "⬅️W"), (292.5, "↖️NW"), (315, "↖️NW"), (337.5, "⬆️N"),
|
||||
(360, "⬆️N")
|
||||
dir_emojis = [
|
||||
(0, "⬆️", "N"), (22.5, "↗️", "NE"), (45, "↗️", "NE"), (67.5, "➡️", "E"),
|
||||
(90, "➡️", "E"), (112.5, "↘️", "SE"), (135, "↘️", "SE"), (157.5, "⬇️", "S"),
|
||||
(180, "⬇️", "S"), (202.5, "↙️", "SW"), (225, "↙️", "SW"), (247.5, "⬅️", "W"),
|
||||
(270, "⬅️", "W"), (292.5, "↖️", "NW"), (315, "↖️", "NW"), (337.5, "⬆️", "N"),
|
||||
(360, "⬆️", "N")
|
||||
]
|
||||
|
||||
# Find closest direction
|
||||
for i in range(len(directions) - 1):
|
||||
if directions[i][0] <= degrees < directions[i + 1][0]:
|
||||
return directions[i][1]
|
||||
for i in range(len(dir_emojis) - 1):
|
||||
if dir_emojis[i][0] <= degrees < dir_emojis[i + 1][0]:
|
||||
emoji, key = dir_emojis[i][1], dir_emojis[i][2]
|
||||
translated = self.translate(f"services.weather_service.wind_directions.{key}")
|
||||
return f"{emoji}{translated}"
|
||||
|
||||
return "⬆️N" # Default to North
|
||||
emoji, key = dir_emojis[-1][1], dir_emojis[-1][2]
|
||||
translated = self.translate(f"services.weather_service.wind_directions.{key}")
|
||||
return f"{emoji}{translated}"
|
||||
|
||||
def _get_weather_description(self, code: int) -> str:
|
||||
"""Convert WMO weather code to description.
|
||||
|
||||
+33
-18
@@ -232,24 +232,39 @@
|
||||
"mqtt_weather_stale": "MQTT weather data is too old",
|
||||
"mqtt_weather_payload_error": "MQTT weather payload error: {detail}"
|
||||
},
|
||||
"gwx": {
|
||||
"description": "Get weather information for any global location (usage: gwx Tokyo)",
|
||||
"help": "Usage: gwx <location> - Get weather for any global location (city, country, or coordinates)",
|
||||
"usage": "Usage: gwx <location> - Example: gwx Tokyo or gwx Paris, France",
|
||||
"error_fetching": "Error fetching weather data",
|
||||
"error_fetching_api": "Error fetching weather data from Open-Meteo",
|
||||
"no_location": "Could not find location '{location}'",
|
||||
"error": "Error getting weather data: {error}",
|
||||
"tomorrow_not_available": "Tomorrow's forecast not available",
|
||||
"tomorrow_error": "Error formatting tomorrow's forecast",
|
||||
"multiday_not_available": "{num_days}-day forecast not available",
|
||||
"multiday_error": "Error formatting {num_days}-day forecast",
|
||||
"mqtt_forecast_not_supported": "Extended forecast is not available for MQTT weather sources",
|
||||
"mqtt_weather_no_subscriber": "MQTT weather subscriber is not active (enable [MqttWeather] and custom.mqtt_weather.* topics)",
|
||||
"mqtt_weather_no_data": "No MQTT weather message received for this topic yet",
|
||||
"mqtt_weather_stale": "MQTT weather data is too old",
|
||||
"mqtt_weather_payload_error": "MQTT weather payload error: {detail}",
|
||||
"periods": {
|
||||
"gwx": {
|
||||
"description": "Get weather for any worldwide location (use: gwx Tokyo)",
|
||||
"help": "Usage: gwx <location> - Weather for any location worldwide (city, country, or coordinates)",
|
||||
"usage": "Usage: gwx <location> - Example: gwx Tokyo or gwx Paris, France",
|
||||
"error_fetching": "Error fetching weather data",
|
||||
"error_fetching_api": "Error fetching weather data from Open-Meteo",
|
||||
"no_location": "Could not find location '{location}'",
|
||||
"error": "Error fetching weather data: {error}",
|
||||
"tomorrow_not_available": "Tomorrow forecast not available",
|
||||
"tomorrow_error": "Error formatting tomorrow forecast",
|
||||
"multiday_not_available": "{num_days}-day forecast not available",
|
||||
"multiday_error": "Error formatting {num_days}-day forecast",
|
||||
"mqtt_forecast_not_supported": "Extended forecast not supported for MQTT weather sources",
|
||||
"mqtt_weather_no_subscriber": "MQTT weather subscriber not active",
|
||||
"mqtt_weather_no_data": "MQTT weather message not yet received",
|
||||
"mqtt_weather_stale": "MQTT weather data is stale",
|
||||
"mqtt_weather_payload_error": "MQTT weather payload error: {detail}",
|
||||
"feels_like": "(feels {value}{unit})",
|
||||
"humidity": "{value}%RH",
|
||||
"dew_point": "💧{value}{unit}",
|
||||
"visibility": "👁️{value}mi",
|
||||
"pressure": "📊{value}hPa",
|
||||
"gust": "G{value}",
|
||||
"day_abbrev": {
|
||||
"Monday": "M",
|
||||
"Tuesday": "T",
|
||||
"Wednesday": "W",
|
||||
"Thursday": "Th",
|
||||
"Friday": "F",
|
||||
"Saturday": "Sa",
|
||||
"Sunday": "Su"
|
||||
},
|
||||
"periods": {
|
||||
"today": "Today",
|
||||
"tonight": "Tonight",
|
||||
"tomorrow": "Tomorrow"
|
||||
|
||||
+37
-22
@@ -84,28 +84,43 @@
|
||||
"mqtt_weather_stale": "Данные MQTT-погоды слишком старые",
|
||||
"mqtt_weather_payload_error": "Ошибка полезной нагрузки MQTT-погоды: {detail}"
|
||||
},
|
||||
"gwx": {
|
||||
"description": "Получить погоду для любой точки мира (использование: gwx Tokyo)",
|
||||
"help": "Использование: gwx <локация> - Погода для любой точки мира (город, страна или координаты)",
|
||||
"usage": "Использование: gwx <локация> - Пример: gwx Tokyo или gwx Paris, France",
|
||||
"error_fetching": "Ошибка получения данных погоды",
|
||||
"error_fetching_api": "Ошибка получения данных погоды из Open-Meteo",
|
||||
"no_location": "Не удалось найти локацию '{location}'",
|
||||
"error": "Ошибка получения данных погоды: {error}",
|
||||
"tomorrow_not_available": "Прогноз на завтра недоступен",
|
||||
"tomorrow_error": "Ошибка форматирования прогноза на завтра",
|
||||
"multiday_not_available": "Прогноз на {num_days} дней недоступен",
|
||||
"multiday_error": "Ошибка форматирования прогноза на {num_days} дней",
|
||||
"mqtt_forecast_not_supported": "Расширенный прогноз недоступен для MQTT-источников погоды",
|
||||
"mqtt_weather_no_subscriber": "MQTT-подписчик погоды не активен",
|
||||
"mqtt_weather_no_data": "Сообщение MQTT-погоды ещё не получено",
|
||||
"mqtt_weather_stale": "Данные MQTT-погоды устарели",
|
||||
"mqtt_weather_payload_error": "Ошибка полезной нагрузки MQTT: {detail}",
|
||||
"periods": {
|
||||
"today": "Сегодня",
|
||||
"tonight": "Сегодня ночью",
|
||||
"tomorrow": "Завтра"
|
||||
},
|
||||
"gwx": {
|
||||
"description": "Получить погоду для любой точки мира (использование: gwx Tokyo)",
|
||||
"help": "Использование: gwx <локация> - Погода для любой точки мира (город, страна или координаты)",
|
||||
"usage": "Использование: gwx <локация> - Пример: gwx Tokyo или gwx Paris, France",
|
||||
"error_fetching": "Ошибка получения данных погоды",
|
||||
"error_fetching_api": "Ошибка получения данных погоды из Open-Meteo",
|
||||
"no_location": "Не удалось найти локацию '{location}'",
|
||||
"error": "Ошибка получения данных погоды: {error}",
|
||||
"tomorrow_not_available": "Прогноз на завтра недоступен",
|
||||
"tomorrow_error": "Ошибка форматирования прогноза на завтра",
|
||||
"multiday_not_available": "Прогноз на {num_days} дней недоступен",
|
||||
"multiday_error": "Ошибка форматирования прогноза на {num_days} дней",
|
||||
"mqtt_forecast_not_supported": "Расширенный прогноз недоступен для MQTT-источников погоды",
|
||||
"mqtt_weather_no_subscriber": "MQTT-подписчик погоды не активен",
|
||||
"mqtt_weather_no_data": "Сообщение MQTT-погоды ещё не получено",
|
||||
"mqtt_weather_stale": "Данные MQTT-погоды устарели",
|
||||
"mqtt_weather_payload_error": "Ошибка полезной нагрузки MQTT: {detail}",
|
||||
"feels_like": "(ош.{value}{unit})",
|
||||
"humidity": "{value}%",
|
||||
"dew_point": "💧{value}{unit}",
|
||||
"visibility": "👁️{value}миль",
|
||||
"pressure": "📊{value}гПа",
|
||||
"gust": "G{value}",
|
||||
"day_abbrev": {
|
||||
"Monday": "Пн",
|
||||
"Tuesday": "Вт",
|
||||
"Wednesday": "Ср",
|
||||
"Thursday": "Чт",
|
||||
"Friday": "Пт",
|
||||
"Saturday": "Сб",
|
||||
"Sunday": "Вс"
|
||||
},
|
||||
"periods": {
|
||||
"today": "Сегодня",
|
||||
"tonight": "Сегодня ночью",
|
||||
"tomorrow": "Завтра"
|
||||
},
|
||||
"weather_descriptions": {
|
||||
"0": "Ясно",
|
||||
"1": "Преимущественно ясно",
|
||||
|
||||
Reference in New Issue
Block a user