Merge branch 'benphelps:main' into kubernetes

pull/448/head
James Wynn 2 years ago committed by GitHub
commit 1ca61114ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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": []
}

@ -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
<!-- prettier-ignore-end -->
<!-- ALL-CONTRIBUTORS-LIST:END -->
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
[![All Contributors](https://img.shields.io/badge/all_contributors-13-orange.svg?style=flat-square)](#contributors)
<!-- ALL-CONTRIBUTORS-BADGE:END -->

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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": "",
"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": "",
"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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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": "ı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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -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"
}
}

@ -3,7 +3,7 @@ import List from "components/bookmarks/list";
export default function BookmarksGroup({ group }) {
return (
<div key={group.name} className="basis-full md:basis-1/2 lg:basis-1/3 xl:basis-1/4 flex-1">
<div key={group.name} className="flex-1">
<h2 className="text-theme-800 dark:text-theme-300 text-xl font-medium">{group.name}</h2>
<ErrorBoundary>
<List bookmarks={group.bookmarks} />

@ -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`,

@ -7,7 +7,7 @@ export default function Block({ value, label }) {
return (
<div
className={classNames(
"bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center p-1",
"bg-theme-200/50 dark:bg-theme-900/20 rounded m-1 flex-1 flex flex-col items-center justify-center text-center p-1",
value === undefined ? "animate-pulse" : ""
)}
>

@ -54,7 +54,7 @@ function Widget({ options }) {
<div className="hidden sm:flex flex-col items-center">
<Icon
condition={data.weather[0].id}
timeOfDay={data.dt > data.sys.sunrise && data.dt < data.sys.sundown ? "day" : "night"}
timeOfDay={data.dt > data.sys.sunrise && data.dt < data.sys.sunset ? "day" : "night"}
/>
</div>
<div className="flex flex-col ml-3 text-left">

@ -272,7 +272,7 @@ function Home({ initialSettings }) {
)}
{bookmarks && (
<div className="grow flex flex-wrap pt-0 p-4 sm:p-8 gap-x-2">
<div className={`grow flex flex-wrap pt-0 p-4 sm:p-8 gap-2 grid-cols-1 lg:grid-cols-2 lg:grid-cols-${Math.min(6, bookmarks.length)}`}>
{bookmarks.map((group) => (
<BookmarksGroup key={group.name} group={group} />
))}

@ -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")),

@ -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 <Container error={t("widget.api_error")} />;
}
if (!gluetunData) {
return (
<Container service={service}>
<Block label="gluetun.public_ip" />
<Block label="gluetun.region" />
<Block label="gluetun.country" />
</Container>
);
}
return (
<Container service={service}>
<Block label="gluetun.public_ip" value={gluetunData.public_ip} />
<Block label="gluetun.region" value={gluetunData.region} />
<Block label="gluetun.country" value={gluetunData.country} />
</Container>
);
}

@ -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;

@ -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 (
<div className="text-theme-700 dark:text-theme-200 relative h-5 w-full rounded-md bg-theme-200/50 dark:bg-theme-900/20 mt-1 flex">
<div className="text-xs z-10 self-center ml-2 relative w-full h-4 grow mr-2">
<div className="absolute w-full whitespace-nowrap text-ellipsis overflow-hidden">{fullTitle}</div>
</div>
</div>
);
}
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 <Container error={t("widget.api_error")} />;
}
if (!navidromeData) {
return (
<SinglePlayingEntry entry={{ title: t("navidrome.please_wait") }} />
);
}
const { nowPlaying } = navidromeData["subsonic-response"];
if (!nowPlaying.entry) {
// nothing playing
return (
<SinglePlayingEntry entry={{ title: t("navidrome.nothing_streaming") }} />
);
}
const nowPlayingEntries = Object.values(nowPlaying.entry);
return (
<div className="flex flex-col pb-1 mx-1">
{nowPlayingEntries.map((entry) => (
<SinglePlayingEntry key={entry.id} entry={entry} />
))}
</div>
);
}

@ -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;

@ -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 <Container error={t("widget.api_error")} />;
}

@ -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);
}
}

@ -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 <Container error={t("widget.api_error")} />;
}
if (!pyloadData) {
return (
<Container service={service}>
<Block label="pyload.speed" />
<Block label="pyload.active" />
<Block label="pyload.queue" />
<Block label="pyload.total" />
</Container>
);
}
return (
<Container service={service}>
<Block label="pyload.speed" value={t("common.bitrate", { value: pyloadData.speed })} />
<Block label="pyload.active" value={t("common.number", { value: pyloadData.active })} />
<Block label="pyload.queue" value={t("common.number", { value: pyloadData.queue })} />
<Block label="pyload.total" value={t("common.number", { value: pyloadData.total })} />
</Container>
);
}

@ -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' });
}

@ -0,0 +1,14 @@
import pyloadProxyHandler from "./proxy";
const widget = {
api: "{url}/api/{endpoint}",
proxyHandler: pyloadProxyHandler,
mappings: {
"status": {
endpoint: "statusServer",
}
}
}
export default widget;

@ -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,

Loading…
Cancel
Save