diff --git a/.all-contributorsrc b/.all-contributorsrc index 1487861d0..f2d28077a 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -1,10 +1,9 @@ { "projectName": "homepage", "projectOwner": "benphelps", - "repoType": "github", - "repoHost": "https://github.com", - "files": ["README.md"], - "imageSize": 50, - "contributorsSortAlphabetically": true, + "files": [ + "README.md" + ], + "imageSize": 100, "contributors": [] } diff --git a/README.md b/README.md index cdfa217e2..3dd0e7946 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ - Images built for AMD64 (x86_64), ARM64, ARMv7 and ARMv6 - Supports all Raspberry Pi's, most SBCs & Apple Silicon - Full i18n support with automatic language detection - - Translations for Catalan, Chinese, Dutch, Finnish, French, German, Hebrew, Hungarian, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romanian, Russian, Spanish, Swedish and Yue + - Translations for Catalan, Chinese, Dutch, Finnish, French, German, Hebrew, Hungarian, Malay, Norwegian Bokmål, Polish, Portuguese, Portuguese (Brazil), Romanian, Russian, Spanish, Swedish and Yue - Want to help translate? [Join the Weblate project](https://hosted.weblate.org/engage/homepage/) - Service & Web Bookmarks - Docker Integration @@ -152,3 +152,9 @@ This is a [Next.js](https://nextjs.org/) application, see their doucmentation fo + + + + +[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors) + diff --git a/public/locales/ar/common.json b/public/locales/ar/common.json index 3e40f83f0..6d565287e 100644 --- a/public/locales/ar/common.json +++ b/public/locales/ar/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/bg/common.json b/public/locales/bg/common.json index 98898d254..0365e3292 100644 --- a/public/locales/bg/common.json +++ b/public/locales/bg/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/ca/common.json b/public/locales/ca/common.json index 16e210ece..fac4a04c2 100644 --- a/public/locales/ca/common.json +++ b/public/locales/ca/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/cs/common.json b/public/locales/cs/common.json index d51f3c649..7e9da1b5a 100644 --- a/public/locales/cs/common.json +++ b/public/locales/cs/common.json @@ -304,5 +304,20 @@ "rejectedPushes": "Zamítnuto", "filters": "Filtry", "indexers": "Indexery" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/da/common.json b/public/locales/da/common.json index e67a66738..99db4725d 100644 --- a/public/locales/da/common.json +++ b/public/locales/da/common.json @@ -1,34 +1,34 @@ { "plex": { - "movies": "Movies", - "tv": "TV Shows", - "streams": "Active Streams" + "movies": "Film", + "tv": "TV-Shows", + "streams": "Aktive Streams" }, "radarr": { - "queued": "Queued", - "movies": "Movies", - "wanted": "Wanted", - "missing": "Missing" + "queued": "I Kø", + "movies": "Film", + "wanted": "Ønskede", + "missing": "Mangler" }, "lidarr": { - "wanted": "Wanted", - "queued": "Queued", + "wanted": "Ønsket", + "queued": "I Kø", "albums": "Albums" }, "jellyseerr": { - "available": "Available", - "pending": "Pending", - "approved": "Approved" + "available": "Tilgængelig", + "pending": "Afventer", + "approved": "Godkendt" }, "overseerr": { - "pending": "Pending", - "approved": "Approved", - "available": "Available" + "pending": "Afventer", + "approved": "Godkendt", + "available": "Tilgængelig" }, "adguard": { - "queries": "Queries", - "blocked": "Blocked", - "filtered": "Filtered", + "queries": "Forespørgsler", + "blocked": "Blokerede", + "filtered": "Filtreret", "latency": "Latency" }, "speedtest": { @@ -38,175 +38,175 @@ }, "npm": { "total": "Total", - "enabled": "Enabled", - "disabled": "Disabled" + "enabled": "Aktiveret", + "disabled": "Deaktiveret" }, "coinmarketcap": { - "30days": "30 Days", - "1day": "1 Day", - "configure": "Configure one or more crypto currencies to track", - "7days": "7 Days", - "1hour": "1 Hour" + "30days": "30 Dage", + "1day": "1 Dag", + "configure": "Konfigurer en eller flere crypto valutaer til tracking", + "7days": "7 Dage", + "1hour": "1 time" }, "strelaysrv": { - "numActiveSessions": "Sessions", - "dataRelayed": "Relayed", - "numConnections": "Connections", + "numActiveSessions": "Sessioner", + "dataRelayed": "Videresendt", + "numConnections": "Forbindelser", "transferRate": "Rate" }, "mastodon": { - "domain_count": "Domains", - "status_count": "Posts", - "user_count": "Users" + "domain_count": "Domæner", + "status_count": "Indlæg", + "user_count": "Brugere" }, "authentik": { - "users": "Users", - "loginsLast24H": "Logins (24h)", - "failedLoginsLast24H": "Failed Logins (24h)" + "users": "Brugere", + "loginsLast24H": "Login (24 timer)", + "failedLoginsLast24H": "Mislykkede logins (24 timer)" }, "glances": { "cpu": "CPU", - "mem": "MEM", - "wait": "Please wait" + "mem": "RAM", + "wait": "Vent venligst" }, "wmo": { - "1-day": "Mainly Sunny", - "48-day": "Foggy", - "48-night": "Foggy", - "51-day": "Light Drizzle", - "51-night": "Light Drizzle", - "66-night": "Freezing Rain", - "67-day": "Freezing Rain", - "67-night": "Freezing Rain", - "71-day": "Light Snow", - "75-night": "Heavy Snow", - "86-day": "Snow Showers", - "86-night": "Snow Showers", - "95-day": "Thunderstorm", - "99-day": "Thunderstorm With Hail", - "99-night": "Thunderstorm With Hail", - "0-day": "Sunny", - "0-night": "Clear", - "1-night": "Mainly Clear", - "2-day": "Partly Cloudy", - "2-night": "Partly Cloudy", - "3-day": "Cloudy", - "3-night": "Cloudy", - "45-day": "Foggy", - "65-day": "Heavy Rain", - "65-night": "Heavy Rain", - "45-night": "Foggy", - "53-day": "Drizzle", - "53-night": "Drizzle", - "55-day": "Heavy Drizzle", - "55-night": "Heavy Drizzle", - "56-day": "Light Freezing Drizzle", - "56-night": "Light Freezing Drizzle", - "57-day": "Freezing Drizzle", - "57-night": "Freezing Drizzle", - "61-day": "Light Rain", - "61-night": "Light Rain", - "63-day": "Rain", - "63-night": "Rain", - "66-day": "Freezing Rain", - "71-night": "Light Snow", - "73-day": "Snow", - "73-night": "Snow", - "75-day": "Heavy Snow", - "77-day": "Snow Grains", - "80-day": "Light Showers", - "80-night": "Light Showers", - "81-day": "Showers", - "77-night": "Snow Grains", - "81-night": "Showers", - "82-day": "Heavy Showers", - "82-night": "Heavy Showers", - "85-day": "Snow Showers", - "85-night": "Snow Showers", - "95-night": "Thunderstorm", - "96-day": "Thunderstorm With Hail", - "96-night": "Thunderstorm With Hail" + "1-day": "Hovedsageligt solrigt", + "48-day": "Tåget", + "48-night": "Tåget", + "51-day": "Let støvregn", + "51-night": "Let støvregn", + "66-night": "Frysende regn", + "67-day": "Frysende regn", + "67-night": "Frysende regn", + "71-day": "Let Sne", + "75-night": "Kraftig Sne", + "86-day": "Snebyger", + "86-night": "Snebyger", + "95-day": "Tordenvejr", + "99-day": "Tordenvejr med hagl", + "99-night": "Tordenvejr med hagl", + "0-day": "Solrig", + "0-night": "Klart", + "1-night": "Hovedsageligt klart", + "2-day": "Delvist skyet", + "2-night": "Delvist skyet", + "3-day": "Skyet", + "3-night": "Skyet", + "45-day": "Tåget", + "65-day": "Kraftig regn", + "65-night": "Kraftig regn", + "45-night": "Tåget", + "53-day": "Støvregn", + "53-night": "Støvregn", + "55-day": "Kraftig støvregn", + "55-night": "Kraftig støvregn", + "56-day": "Let frysende støvregn", + "56-night": "Let frysende støvregn", + "57-day": "Frysende støvregn", + "57-night": "Frysende støvregn", + "61-day": "Let Regn", + "61-night": "Let Regn", + "63-day": "Regn", + "63-night": "Regn", + "66-day": "Frysende regn", + "71-night": "Let Sne", + "73-day": "Sne", + "73-night": "Sne", + "75-day": "Kraftig Sne", + "77-day": "Snekorn", + "80-day": "Lette byger", + "80-night": "Lette byger", + "81-day": "Byger", + "77-night": "Snekorn", + "81-night": "Byger", + "82-day": "Kraftige Byger", + "82-night": "Kraftige Byger", + "85-day": "Snebyger", + "85-night": "Snebyger", + "95-night": "Tordenvejr", + "96-day": "Tordenvejr med hagl", + "96-night": "Tordenvejr med hagl" }, "homebridge": { "available_update": "System", - "updates": "Updates", - "update_available": "Update Available", - "up_to_date": "Up to Date", + "updates": "Opdateringer", + "update_available": "Opdateringer tilgængelige", + "up_to_date": "Opdateret", "child_bridges": "Child Bridges", "child_bridges_status": "{{ok}}/{{total}}" }, "widget": { - "missing_type": "Missing Widget Type: {{type}}", - "api_error": "API Error", + "missing_type": "Manglende Widget Type: {{type}}", + "api_error": "API fejl", "status": "Status" }, "weather": { - "current": "Current Location", - "allow": "Click to allow", - "updating": "Updating", - "wait": "Please wait" + "current": "Nuværende lokation", + "allow": "Klik for at tillade", + "updating": "Opdaterer", + "wait": "Vent venligst" }, "search": { - "placeholder": "Search…" + "placeholder": "Søg…" }, "resources": { "cpu": "CPU", "total": "Total", - "free": "Free", - "used": "Used", - "load": "Load" + "free": "Fri", + "used": "Brugt", + "load": "Belastning" }, "unifi": { - "users": "Users", - "uptime": "System Uptime", - "days": "Days", + "users": "Brugere", + "uptime": "System Oppetid", + "days": "Dage", "wan": "WAN", "lan": "LAN", - "wlan": "WLAN", - "devices": "Devices", - "lan_devices": "LAN Devices", - "wlan_devices": "WLAN Devices", - "lan_users": "LAN Users", - "wlan_users": "WLAN Users", - "up": "UP", - "down": "DOWN", - "wait": "Please wait" + "wlan": "Wifi", + "devices": "Enheder", + "lan_devices": "LAN Enheder", + "wlan_devices": "WLAN Enheder", + "lan_users": "LAN Brugere", + "wlan_users": "WLAN Brugere", + "up": "Oppe", + "down": "NED", + "wait": "Vent venligst" }, "docker": { "cpu": "CPU", "rx": "RX", "tx": "TX", - "mem": "MEM", + "mem": "RAM", "offline": "Offline" }, "emby": { - "playing": "Playing", - "transcoding": "Transcoding", + "playing": "Afspiller", + "transcoding": "Transcoder", "bitrate": "Bitrate", - "no_active": "No Active Streams" + "no_active": "Ingen Aktive Streams" }, "changedetectionio": { - "totalObserved": "Total Observed", - "diffsDetected": "Diffs Detected" + "totalObserved": "Total Observeret", + "diffsDetected": "Forskelle Detekteret" }, "tautulli": { - "playing": "Playing", - "transcoding": "Transcoding", + "playing": "Afspiller", + "transcoding": "Transcoder", "bitrate": "Bitrate", - "no_active": "No Active Streams" + "no_active": "Ingen Aktive Streams" }, "nzbget": { "rate": "Rate", - "remaining": "Remaining", - "downloaded": "Downloaded" + "remaining": "Manglende", + "downloaded": "Hentet" }, "sabnzbd": { "rate": "Rate", - "queue": "Queue", - "timeleft": "Time Left" + "queue": "Kø", + "timeleft": "Resterende tid" }, "rutorrent": { - "active": "Active", + "active": "Aktive", "upload": "Upload", "download": "Download" }, @@ -223,86 +223,101 @@ "seed": "Seed" }, "sonarr": { - "wanted": "Wanted", - "queued": "Queued", - "series": "Series" + "wanted": "Ønsket", + "queued": "I Kø", + "series": "Serier" }, "readarr": { - "wanted": "Wanted", - "queued": "Queued", - "books": "Books" + "wanted": "Ønskede", + "queued": "I Kø", + "books": "Bøger" }, "bazarr": { - "missingEpisodes": "Missing Episodes", - "missingMovies": "Missing Movies" + "missingEpisodes": "Manglende Afsnit", + "missingMovies": "Manglende Film" }, "ombi": { - "pending": "Pending", - "approved": "Approved", - "available": "Available" + "pending": "Afventer", + "approved": "Godkendt", + "available": "Tilgængelig" }, "pihole": { - "blocked": "Blocked", + "blocked": "Blokerede", "gravity": "Gravity", - "queries": "Queries" + "queries": "Forespørgsler" }, "portainer": { - "running": "Running", - "stopped": "Stopped", + "running": "Kørende", + "stopped": "Stoppede", "total": "Total" }, "traefik": { - "routers": "Routers", + "routers": "Routere", "services": "Services", "middleware": "Middleware" }, "gotify": { - "apps": "Applications", - "clients": "Clients", - "messages": "Messages" + "apps": "Applikationer", + "clients": "Klienter", + "messages": "Beskeder" }, "prowlarr": { - "enableIndexers": "Indexers", + "enableIndexers": "Indeksører", "numberOfGrabs": "Grabs", - "numberOfQueries": "Queries", + "numberOfQueries": "Forespørgsler", "numberOfFailGrabs": "Fail Grabs", - "numberOfFailQueries": "Fail Queries" + "numberOfFailQueries": "Fejl forespørgsler" }, "jackett": { - "configured": "Configured", - "errored": "Errored" + "configured": "Konfigureret", + "errored": "Fejlede" }, "proxmox": { - "mem": "MEM", + "mem": "RAM", "cpu": "CPU", "lxc": "LXC", "vms": "VMs" }, "quicklaunch": { - "bookmark": "Bookmark", + "bookmark": "Bogmærker", "service": "Service" }, "watchtower": { - "containers_scanned": "Scanned", - "containers_updated": "Updated", - "containers_failed": "Failed" + "containers_scanned": "Scannet", + "containers_updated": "Opdateret", + "containers_failed": "Fejlet" }, "autobrr": { - "indexers": "Indexers", - "approvedPushes": "Approved", - "rejectedPushes": "Rejected", - "filters": "Filters" + "indexers": "Indeksører", + "approvedPushes": "Godkendte", + "rejectedPushes": "Afviste", + "filters": "Filtre" }, "tubearchivist": { - "downloads": "Queue", - "videos": "Videos", - "channels": "Channels", - "playlists": "Playlists" + "downloads": "Kø", + "videos": "Videoer", + "channels": "Kanaler", + "playlists": "Afspilningslister" }, "truenas": { - "load": "System Load", - "uptime": "Uptime", - "alerts": "Alerts", + "load": "Systembelastning", + "uptime": "Oppetid", + "alerts": "Advarsler", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "Ingen Aktive Streams", + "please_wait": "Vent venligst" + }, + "pyload": { + "speed": "Hastighed", + "active": "Aktive", + "queue": "Kø", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/de/common.json b/public/locales/de/common.json index 315ec0e4f..f8c59567c 100644 --- a/public/locales/de/common.json +++ b/public/locales/de/common.json @@ -47,7 +47,7 @@ "wanted": "Gesucht", "queued": "In Warteschlange", "movies": "Filme", - "missing": "Missing" + "missing": "Fehlt" }, "readarr": { "wanted": "Gesucht", @@ -194,9 +194,9 @@ "wait": "Bitte warten", "lan": "LAN", "wlan": "WLAN", - "devices": "Devices", - "lan_devices": "LAN Devices", - "wlan_devices": "WLAN Devices" + "devices": "Geräte", + "lan_devices": "LAN-Geräte", + "wlan_devices": "WLAN Geräte" }, "plex": { "streams": "Aktive Streams", @@ -204,105 +204,120 @@ "tv": "TV Sendungen" }, "glances": { - "cpu": "CPU", + "cpu": "Prozessor", "mem": "RAM", "wait": "Bitte warten" }, "changedetectionio": { - "totalObserved": "Total Observed", - "diffsDetected": "Diffs Detected" + "totalObserved": "Gesamt beobachtet", + "diffsDetected": "Erkannte Differenzen" }, "wmo": { - "0-day": "Sunny", - "0-night": "Clear", - "1-day": "Mainly Sunny", - "1-night": "Mainly Clear", - "2-day": "Partly Cloudy", - "2-night": "Partly Cloudy", - "3-day": "Cloudy", - "57-day": "Freezing Drizzle", - "61-day": "Light Rain", - "65-night": "Heavy Rain", - "66-day": "Freezing Rain", - "66-night": "Freezing Rain", - "3-night": "Cloudy", - "45-day": "Foggy", - "45-night": "Foggy", - "48-day": "Foggy", - "48-night": "Foggy", - "51-day": "Light Drizzle", - "51-night": "Light Drizzle", - "55-day": "Heavy Drizzle", - "53-day": "Drizzle", - "53-night": "Drizzle", - "55-night": "Heavy Drizzle", - "56-day": "Light Freezing Drizzle", - "56-night": "Light Freezing Drizzle", - "57-night": "Freezing Drizzle", - "61-night": "Light Rain", - "63-day": "Rain", - "63-night": "Rain", - "65-day": "Heavy Rain", - "67-day": "Freezing Rain", - "67-night": "Freezing Rain", - "71-day": "Light Snow", - "71-night": "Light Snow", - "73-day": "Snow", - "73-night": "Snow", - "75-day": "Heavy Snow", - "75-night": "Heavy Snow", - "77-day": "Snow Grains", - "77-night": "Snow Grains", - "80-day": "Light Showers", - "80-night": "Light Showers", - "81-day": "Showers", - "81-night": "Showers", - "82-day": "Heavy Showers", - "82-night": "Heavy Showers", - "85-day": "Snow Showers", - "85-night": "Snow Showers", - "86-day": "Snow Showers", - "86-night": "Snow Showers", - "95-day": "Thunderstorm", - "95-night": "Thunderstorm", - "96-day": "Thunderstorm With Hail", - "96-night": "Thunderstorm With Hail", - "99-day": "Thunderstorm With Hail", - "99-night": "Thunderstorm With Hail" + "0-day": "Sonnig", + "0-night": "Klar", + "1-day": "Überwiegend sonnig", + "1-night": "Überwiegend klar", + "2-day": "Teilweise bewölkt", + "2-night": "Teilweise bewölkt", + "3-day": "bewölkt", + "57-day": "Gefrierender Nieselregen", + "61-day": "Leichter Regen", + "65-night": "Starker Regen", + "66-day": "Gefrierender Regen", + "66-night": "Gefrierender Regen", + "3-night": "Bewölkt", + "45-day": "Neblig", + "45-night": "Neblig", + "48-day": "Neblig", + "48-night": "Neblig", + "51-day": "Leichter Nieselregen", + "51-night": "Leichter Nieselregen", + "55-day": "Starker Nieselregen", + "53-day": "Nieselregen", + "53-night": "Nieselregen", + "55-night": "Starker Nieselregen", + "56-day": "Leichter gefrierender Nieselregen", + "56-night": "Leichter eisiger Nieselregen", + "57-night": "Gefrierender Nieselregen", + "61-night": "Leichter Regen", + "63-day": "Regen", + "63-night": "Regen", + "65-day": "Starker Regen", + "67-day": "Gefrierender Regen", + "67-night": "Gefrierender Regen", + "71-day": "Leichter Schneefall", + "71-night": "Leichter Schnee", + "73-day": "Schnee", + "73-night": "Schnee", + "75-day": "Schwerer Schnee", + "75-night": "Schwerer Schnee", + "77-day": "Schneegriesel", + "77-night": "Schneegriesel", + "80-day": "Leichter Schauer", + "80-night": "Leichter Schauer", + "81-day": "Schauer", + "81-night": "Schauer", + "82-day": "Starke Regenschauer", + "82-night": "Starke Regenschauer", + "85-day": "Schneeschauer", + "85-night": "Schneeregen", + "86-day": "Schneeregen", + "86-night": "Schneeregen", + "95-day": "Gewitter", + "95-night": "Gewitter", + "96-day": "Gewitter mit Hagel", + "96-night": "Gewitter mit Hagel", + "99-day": "Gewitter mit Hagel", + "99-night": "Gewitter mit Hagel" }, "quicklaunch": { - "bookmark": "Bookmark", - "service": "Service" + "bookmark": "Lesezeichen", + "service": "Dienst" }, "homebridge": { "available_update": "System", - "updates": "Updates", - "update_available": "Update Available", - "up_to_date": "Up to Date", + "updates": "Aktualisierungen", + "update_available": "Aktualisierung verfügbar", + "up_to_date": "Aktuell", "child_bridges": "Child Bridges", "child_bridges_status": "{{ok}}/{{total}}" }, "autobrr": { - "approvedPushes": "Approved", - "rejectedPushes": "Rejected", - "filters": "Filters", - "indexers": "Indexers" + "approvedPushes": "Genehmigt", + "rejectedPushes": "Abgelehnt", + "filters": "Filter", + "indexers": "Indexer" }, "watchtower": { - "containers_scanned": "Scanned", - "containers_updated": "Updated", - "containers_failed": "Failed" + "containers_scanned": "Überprüft", + "containers_updated": "Aktualisiert", + "containers_failed": "Fehlgeschlagen" }, "tubearchivist": { - "downloads": "Queue", + "downloads": "Warteschlange", "videos": "Videos", - "channels": "Channels", - "playlists": "Playlists" + "channels": "Kanäle", + "playlists": "Wiedergabelisten" }, "truenas": { - "load": "System Load", - "uptime": "Uptime", - "alerts": "Alerts", + "load": "Systembelastung", + "uptime": "Betriebszeit", + "alerts": "Warnungen", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/en/common.json b/public/locales/en/common.json index 8784443a4..cc946e783 100644 --- a/public/locales/en/common.json +++ b/public/locales/en/common.json @@ -168,6 +168,10 @@ "services": "Services", "middleware": "Middleware" }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, "npm": { "enabled": "Enabled", "disabled": "Disabled", @@ -315,5 +319,16 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/es/common.json b/public/locales/es/common.json index 5de221ea2..4e98e30e6 100644 --- a/public/locales/es/common.json +++ b/public/locales/es/common.json @@ -82,7 +82,7 @@ "traefik": { "routers": "Enrutadores", "services": "Servicios", - "middleware": "Middleware" + "middleware": "Software intermedio" }, "npm": { "enabled": "Activado", @@ -304,5 +304,20 @@ "uptime": "Tiempo de la actividad", "alerts": "Alertas", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "Sin transmisiones activas", + "please_wait": "Espere por favor" + }, + "pyload": { + "speed": "Velocidad", + "active": "Activo", + "queue": "Cola", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/fi/common.json b/public/locales/fi/common.json index 3e8c69bf8..07b480f02 100644 --- a/public/locales/fi/common.json +++ b/public/locales/fi/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/fr/common.json b/public/locales/fr/common.json index 3e0ffccbe..b9b61611a 100644 --- a/public/locales/fr/common.json +++ b/public/locales/fr/common.json @@ -304,5 +304,20 @@ "uptime": "Démarré depuis", "alerts": "Alertes", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "Aucun flux actif", + "please_wait": "Merci de patienter" + }, + "pyload": { + "speed": "Débit", + "active": "Actif", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/he/common.json b/public/locales/he/common.json index fe7fd3aef..296bfc4eb 100644 --- a/public/locales/he/common.json +++ b/public/locales/he/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/hi/common.json b/public/locales/hi/common.json new file mode 100644 index 000000000..d3075aba7 --- /dev/null +++ b/public/locales/hi/common.json @@ -0,0 +1,323 @@ +{ + "widget": { + "missing_type": "Missing Widget Type: {{type}}", + "api_error": "API Error", + "status": "Status" + }, + "weather": { + "current": "Current Location", + "allow": "Click to allow", + "updating": "Updating", + "wait": "Please wait" + }, + "readarr": { + "queued": "Queued", + "books": "Books", + "wanted": "Wanted" + }, + "bazarr": { + "missingEpisodes": "Missing Episodes", + "missingMovies": "Missing Movies" + }, + "ombi": { + "pending": "Pending", + "approved": "Approved", + "available": "Available" + }, + "jellyseerr": { + "pending": "Pending", + "approved": "Approved", + "available": "Available" + }, + "traefik": { + "services": "Services", + "middleware": "Middleware", + "routers": "Routers" + }, + "mastodon": { + "domain_count": "Domains", + "user_count": "Users", + "status_count": "Posts" + }, + "authentik": { + "users": "Users", + "loginsLast24H": "Logins (24h)", + "failedLoginsLast24H": "Failed Logins (24h)" + }, + "search": { + "placeholder": "Search…" + }, + "resources": { + "cpu": "CPU", + "total": "Total", + "free": "Free", + "used": "Used", + "load": "Load" + }, + "unifi": { + "users": "Users", + "uptime": "System Uptime", + "days": "Days", + "wan": "WAN", + "lan": "LAN", + "wlan": "WLAN", + "devices": "Devices", + "lan_devices": "LAN Devices", + "wlan_devices": "WLAN Devices", + "lan_users": "LAN Users", + "wlan_users": "WLAN Users", + "up": "UP", + "down": "DOWN", + "wait": "Please wait" + }, + "docker": { + "rx": "RX", + "tx": "TX", + "mem": "MEM", + "cpu": "CPU", + "offline": "Offline" + }, + "emby": { + "playing": "Playing", + "transcoding": "Transcoding", + "bitrate": "Bitrate", + "no_active": "No Active Streams" + }, + "changedetectionio": { + "totalObserved": "Total Observed", + "diffsDetected": "Diffs Detected" + }, + "tautulli": { + "playing": "Playing", + "transcoding": "Transcoding", + "bitrate": "Bitrate", + "no_active": "No Active Streams" + }, + "nzbget": { + "rate": "Rate", + "remaining": "Remaining", + "downloaded": "Downloaded" + }, + "plex": { + "streams": "Active Streams", + "movies": "Movies", + "tv": "TV Shows" + }, + "sabnzbd": { + "rate": "Rate", + "queue": "Queue", + "timeleft": "Time Left" + }, + "rutorrent": { + "active": "Active", + "upload": "Upload", + "download": "Download" + }, + "transmission": { + "download": "Download", + "upload": "Upload", + "leech": "Leech", + "seed": "Seed" + }, + "qbittorrent": { + "download": "Download", + "upload": "Upload", + "leech": "Leech", + "seed": "Seed" + }, + "sonarr": { + "wanted": "Wanted", + "queued": "Queued", + "series": "Series" + }, + "radarr": { + "wanted": "Wanted", + "missing": "Missing", + "queued": "Queued", + "movies": "Movies" + }, + "lidarr": { + "wanted": "Wanted", + "queued": "Queued", + "albums": "Albums" + }, + "overseerr": { + "pending": "Pending", + "approved": "Approved", + "available": "Available" + }, + "pihole": { + "queries": "Queries", + "blocked": "Blocked", + "gravity": "Gravity" + }, + "adguard": { + "queries": "Queries", + "blocked": "Blocked", + "filtered": "Filtered", + "latency": "Latency" + }, + "speedtest": { + "upload": "Upload", + "download": "Download", + "ping": "Ping" + }, + "portainer": { + "running": "Running", + "stopped": "Stopped", + "total": "Total" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "npm": { + "enabled": "Enabled", + "disabled": "Disabled", + "total": "Total" + }, + "coinmarketcap": { + "configure": "Configure one or more crypto currencies to track", + "1hour": "1 Hour", + "1day": "1 Day", + "7days": "7 Days", + "30days": "30 Days" + }, + "gotify": { + "apps": "Applications", + "clients": "Clients", + "messages": "Messages" + }, + "prowlarr": { + "enableIndexers": "Indexers", + "numberOfGrabs": "Grabs", + "numberOfQueries": "Queries", + "numberOfFailGrabs": "Fail Grabs", + "numberOfFailQueries": "Fail Queries" + }, + "jackett": { + "configured": "Configured", + "errored": "Errored" + }, + "strelaysrv": { + "numActiveSessions": "Sessions", + "numConnections": "Connections", + "dataRelayed": "Relayed", + "transferRate": "Rate" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "VMs" + }, + "glances": { + "cpu": "CPU", + "mem": "MEM", + "wait": "Please wait" + }, + "quicklaunch": { + "bookmark": "Bookmark", + "service": "Service" + }, + "wmo": { + "0-day": "Sunny", + "0-night": "Clear", + "1-day": "Mainly Sunny", + "1-night": "Mainly Clear", + "2-day": "Partly Cloudy", + "2-night": "Partly Cloudy", + "3-day": "Cloudy", + "3-night": "Cloudy", + "45-day": "Foggy", + "45-night": "Foggy", + "48-day": "Foggy", + "48-night": "Foggy", + "51-day": "Light Drizzle", + "51-night": "Light Drizzle", + "53-day": "Drizzle", + "53-night": "Drizzle", + "55-day": "Heavy Drizzle", + "55-night": "Heavy Drizzle", + "56-day": "Light Freezing Drizzle", + "56-night": "Light Freezing Drizzle", + "57-day": "Freezing Drizzle", + "57-night": "Freezing Drizzle", + "61-day": "Light Rain", + "61-night": "Light Rain", + "63-day": "Rain", + "63-night": "Rain", + "65-day": "Heavy Rain", + "65-night": "Heavy Rain", + "66-day": "Freezing Rain", + "66-night": "Freezing Rain", + "67-day": "Freezing Rain", + "67-night": "Freezing Rain", + "71-day": "Light Snow", + "71-night": "Light Snow", + "73-day": "Snow", + "73-night": "Snow", + "75-day": "Heavy Snow", + "75-night": "Heavy Snow", + "77-day": "Snow Grains", + "77-night": "Snow Grains", + "80-day": "Light Showers", + "80-night": "Light Showers", + "81-day": "Showers", + "81-night": "Showers", + "82-day": "Heavy Showers", + "82-night": "Heavy Showers", + "85-day": "Snow Showers", + "85-night": "Snow Showers", + "86-day": "Snow Showers", + "86-night": "Snow Showers", + "95-day": "Thunderstorm", + "95-night": "Thunderstorm", + "96-day": "Thunderstorm With Hail", + "96-night": "Thunderstorm With Hail", + "99-day": "Thunderstorm With Hail", + "99-night": "Thunderstorm With Hail" + }, + "homebridge": { + "available_update": "System", + "updates": "Updates", + "update_available": "Update Available", + "up_to_date": "Up to Date", + "child_bridges": "Child Bridges", + "child_bridges_status": "{{ok}}/{{total}}" + }, + "watchtower": { + "containers_scanned": "Scanned", + "containers_updated": "Updated", + "containers_failed": "Failed" + }, + "autobrr": { + "approvedPushes": "Approved", + "rejectedPushes": "Rejected", + "filters": "Filters", + "indexers": "Indexers" + }, + "tubearchivist": { + "downloads": "Queue", + "videos": "Videos", + "channels": "Channels", + "playlists": "Playlists" + }, + "truenas": { + "load": "System Load", + "uptime": "Uptime", + "time": "{{value, number(style: unit; unitDisplay: long;)}}", + "alerts": "Alerts" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" + } +} diff --git a/public/locales/hr/common.json b/public/locales/hr/common.json index 083faebd4..12c972625 100644 --- a/public/locales/hr/common.json +++ b/public/locales/hr/common.json @@ -189,8 +189,8 @@ "wan": "WAN", "lan_users": "LAN korisnici", "wlan_users": "WLAN korisnici", - "up": "Upaljen", - "down": "Ugašen", + "up": "SLANJE", + "down": "PRIMANJE", "wait": "Pričekaj", "lan": "LAN", "wlan": "WLAN", @@ -265,10 +265,10 @@ "86-night": "Snježni pljuskovi", "95-day": "Oluja", "95-night": "Oluja", - "96-day": "Oluja s grmljavinom", - "96-night": "Oluja s grmljavinom", - "99-day": "Oluja s grmljavinom", - "99-night": "Oluja s grmljavinom" + "96-day": "Oluja s tučom", + "96-night": "Oluja s tučom", + "99-day": "Oluja s tučom", + "99-night": "Oluja s tučom" }, "quicklaunch": { "bookmark": "Straničnik", @@ -304,5 +304,20 @@ "uptime": "Radno vrijeme", "alerts": "Upozorenja", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "Nema aktivnih prijenosa", + "please_wait": "Pričekaj" + }, + "pyload": { + "speed": "Brzina", + "active": "Aktivno", + "queue": "Red čekanja", + "total": "Ukupno" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/hu/common.json b/public/locales/hu/common.json index 3af2cd6b3..f00dc9750 100644 --- a/public/locales/hu/common.json +++ b/public/locales/hu/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/it/common.json b/public/locales/it/common.json index 52306bac2..9478d420d 100644 --- a/public/locales/it/common.json +++ b/public/locales/it/common.json @@ -123,11 +123,11 @@ "messages": "Messaggi" }, "prowlarr": { - "enableIndexers": "Indexers", + "enableIndexers": "Indicizzatori", "numberOfGrabs": "Grabs", "numberOfQueries": "Queries", - "numberOfFailGrabs": "Fail Grabs", - "numberOfFailQueries": "Fail Queries" + "numberOfFailGrabs": "Grabs Falliti", + "numberOfFailQueries": "Queries Fallite" }, "transmission": { "download": "Download", @@ -184,7 +184,7 @@ }, "unifi": { "users": "Utenti", - "uptime": "System Uptime", + "uptime": "Uptime di Sistema", "days": "Giorni", "wan": "WAN", "lan_users": "Utenti LAN", @@ -209,16 +209,16 @@ "wait": "Attendere prego" }, "changedetectionio": { - "totalObserved": "Total Observed", - "diffsDetected": "Diffs Detected" + "totalObserved": "Totale Osservato", + "diffsDetected": "Differenze Rilevate" }, "wmo": { - "65-day": "Heavy Rain", + "65-day": "Pioggia Intensa", "2-night": "Parzialmente Nuvoloso", "0-day": "Solleggiato", - "0-night": "Clear", - "1-day": "Mainly Sunny", - "1-night": "Mainly Clear", + "0-night": "Pulisci", + "1-day": "Principalmente Soleggiato", + "1-night": "Principalmente Sereno", "2-day": "Parzialmente Nuvoloso", "3-day": "Nuvoloso", "3-night": "Nuvoloso", @@ -232,37 +232,37 @@ "53-night": "Pioggerella", "55-day": "Pioggerella Pesante", "55-night": "Pioggerella Pesante", - "56-day": "Light Freezing Drizzle", - "56-night": "Light Freezing Drizzle", - "57-day": "Freezing Drizzle", - "57-night": "Freezing Drizzle", + "56-day": "Leggera Pioggia Gelata", + "56-night": "Leggera Pioggia Gelata", + "57-day": "Pioggerella Gelata", + "57-night": "Pioggerella Gelata", "61-day": "Pioggia Leggera", "61-night": "Pioggia Leggera", "63-day": "Pioggia", "63-night": "Pioggia", - "65-night": "Heavy Rain", + "65-night": "Pioggia Intensa", "66-day": "Grandine", "66-night": "Grandine", "67-day": "Grandine", "67-night": "Grandine", - "71-day": "Light Snow", - "71-night": "Light Snow", + "71-day": "Leggera Nevicata", + "71-night": "Leggera Nevicata", "73-day": "Neve", "73-night": "Neve", - "75-day": "Heavy Snow", - "75-night": "Heavy Snow", - "77-day": "Snow Grains", - "77-night": "Snow Grains", - "80-day": "Light Showers", - "80-night": "Light Showers", - "81-day": "Showers", - "81-night": "Showers", - "82-day": "Heavy Showers", - "82-night": "Heavy Showers", - "85-day": "Snow Showers", - "85-night": "Snow Showers", - "86-day": "Snow Showers", - "86-night": "Snow Showers", + "75-day": "Nevicata Intensa", + "75-night": "Nevicata Intensa", + "77-day": "Fiocchi di Neve", + "77-night": "Fiocchi di Neve", + "80-day": "Leggeri Rovesci", + "80-night": "Leggeri Rovesci", + "81-day": "Rovesci", + "81-night": "Rovesci", + "82-day": "Intensi Rovesci", + "82-night": "Intensi Rovesci", + "85-day": "Rovesci di Neve", + "85-night": "Rovesci di Neve", + "86-day": "Rovesci di Neve", + "86-night": "Rovesci di Neve", "95-day": "Temporale", "95-night": "Temporale", "96-day": "Temporale con grandine", @@ -271,38 +271,53 @@ "99-night": "Temporale con grandine" }, "quicklaunch": { - "bookmark": "Bookmark", + "bookmark": "Segnalibro", "service": "Servizio" }, "homebridge": { - "available_update": "System", - "updates": "Updates", - "update_available": "Update Available", - "up_to_date": "Up to Date", + "available_update": "Sistema", + "updates": "Aggiornamenti", + "update_available": "Aggiornamento Disponibile", + "up_to_date": "Aggiornato", "child_bridges": "Child Bridges", "child_bridges_status": "{{ok}}/{{total}}" }, "autobrr": { - "approvedPushes": "Approved", - "rejectedPushes": "Rejected", - "filters": "Filters", - "indexers": "Indexers" + "approvedPushes": "Approvato", + "rejectedPushes": "Rifiutato", + "filters": "Filtri", + "indexers": "Indicizzatori" }, "watchtower": { - "containers_scanned": "Scanned", - "containers_updated": "Updated", - "containers_failed": "Failed" + "containers_scanned": "Scansionato", + "containers_updated": "Aggiornato", + "containers_failed": "Fallito" }, "tubearchivist": { - "downloads": "Queue", - "videos": "Videos", - "channels": "Channels", + "downloads": "Coda", + "videos": "Video", + "channels": "Canali", "playlists": "Playlists" }, "truenas": { - "load": "System Load", + "load": "Carico di Sistema", "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "Nessun Sistema Attivo", + "please_wait": "Attendere, Prego" + }, + "pyload": { + "speed": "Velocità", + "active": "Attivo", + "queue": "Coda", + "total": "Totale" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/ms/common.json b/public/locales/ms/common.json new file mode 100644 index 000000000..761d85e91 --- /dev/null +++ b/public/locales/ms/common.json @@ -0,0 +1,323 @@ +{ + "resources": { + "cpu": "CPU", + "total": "Jumlah", + "free": "Bebas", + "used": "Telah diguna", + "load": "Beban" + }, + "unifi": { + "uptime": "Masa Operasi Sistem", + "users": "Pengguna", + "days": "Hari", + "wan": "WAN", + "lan": "LAN", + "wlan": "WLAN", + "devices": "Peranti", + "lan_devices": "Peranti LAN", + "wlan_devices": "Peranti WLAN", + "lan_users": "Pengguna LAN", + "wlan_users": "Pengguna WLAN", + "up": "HIDUP", + "down": "MATI", + "wait": "Sila tunggu" + }, + "lidarr": { + "queued": "Dibaris Gilir", + "albums": "Album", + "wanted": "Mahu" + }, + "readarr": { + "wanted": "Mahu", + "queued": "Dibaris Gilir", + "books": "Buku" + }, + "jellyseerr": { + "pending": "Tertangguh", + "approved": "Lulus", + "available": "Sudah Ada" + }, + "coinmarketcap": { + "30days": "30 Hari", + "configure": "Konfigurasikan satu atau lebih matawang crypto untuk dipantau", + "1hour": "1 Jam", + "1day": "1 Hari", + "7days": "7 Hari" + }, + "gotify": { + "apps": "Aplikasi", + "clients": "Klien", + "messages": "Mesej" + }, + "proxmox": { + "mem": "MEM", + "cpu": "CPU", + "lxc": "LXC", + "vms": "Mesin Maya" + }, + "glances": { + "cpu": "CPU", + "mem": "MEM", + "wait": "Sila tunggu" + }, + "quicklaunch": { + "bookmark": "Tandabuku", + "service": "Servis" + }, + "wmo": { + "0-day": "Terik", + "0-night": "Cerah", + "1-day": "Sebahagian Besar Terik", + "1-night": "Sebahagian Besar Cerah", + "63-day": "Hujan", + "63-night": "Hujan", + "2-day": "Sebahagian Mendung", + "2-night": "Sebahagian Mendung", + "3-day": "Mendung", + "3-night": "Mendung", + "45-day": "Berkabus", + "45-night": "Berkabus", + "48-day": "Berkabus", + "48-night": "Berkabus", + "51-day": "Gerimis", + "51-night": "Gerimis", + "53-day": "Renyai", + "53-night": "Renyai", + "55-day": "Renyai Kuat", + "55-night": "Renyai Kuat", + "56-day": "Gerimis Sejuk Ringan", + "56-night": "Gerimis Sejuk Ringan", + "57-day": "Gerimis Sejuk", + "57-night": "Gerimis Sejuk", + "61-day": "Hujan Renyai", + "61-night": "Hujan Renyai", + "65-day": "Hujan Lebat", + "65-night": "Hujan Lebat", + "66-day": "Hujan Sejuk", + "66-night": "Hujan Sejuk", + "67-day": "Hujan Sejuk", + "67-night": "Hujan Sejuk", + "71-day": "Salji Ringan", + "71-night": "Salji Ringan", + "73-day": "Salji", + "73-night": "Salji", + "75-day": "Salji Lebat", + "75-night": "Salji Lebat", + "81-day": "Rintik", + "77-day": "Butiran Salji", + "77-night": "Butiran Salji", + "80-day": "Rintik Ringan", + "80-night": "Rintik Ringan", + "81-night": "Rintik", + "82-day": "Rintik Lebat", + "82-night": "Rintik Lebat", + "85-day": "Rintik Salji", + "85-night": "Rintik Salji", + "86-day": "Rintik Salji", + "86-night": "Rintik Salji", + "95-day": "Ribut", + "95-night": "Ribut", + "96-day": "Ribut Hujan Batu", + "96-night": "Ribut Hujan Batu", + "99-day": "Ribut Hujan Batu", + "99-night": "Ribut Hujan Batu" + }, + "widget": { + "missing_type": "Jenis Widget Hilang: {{type}}", + "api_error": "Masalah API", + "status": "Status" + }, + "weather": { + "current": "Lokasi Sekarang", + "allow": "Klik untuk benarkan", + "updating": "Mengemas kini", + "wait": "Sila tunggu" + }, + "search": { + "placeholder": "Carian…" + }, + "nzbget": { + "remaining": "Baki", + "downloaded": "Telah Muat Turun", + "rate": "Kadar" + }, + "docker": { + "rx": "RX", + "tx": "TX", + "mem": "MEM", + "cpu": "CPU", + "offline": "Luar talian" + }, + "changedetectionio": { + "totalObserved": "Jumlah Diperhatikan", + "diffsDetected": "Perbezaan Dikesan" + }, + "emby": { + "playing": "Sedang dimainkan", + "transcoding": "Transkoding", + "bitrate": "Kadar bit", + "no_active": "Tiada Strim Aktif" + }, + "tautulli": { + "playing": "Sedang Dimainkan", + "transcoding": "Transkoding", + "bitrate": "Kadar bit", + "no_active": "Tiada Strim Aktif" + }, + "plex": { + "streams": "Strim Aktif", + "movies": "Filem", + "tv": "Rancangan TV" + }, + "sabnzbd": { + "rate": "Kadar", + "queue": "Barisan", + "timeleft": "Masa Tinggal" + }, + "rutorrent": { + "active": "Aktif", + "upload": "Muat Naik", + "download": "Muat Turun" + }, + "transmission": { + "leech": "Leech", + "download": "Muat Turun", + "upload": "Muat Naik", + "seed": "Seed" + }, + "qbittorrent": { + "download": "Muat Turun", + "upload": "Muat Naik", + "leech": "Leech", + "seed": "Seed" + }, + "sonarr": { + "wanted": "Mahu", + "queued": "Dibaris Gilir", + "series": "Bersiri" + }, + "radarr": { + "wanted": "Mahu", + "missing": "Hilang", + "queued": "Dibaris Gilir", + "movies": "Filem" + }, + "bazarr": { + "missingEpisodes": "Episod Yang Hilang", + "missingMovies": "Filem Yang Hilang" + }, + "ombi": { + "pending": "Tertunda", + "approved": "Lulus", + "available": "Sudah Ada" + }, + "overseerr": { + "pending": "Tertangguh", + "approved": "Lulus", + "available": "Sudah Ada" + }, + "pihole": { + "queries": "Permintaan", + "blocked": "Disekat", + "gravity": "Gravity" + }, + "adguard": { + "queries": "Permintaan", + "blocked": "Disekat", + "filtered": "Ditapis", + "latency": "Kependaman" + }, + "speedtest": { + "upload": "Muat Naik", + "download": "Muat Turun", + "ping": "Ping" + }, + "portainer": { + "running": "Sedang Berjalan", + "stopped": "Terhenti", + "total": "Jumlah" + }, + "traefik": { + "routers": "Router", + "services": "Servis", + "middleware": "Perisian Tengah" + }, + "npm": { + "enabled": "Didayakan", + "disabled": "Dinyahdayakan", + "total": "Jumlah" + }, + "prowlarr": { + "enableIndexers": "Pengindeks", + "numberOfGrabs": "Capai", + "numberOfQueries": "Permintaan", + "numberOfFailGrabs": "Capai Yang Ggagal", + "numberOfFailQueries": "Permintaan Yang Gagal" + }, + "jackett": { + "configured": "Telah Dikonfigurasi", + "errored": "Telah Tersalah" + }, + "strelaysrv": { + "numActiveSessions": "Sesi", + "numConnections": "Penyambungan", + "dataRelayed": "Disalurkan", + "transferRate": "Kadar" + }, + "mastodon": { + "user_count": "Pengguna", + "status_count": "Pos", + "domain_count": "Domain" + }, + "authentik": { + "users": "Pengguna", + "loginsLast24H": "Logmasuk (24j)", + "failedLoginsLast24H": "Logmasuk Gagal (24j)" + }, + "homebridge": { + "child_bridges_status": "{{ok}}/{{total}}", + "available_update": "Sistem", + "updates": "Kemaskini", + "update_available": "Kemaskini Tersedia", + "up_to_date": "Terkemaskini", + "child_bridges": "Jambatan Anak" + }, + "watchtower": { + "containers_scanned": "Terimbas", + "containers_updated": "Dikemaskini", + "containers_failed": "Gagal" + }, + "autobrr": { + "approvedPushes": "Lulus", + "rejectedPushes": "Ditolak", + "filters": "Tapisan", + "indexers": "Pengindeks" + }, + "tubearchivist": { + "downloads": "Baris Gilir", + "videos": "Video", + "channels": "Saluran", + "playlists": "Senarai Siar" + }, + "truenas": { + "load": "Beban Sistem", + "uptime": "Masa Hidup", + "alerts": "Amaran", + "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "Tiada Strim Aktif", + "please_wait": "Sila tunggu" + }, + "pyload": { + "speed": "Kelajuan", + "active": "Aktif", + "queue": "Baris Gilir", + "total": "Jumlah" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" + } +} diff --git a/public/locales/nb-NO/common.json b/public/locales/nb-NO/common.json index 3b54e638d..0f7680f76 100644 --- a/public/locales/nb-NO/common.json +++ b/public/locales/nb-NO/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/nl/common.json b/public/locales/nl/common.json index bd53b72b0..ae5cd06e4 100644 --- a/public/locales/nl/common.json +++ b/public/locales/nl/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "total": "Total", + "queue": "Queue" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/pl/common.json b/public/locales/pl/common.json index d29ba7762..41495b3e2 100644 --- a/public/locales/pl/common.json +++ b/public/locales/pl/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "please_wait": "Please Wait", + "nothing_streaming": "No Active Streams" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/pt-BR/common.json b/public/locales/pt-BR/common.json index 899606f62..a73d6b483 100644 --- a/public/locales/pt-BR/common.json +++ b/public/locales/pt-BR/common.json @@ -209,8 +209,8 @@ "wait": "Please wait" }, "changedetectionio": { - "totalObserved": "Total Observed", - "diffsDetected": "Diffs Detected" + "totalObserved": "Observados", + "diffsDetected": "Mudanças" }, "wmo": { "1-night": "Mainly Clear", @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/pt/common.json b/public/locales/pt/common.json index a802e1c00..5f22a5b85 100644 --- a/public/locales/pt/common.json +++ b/public/locales/pt/common.json @@ -315,5 +315,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "queue": "Queue", + "total": "Total", + "speed": "Speed", + "active": "Active" + }, + "gluetun": { + "region": "Region", + "country": "Country", + "public_ip": "Public IP" } } diff --git a/public/locales/ro/common.json b/public/locales/ro/common.json index 3927aa00d..a57ea01b0 100644 --- a/public/locales/ro/common.json +++ b/public/locales/ro/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/ru/common.json b/public/locales/ru/common.json index 13912bd5b..762b3e904 100644 --- a/public/locales/ru/common.json +++ b/public/locales/ru/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/sr/common.json b/public/locales/sr/common.json index 5eab21931..8fe0a6e0f 100644 --- a/public/locales/sr/common.json +++ b/public/locales/sr/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/sv/common.json b/public/locales/sv/common.json index 83bce2698..87f2061f0 100644 --- a/public/locales/sv/common.json +++ b/public/locales/sv/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/te/common.json b/public/locales/te/common.json index cbe1bce55..7ad2daceb 100644 --- a/public/locales/te/common.json +++ b/public/locales/te/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/tr/common.json b/public/locales/tr/common.json index c145d4bff..f431239de 100644 --- a/public/locales/tr/common.json +++ b/public/locales/tr/common.json @@ -213,96 +213,111 @@ "diffsDetected": "Farklar Algılandı" }, "wmo": { - "99-day": "Thunderstorm With Hail", - "0-day": "Sunny", - "0-night": "Clear", - "1-day": "Mainly Sunny", - "1-night": "Mainly Clear", - "2-day": "Partly Cloudy", - "2-night": "Partly Cloudy", - "3-day": "Cloudy", - "3-night": "Cloudy", - "45-day": "Foggy", - "45-night": "Foggy", - "48-day": "Foggy", - "48-night": "Foggy", - "51-day": "Light Drizzle", - "51-night": "Light Drizzle", - "53-day": "Drizzle", - "53-night": "Drizzle", - "55-day": "Heavy Drizzle", - "55-night": "Heavy Drizzle", - "56-day": "Light Freezing Drizzle", - "56-night": "Light Freezing Drizzle", - "57-day": "Freezing Drizzle", - "57-night": "Freezing Drizzle", - "61-day": "Light Rain", - "61-night": "Light Rain", - "63-day": "Rain", - "63-night": "Rain", - "65-day": "Heavy Rain", - "65-night": "Heavy Rain", - "66-day": "Freezing Rain", - "66-night": "Freezing Rain", - "67-day": "Freezing Rain", - "67-night": "Freezing Rain", - "71-day": "Light Snow", - "71-night": "Light Snow", - "73-day": "Snow", - "73-night": "Snow", - "75-day": "Heavy Snow", - "75-night": "Heavy Snow", - "77-day": "Snow Grains", - "77-night": "Snow Grains", - "80-day": "Light Showers", - "80-night": "Light Showers", - "81-day": "Showers", - "81-night": "Showers", - "82-day": "Heavy Showers", - "95-night": "Thunderstorm", - "82-night": "Heavy Showers", - "85-day": "Snow Showers", - "85-night": "Snow Showers", - "86-day": "Snow Showers", - "86-night": "Snow Showers", - "95-day": "Thunderstorm", - "96-day": "Thunderstorm With Hail", - "96-night": "Thunderstorm With Hail", - "99-night": "Thunderstorm With Hail" + "99-day": "Dolu İle Gök Gürültülü Fırtına", + "0-day": "Güneşli", + "0-night": "Açık", + "1-day": "Çoğunlukla Güneşli", + "1-night": "Çoğunlukla Açık", + "2-day": "Parçalı Bulutlu", + "2-night": "Parçalı Bulutlu", + "3-day": "Bulutlu", + "3-night": "Bulutlu", + "45-day": "Sisli", + "45-night": "Sisli", + "48-day": "Sisli", + "48-night": "Sisli", + "51-day": "Az Çiseleyen Yağmur", + "51-night": "Az Çiseleyen Yağmur", + "53-day": "Çiseleyen Yağmur", + "53-night": "Çiseleyen Yağmur", + "55-day": "Çok Çiseleyen Yağmur", + "55-night": "Çok Çiseleyen Yağmur", + "56-day": "Soğuk Az Çiseleyen Yağmur", + "56-night": "Soğuk Az Çiseleyen Yağmur", + "57-day": "Soğuk Çiseleyen Yağmur", + "57-night": "Soğuk Çiseleyen Yağmur", + "61-day": "Hafif Yağmur", + "61-night": "Hafif Yağmur", + "63-day": "Yağmur", + "63-night": "Yağmur", + "65-day": "Çok Yağmur", + "65-night": "Çok Yağmur", + "66-day": "Dondurucu Yağmur", + "66-night": "Dondurucu Yağmur", + "67-day": "Dondurucu Yağmur", + "67-night": "Dondurucu Yağmur", + "71-day": "Hafif Kar", + "71-night": "Hafif Kar", + "73-day": "Kar", + "73-night": "Kar", + "75-day": "Çok Kar", + "75-night": "Çok Kar", + "77-day": "Kar Taneleri", + "77-night": "Kar Taneleri", + "80-day": "Hafif Sağanak", + "80-night": "Hafif Sağanak", + "81-day": "Sağanak", + "81-night": "Sağanak", + "82-day": "Yoğun Sağanak", + "95-night": "Gök Gürültülü Fırtına", + "82-night": "Yoğun Sağanak", + "85-day": "Karlı Sağanak", + "85-night": "Karlı Sağanak", + "86-day": "Karlı Sağanak", + "86-night": "Karlı Sağanak", + "95-day": "Gök Gürültülü Fırtına", + "96-day": "Dolu İle Gök Gürültülü Fırtına", + "96-night": "Dolu İle Gök Gürültülü Fırtına", + "99-night": "Dolu İle Gök Gürültülü Fırtına" }, "quicklaunch": { - "bookmark": "Bookmark", - "service": "Service" + "bookmark": "Yer İmi", + "service": "Hizmet" }, "homebridge": { - "available_update": "System", - "updates": "Updates", - "update_available": "Update Available", - "up_to_date": "Up to Date", - "child_bridges": "Child Bridges", + "available_update": "Sistem", + "updates": "Güncellemeler", + "update_available": "Güncelleme Kullanılabilir", + "up_to_date": "Güncel", + "child_bridges": "Alt Köprüler", "child_bridges_status": "{{ok}}/{{total}}" }, "autobrr": { - "approvedPushes": "Approved", - "rejectedPushes": "Rejected", - "filters": "Filters", - "indexers": "Indexers" + "approvedPushes": "Onaylandı", + "rejectedPushes": "Reddedildi", + "filters": "Süzgeçler", + "indexers": "Dizin Oluşturucular" }, "watchtower": { - "containers_scanned": "Scanned", - "containers_updated": "Updated", - "containers_failed": "Failed" + "containers_scanned": "Tarandı", + "containers_updated": "Güncellendi", + "containers_failed": "Başarısız" }, "tubearchivist": { - "downloads": "Queue", - "videos": "Videos", - "channels": "Channels", - "playlists": "Playlists" + "downloads": "Kuyruk", + "videos": "Videolar", + "channels": "Kanallar", + "playlists": "Oynatma Listeleri" }, "truenas": { - "load": "System Load", - "uptime": "Uptime", - "alerts": "Alerts", + "load": "Sistem Yükü", + "uptime": "Çalışma Süresi", + "alerts": "Alarmlar", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "Geçerli Akış Yok", + "please_wait": "Lütfen Bekleyin" + }, + "pyload": { + "speed": "Hız", + "active": "Geçerli", + "queue": "Kuyruk", + "total": "Toplam" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/vi/common.json b/public/locales/vi/common.json index 593b9c18d..cf3db360a 100644 --- a/public/locales/vi/common.json +++ b/public/locales/vi/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/yue/common.json b/public/locales/yue/common.json index b36caac6c..7932f9088 100644 --- a/public/locales/yue/common.json +++ b/public/locales/yue/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/zh-CN/common.json b/public/locales/zh-CN/common.json index 2a09311d5..5459d7c69 100644 --- a/public/locales/zh-CN/common.json +++ b/public/locales/zh-CN/common.json @@ -47,7 +47,7 @@ "wanted": "想看", "queued": "队列", "movies": "电影", - "missing": "Missing" + "missing": "丢失" }, "readarr": { "wanted": "订阅", @@ -192,11 +192,11 @@ "up": "向上", "down": "向下", "wait": "请稍候", - "lan": "LAN", - "wlan": "WLAN", - "devices": "Devices", - "lan_devices": "LAN Devices", - "wlan_devices": "WLAN Devices" + "lan": "局域网", + "wlan": "无线局域网", + "devices": "设备", + "lan_devices": "局域网设备", + "wlan_devices": "无线局域网设备" }, "plex": { "streams": "活动流", @@ -209,26 +209,26 @@ "wait": "请稍等" }, "changedetectionio": { - "totalObserved": "Total Observed", - "diffsDetected": "Diffs Detected" + "totalObserved": "观察到的总数", + "diffsDetected": "检测到差异" }, "wmo": { - "0-day": "Sunny", - "0-night": "Clear", - "1-day": "Mainly Sunny", - "3-day": "Cloudy", - "3-night": "Cloudy", - "45-day": "Foggy", - "48-day": "Foggy", - "51-day": "Light Drizzle", + "0-day": "晴天", + "0-night": "晴朗", + "1-day": "主要是晴天", + "3-day": "阴天", + "3-night": "阴天", + "45-day": "有雾", + "48-day": "有雾", + "51-day": "小雨", "73-night": "Snow", "75-day": "Heavy Snow", - "1-night": "Mainly Clear", - "2-day": "Partly Cloudy", - "2-night": "Partly Cloudy", - "45-night": "Foggy", - "48-night": "Foggy", - "51-night": "Light Drizzle", + "1-night": "大部晴朗", + "2-day": "多云", + "2-night": "多云", + "45-night": "有雾", + "48-night": "有雾", + "51-night": "小雨", "53-day": "Drizzle", "53-night": "Drizzle", "55-day": "Heavy Drizzle", @@ -271,8 +271,8 @@ "99-night": "Thunderstorm With Hail" }, "quicklaunch": { - "bookmark": "Bookmark", - "service": "Service" + "bookmark": "书签", + "service": "服务" }, "homebridge": { "available_update": "System", @@ -302,7 +302,22 @@ "truenas": { "load": "System Load", "uptime": "Uptime", - "alerts": "Alerts", + "alerts": "警报", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "暂无播放", + "please_wait": "请等待" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/public/locales/zh-Hant/common.json b/public/locales/zh-Hant/common.json index 24b885900..c4673c322 100644 --- a/public/locales/zh-Hant/common.json +++ b/public/locales/zh-Hant/common.json @@ -304,5 +304,20 @@ "uptime": "Uptime", "alerts": "Alerts", "time": "{{value, number(style: unit; unitDisplay: long;)}}" + }, + "navidrome": { + "nothing_streaming": "No Active Streams", + "please_wait": "Please Wait" + }, + "pyload": { + "speed": "Speed", + "active": "Active", + "queue": "Queue", + "total": "Total" + }, + "gluetun": { + "public_ip": "Public IP", + "region": "Region", + "country": "Country" } } diff --git a/src/components/bookmarks/group.jsx b/src/components/bookmarks/group.jsx index 1eb86e1a3..2910245c3 100644 --- a/src/components/bookmarks/group.jsx +++ b/src/components/bookmarks/group.jsx @@ -3,7 +3,7 @@ import List from "components/bookmarks/list"; export default function BookmarksGroup({ group }) { return ( -
+

{group.name}

diff --git a/src/components/resolvedicon.jsx b/src/components/resolvedicon.jsx index d973ab4b2..2a3701e83 100644 --- a/src/components/resolvedicon.jsx +++ b/src/components/resolvedicon.jsx @@ -14,8 +14,8 @@ export default function ResolvedIcon({ icon }) { style={{ width: 32, height: 32, - 'max-width': '100%', - 'max-height': '100%', + maxWidth: '100%', + maxHeight: '100%', background: "linear-gradient(180deg, rgb(var(--color-logo-start)), rgb(var(--color-logo-stop)))", mask: `url(https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/${iconName}.svg) no-repeat center / contain`, WebkitMask: `url(https://cdn.jsdelivr.net/npm/@mdi/svg@latest/svg/${iconName}.svg) no-repeat center / contain`, diff --git a/src/components/services/widget/block.jsx b/src/components/services/widget/block.jsx index 00a507720..2af53fff0 100644 --- a/src/components/services/widget/block.jsx +++ b/src/components/services/widget/block.jsx @@ -7,7 +7,7 @@ export default function Block({ value, label }) { return (
diff --git a/src/components/widgets/openweathermap/weather.jsx b/src/components/widgets/openweathermap/weather.jsx index 6a1f2a16d..49f428a04 100644 --- a/src/components/widgets/openweathermap/weather.jsx +++ b/src/components/widgets/openweathermap/weather.jsx @@ -54,7 +54,7 @@ function Widget({ options }) {
data.sys.sunrise && data.dt < data.sys.sundown ? "day" : "night"} + timeOfDay={data.dt > data.sys.sunrise && data.dt < data.sys.sunset ? "day" : "night"} />
diff --git a/src/pages/index.jsx b/src/pages/index.jsx index 88c25cc47..d9e79786f 100644 --- a/src/pages/index.jsx +++ b/src/pages/index.jsx @@ -272,7 +272,7 @@ function Home({ initialSettings }) { )} {bookmarks && ( -
+
{bookmarks.map((group) => ( ))} diff --git a/src/widgets/components.js b/src/widgets/components.js index 026f9dade..7dc7fcaca 100644 --- a/src/widgets/components.js +++ b/src/widgets/components.js @@ -10,6 +10,7 @@ const components = { docker: dynamic(() => import("./docker/component")), kubernetes: dynamic(() => import("./kubernetes/component")), emby: dynamic(() => import("./emby/component")), + gluetun: dynamic(() => import("./gluetun/component")), gotify: dynamic(() => import("./gotify/component")), homebridge: dynamic(() => import("./homebridge/component")), jackett: dynamic(() => import("./jackett/component")), @@ -17,6 +18,7 @@ const components = { jellyseerr: dynamic(() => import("./jellyseerr/component")), lidarr: dynamic(() => import("./lidarr/component")), mastodon: dynamic(() => import("./mastodon/component")), + navidrome: dynamic(() => import("./navidrome/component")), npm: dynamic(() => import("./npm/component")), nzbget: dynamic(() => import("./nzbget/component")), ombi: dynamic(() => import("./ombi/component")), @@ -26,6 +28,7 @@ const components = { portainer: dynamic(() => import("./portainer/component")), prowlarr: dynamic(() => import("./prowlarr/component")), proxmox: dynamic(() => import("./proxmox/component")), + pyload: dynamic(() => import("./pyload/component")), qbittorrent: dynamic(() => import("./qbittorrent/component")), radarr: dynamic(() => import("./radarr/component")), readarr: dynamic(() => import("./readarr/component")), diff --git a/src/widgets/gluetun/component.jsx b/src/widgets/gluetun/component.jsx new file mode 100644 index 000000000..f20c400b9 --- /dev/null +++ b/src/widgets/gluetun/component.jsx @@ -0,0 +1,35 @@ +import { useTranslation } from "next-i18next"; + +import Container from "components/services/widget/container"; +import Block from "components/services/widget/block"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + +export default function Component({ service }) { + const { t } = useTranslation(); + + const { widget } = service; + + const { data: gluetunData, error: gluetunError } = useWidgetAPI(widget, "ip"); + + if (gluetunError) { + return ; + } + + if (!gluetunData) { + return ( + + + + + + ); + } + + return ( + + + + + + ); +} diff --git a/src/widgets/gluetun/widget.js b/src/widgets/gluetun/widget.js new file mode 100644 index 000000000..59aa39efe --- /dev/null +++ b/src/widgets/gluetun/widget.js @@ -0,0 +1,14 @@ +import genericProxyHandler from "utils/proxy/handlers/generic"; + +const widget = { + api: "{url}/v1/{endpoint}", + proxyHandler: genericProxyHandler, + + mappings: { + ip: { + endpoint: "publicip/ip", + }, + }, +}; + +export default widget; diff --git a/src/widgets/navidrome/component.jsx b/src/widgets/navidrome/component.jsx new file mode 100644 index 000000000..f4f3e6721 --- /dev/null +++ b/src/widgets/navidrome/component.jsx @@ -0,0 +1,56 @@ +import { useTranslation } from "next-i18next"; + +import Container from "components/services/widget/container"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + +function SinglePlayingEntry({ entry }) { + const { username, artist, title, album } = entry; + let fullTitle = title; + if (artist) fullTitle = `${artist} - ${title}`; + if (album) fullTitle += ` — ${album}`; + if (username) fullTitle += ` (${username})`; + + return ( +
+
+
{fullTitle}
+
+
+ ); +} + +export default function Component({ service }) { + const { t } = useTranslation(); + + const { widget } = service; + + const { data: navidromeData, error: navidromeError } = useWidgetAPI(widget, "getNowPlaying"); + + if (navidromeError || navidromeData?.error || navidromeData?.["subsonic-response"]?.error) { + return ; + } + + if (!navidromeData) { + return ( + + ); + } + + const { nowPlaying } = navidromeData["subsonic-response"]; + if (!nowPlaying.entry) { + // nothing playing + return ( + + ); + } + + const nowPlayingEntries = Object.values(nowPlaying.entry); + + return ( +
+ {nowPlayingEntries.map((entry) => ( + + ))} +
+ ); +} diff --git a/src/widgets/navidrome/widget.js b/src/widgets/navidrome/widget.js new file mode 100644 index 000000000..9d7c03d45 --- /dev/null +++ b/src/widgets/navidrome/widget.js @@ -0,0 +1,14 @@ +import genericProxyHandler from "utils/proxy/handlers/generic"; + +const widget = { + api: "{url}/rest/{endpoint}?u={user}&t={token}&s={salt}&v=1.16.1&c=homepage&f=json", + proxyHandler: genericProxyHandler, + + mappings: { + "getNowPlaying": { + endpoint: "getNowPlaying", + }, + }, +}; + +export default widget; diff --git a/src/widgets/npm/component.jsx b/src/widgets/npm/component.jsx index b35e27c85..92aef0359 100644 --- a/src/widgets/npm/component.jsx +++ b/src/widgets/npm/component.jsx @@ -11,7 +11,7 @@ export default function Component({ service }) { const { data: infoData, error: infoError } = useWidgetAPI(widget, "nginx/proxy-hosts"); - if (infoError) { + if (infoError || infoData?.error) { return ; } diff --git a/src/widgets/npm/proxy.js b/src/widgets/npm/proxy.js index eed43b571..ff15db62b 100644 --- a/src/widgets/npm/proxy.js +++ b/src/widgets/npm/proxy.js @@ -1,6 +1,33 @@ +import cache from "memory-cache"; + import getServiceWidget from "utils/config/service-helpers"; import { formatApiCall } from "utils/proxy/api-helpers"; +import { httpProxy } from "utils/proxy/http"; import widgets from "widgets/widgets"; +import createLogger from "utils/logger"; + +const proxyName = "npmProxyHandler"; +const tokenCacheKey = `${proxyName}__token`; +const logger = createLogger(proxyName); + +async function login(loginUrl, username, password) { + const authResponse = await httpProxy(loginUrl, { + method: "POST", + body: JSON.stringify({ identity: username, secret: password }), + headers: { + "Content-Type": "application/json", + }, + }); + + const status = authResponse[0]; + const data = JSON.parse(Buffer.from(authResponse[2]).toString()); + + if (status === 200) { + cache.put(tokenCacheKey, data.token); + } + + return [status, data.token ?? data]; +} export default async function npmProxyHandler(req, res) { const { group, service, endpoint } = req.query; @@ -14,27 +41,54 @@ export default async function npmProxyHandler(req, res) { if (widget) { const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget })); - const loginUrl = `${widget.url}/api/tokens`; - const body = { identity: widget.username, secret: widget.password }; - const authResponse = await fetch(loginUrl, { - method: "POST", - body: JSON.stringify(body), - headers: { - "Content-Type": "application/json", - }, - }).then((response) => response.json()); + let status; + let contentType; + let data; + + let token = cache.get(tokenCacheKey); + if (!token) { + [status, token] = await login(loginUrl, widget.username, widget.password); + if (status !== 200) { + logger.debug(`HTTTP ${status} logging into npm api: ${data}`); + return res.status(status).send(data); + } + } - const apiResponse = await fetch(url, { + [status, contentType, data] = await httpProxy(url, { method: "GET", headers: { "Content-Type": "application/json", - Authorization: `Bearer ${authResponse.token}`, + Authorization: `Bearer ${token}`, }, - }).then((response) => response.json()); + }); + + if (status === 403) { + logger.debug(`HTTTP ${status} retrieving data from npm api, logging in and trying again.`); + cache.del(tokenCacheKey); + [status, token] = await login(loginUrl, widget.username, widget.password); + + if (status !== 200) { + logger.debug(`HTTTP ${status} logging into npm api: ${data}`); + return res.status(status).send(data); + } + + // eslint-disable-next-line no-unused-vars + [status, contentType, data] = await httpProxy(url, { + method: "GET", + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${token}`, + }, + }); + } + + if (status !== 200) { + return res.status(status).send(data); + } - return res.send(apiResponse); + return res.send(data); } } diff --git a/src/widgets/pyload/component.jsx b/src/widgets/pyload/component.jsx new file mode 100644 index 000000000..958733c31 --- /dev/null +++ b/src/widgets/pyload/component.jsx @@ -0,0 +1,35 @@ +import { useTranslation } from 'next-i18next' + +import Container from "components/services/widget/container"; +import Block from "components/services/widget/block"; +import useWidgetAPI from "utils/proxy/use-widget-api"; + +export default function Component({ service }) { + const { t } = useTranslation(); + const { widget } = service; + const { data: pyloadData, error: pyloadError } = useWidgetAPI(widget, "status"); + + if (pyloadError || pyloadData?.error) { + return ; + } + + if (!pyloadData) { + return ( + + + + + + + ); + } + + return ( + + + + + + + ); +} diff --git a/src/widgets/pyload/proxy.js b/src/widgets/pyload/proxy.js new file mode 100644 index 000000000..46b28684a --- /dev/null +++ b/src/widgets/pyload/proxy.js @@ -0,0 +1,102 @@ +import cache from 'memory-cache'; + +import getServiceWidget from 'utils/config/service-helpers'; +import { formatApiCall } from 'utils/proxy/api-helpers'; +import widgets from 'widgets/widgets'; +import createLogger from 'utils/logger'; +import { httpProxy } from 'utils/proxy/http'; + +const proxyName = 'pyloadProxyHandler'; +const logger = createLogger(proxyName); +const sessionCacheKey = `${proxyName}__sessionId`; +const isNgCacheKey = `${proxyName}__isNg`; + +async function fetchFromPyloadAPI(url, sessionId, params) { + const options = { + body: params + ? Object.keys(params) + .map((prop) => `${prop}=${params[prop]}`) + .join('&') + : `session=${sessionId}`, + method: 'POST', + headers: { + 'Content-Type': 'application/x-www-form-urlencoded', + }, + }; + + // see https://github.com/benphelps/homepage/issues/517 + const isNg = cache.get(isNgCacheKey); + if (isNg && !params) { + delete options.body; + options.headers.Cookie = cache.get(sessionCacheKey); + } + + // eslint-disable-next-line no-unused-vars + const [status, contentType, data, responseHeaders] = await httpProxy(url, options); + let returnData; + try { + returnData = JSON.parse(Buffer.from(data).toString()); + } catch(e) { + logger.error(`Error logging into pyload API: ${JSON.stringify(data)}`); + returnData = data; + } + return [status, returnData, responseHeaders]; +} + +async function login(loginUrl, username, password = '') { + const [status, sessionId, responseHeaders] = await fetchFromPyloadAPI(loginUrl, null, { username, password }); + + // this API actually returns status 200 even on login failure + if (status !== 200 || sessionId === false) { + logger.error(`HTTP ${status} logging into Pyload API, returned: ${JSON.stringify(sessionId)}`); + } else if (responseHeaders['set-cookie']?.join().includes('pyload_session')) { + // Support pyload-ng, see https://github.com/benphelps/homepage/issues/517 + cache.put(isNgCacheKey, true); + const sessionCookie = responseHeaders['set-cookie'][0]; + cache.put(sessionCacheKey, sessionCookie, 60 * 60 * 23 * 1000); // cache for 23h + } else { + cache.put(sessionCacheKey, sessionId); + } + + return sessionId; +} + +export default async function pyloadProxyHandler(req, res) { + const { group, service, endpoint } = req.query; + + try { + if (group && service) { + const widget = await getServiceWidget(group, service); + + if (widget) { + const url = new URL(formatApiCall(widgets[widget.type].api, { endpoint, ...widget })); + const loginUrl = `${widget.url}/api/login`; + + let sessionId = cache.get(sessionCacheKey) ?? await login(loginUrl, widget.username, widget.password); + let [status, data] = await fetchFromPyloadAPI(url, sessionId); + + if (status === 403 || status === 401) { + logger.info('Failed to retrieve data from Pyload API, trying to login again...'); + cache.del(sessionCacheKey); + sessionId = await login(loginUrl, widget.username, widget.password); + [status, data] = await fetchFromPyloadAPI(url, sessionId); + } + + if (data?.error || status !== 200) { + try { + return res.status(status).send(Buffer.from(data).toString()); + } catch (e) { + return res.status(status).send(data); + } + } + + return res.json(data); + } + } + } catch (e) { + logger.error(e); + return res.status(500).send(e.toString()); + } + + return res.status(400).json({ error: 'Invalid proxy service type' }); +} diff --git a/src/widgets/pyload/widget.js b/src/widgets/pyload/widget.js new file mode 100644 index 000000000..71073c0f1 --- /dev/null +++ b/src/widgets/pyload/widget.js @@ -0,0 +1,14 @@ +import pyloadProxyHandler from "./proxy"; + +const widget = { + api: "{url}/api/{endpoint}", + proxyHandler: pyloadProxyHandler, + + mappings: { + "status": { + endpoint: "statusServer", + } + } +} + +export default widget; diff --git a/src/widgets/widgets.js b/src/widgets/widgets.js index 7bad4013b..66e29086a 100644 --- a/src/widgets/widgets.js +++ b/src/widgets/widgets.js @@ -5,12 +5,14 @@ import bazarr from "./bazarr/widget"; import changedetectionio from "./changedetectionio/widget"; import coinmarketcap from "./coinmarketcap/widget"; import emby from "./emby/widget"; +import gluetun from "./gluetun/widget"; import gotify from "./gotify/widget"; import homebridge from "./homebridge/widget"; import jackett from "./jackett/widget"; import jellyseerr from "./jellyseerr/widget"; import lidarr from "./lidarr/widget"; import mastodon from "./mastodon/widget"; +import navidrome from "./navidrome/widget"; import npm from "./npm/widget"; import nzbget from "./nzbget/widget"; import ombi from "./ombi/widget"; @@ -20,6 +22,7 @@ import plex from "./plex/widget"; import portainer from "./portainer/widget"; import prowlarr from "./prowlarr/widget"; import proxmox from "./proxmox/widget"; +import pyload from "./pyload/widget"; import qbittorrent from "./qbittorrent/widget"; import radarr from "./radarr/widget"; import readarr from "./readarr/widget"; @@ -44,6 +47,7 @@ const widgets = { changedetectionio, coinmarketcap, emby, + gluetun, gotify, homebridge, jackett, @@ -51,6 +55,7 @@ const widgets = { jellyseerr, lidarr, mastodon, + navidrome, npm, nzbget, ombi, @@ -60,6 +65,7 @@ const widgets = { portainer, prowlarr, proxmox, + pyload, qbittorrent, radarr, readarr,