fix(weather): correct wind speed value and unit label for imperial units

fix(weather): correct wind speed value and unit label for imperial units
This commit is contained in:
ulsklyc
2026-04-22 07:42:48 +02:00
committed by GitHub
20 changed files with 30 additions and 20 deletions
+6
View File
@@ -7,6 +7,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased] ## [Unreleased]
## [0.23.3] - 2026-04-22
### Fixed
- Weather widget: wind speed is no longer multiplied by 3.6 when `OPENWEATHER_UNITS=imperial` (the API already returns mph; the conversion was only correct for metric/standard)
- Weather widget: wind unit label now shows `mph` for imperial and `km/h` for metric/standard instead of always showing `km/h`
## [0.23.2] - 2026-04-22 ## [0.23.2] - 2026-04-22
### Fixed ### Fixed
+2 -2
View File
@@ -1,12 +1,12 @@
{ {
"name": "oikos", "name": "oikos",
"version": "0.23.2", "version": "0.23.3",
"lockfileVersion": 3, "lockfileVersion": 3,
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "oikos", "name": "oikos",
"version": "0.23.2", "version": "0.23.3",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"bcrypt": "^6.0.0", "bcrypt": "^6.0.0",
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "oikos", "name": "oikos",
"version": "0.23.2", "version": "0.23.3",
"description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.", "description": "Self-hosted family planner - calendar, tasks, shopping, meal planning, budget and more. Private, open-source, no subscription.",
"main": "server/index.js", "main": "server/index.js",
"type": "module", "type": "module",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "تحديث الطقس", "weatherRefresh": "تحديث الطقس",
"weatherRefreshTitle": "تحديث", "weatherRefreshTitle": "تحديث",
"weatherUpdated": "تم تحديث الطقس", "weatherUpdated": "تم تحديث الطقس",
"weatherFeelsLike": "الإحساس {{temp}}° · {{humidity}}% · الريح {{wind}} كم/س", "weatherFeelsLike": "الإحساس {{temp}}° · {{humidity}}% · الريح {{wind}} {{windUnit}}",
"fabTaskLabel": "إضافة مهمة", "fabTaskLabel": "إضافة مهمة",
"fabCalendarLabel": "إضافة حدث", "fabCalendarLabel": "إضافة حدث",
"fabShoppingLabel": "إضافة تسوق", "fabShoppingLabel": "إضافة تسوق",
+1 -1
View File
@@ -72,7 +72,7 @@
"weatherRefresh": "Wetter aktualisieren", "weatherRefresh": "Wetter aktualisieren",
"weatherRefreshTitle": "Aktualisieren", "weatherRefreshTitle": "Aktualisieren",
"weatherUpdated": "Wetter aktualisiert", "weatherUpdated": "Wetter aktualisiert",
"weatherFeelsLike": "Gefühlt {{temp}}° · {{humidity}}% · Wind {{wind}} km/h", "weatherFeelsLike": "Gefühlt {{temp}}° · {{humidity}}% · Wind {{wind}} {{windUnit}}",
"fabTaskLabel": "Aufgabe hinzufügen", "fabTaskLabel": "Aufgabe hinzufügen",
"fabCalendarLabel": "Termin hinzufügen", "fabCalendarLabel": "Termin hinzufügen",
"fabShoppingLabel": "Einkauf hinzufügen", "fabShoppingLabel": "Einkauf hinzufügen",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Ανανέωση καιρού", "weatherRefresh": "Ανανέωση καιρού",
"weatherRefreshTitle": "Ανανέωση", "weatherRefreshTitle": "Ανανέωση",
"weatherUpdated": "Καιρός ενημερώθηκε", "weatherUpdated": "Καιρός ενημερώθηκε",
"weatherFeelsLike": "Αίσθηση {{temp}}° · {{humidity}}% · Άνεμος {{wind}} χλμ/ώ", "weatherFeelsLike": "Αίσθηση {{temp}}° · {{humidity}}% · Άνεμος {{wind}} {{windUnit}}",
"fabTaskLabel": "Προσθήκη εργασίας", "fabTaskLabel": "Προσθήκη εργασίας",
"fabCalendarLabel": "Προσθήκη εκδήλωσης", "fabCalendarLabel": "Προσθήκη εκδήλωσης",
"fabShoppingLabel": "Προσθήκη αγοράς", "fabShoppingLabel": "Προσθήκη αγοράς",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Refresh weather", "weatherRefresh": "Refresh weather",
"weatherRefreshTitle": "Refresh", "weatherRefreshTitle": "Refresh",
"weatherUpdated": "Weather updated", "weatherUpdated": "Weather updated",
"weatherFeelsLike": "Feels like {{temp}}° · {{humidity}}% · Wind {{wind}} km/h", "weatherFeelsLike": "Feels like {{temp}}° · {{humidity}}% · Wind {{wind}} {{windUnit}}",
"fabTaskLabel": "Add task", "fabTaskLabel": "Add task",
"fabCalendarLabel": "Add event", "fabCalendarLabel": "Add event",
"fabShoppingLabel": "Add shopping", "fabShoppingLabel": "Add shopping",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Actualizar tiempo", "weatherRefresh": "Actualizar tiempo",
"weatherRefreshTitle": "Actualizar", "weatherRefreshTitle": "Actualizar",
"weatherUpdated": "Tiempo actualizado", "weatherUpdated": "Tiempo actualizado",
"weatherFeelsLike": "Sensación {{temp}}° · {{humidity}}% · Viento {{wind}} km/h", "weatherFeelsLike": "Sensación {{temp}}° · {{humidity}}% · Viento {{wind}} {{windUnit}}",
"fabTaskLabel": "Añadir tarea", "fabTaskLabel": "Añadir tarea",
"fabCalendarLabel": "Añadir evento", "fabCalendarLabel": "Añadir evento",
"fabShoppingLabel": "Añadir compra", "fabShoppingLabel": "Añadir compra",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Actualiser la météo", "weatherRefresh": "Actualiser la météo",
"weatherRefreshTitle": "Actualiser", "weatherRefreshTitle": "Actualiser",
"weatherUpdated": "Météo mise à jour", "weatherUpdated": "Météo mise à jour",
"weatherFeelsLike": "Ressenti {{temp}}° · {{humidity}}% · Vent {{wind}} km/h", "weatherFeelsLike": "Ressenti {{temp}}° · {{humidity}}% · Vent {{wind}} {{windUnit}}",
"fabTaskLabel": "Ajouter une tâche", "fabTaskLabel": "Ajouter une tâche",
"fabCalendarLabel": "Ajouter un événement", "fabCalendarLabel": "Ajouter un événement",
"fabShoppingLabel": "Ajouter une course", "fabShoppingLabel": "Ajouter une course",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "मौसम अपडेट करें", "weatherRefresh": "मौसम अपडेट करें",
"weatherRefreshTitle": "अपडेट", "weatherRefreshTitle": "अपडेट",
"weatherUpdated": "मौसम अपडेट हो गया", "weatherUpdated": "मौसम अपडेट हो गया",
"weatherFeelsLike": "महसूस होता है {{temp}}° · {{humidity}}% · हवा {{wind}} km/h", "weatherFeelsLike": "महसूस होता है {{temp}}° · {{humidity}}% · हवा {{wind}} {{windUnit}}",
"fabTaskLabel": "कार्य जोड़ें", "fabTaskLabel": "कार्य जोड़ें",
"fabCalendarLabel": "कार्यक्रम जोड़ें", "fabCalendarLabel": "कार्यक्रम जोड़ें",
"fabShoppingLabel": "खरीदारी जोड़ें", "fabShoppingLabel": "खरीदारी जोड़ें",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Aggiorna meteo", "weatherRefresh": "Aggiorna meteo",
"weatherRefreshTitle": "Aggiorna", "weatherRefreshTitle": "Aggiorna",
"weatherUpdated": "Meteo aggiornato", "weatherUpdated": "Meteo aggiornato",
"weatherFeelsLike": "Percepiti {{temp}}° · {{humidity}}% · Vento {{wind}} km/h", "weatherFeelsLike": "Percepiti {{temp}}° · {{humidity}}% · Vento {{wind}} {{windUnit}}",
"fabTaskLabel": "Aggiungi compito", "fabTaskLabel": "Aggiungi compito",
"fabCalendarLabel": "Aggiungi evento", "fabCalendarLabel": "Aggiungi evento",
"fabShoppingLabel": "Aggiungi spesa", "fabShoppingLabel": "Aggiungi spesa",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "天気を更新", "weatherRefresh": "天気を更新",
"weatherRefreshTitle": "更新", "weatherRefreshTitle": "更新",
"weatherUpdated": "天気を更新しました", "weatherUpdated": "天気を更新しました",
"weatherFeelsLike": "体感 {{temp}}° · {{humidity}}% · 風速 {{wind}} km/h", "weatherFeelsLike": "体感 {{temp}}° · {{humidity}}% · 風速 {{wind}} {{windUnit}}",
"fabTaskLabel": "タスクを追加", "fabTaskLabel": "タスクを追加",
"fabCalendarLabel": "予定を追加", "fabCalendarLabel": "予定を追加",
"fabShoppingLabel": "買い物を追加", "fabShoppingLabel": "買い物を追加",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Atualizar clima", "weatherRefresh": "Atualizar clima",
"weatherRefreshTitle": "Atualizar", "weatherRefreshTitle": "Atualizar",
"weatherUpdated": "Clima atualizado", "weatherUpdated": "Clima atualizado",
"weatherFeelsLike": "Sensação {{temp}}° · {{humidity}}% · Vento {{wind}} km/h", "weatherFeelsLike": "Sensação {{temp}}° · {{humidity}}% · Vento {{wind}} {{windUnit}}",
"fabTaskLabel": "Adicionar tarefa", "fabTaskLabel": "Adicionar tarefa",
"fabCalendarLabel": "Adicionar evento", "fabCalendarLabel": "Adicionar evento",
"fabShoppingLabel": "Adicionar compra", "fabShoppingLabel": "Adicionar compra",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Обновить погоду", "weatherRefresh": "Обновить погоду",
"weatherRefreshTitle": "Обновить", "weatherRefreshTitle": "Обновить",
"weatherUpdated": "Погода обновлена", "weatherUpdated": "Погода обновлена",
"weatherFeelsLike": "Ощущается как {{temp}}° · {{humidity}}% · Ветер {{wind}} км/ч", "weatherFeelsLike": "Ощущается как {{temp}}° · {{humidity}}% · Ветер {{wind}} {{windUnit}}",
"fabTaskLabel": "Добавить задачу", "fabTaskLabel": "Добавить задачу",
"fabCalendarLabel": "Добавить событие", "fabCalendarLabel": "Добавить событие",
"fabShoppingLabel": "Добавить покупку", "fabShoppingLabel": "Добавить покупку",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Uppdatera vädret", "weatherRefresh": "Uppdatera vädret",
"weatherRefreshTitle": "Uppdatera", "weatherRefreshTitle": "Uppdatera",
"weatherUpdated": "Väder uppdaterat", "weatherUpdated": "Väder uppdaterat",
"weatherFeelsLike": "Känns som {{temp}}° · {{humidity}}% · Vind {{wind}} km/h", "weatherFeelsLike": "Känns som {{temp}}° · {{humidity}}% · Vind {{wind}} {{windUnit}}",
"fabTaskLabel": "Lägg till uppgift", "fabTaskLabel": "Lägg till uppgift",
"fabCalendarLabel": "Lägg till händelse", "fabCalendarLabel": "Lägg till händelse",
"fabShoppingLabel": "Lägg till shopping", "fabShoppingLabel": "Lägg till shopping",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Hava durumunu yenile", "weatherRefresh": "Hava durumunu yenile",
"weatherRefreshTitle": "Yenile", "weatherRefreshTitle": "Yenile",
"weatherUpdated": "Hava durumu güncellendi", "weatherUpdated": "Hava durumu güncellendi",
"weatherFeelsLike": "Hissedilen {{temp}}° · {{humidity}}% · Rüzgar {{wind}} km/s", "weatherFeelsLike": "Hissedilen {{temp}}° · {{humidity}}% · Rüzgar {{wind}} {{windUnit}}",
"fabTaskLabel": "Görev ekle", "fabTaskLabel": "Görev ekle",
"fabCalendarLabel": "Etkinlik ekle", "fabCalendarLabel": "Etkinlik ekle",
"fabShoppingLabel": "Alışveriş ekle", "fabShoppingLabel": "Alışveriş ekle",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "Оновити погоду", "weatherRefresh": "Оновити погоду",
"weatherRefreshTitle": "Оновити", "weatherRefreshTitle": "Оновити",
"weatherUpdated": "Погоду оновлено", "weatherUpdated": "Погоду оновлено",
"weatherFeelsLike": "Відчувається як {{temp}}° · {{humidity}}% · Вітер {{wind}} км/год", "weatherFeelsLike": "Відчувається як {{temp}}° · {{humidity}}% · Вітер {{wind}} {{windUnit}}",
"fabTaskLabel": "Додати завдання", "fabTaskLabel": "Додати завдання",
"fabCalendarLabel": "Додати подію", "fabCalendarLabel": "Додати подію",
"fabShoppingLabel": "Додати покупку", "fabShoppingLabel": "Додати покупку",
+1 -1
View File
@@ -65,7 +65,7 @@
"weatherRefresh": "刷新天气", "weatherRefresh": "刷新天气",
"weatherRefreshTitle": "刷新", "weatherRefreshTitle": "刷新",
"weatherUpdated": "天气已更新", "weatherUpdated": "天气已更新",
"weatherFeelsLike": "体感 {{temp}}° · {{humidity}}% · 风速 {{wind}} km/h", "weatherFeelsLike": "体感 {{temp}}° · {{humidity}}% · 风速 {{wind}} {{windUnit}}",
"fabTaskLabel": "添加任务", "fabTaskLabel": "添加任务",
"fabCalendarLabel": "添加日程", "fabCalendarLabel": "添加日程",
"fabShoppingLabel": "添加购物", "fabShoppingLabel": "添加购物",
+2 -1
View File
@@ -390,6 +390,7 @@ function renderWeatherWidget(weather) {
const { city, current, forecast, units } = weather; const { city, current, forecast, units } = weather;
const unitSymbol = units === 'imperial' ? '°F' : units === 'standard' ? 'K' : '°C'; const unitSymbol = units === 'imperial' ? '°F' : units === 'standard' ? 'K' : '°C';
const windUnit = units === 'imperial' ? 'mph' : 'km/h';
const forecastHtml = forecast.map((d, i) => { const forecastHtml = forecast.map((d, i) => {
const date = new Date(d.date + 'T12:00:00'); const date = new Date(d.date + 'T12:00:00');
@@ -419,7 +420,7 @@ function renderWeatherWidget(weather) {
<div class="weather-widget__desc">${esc(current.desc)}</div> <div class="weather-widget__desc">${esc(current.desc)}</div>
<div class="weather-widget__city">${esc(city)}</div> <div class="weather-widget__city">${esc(city)}</div>
<div class="weather-widget__meta"> <div class="weather-widget__meta">
${t('dashboard.weatherFeelsLike', { temp: current.feels_like, humidity: current.humidity, wind: current.wind_speed })} ${t('dashboard.weatherFeelsLike', { temp: current.feels_like, humidity: current.humidity, wind: current.wind_speed, windUnit })}
</div> </div>
</div> </div>
<img class="weather-widget__icon" src="${WEATHER_ICON_BASE}${current.icon}" <img class="weather-widget__icon" src="${WEATHER_ICON_BASE}${current.icon}"
+4 -1
View File
@@ -105,7 +105,10 @@ router.get('/', async (req, res) => {
humidity: currentJson.main.humidity, humidity: currentJson.main.humidity,
icon: currentJson.weather[0]?.icon, icon: currentJson.weather[0]?.icon,
desc: currentJson.weather[0]?.description, desc: currentJson.weather[0]?.description,
wind_speed: Math.round((currentJson.wind?.speed ?? 0) * 3.6), // m/s → km/h // metric/standard: m/s → km/h; imperial: already mph
wind_speed: units === 'imperial'
? Math.round(currentJson.wind?.speed ?? 0)
: Math.round((currentJson.wind?.speed ?? 0) * 3.6),
}, },
forecast: forecastDays, forecast: forecastDays,
}; };