Skip to content

Commit 89a3721

Browse files
CopilotBaloMueller
andauthored
Merge PR fatihak#670 from upstream (weather localization support)
# Conflicts: # src/plugins/weather/settings.html # src/plugins/weather/weather.py Co-authored-by: BaloMueller <793558+BaloMueller@users.noreply.github.com>
2 parents 0a605dd + c41997b commit 89a3721

3 files changed

Lines changed: 200 additions & 2 deletions

File tree

src/plugins/weather/render/weather.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@
3838
<div class="data-point-label">{{ dp.label }}</div>
3939
<div class="data-point-measurement">
4040
{{ dp.measurement }}{% if dp.unit %}<span class="data-point-unit">{{ dp.unit }}</span>{% endif %}
41-
{% if dp.label == "Wind" %}
41+
{% if dp.key == "Wind" %}
4242
<span class="wind-arrow-symbol">{{ dp.arrow }}</span>
4343
{% endif %}
4444
</div>

src/plugins/weather/settings.html

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,20 @@
11
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
22
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
33

4+
<div class="form-group">
5+
<label for="language" class="form-label">Language:</label>
6+
<select id="language" name="language" class="form-input">
7+
<option value="nl">Dutch</option>
8+
<option value="en">English</option>
9+
<option value="fr">French</option>
10+
<option value="de">German</option>
11+
<option value="id">Indonesian</option>
12+
<option value="it">Italian</option>
13+
<option value="pt">Portuguese</option>
14+
<option value="es">Spanish</option>
15+
</select>
16+
</div>
17+
418
<div class="form-group">
519
<label class="form-label">Location: </label>
620
<div class="form-group">
@@ -289,6 +303,12 @@ <h2 id="modalTitle">Select Location</h2>
289303
});
290304

291305
if (loadPluginSettings) {
306+
const language = document.getElementById('language');
307+
const hasConfiguredLanguage = Array.from(language.options).some(
308+
(option) => option.value === pluginSettings.language
309+
);
310+
language.value = hasConfiguredLanguage ? pluginSettings.language : 'en';
311+
292312
document.getElementById('latitude').value = pluginSettings.latitude ?? '';
293313
document.getElementById('longitude').value = pluginSettings.longitude ?? '';
294314

@@ -326,6 +346,7 @@ <h2 id="modalTitle">Select Location</h2>
326346
document.getElementById('customTitle').value = pluginSettings.customTitle || '';
327347
} else {
328348
// set default values
349+
document.getElementById('language').value = 'en';
329350
document.getElementById('units').value = "imperial";
330351
document.getElementById('language').value = "en";
331352
document.getElementById('displayRefreshTime').checked = true;

src/plugins/weather/weather.py

Lines changed: 178 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,181 @@ def get_moon_phase_name(phase_age: float) -> str:
6464
"imperial": "temperature_unit=fahrenheit&wind_speed_unit=mph&precipitation_unit=inch"
6565
}
6666

67+
# Locale data for date/day name translation.
68+
# days: full weekday names (0=Monday), days_short: abbreviated (0=Monday),
69+
# months: full month names (0=January).
70+
# ui: translated UI strings used in the weather template and data points.
71+
# "en": None uses strftime/English directly.
72+
LOCALE_DATA = {
73+
"de": {
74+
"days": ["Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag", "Sonntag"],
75+
"days_short": ["Mo", "Di", "Mi", "Do", "Fr", "Sa", "So"],
76+
"months": ["Januar", "Februar", "März", "April", "Mai", "Juni",
77+
"Juli", "August", "September", "Oktober", "November", "Dezember"],
78+
"ui": {
79+
"last_refresh": "Letzte Aktualisierung",
80+
"feels_like": "Gefühlt",
81+
"sunrise": "Sonnenaufgang",
82+
"sunset": "Sonnenuntergang",
83+
"wind": "Wind",
84+
"humidity": "Luftfeuchtigkeit",
85+
"pressure": "Luftdruck",
86+
"uv_index": "UV-Index",
87+
"visibility": "Sichtweite",
88+
"air_quality": "Luftqualität",
89+
"aqi_scale": ["Gut", "Mäßig", "Mittelmäßig", "Schlecht", "Sehr schlecht"],
90+
"aqi_scale_om": ["Gut", "Mäßig", "Mittelmäßig", "Schlecht", "Sehr schlecht", "Extrem schlecht"],
91+
},
92+
},
93+
"en": None, # English uses strftime directly
94+
"es": {
95+
"days": ["Lunes", "Martes", "Miércoles", "Jueves", "Viernes", "Sábado", "Domingo"],
96+
"days_short": ["Lun", "Mar", "Mié", "Jue", "Vie", "Sáb", "Dom"],
97+
"months": ["Enero", "Febrero", "Marzo", "Abril", "Mayo", "Junio",
98+
"Julio", "Agosto", "Septiembre", "Octubre", "Noviembre", "Diciembre"],
99+
"ui": {
100+
"last_refresh": "Última actualización",
101+
"feels_like": "Sensación",
102+
"sunrise": "Amanecer",
103+
"sunset": "Atardecer",
104+
"wind": "Viento",
105+
"humidity": "Humedad",
106+
"pressure": "Presión",
107+
"uv_index": "Índice UV",
108+
"visibility": "Visibilidad",
109+
"air_quality": "Calidad aire",
110+
"aqi_scale": ["Buena", "Aceptable", "Moderada", "Mala", "Muy mala"],
111+
"aqi_scale_om": ["Buena", "Aceptable", "Moderada", "Mala", "Muy mala", "Extrema"],
112+
},
113+
},
114+
"fr": {
115+
"days": ["Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi", "Samedi", "Dimanche"],
116+
"days_short": ["Lun", "Mar", "Mer", "Jeu", "Ven", "Sam", "Dim"],
117+
"months": ["Janvier", "Février", "Mars", "Avril", "Mai", "Juin",
118+
"Juillet", "Août", "Septembre", "Octobre", "Novembre", "Décembre"],
119+
"ui": {
120+
"last_refresh": "Dernière mise à jour",
121+
"feels_like": "Ressenti",
122+
"sunrise": "Lever du soleil",
123+
"sunset": "Coucher du soleil",
124+
"wind": "Vent",
125+
"humidity": "Humidité",
126+
"pressure": "Pression",
127+
"uv_index": "Indice UV",
128+
"visibility": "Visibilité",
129+
"air_quality": "Qualité de l'air",
130+
"aqi_scale": ["Bonne", "Correcte", "Moyenne", "Mauvaise", "Très mauvaise"],
131+
"aqi_scale_om": ["Bonne", "Correcte", "Moyenne", "Mauvaise", "Très mauvaise", "Extrêmement mauvaise"],
132+
},
133+
},
134+
"id": {
135+
"days": ["Senin", "Selasa", "Rabu", "Kamis", "Jumat", "Sabtu", "Minggu"],
136+
"days_short": ["Sen", "Sel", "Rab", "Kam", "Jum", "Sab", "Min"],
137+
"months": ["Januari", "Februari", "Maret", "April", "Mei", "Juni",
138+
"Juli", "Agustus", "September", "Oktober", "November", "Desember"],
139+
"ui": {
140+
"last_refresh": "Pembaruan terakhir",
141+
"feels_like": "Terasa",
142+
"sunrise": "Matahari terbit",
143+
"sunset": "Matahari terbenam",
144+
"wind": "Angin",
145+
"humidity": "Kelembaban",
146+
"pressure": "Tekanan",
147+
"uv_index": "Indeks UV",
148+
"visibility": "Jarak pandang",
149+
"air_quality": "Kualitas udara",
150+
"aqi_scale": ["Baik", "Sedang", "Buruk ringan", "Buruk", "Sangat buruk"],
151+
"aqi_scale_om": ["Baik", "Sedang", "Buruk ringan", "Buruk", "Sangat buruk", "Berbahaya"],
152+
},
153+
},
154+
"it": {
155+
"days": ["Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato", "Domenica"],
156+
"days_short": ["Lun", "Mar", "Mer", "Gio", "Ven", "Sab", "Dom"],
157+
"months": ["Gennaio", "Febbraio", "Marzo", "Aprile", "Maggio", "Giugno",
158+
"Luglio", "Agosto", "Settembre", "Ottobre", "Novembre", "Dicembre"],
159+
"ui": {
160+
"last_refresh": "Ultimo aggiornamento",
161+
"feels_like": "Percepita",
162+
"sunrise": "Alba",
163+
"sunset": "Tramonto",
164+
"wind": "Vento",
165+
"humidity": "Umidità",
166+
"pressure": "Pressione",
167+
"uv_index": "Indice UV",
168+
"visibility": "Visibilità",
169+
"air_quality": "Qualità aria",
170+
"aqi_scale": ["Buona", "Discreta", "Moderata", "Scarsa", "Pessima"],
171+
"aqi_scale_om": ["Buona", "Discreta", "Moderata", "Scarsa", "Pessima", "Pericolosa"],
172+
},
173+
},
174+
"nl": {
175+
"days": ["Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag", "Zondag"],
176+
"days_short": ["Ma", "Di", "Wo", "Do", "Vr", "Za", "Zo"],
177+
"months": ["Januari", "Februari", "Maart", "April", "Mei", "Juni",
178+
"Juli", "Augustus", "September", "Oktober", "November", "December"],
179+
"ui": {
180+
"last_refresh": "Laatste verversing",
181+
"feels_like": "Voelt als",
182+
"sunrise": "Zonsopgang",
183+
"sunset": "Zonsondergang",
184+
"wind": "Wind",
185+
"humidity": "Vochtigheid",
186+
"pressure": "Luchtdruk",
187+
"uv_index": "UV-index",
188+
"visibility": "Zichtbaarheid",
189+
"air_quality": "Luchtkwaliteit",
190+
"aqi_scale": ["Goed", "Matig", "Onvoldoende", "Slecht", "Zeer slecht"],
191+
"aqi_scale_om": ["Goed", "Matig", "Onvoldoende", "Slecht", "Zeer slecht", "Gevaarlijk"],
192+
},
193+
},
194+
"pt": {
195+
"days": ["Segunda", "Terça", "Quarta", "Quinta", "Sexta", "Sábado", "Domingo"],
196+
"days_short": ["Seg", "Ter", "Qua", "Qui", "Sex", "Sáb", "Dom"],
197+
"months": ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho",
198+
"Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
199+
"ui": {
200+
"last_refresh": "Última atualização",
201+
"feels_like": "Sensação",
202+
"sunrise": "Nascer do sol",
203+
"sunset": "Pôr do sol",
204+
"wind": "Vento",
205+
"humidity": "Umidade",
206+
"pressure": "Pressão",
207+
"uv_index": "Índice UV",
208+
"visibility": "Visibilidade",
209+
"air_quality": "Qualidade ar",
210+
"aqi_scale": ["Boa", "Razoável", "Moderada", "Ruim", "Muito ruim"],
211+
"aqi_scale_om": ["Boa", "Razoável", "Moderada", "Ruim", "Muito ruim", "Péssima"],
212+
},
213+
},
214+
}
215+
216+
217+
def get_localized_date(dt, language):
218+
"""Return a localized date string equivalent to strftime('%A, %B %d')."""
219+
locale = LOCALE_DATA.get(language)
220+
if locale:
221+
day_name = locale["days"][dt.weekday()]
222+
month_name = locale["months"][dt.month - 1]
223+
return f"{day_name}, {month_name} {dt.day:02d}"
224+
return dt.strftime("%A, %B %d")
225+
226+
227+
def get_localized_day_short(dt, language):
228+
"""Return a localized abbreviated weekday name equivalent to strftime('%a')."""
229+
locale = LOCALE_DATA.get(language)
230+
if locale:
231+
return locale["days_short"][dt.weekday()]
232+
return dt.strftime("%a")
233+
234+
235+
def get_ui_label(key, language, default=None):
236+
"""Return a translated UI string for the given key and language."""
237+
locale = LOCALE_DATA.get(language)
238+
if locale and "ui" in locale:
239+
return locale["ui"].get(key, default or key)
240+
return default or key
241+
67242
class Weather(BasePlugin):
68243
def generate_settings_template(self):
69244
template_params = super().generate_settings_template()
@@ -568,7 +743,9 @@ def parse_data_points(self, weather, air_quality, tz, units, time_format, langua
568743
"icon": self.get_plugin_dir('icons/visibility.png')
569744
})
570745

571-
aqi = air_quality.get('list', [])[0].get("main", {}).get("aqi")
746+
aqi = (air_quality.get('list') or [{}])[0].get("main", {}).get("aqi")
747+
locale = LOCALE_DATA.get(language)
748+
aqi_scale = locale["ui"]["aqi_scale"] if locale and "ui" in locale else ["Good", "Fair", "Moderate", "Poor", "Very Poor"]
572749
data_points.append({
573750
"label": get_translation(language, "air_quality"),
574751
"measurement": aqi,

0 commit comments

Comments
 (0)