diff --git a/README.md b/README.md
index 3dd0e7946..6409c2d23 100644
--- a/README.md
+++ b/README.md
@@ -47,12 +47,12 @@
- Service Integration
- Sonarr, Radarr, Readarr, Prowlarr, Bazarr, Lidarr, Emby, Jellyfin, Tautulli (Plex)
- Ombi, Overseerr, Jellyseerr, Jackett, NZBGet, SABnzbd, ruTorrent, Transmission, qBittorrent
- - Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify, Syncthing Relay Server, Authentic, Proxmox
+ - Portainer, Traefik, Speedtest Tracker, PiHole, AdGuard Home, Nginx Proxy Manager, Gotify, Syncthing Relay Server, Authentik, Proxmox
- Information Providers
- Coin Market Cap, Mastodon
- Information & Utility Widgets
- System Stats (Disk, CPU, Memory)
- - Weather via WeatherAPI.com or OpenWeatherMap
+ - Weather via [OpenWeatherMap](https://openweathermap.org/) or [Open-Meteo](https://open-meteo.com/)
- Search Bar
- Customizable
- 21 theme colors with light and dark mode support
diff --git a/public/locales/hr/common.json b/public/locales/hr/common.json
index f79649386..58539904d 100644
--- a/public/locales/hr/common.json
+++ b/public/locales/hr/common.json
@@ -24,7 +24,7 @@
"available": "Dostupno",
"pending": "Predstoji",
"approved": "Odobreno",
- "processing": "Processing"
+ "processing": "Obrada"
},
"pihole": {
"queries": "Upiti",
@@ -345,20 +345,20 @@
"total": "Ukupno"
},
"deluge": {
- "download": "Download",
- "upload": "Upload",
+ "download": "Preuzimanje",
+ "upload": "Prijenos",
"leech": "Leech",
"seed": "Seed"
},
"diskstation": {
- "download": "Download",
- "upload": "Upload",
+ "download": "Preuzimanje",
+ "upload": "Prijenos",
"leech": "Leech",
"seed": "Seed"
},
"flood": {
- "download": "Download",
- "upload": "Upload",
+ "download": "Preuzimanje",
+ "upload": "Prijenos",
"leech": "Leech",
"seed": "Seed"
}
diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json
index 93058498a..3cde6047e 100644
--- a/public/locales/pt/common.json
+++ b/public/locales/pt/common.json
@@ -3,10 +3,10 @@
"missing_type": "Widget ausente: {{type}}",
"api_error": "Erro da API",
"status": "Status",
- "information": "Information",
- "url": "URL",
+ "information": "Informação",
+ "url": "Endereço URL",
"raw_error": "Raw Error",
- "response_data": "Response Data"
+ "response_data": "Dados da Resposta"
},
"search": {
"placeholder": "Pesquisar…"
@@ -24,8 +24,8 @@
"mem": "Mem",
"cpu": "CPU",
"offline": "Desligado",
- "error": "Error",
- "unknown": "Unknown"
+ "error": "Erro",
+ "unknown": "Desconhecido"
},
"emby": {
"playing": "A reproduzir",
@@ -150,7 +150,7 @@
"transmission": {
"download": "Baixando",
"upload": "Enviando",
- "leech": "Sanguessugas",
+ "leech": "Leech",
"seed": "Semeadores"
},
"jackett": {
@@ -201,25 +201,25 @@
"vms": "VMs"
},
"unifi": {
- "users": "Users",
- "uptime": "System Uptime",
- "days": "Days",
+ "users": "Utilizadores",
+ "uptime": "Tempo de Atividade do Sistema",
+ "days": "Dias",
"wan": "WAN",
- "lan_users": "LAN Users",
- "wlan_users": "WLAN Users",
+ "lan_users": "Utilizadores LAN",
+ "wlan_users": "Utilizadores WLAN",
"up": "UP",
"down": "DOWN",
- "wait": "Please wait",
+ "wait": "Por favor aguarde",
"lan": "LAN",
"wlan": "WLAN",
- "devices": "Devices",
- "lan_devices": "LAN Devices",
- "wlan_devices": "WLAN Devices"
+ "devices": "Dispositivos",
+ "lan_devices": "Dispositivos LAN",
+ "wlan_devices": "Dispositivos WLAN"
},
"plex": {
- "streams": "Active Streams",
- "movies": "Movies",
- "tv": "TV Shows"
+ "streams": "Streams Ativas",
+ "movies": "Filmes",
+ "tv": "Series de TV"
},
"glances": {
"cpu": "CPU",
@@ -227,8 +227,8 @@
"wait": "Please wait"
},
"changedetectionio": {
- "totalObserved": "Total Observed",
- "diffsDetected": "Diffs Detected"
+ "totalObserved": "Total Observado",
+ "diffsDetected": "Diferenças Detetadas"
},
"wmo": {
"0-day": "Sunny",
@@ -343,7 +343,7 @@
"hd": "HD"
},
"ping": {
- "error": "Error",
+ "error": "Erro",
"ping": "Ping"
},
"scrutiny": {
@@ -368,8 +368,8 @@
"seed": "Seed"
},
"flood": {
- "download": "Download",
- "upload": "Upload",
+ "download": "Descarregar",
+ "upload": "Carregar",
"leech": "Leech",
"seed": "Seed"
}
diff --git a/src/components/widgets/openmeteo/icon.jsx b/src/components/widgets/openmeteo/icon.jsx
index a2b01ba19..12d93fcb1 100644
--- a/src/components/widgets/openmeteo/icon.jsx
+++ b/src/components/widgets/openmeteo/icon.jsx
@@ -1,4 +1,4 @@
-import mapIcon from "utils/weather/owm-condition-map";
+import mapIcon from "utils/weather/openmeteo-condition-map";
export default function Icon({ condition, timeOfDay }) {
const IconComponent = mapIcon(condition, timeOfDay);
diff --git a/src/pages/api/widgets/openmeteo.js b/src/pages/api/widgets/openmeteo.js
index e79931cb6..372336451 100644
--- a/src/pages/api/widgets/openmeteo.js
+++ b/src/pages/api/widgets/openmeteo.js
@@ -1,8 +1,9 @@
import cachedFetch from "utils/proxy/cached-fetch";
export default async function handler(req, res) {
- const { latitude, longitude, units, cache } = req.query;
+ const { latitude, longitude, units, cache, timezone } = req.query;
const degrees = units === "imperial" ? "fahrenheit" : "celsius";
- const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=sunrise,sunset¤t_weather=true&temperature_unit=${degrees}&timezone=auto`;
+ const timezeone = timezone ?? 'auto'
+ const apiUrl = `https://api.open-meteo.com/v1/forecast?latitude=${latitude}&longitude=${longitude}&daily=sunrise,sunset¤t_weather=true&temperature_unit=${degrees}&timezone=${timezeone}`;
return res.send(await cachedFetch(apiUrl, cache));
}
\ No newline at end of file
diff --git a/src/utils/weather/openmeteo-condition-map.js b/src/utils/weather/openmeteo-condition-map.js
new file mode 100644
index 000000000..9ae673657
--- /dev/null
+++ b/src/utils/weather/openmeteo-condition-map.js
@@ -0,0 +1,211 @@
+import * as Icons from "react-icons/wi";
+
+// see https://open-meteo.com/en/docs
+
+const conditions = [
+ {
+ code: 1,
+ icon: {
+ day: Icons.WiDayCloudy,
+ night: Icons.WiNightAltCloudy,
+ },
+ },
+ {
+ code: 2,
+ icon: {
+ day: Icons.WiDayCloudy,
+ night: Icons.WiNightAltCloudy,
+ },
+ },
+ {
+ code: 3,
+ icon: {
+ day: Icons.WiDayCloudy,
+ night: Icons.WiNightAltCloudy,
+ },
+ },
+ {
+ code: 45,
+ icon: {
+ day: Icons.WiDayFog,
+ night: Icons.WiNightFog,
+ },
+ },
+ {
+ code: 48,
+ icon: {
+ day: Icons.WiDayFog,
+ night: Icons.WiNightFog,
+ },
+ },
+ {
+ code: 51,
+ icon: {
+ day: Icons.WiDaySprinkle,
+ night: Icons.WiNightAltSprinkle,
+ },
+ },
+ {
+ code: 53,
+ icon: {
+ day: Icons.WiDaySprinkle,
+ night: Icons.WiNightAltSprinkle,
+ },
+ },
+ {
+ code: 55,
+ icon: {
+ day: Icons.WiDaySprinkle,
+ night: Icons.WiNightAltSprinkle,
+ },
+ },
+ {
+ code: 56,
+ icon: {
+ day: Icons.WiDaySleet,
+ night: Icons.WiNightAltSleet,
+ },
+ },
+ {
+ code: 57,
+ icon: {
+ day: Icons.WiDaySleet,
+ night: Icons.WiNightAltSleet,
+ },
+ },
+ {
+ code: 61,
+ icon: {
+ day: Icons.WiDayShowers,
+ night: Icons.WiNightAltShowers,
+ },
+ },
+ {
+ code: 63,
+ icon: {
+ day: Icons.WiDayShowers,
+ night: Icons.WiNightAltShowers,
+ },
+ },
+ {
+ code: 65,
+ icon: {
+ day: Icons.WiDayShowers,
+ night: Icons.WiNightAltShowers,
+ },
+ },
+ {
+ code: 66,
+ icon: {
+ day: Icons.WiDaySleet,
+ night: Icons.WiNightAltSleet,
+ },
+ },
+ {
+ code: 67,
+ icon: {
+ day: Icons.WiDaySleet,
+ night: Icons.WiNightAltSleet,
+ },
+ },
+ {
+ code: 71,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 73,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 75,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 77,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 80,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 81,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 82,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 85,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 86,
+ icon: {
+ day: Icons.WiDaySnow,
+ night: Icons.WiNightAltSnow,
+ },
+ },
+ {
+ code: 95,
+ icon: {
+ day: Icons.WiDayThunderstorm,
+ night: Icons.WiNightAltThunderstorm,
+ },
+ },
+ {
+ code: 96,
+ icon: {
+ day: Icons.WiDayThunderstorm,
+ night: Icons.WiNightAltThunderstorm,
+ },
+ },
+ {
+ code: 99,
+ icon: {
+ day: Icons.WiDayThunderstorm,
+ night: Icons.WiNightAltThunderstorm,
+ },
+ },
+];
+
+export default function mapIcon(weatherStatusCode, timeOfDay) {
+ const mapping = conditions.find((condition) => condition.code === weatherStatusCode);
+
+ if (mapping) {
+ if (timeOfDay === "day") {
+ return mapping.icon.day;
+ }
+
+ if (timeOfDay === "night") {
+ return mapping.icon.night;
+ }
+ }
+
+ return Icons.WiDaySunny;
+}
diff --git a/src/widgets/flood/component.jsx b/src/widgets/flood/component.jsx
index 4676d798b..80ad2b28c 100644
--- a/src/widgets/flood/component.jsx
+++ b/src/widgets/flood/component.jsx
@@ -11,11 +11,11 @@ export default function Component({ service }) {
const { data: torrentData, error: torrentError } = useWidgetAPI(widget, "torrents");
- if (torrentError) {
- return ;
+ if (torrentError || !torrentData?.torrents) {
+ return ;
}
- if (!torrentData) {
+ if (!torrentData || !torrentData.torrents) {
return (