Merge remote-tracking branch 'upstream/main' into main

This commit is contained in:
KillahBee 2023-01-31 11:34:08 -05:00
commit b1fbbf2264
51 changed files with 1221 additions and 332 deletions

View File

@ -3,16 +3,16 @@
"missing_type": "نوع القطعة مفقود: {{type}}", "missing_type": "نوع القطعة مفقود: {{type}}",
"api_error": "API خطأ", "api_error": "API خطأ",
"status": "الحالة", "status": "الحالة",
"information": "Information", "information": "معلومات",
"url": "URL", "url": "URL",
"raw_error": "Raw Error", "raw_error": "Raw Error",
"response_data": "Response Data" "response_data": "بيانات الاستجابة"
}, },
"weather": { "weather": {
"current": "الموقع الحالي", "current": "الموقع الحالي",
"allow": "اضغط للسماح", "allow": "أنقر للسماح",
"updating": "جاري التحديث", "updating": "جاري التحديث",
"wait": "الرجاء الانتظار" "wait": "الرجاء الإنتظار"
}, },
"search": { "search": {
"placeholder": "بحث …" "placeholder": "بحث …"
@ -27,88 +27,88 @@
"unifi": { "unifi": {
"users": "المستخدمون", "users": "المستخدمون",
"uptime": "مدة تشغيل النظام", "uptime": "مدة تشغيل النظام",
"days": "ايام", "days": "أيام",
"wan": "WAN", "wan": "WAN",
"lan": "LAN", "lan": "LAN",
"wlan": "WLAN", "wlan": "WLAN",
"devices": "الاجهزة", "devices": "الأجهزة",
"lan_devices": "LAN اجهزة", "lan_devices": "LAN أجهزة",
"wlan_devices": "WLAN احهزة", "wlan_devices": "WLAN أجهزة",
"lan_users": "LAN مستخدمين", "lan_users": "LAN مستخدمين",
"wlan_users": "WLAN مستخدمين", "wlan_users": "WLAN مستخدمين",
"up": "اعلي", "up": "يعمل",
"down": "اسفل", "down": "لا يعمل",
"wait": "الرجاء الانتظار" "wait": "الرجاء الإنتظار"
}, },
"wmo": { "wmo": {
"73-day": "Snow", "73-day": "ثلج",
"0-day": "Sunny", "0-day": "مشمس",
"0-night": "Clear", "0-night": "صافي",
"1-day": "Mainly Sunny", "1-day": "مشمس غالباً",
"1-night": "Mainly Clear", "1-night": "صافي غالباً",
"2-day": "Partly Cloudy", "2-day": "غائم جزئياً",
"2-night": "Partly Cloudy", "2-night": "غائم جزئياً",
"3-day": "Cloudy", "3-day": "غائم",
"3-night": "Cloudy", "3-night": "غائم",
"45-day": "Foggy", "45-day": "ضبابي",
"45-night": "Foggy", "45-night": "ضبابي",
"48-day": "Foggy", "48-day": "ضبابي",
"48-night": "Foggy", "48-night": "ضبابي",
"51-day": "Light Drizzle", "51-day": "رذاذ خفيف",
"51-night": "Light Drizzle", "51-night": "رذاذ خفيف",
"53-day": "Drizzle", "53-day": "رذاذ",
"53-night": "Drizzle", "53-night": "رذاذ",
"55-day": "Heavy Drizzle", "55-day": "رذاذ كثيف",
"55-night": "Heavy Drizzle", "55-night": "رذاذ كثيف",
"56-day": "Light Freezing Drizzle", "56-day": "رذاذ متجمد خفيف",
"56-night": "Light Freezing Drizzle", "56-night": "رذاذ متجمد خفيف",
"57-day": "Freezing Drizzle", "57-day": "رذاذ متجمد",
"57-night": "Freezing Drizzle", "57-night": "رذاذ متجمد",
"61-day": "Light Rain", "61-day": "مطر خفيف",
"61-night": "Light Rain", "61-night": "مطر خفيف",
"63-day": "Rain", "63-day": "مطر",
"63-night": "Rain", "63-night": "مطر",
"65-day": "Heavy Rain", "65-day": "مطر شديد",
"65-night": "Heavy Rain", "65-night": "مطر شديد",
"66-day": "Freezing Rain", "66-day": "مطر متجمد",
"66-night": "Freezing Rain", "66-night": "مطر متجمد",
"67-day": "Freezing Rain", "67-day": "مطر متجمد",
"67-night": "Freezing Rain", "67-night": "مطر متجمد",
"71-day": "Light Snow", "71-day": "ثلج خفيف",
"71-night": "Light Snow", "71-night": "ثلج خفيف",
"73-night": "Snow", "73-night": "ثلج",
"75-day": "Heavy Snow", "75-day": "ثلج شديد",
"75-night": "Heavy Snow", "75-night": "ثلج شديد",
"77-day": "Snow Grains", "77-day": "حبيبات الثلج",
"77-night": "Snow Grains", "77-night": "حبيبات الثلج",
"80-day": "Light Showers", "80-day": "أمطار خفيفة",
"80-night": "Light Showers", "80-night": "أمطار خفيفة",
"81-day": "Showers", "81-day": "أمطار",
"81-night": "Showers", "81-night": "أمطار",
"82-day": "Heavy Showers", "82-day": "أمطار شديدة",
"82-night": "Heavy Showers", "82-night": "أمطار شديدة",
"85-day": "Snow Showers", "85-day": "زخات الثلوج",
"85-night": "Snow Showers", "85-night": "زخات الثلوج",
"86-day": "Snow Showers", "86-day": "زخات الثلوج",
"86-night": "Snow Showers", "86-night": "زخات الثلوج",
"95-day": "Thunderstorm", "95-day": "عاصفة رعدية",
"95-night": "Thunderstorm", "95-night": "‬عاصفة رعدية",
"96-day": "Thunderstorm With Hail", "96-day": "عاصفة رعدية مع مطر",
"96-night": "Thunderstorm With Hail", "96-night": "عاصفة رعدية مع مطر",
"99-day": "Thunderstorm With Hail", "99-day": "عاصفة رعدية مع مطر",
"99-night": "Thunderstorm With Hail" "99-night": "عاصفة رعدية مع مطر"
}, },
"docker": { "docker": {
"rx": "RX", "rx": "RX",
"tx": "TX", "tx": "TX",
"mem": "الرام", "mem": "الذاكرة",
"cpu": "المعالج", "cpu": "المعالج",
"offline": "غير متصل", "offline": "غير متصل",
"error": "Error", "error": "خطأ",
"unknown": "Unknown" "unknown": "مجهول"
}, },
"emby": { "emby": {
"playing": "يعمل الان", "playing": "يعمل الآن",
"transcoding": "التحويل", "transcoding": "التحويل",
"bitrate": "معدل البت", "bitrate": "معدل البت",
"no_active": "No Active Streams" "no_active": "No Active Streams"
@ -118,307 +118,325 @@
"diffsDetected": "Diffs Detected" "diffsDetected": "Diffs Detected"
}, },
"tautulli": { "tautulli": {
"playing": "Playing", "playing": "يشتغل",
"transcoding": "Transcoding", "transcoding": "التحويل",
"bitrate": "Bitrate", "bitrate": "معدل البت",
"no_active": "No Active Streams" "no_active": "No Active Streams"
}, },
"nzbget": { "nzbget": {
"rate": "Rate", "rate": "معدل",
"remaining": "Remaining", "remaining": "متبقي",
"downloaded": "Downloaded" "downloaded": "مُنزل"
}, },
"plex": { "plex": {
"streams": "Active Streams", "streams": "Active Streams",
"movies": "Movies", "movies": "أفلام",
"tv": "TV Shows" "tv": "مسلسلات"
}, },
"sabnzbd": { "sabnzbd": {
"rate": "Rate", "rate": "معدل",
"queue": "Queue", "queue": "إنتظار",
"timeleft": "Time Left" "timeleft": "الوقت المتبقي"
}, },
"rutorrent": { "rutorrent": {
"active": "Active", "active": "نشط",
"upload": "Upload", "upload": "تحميل",
"download": "Download" "download": "تنزيل"
}, },
"transmission": { "transmission": {
"download": "Download", "download": "تنزيل",
"upload": "Upload", "upload": "تحميل",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"qbittorrent": { "qbittorrent": {
"download": "Download", "download": "تنزيل",
"upload": "Upload", "upload": "تحميل",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"sonarr": { "sonarr": {
"wanted": "Wanted", "wanted": "مطلوب",
"queued": "Queued", "queued": "في الإنتظار",
"series": "Series" "series": "سلسلة"
}, },
"radarr": { "radarr": {
"wanted": "Wanted", "wanted": "مطلوب",
"missing": "Missing", "missing": "مفقود",
"queued": "Queued", "queued": "في الإنتظار",
"movies": "Movies" "movies": "أفلام"
}, },
"lidarr": { "lidarr": {
"wanted": "Wanted", "wanted": "مطلوب",
"queued": "Queued", "queued": "في الإنتظار",
"albums": "Albums" "albums": "ألبومات"
}, },
"readarr": { "readarr": {
"wanted": "Wanted", "wanted": "مطلوب",
"queued": "Queued", "queued": "في الإنتظار",
"books": "Books" "books": "كتب"
}, },
"bazarr": { "bazarr": {
"missingEpisodes": "Missing Episodes", "missingEpisodes": "حلقات مفقودة",
"missingMovies": "Missing Movies" "missingMovies": "أفلام مفقودة"
}, },
"ombi": { "ombi": {
"pending": "Pending", "pending": "معلق",
"approved": "Approved", "approved": "مصدق",
"available": "Available" "available": "متاح"
}, },
"jellyseerr": { "jellyseerr": {
"pending": "Pending", "pending": "معلق",
"approved": "Approved", "approved": "مصدق",
"available": "Available" "available": "متاح"
}, },
"overseerr": { "overseerr": {
"pending": "Pending", "pending": "معلق",
"approved": "Approved", "approved": "مصدق",
"available": "Available", "available": "متاح",
"processing": "Processing" "processing": "معالجة"
}, },
"pihole": { "pihole": {
"queries": "Queries", "queries": "الاستعلامات",
"blocked": "Blocked", "blocked": "محظور",
"gravity": "Gravity" "gravity": "الجاذبية"
}, },
"adguard": { "adguard": {
"queries": "Queries", "queries": "الاستعلامات",
"blocked": "Blocked", "blocked": "محظور",
"filtered": "Filtered", "filtered": "مرشح",
"latency": "Latency" "latency": "الإستجابة"
}, },
"speedtest": { "speedtest": {
"upload": "Upload", "upload": "التحميل",
"download": "Download", "download": "تنزيل",
"ping": "Ping" "ping": "Ping"
}, },
"portainer": { "portainer": {
"running": "Running", "running": "يعمل",
"stopped": "Stopped", "stopped": "متوقف",
"total": "Total" "total": "مجموع"
}, },
"traefik": { "traefik": {
"routers": "Routers", "routers": "راوتر",
"services": "Services", "services": "خدمات",
"middleware": "Middleware" "middleware": "الوسيطة"
}, },
"npm": { "npm": {
"enabled": "Enabled", "enabled": "مفعل",
"disabled": "Disabled", "disabled": "معطل",
"total": "Total" "total": "مجموع"
}, },
"coinmarketcap": { "coinmarketcap": {
"configure": "Configure one or more crypto currencies to track", "configure": "قم بأنشاء عملة تشفير واحدة أو أكثر للتتبع",
"1hour": "1 Hour", "1hour": "١ ساعة",
"1day": "1 Day", "1day": "١ يوم",
"7days": "7 Days", "7days": "٧ أيام",
"30days": "30 Days" "30days": "٣٠ يوم"
}, },
"gotify": { "gotify": {
"apps": "Applications", "apps": "التطبيقات",
"clients": "Clients", "clients": "العملاء",
"messages": "Messages" "messages": "الرسائل"
}, },
"prowlarr": { "prowlarr": {
"enableIndexers": "Indexers", "enableIndexers": "مفهرسات",
"numberOfGrabs": "Grabs", "numberOfGrabs": "Grabs",
"numberOfQueries": "Queries", "numberOfQueries": "الاستعلامات",
"numberOfFailGrabs": "Fail Grabs", "numberOfFailGrabs": "Fail Grabs",
"numberOfFailQueries": "Fail Queries" "numberOfFailQueries": "فشل الاستعلامات"
}, },
"jackett": { "jackett": {
"configured": "Configured", "configured": "Configured",
"errored": "Errored" "errored": "خطأ"
}, },
"strelaysrv": { "strelaysrv": {
"numActiveSessions": "Sessions", "numActiveSessions": "الجلسات",
"numConnections": "Connections", "numConnections": "التوصيلات",
"dataRelayed": "Relayed", "dataRelayed": "Relayed",
"transferRate": "Rate" "transferRate": "معدل"
}, },
"mastodon": { "mastodon": {
"user_count": "Users", "user_count": "المستخدمين",
"status_count": "Posts", "status_count": "Posts",
"domain_count": "Domains" "domain_count": "Domains"
}, },
"authentik": { "authentik": {
"users": "Users", "users": "المستخدمين",
"loginsLast24H": "Logins (24h)", "loginsLast24H": "تسجيلات الدخول (٢٤س)",
"failedLoginsLast24H": "Failed Logins (24h)" "failedLoginsLast24H": "فشل تسجيلات الدخول (٢٤س)"
}, },
"proxmox": { "proxmox": {
"mem": "MEM", "mem": "الذاكرة",
"cpu": "CPU", "cpu": "المعالج",
"lxc": "LXC", "lxc": "LXC",
"vms": "VMs" "vms": "VMs"
}, },
"glances": { "glances": {
"cpu": "CPU", "cpu": "معالج",
"mem": "MEM", "mem": "الذاكرة",
"wait": "Please wait" "wait": "الرجاء الإنتظار"
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "مفضلة",
"service": "Service" "service": "خدمة",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "نظام",
"updates": "Updates", "updates": "تحديثات",
"update_available": "Update Available", "update_available": "تحديث متاح",
"up_to_date": "Up to Date", "up_to_date": "حتى الآن",
"child_bridges": "Child Bridges", "child_bridges": "Child Bridges",
"child_bridges_status": "{{ok}}/{{total}}" "child_bridges_status": "{{ok}}/{{total}}"
}, },
"watchtower": { "watchtower": {
"containers_scanned": "Scanned", "containers_scanned": "Scanned",
"containers_updated": "Updated", "containers_updated": "محدث",
"containers_failed": "Failed" "containers_failed": "فشل"
}, },
"autobrr": { "autobrr": {
"approvedPushes": "Approved", "approvedPushes": "مصدق",
"rejectedPushes": "Rejected", "rejectedPushes": "مرفوض",
"filters": "Filters", "filters": "المرشحات",
"indexers": "Indexers" "indexers": "مفهرسات"
}, },
"tubearchivist": { "tubearchivist": {
"downloads": "Queue", "downloads": "إنتظار",
"videos": "Videos", "videos": "الفيديوهات",
"channels": "Channels", "channels": "القنوات",
"playlists": "Playlists" "playlists": "قوائم التشغيل"
}, },
"truenas": { "truenas": {
"load": "System Load", "load": "حمل النظام",
"uptime": "Uptime", "uptime": "مدة التشغيل",
"alerts": "Alerts", "alerts": "تنبيهات",
"time": "{{value, number(style: unit; unitDisplay: long;)}}" "time": "{{value, number(style: unit; unitDisplay: long;)}}"
}, },
"navidrome": { "navidrome": {
"nothing_streaming": "No Active Streams", "nothing_streaming": "No Active Streams",
"please_wait": "Please Wait" "please_wait": "الرجاء الإنتظار"
}, },
"pyload": { "pyload": {
"speed": "Speed", "speed": "السرعة",
"active": "Active", "active": "نشط",
"queue": "Queue", "queue": "إنتظار",
"total": "Total" "total": "مجموع"
}, },
"gluetun": { "gluetun": {
"public_ip": "Public IP", "public_ip": "العام IP",
"region": "Region", "region": "منطقة",
"country": "Country" "country": "الدولة"
}, },
"hdhomerun": { "hdhomerun": {
"channels": "Channels", "channels": "قنوات",
"hd": "HD" "hd": "HD"
}, },
"ping": { "ping": {
"error": "Error", "error": "خطأ",
"ping": "Ping" "ping": "Ping"
}, },
"scrutiny": { "scrutiny": {
"passed": "Passed", "passed": "إجتاز",
"failed": "Failed", "failed": "فشل",
"unknown": "Unknown" "unknown": "مجهول"
}, },
"paperlessngx": { "paperlessngx": {
"inbox": "Inbox", "inbox": "صندوق الوارد",
"total": "Total" "total": "المجموع"
}, },
"deluge": { "deluge": {
"download": "Download", "download": "تنزيل",
"upload": "Upload", "upload": "تحميل",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"flood": { "flood": {
"download": "Download", "download": "التنزيل",
"upload": "Upload", "upload": "التحميل",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"tdarr": { "tdarr": {
"queue": "Queue", "queue": "إنتظار",
"processed": "Processed", "processed": "معالجة",
"errored": "Errored", "errored": "خطأ",
"saved": "Saved" "saved": "حفظ"
}, },
"miniflux": { "miniflux": {
"read": "Read", "read": "قراءة",
"unread": "Unread" "unread": "غير مقروء"
}, },
"nextdns": { "nextdns": {
"wait": "Please Wait", "wait": "الرجاء الإنتظار",
"no_devices": "No Device Data Received" "no_devices": "لم يتم استلام بيانات الجهاز"
}, },
"common": { "common": {
"bibyterate": "{{value, rate(bits: false; binary: true)}}", "bibyterate": "{{value, rate(bits: false; binary: true)}}",
"bibitrate": "{{value, rate(bits: true; binary: true)}}" "bibitrate": "{{value, rate(bits: true; binary: true)}}"
}, },
"omada": { "omada": {
"connectedAp": "Connected APs", "connectedAp": "المتصلة APs",
"activeUser": "Active devices", "activeUser": "الأجهزة النشطة",
"alerts": "Alerts", "alerts": "تنبيهات",
"connectedGateway": "Connected gateways", "connectedGateway": "Connected gateways",
"connectedSwitches": "Connected switches" "connectedSwitches": "Connected switches"
}, },
"downloadstation": { "downloadstation": {
"download": "Download", "download": "تنزيل",
"upload": "Upload", "upload": "تحميل",
"leech": "Leech", "leech": "Leech",
"seed": "Seed" "seed": "Seed"
}, },
"mikrotik": { "mikrotik": {
"cpuLoad": "CPU Load", "cpuLoad": "حمل المعالج",
"memoryUsed": "Memory Used", "memoryUsed": "الذاكرة الستخدمة",
"uptime": "Uptime", "uptime": "مدة التشغيل",
"numberOfLeases": "Leases" "numberOfLeases": "Leases"
}, },
"xteve": { "xteve": {
"streams_all": "All Streams", "streams_all": "All Streams",
"streams_active": "Active Streams", "streams_active": "Active Streams",
"streams_xepg": "XEPG Channels" "streams_xepg": "XEPG قنوات"
}, },
"opnsense": { "opnsense": {
"cpu": "CPU Load", "cpu": "حمل المعالج",
"memory": "Active Memory", "memory": "الذاكرة النشطة",
"wanUpload": "WAN Upload", "wanUpload": "WAN التحميل",
"wanDownload": "WAN Download" "wanDownload": "WAN التنزيل"
}, },
"moonraker": { "moonraker": {
"printer_state": "Printer State", "printer_state": "حالة الطابعة",
"print_status": "Print Status", "print_status": "حالة الطابعة",
"print_progress": "Progress", "print_progress": "تقدم",
"layers": "Layers" "layers": "طبقات"
}, },
"medusa": { "medusa": {
"wanted": "Wanted", "wanted": "مطلوب",
"queued": "Queued", "queued": "في الإنتظار",
"series": "Series" "series": "سلسلة"
}, },
"octoprint": { "octoprint": {
"printer_state": "Status", "printer_state": "حالة",
"temp_tool": "Tool temp", "temp_tool": "أداة درجة الحرارة",
"temp_bed": "Bed temp", "temp_bed": "درجة حرارة السرير",
"job_completion": "Completion" "job_completion": "إتمام"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "حالة"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -184,7 +184,7 @@
"failedLoginsLast24H": "Errors d'inici de sessió (24h)" "failedLoginsLast24H": "Errors d'inici de sessió (24h)"
}, },
"proxmox": { "proxmox": {
"vms": "Màquines Virtuals", "vms": "VMs",
"mem": "Memòria", "mem": "Memòria",
"cpu": "Processador", "cpu": "Processador",
"lxc": "LXC" "lxc": "LXC"
@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Marcador", "bookmark": "Marcador",
"service": "Servei" "service": "Servei",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "Sistema", "available_update": "Sistema",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -291,7 +291,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Záložka", "bookmark": "Záložka",
"service": "Služba" "service": "Služba",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"update_available": "Dostupná aktualizace", "update_available": "Dostupná aktualizace",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -287,7 +287,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bogmærker", "bookmark": "Bogmærker",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"watchtower": { "watchtower": {
"containers_scanned": "Scannet", "containers_scanned": "Scannet",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Lesezeichen", "bookmark": "Lesezeichen",
"service": "Dienst" "service": "Dienst",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"cpu_usage": "CPU",
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -282,7 +282,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"wmo": { "wmo": {
"0-day": "Sunny", "0-day": "Sunny",
@ -430,8 +432,20 @@
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
}, },
"cloudflared" { "cloudflared": {
"origin_ip": "Origin IP", "origin_ip": "Origin IP",
"status": "Status" "status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -235,7 +235,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Servo" "service": "Servo",
"search": "Search",
"custom": "Custom"
}, },
"wmo": { "wmo": {
"0-day": "Suna", "0-day": "Suna",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Marcadores", "bookmark": "Marcadores",
"service": "Servicio" "service": "Servicio",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "Sistema", "available_update": "Sistema",
@ -420,5 +422,21 @@
"printer_state": "Status", "printer_state": "Status",
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "IP de origen",
"status": "Estado"
},
"proxmoxbackupserver": {
"cpu_usage": "CPU",
"datastore_usage": "Almacén de datos",
"failed_tasks_24h": "Tareas fallidas en 24h",
"memory_usage": "Memoria"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -194,7 +194,7 @@
"uptime": "System Uptime", "uptime": "System Uptime",
"lan_users": "LAN Users", "lan_users": "LAN Users",
"wlan_users": "WLAN Users", "wlan_users": "WLAN Users",
"wait": "Please wait", "wait": "Odota, ole hyvä",
"days": "Days", "days": "Days",
"wan": "WAN", "wan": "WAN",
"up": "UP", "up": "UP",
@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -314,7 +316,7 @@
}, },
"navidrome": { "navidrome": {
"nothing_streaming": "No Active Streams", "nothing_streaming": "No Active Streams",
"please_wait": "Please Wait" "please_wait": "Odota, ole hyvä"
}, },
"pyload": { "pyload": {
"speed": "Speed", "speed": "Speed",
@ -411,14 +413,30 @@
"layers": "Layers" "layers": "Layers"
}, },
"medusa": { "medusa": {
"wanted": "Wanted", "wanted": "Haluttu",
"queued": "Queued", "queued": "Jonossa",
"series": "Series" "series": "Sarja"
}, },
"octoprint": { "octoprint": {
"printer_state": "Status", "printer_state": "Status",
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Signet", "bookmark": "Signet",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "Système", "available_update": "Système",
@ -419,6 +421,22 @@
"printer_state": "Status", "printer_state": "Status",
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Achèvement"
},
"cloudflared": {
"origin_ip": "IP Publique",
"status": "Statut"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Tâches échouées 24h",
"cpu_usage": "CPU",
"memory_usage": "Mémoire"
},
"immich": {
"users": "Utilisateurs",
"photos": "Photos",
"videos": "Vidéos",
"storage": "Stockage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -225,7 +225,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"wmo": { "wmo": {
"0-day": "Sunny", "0-day": "Sunny",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Straničnik", "bookmark": "Straničnik",
"service": "Usluga" "service": "Usluga",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "Sustav", "available_update": "Sustav",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Segnalibro", "bookmark": "Segnalibro",
"service": "Servizio" "service": "Servizio",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "Sistema", "available_update": "Sistema",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"wmo": { "wmo": {
"0-day": "Sunny", "0-day": "Sunny",
@ -420,5 +422,21 @@
"printer_state": "Status", "printer_state": "Status",
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -273,7 +273,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"wmo": { "wmo": {
"0-day": "Saulains", "0-day": "Saulains",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -62,7 +62,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Tandabuku", "bookmark": "Tandabuku",
"service": "Servis" "service": "Servis",
"search": "Search",
"custom": "Custom"
}, },
"wmo": { "wmo": {
"0-day": "Terik", "0-day": "Terik",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Zakładka", "bookmark": "Zakładka",
"service": "Usługi" "service": "Usługi",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -292,7 +292,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Marcador", "bookmark": "Marcador",
"service": "Serviço" "service": "Serviço",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "Sistema", "available_update": "Sistema",
@ -429,5 +431,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"update_available": "Update Available", "update_available": "Update Available",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "బుక్మార్క్", "bookmark": "బుక్మార్క్",
"service": "సేవ" "service": "సేవ",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "వ్యవస్థ", "available_update": "వ్యవస్థ",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Yer İmi", "bookmark": "Yer İmi",
"service": "Hizmet" "service": "Hizmet",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "Sistem", "available_update": "Sistem",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -341,7 +341,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Закладка", "bookmark": "Закладка",
"service": "Сервіс" "service": "Сервіс",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "Система", "available_update": "Система",
@ -416,9 +418,25 @@
"series": "Серії" "series": "Серії"
}, },
"octoprint": { "octoprint": {
"printer_state": "Status", "printer_state": "Стан",
"temp_tool": "Tool temp", "temp_tool": "Температура інструменту",
"temp_bed": "Bed temp", "temp_bed": "Температура ліжка",
"job_completion": "Completion" "job_completion": "Завершення"
},
"cloudflared": {
"origin_ip": "Походження IP",
"status": "Стан"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "Bookmark", "bookmark": "Bookmark",
"service": "Service" "service": "Service",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -3,10 +3,10 @@
"missing_type": "缺少小部件类型:{{type}}", "missing_type": "缺少小部件类型:{{type}}",
"api_error": "API错误", "api_error": "API错误",
"status": "状态", "status": "状态",
"information": "Information", "information": "信息",
"url": "URL", "url": "URL",
"raw_error": "Raw Error", "raw_error": "原始错误",
"response_data": "Response Data" "response_data": "返回数据"
}, },
"search": { "search": {
"placeholder": "搜索…" "placeholder": "搜索…"
@ -24,8 +24,8 @@
"mem": "内存", "mem": "内存",
"cpu": "处理器", "cpu": "处理器",
"offline": "离线", "offline": "离线",
"error": "Error", "error": "错误",
"unknown": "Unknown" "unknown": "未知"
}, },
"emby": { "emby": {
"playing": "播放中", "playing": "播放中",
@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "书签", "bookmark": "书签",
"service": "服务" "service": "服务",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "System", "available_update": "System",
@ -332,7 +334,7 @@
"hd": "HD" "hd": "HD"
}, },
"ping": { "ping": {
"error": "Error", "error": "错误",
"ping": "Ping" "ping": "Ping"
}, },
"scrutiny": { "scrutiny": {
@ -345,22 +347,22 @@
"total": "Total" "total": "Total"
}, },
"deluge": { "deluge": {
"download": "Download", "download": "下载",
"upload": "Upload", "upload": "上传",
"leech": "Leech", "leech": "下载中",
"seed": "Seed" "seed": "做种"
}, },
"flood": { "flood": {
"leech": "Leech", "leech": "下载中",
"download": "Download", "download": "下载",
"upload": "Upload", "upload": "上传",
"seed": "Seed" "seed": "做种"
}, },
"tdarr": { "tdarr": {
"saved": "Saved", "saved": "Saved",
"queue": "Queue", "queue": "队列",
"processed": "Processed", "processed": "Processed",
"errored": "Errored" "errored": "出错"
}, },
"miniflux": { "miniflux": {
"read": "Read", "read": "Read",
@ -376,16 +378,16 @@
}, },
"omada": { "omada": {
"connectedAp": "Connected APs", "connectedAp": "Connected APs",
"activeUser": "Active devices", "activeUser": "活跃设备",
"alerts": "Alerts", "alerts": "警报",
"connectedGateway": "Connected gateways", "connectedGateway": "已连接网关",
"connectedSwitches": "Connected switches" "connectedSwitches": "已连接开关"
}, },
"downloadstation": { "downloadstation": {
"download": "Download", "download": "下载",
"upload": "Upload", "upload": "上传",
"leech": "Leech", "leech": "下载中",
"seed": "Seed" "seed": "做种"
}, },
"mikrotik": { "mikrotik": {
"cpuLoad": "CPU Load", "cpuLoad": "CPU Load",
@ -420,5 +422,21 @@
"temp_tool": "Tool temp", "temp_tool": "Tool temp",
"temp_bed": "Bed temp", "temp_bed": "Bed temp",
"job_completion": "Completion" "job_completion": "Completion"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -279,7 +279,9 @@
}, },
"quicklaunch": { "quicklaunch": {
"bookmark": "書籤", "bookmark": "書籤",
"service": "服務" "service": "服務",
"search": "Search",
"custom": "Custom"
}, },
"homebridge": { "homebridge": {
"available_update": "系統", "available_update": "系統",
@ -416,9 +418,25 @@
"series": "影集" "series": "影集"
}, },
"octoprint": { "octoprint": {
"printer_state": "Status", "printer_state": "狀態",
"temp_tool": "Tool temp", "temp_tool": "噴頭溫度",
"temp_bed": "Bed temp", "temp_bed": "平台溫度",
"job_completion": "Completion" "job_completion": "完成度"
},
"cloudflared": {
"origin_ip": "Origin IP",
"status": "Status"
},
"proxmoxbackupserver": {
"datastore_usage": "Datastore",
"failed_tasks_24h": "Failed Tasks 24h",
"cpu_usage": "CPU",
"memory_usage": "Memory"
},
"immich": {
"users": "Users",
"photos": "Photos",
"videos": "Videos",
"storage": "Storage"
} }
} }

View File

@ -6,7 +6,7 @@ import ResolvedIcon from "./resolvedicon";
import { SettingsContext } from "utils/contexts/settings"; import { SettingsContext } from "utils/contexts/settings";
export default function QuickLaunch({servicesAndBookmarks, searchString, setSearchString, isOpen, close, searchDescriptions}) { export default function QuickLaunch({servicesAndBookmarks, searchString, setSearchString, isOpen, close, searchDescriptions, searchProvider}) {
const { t } = useTranslation(); const { t } = useTranslation();
const { settings } = useContext(SettingsContext); const { settings } = useContext(SettingsContext);
@ -34,7 +34,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
function handleSearchKeyDown(event) { function handleSearchKeyDown(event) {
if (!isOpen) return; if (!isOpen) return;
if (event.key === "Escape") { if (event.key === "Escape") {
closeAndReset(); closeAndReset();
event.preventDefault(); event.preventDefault();
@ -50,6 +50,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
} }
} }
function handleItemHover(event) { function handleItemHover(event) {
setCurrentItemIndex(parseInt(event.target?.dataset?.index, 10)); setCurrentItemIndex(parseInt(event.target?.dataset?.index, 10));
} }
@ -75,6 +76,15 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
if (searchDescriptions) { if (searchDescriptions) {
newResults = newResults.sort((a, b) => b.priority - a.priority); newResults = newResults.sort((a, b) => b.priority - a.priority);
} }
if (searchProvider) {
newResults.push(
{
href: searchProvider.url + encodeURIComponent(searchString),
name: `${searchProvider.name ?? t("quicklaunch.custom")} ${t("quicklaunch.search")} `,
type: 'search',
}
)
}
setResults(newResults); setResults(newResults);
@ -82,7 +92,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
setCurrentItemIndex(0); setCurrentItemIndex(0);
} }
} }
}, [searchString, servicesAndBookmarks, searchDescriptions]); }, [searchString, servicesAndBookmarks, searchDescriptions, searchProvider, t]);
const [hidden, setHidden] = useState(true); const [hidden, setHidden] = useState(true);
@ -90,7 +100,7 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
function handleBackdropClick(event) { function handleBackdropClick(event) {
if (event.target?.tagName === "DIV") closeAndReset(); if (event.target?.tagName === "DIV") closeAndReset();
} }
if (isOpen) { if (isOpen) {
searchField.current.focus(); searchField.current.focus();
document.body.addEventListener('click', handleBackdropClick); document.body.addEventListener('click', handleBackdropClick);
@ -135,20 +145,20 @@ export default function QuickLaunch({servicesAndBookmarks, searchString, setSear
i === currentItemIndex && "bg-theme-300/50 dark:bg-theme-700/50", i === currentItemIndex && "bg-theme-300/50 dark:bg-theme-700/50",
)} onClick={handleItemClick}> )} onClick={handleItemClick}>
<div className="flex flex-row items-center mr-4 pointer-events-none"> <div className="flex flex-row items-center mr-4 pointer-events-none">
<div className="w-5 text-xs mr-4"> {(r.icon || r.abbr) && <div className="w-5 text-xs mr-4">
{r.icon && <ResolvedIcon icon={r.icon} />} {r.icon && <ResolvedIcon icon={r.icon} />}
{r.abbr && r.abbr} {r.abbr && r.abbr}
</div> </div>}
<div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none"> <div className="flex flex-col md:flex-row text-left items-baseline mr-4 pointer-events-none">
<span className="mr-4">{r.name}</span> <span className="mr-4">{r.name}</span>
{r.description && {r.description &&
<span className="text-xs text-theme-600 text-light"> <span className="text-xs text-theme-600 text-light">
{searchDescriptions && r.priority < 2 ? highlightText(r.description) : r.description} {searchDescriptions && r.priority < 2 ? highlightText(r.description) : r.description}
</span> </span>
} }
</div> </div>
</div> </div>
<div className="text-xs text-theme-600 font-bold pointer-events-none">{r.type === 'service' ? t("quicklaunch.service") : t("quicklaunch.bookmark")}</div> <div className="text-xs text-theme-600 font-bold pointer-events-none">{t(`quicklaunch.${r.type ? r.type.toLowerCase() : 'bookmark'}`)}</div>
</button> </button>
</li> </li>
))} ))}

View File

@ -1,9 +1,11 @@
import { useState } from "react"; import { useState, useEffect, Fragment } from "react";
import { useTranslation } from "next-i18next"; import { useTranslation } from "next-i18next";
import { FiSearch } from "react-icons/fi"; import { FiSearch } from "react-icons/fi";
import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu, SiBrave } from "react-icons/si"; import { SiDuckduckgo, SiMicrosoftbing, SiGoogle, SiBaidu, SiBrave } from "react-icons/si";
import { Listbox, Transition } from "@headlessui/react";
import classNames from "classnames";
const providers = { export const searchProviders = {
google: { google: {
name: "Google", name: "Google",
url: "https://www.google.com/search?q=", url: "https://www.google.com/search?q=",
@ -36,21 +38,55 @@ const providers = {
}, },
}; };
function getAvailableProviderIds(options) {
if (options.provider && Array.isArray(options.provider)) {
return Object.keys(searchProviders).filter((value) => options.provider.includes(value));
}
if (options.provider && searchProviders[options.provider]) {
return [options.provider];
}
return null;
}
const localStorageKey = "search-name";
export function getStoredProvider() {
if (typeof window !== 'undefined') {
const storedName = localStorage.getItem(localStorageKey);
if (storedName) {
return Object.values(searchProviders).find((el) => el.name === storedName);
}
}
return null;
}
export default function Search({ options }) { export default function Search({ options }) {
const { t } = useTranslation(); const { t } = useTranslation();
const provider = providers[options.provider]; const availableProviderIds = getAvailableProviderIds(options);
const [query, setQuery] = useState("");
if (!provider) { const [query, setQuery] = useState("");
const [selectedProvider, setSelectedProvider] = useState(searchProviders[availableProviderIds[0] ?? searchProviders.google]);
useEffect(() => {
const storedProvider = getStoredProvider();
let storedProviderKey = null;
storedProviderKey = Object.keys(searchProviders).find((pkey) => searchProviders[pkey] === storedProvider);
if (storedProvider && availableProviderIds.includes(storedProviderKey)) {
setSelectedProvider(storedProvider);
}
}, [availableProviderIds]);
if (!availableProviderIds) {
return null; return null;
} }
function handleSubmit(event) { function handleSubmit(event) {
const q = encodeURIComponent(query); const q = encodeURIComponent(query);
if (provider.url) { const url = { selectedProvider };
window.open(`${provider.url}${q}`, options.target || "_blank"); if (url) {
window.open(`${url}${q}`, options.target || "_blank");
} else { } else {
window.open(`${options.url}${q}`, options.target || "_blank"); window.open(`${options.url}${q}`, options.target || "_blank");
} }
@ -60,6 +96,11 @@ export default function Search({ options }) {
setQuery(""); setQuery("");
} }
const onChangeProvider = (provider) => {
setSelectedProvider(provider);
localStorage.setItem(localStorageKey, provider.name);
}
return ( return (
<form className="flex-col relative h-8 my-4 min-w-fit grow first:ml-0 ml-4" onSubmit={handleSubmit}> <form className="flex-col relative h-8 my-4 min-w-fit grow first:ml-0 ml-4" onSubmit={handleSubmit}>
<div className="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none w-full text-theme-800 dark:text-white" /> <div className="flex absolute inset-y-0 left-0 items-center pl-3 pointer-events-none w-full text-theme-800 dark:text-white" />
@ -82,17 +123,55 @@ export default function Search({ options }) {
// eslint-disable-next-line jsx-a11y/no-autofocus // eslint-disable-next-line jsx-a11y/no-autofocus
autoFocus={options.focus} autoFocus={options.focus}
/> />
<button <Listbox as="div" value={selectedProvider} onChange={onChangeProvider} className="relative text-left" disabled={availableProviderIds?.length === 1}>
type="submit" <div>
className=" <Listbox.Button
className="
absolute right-0.5 bottom-0.5 rounded-r-md px-4 py-2 border-1 absolute right-0.5 bottom-0.5 rounded-r-md px-4 py-2 border-1
text-white font-medium text-sm text-white font-medium text-sm
bg-theme-600/40 dark:bg-white/10 bg-theme-600/40 dark:bg-white/10
focus:ring-theme-500 dark:focus:ring-white/50" focus:ring-theme-500 dark:focus:ring-white/50"
> >
<provider.icon className="text-white w-3 h-3" /> <selectedProvider.icon className="text-white w-3 h-3" />
<span className="sr-only">{t("search.search")}</span> <span className="sr-only">{t("search.search")}</span>
</button> </Listbox.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Listbox.Options
className="absolute right-0 z-10 mt-1 origin-top-right rounded-md
bg-theme-100 dark:bg-theme-600 shadow-lg
ring-1 ring-black ring-opacity-5 focus:outline-none"
>
<div className="flex flex-col">
{availableProviderIds.map((providerId) => {
const p = searchProviders[providerId];
return (
<Listbox.Option key={providerId} value={p} as={Fragment}>
{({ active }) => (
<li
className={classNames(
"rounded-md cursor-pointer",
active ? "bg-theme-600/10 dark:bg-white/10 dark:text-gray-900" : "dark:text-gray-100"
)}
>
<p.icon className="h-4 w-4 mx-4 my-2" />
</li>
)}
</Listbox.Option>
);
})}
</div>
</Listbox.Options>
</Transition>
</Listbox>
</form> </form>
); );
} }

View File

@ -22,6 +22,7 @@ import { bookmarksResponse, servicesResponse, widgetsResponse } from "utils/conf
import ErrorBoundary from "components/errorboundry"; import ErrorBoundary from "components/errorboundry";
import themes from "utils/styles/themes"; import themes from "utils/styles/themes";
import QuickLaunch from "components/quicklaunch"; import QuickLaunch from "components/quicklaunch";
import { getStoredProvider, searchProviders } from "components/widgets/search/search";
const ThemeToggle = dynamic(() => import("components/toggles/theme"), { const ThemeToggle = dynamic(() => import("components/toggles/theme"), {
ssr: false, ssr: false,
@ -193,6 +194,20 @@ function Home({ initialSettings }) {
const [searching, setSearching] = useState(false); const [searching, setSearching] = useState(false);
const [searchString, setSearchString] = useState(""); const [searchString, setSearchString] = useState("");
let searchProvider = null;
const searchWidget = Object.values(widgets).find(w => w.type === "search");
if (searchWidget) {
if (Array.isArray(searchWidget.options?.provider)) {
// if search provider is a list, try to retrieve from localstorage, fall back to the first
searchProvider = getStoredProvider() ?? searchProviders[searchWidget.options.provider[0]];
} else if (searchWidget.options?.provider === 'custom') {
searchProvider = {
url: searchWidget.options.url
}
} else {
searchProvider = searchProviders[searchWidget.options?.provider];
}
}
useEffect(() => { useEffect(() => {
function handleKeyDown(e) { function handleKeyDown(e) {
@ -251,6 +266,7 @@ function Home({ initialSettings }) {
isOpen={searching} isOpen={searching}
close={setSearching} close={setSearching}
searchDescriptions={settings.quicklaunch?.searchDescriptions} searchDescriptions={settings.quicklaunch?.searchDescriptions}
searchProvider={settings.quicklaunch?.hideInternetSearch ? null : searchProvider}
/> />
{widgets && ( {widgets && (
<> <>

View File

@ -13,6 +13,17 @@ import {
} from "utils/config/service-helpers"; } from "utils/config/service-helpers";
import { cleanWidgetGroups, widgetsFromConfig } from "utils/config/widget-helpers"; import { cleanWidgetGroups, widgetsFromConfig } from "utils/config/widget-helpers";
/**
* Compares services by weight then by name.
*/
function compareServices(service1, service2) {
const comp = service1.weight - service2.weight;
if (comp !== 0) {
return comp;
}
return service1.name.localeCompare(service2.name);
}
export async function bookmarksResponse() { export async function bookmarksResponse() {
checkAndCopyConfig("bookmarks.yaml"); checkAndCopyConfig("bookmarks.yaml");
@ -112,7 +123,8 @@ export async function servicesResponse() {
...discoveredDockerGroup.services, ...discoveredDockerGroup.services,
...discoveredKubernetesGroup.services, ...discoveredKubernetesGroup.services,
...configuredGroup.services ...configuredGroup.services
].filter((service) => service), ].filter((service) => service)
.sort(compareServices),
}; };
if (definedLayouts) { if (definedLayouts) {

View File

@ -33,6 +33,15 @@ export async function servicesFromConfig() {
})), })),
})); }));
// add default weight to services based on their position in the configuration
servicesArray.forEach((group, groupIndex) => {
group.services.forEach((service, serviceIndex) => {
if(!service.weight) {
servicesArray[groupIndex].services[serviceIndex].weight = (serviceIndex + 1) * 100;
}
});
});
return servicesArray; return servicesArray;
} }
@ -152,6 +161,7 @@ export async function servicesFromKubernetes() {
href: ingress.metadata.annotations[`${ANNOTATION_BASE}/href`] || getUrlFromIngress(ingress), href: ingress.metadata.annotations[`${ANNOTATION_BASE}/href`] || getUrlFromIngress(ingress),
name: ingress.metadata.annotations[`${ANNOTATION_BASE}/name`] || ingress.metadata.name, name: ingress.metadata.annotations[`${ANNOTATION_BASE}/name`] || ingress.metadata.name,
group: ingress.metadata.annotations[`${ANNOTATION_BASE}/group`] || "Kubernetes", group: ingress.metadata.annotations[`${ANNOTATION_BASE}/group`] || "Kubernetes",
weight: ingress.metadata.annotations[`${ANNOTATION_BASE}/weight`] || '0',
icon: ingress.metadata.annotations[`${ANNOTATION_BASE}/icon`] || '', icon: ingress.metadata.annotations[`${ANNOTATION_BASE}/icon`] || '',
description: ingress.metadata.annotations[`${ANNOTATION_BASE}/description`] || '', description: ingress.metadata.annotations[`${ANNOTATION_BASE}/description`] || '',
}; };
@ -201,6 +211,17 @@ export function cleanServiceGroups(groups) {
name: serviceGroup.name, name: serviceGroup.name,
services: serviceGroup.services.map((service) => { services: serviceGroup.services.map((service) => {
const cleanedService = { ...service }; const cleanedService = { ...service };
if (typeof service.weight === 'string') {
const weight = parseInt(service.weight, 10);
if (Number.isNaN(weight)) {
cleanedService.weight = 0;
} else {
cleanedService.weight = weight;
}
}
if (typeof cleanedService.weight !== "number") {
cleanedService.weight = 0;
}
if (cleanedService.widget) { if (cleanedService.widget) {
// whitelisted set of keys to pass to the frontend // whitelisted set of keys to pass to the frontend
@ -218,9 +239,11 @@ export function cleanServiceGroups(groups) {
wan // opnsense widget wan // opnsense widget
} = cleanedService.widget; } = cleanedService.widget;
const fieldsList = typeof fields === 'string' ? JSON.parse(fields) : fields;
cleanedService.widget = { cleanedService.widget = {
type, type,
fields: fields || null, fields: fieldsList || null,
service_name: service.name, service_name: service.name,
service_group: serviceGroup.name, service_group: serviceGroup.name,
}; };

View File

@ -34,6 +34,9 @@ export default async function credentialedProxyHandler(req, res, map) {
headers.Authorization = `Bearer ${widget.key}`; headers.Authorization = `Bearer ${widget.key}`;
} else if (widget.type === "proxmox") { } else if (widget.type === "proxmox") {
headers.Authorization = `PVEAPIToken=${widget.username}=${widget.password}`; headers.Authorization = `PVEAPIToken=${widget.username}=${widget.password}`;
} else if (widget.type === "proxmoxbackupserver") {
delete headers["Content-Type"];
headers.Authorization = `PBSAPIToken=${widget.username}:${widget.password}`;
} else if (widget.type === "autobrr") { } else if (widget.type === "autobrr") {
headers["X-API-Token"] = `${widget.key}`; headers["X-API-Token"] = `${widget.key}`;
} else if (widget.type === "tubearchivist") { } else if (widget.type === "tubearchivist") {

View File

@ -20,10 +20,12 @@ export default function Component({ service }) {
); );
} }
const originIP = statsData.result.connections?.origin_ip ?? statsData.result.connections[0]?.origin_ip;
return ( return (
<Container service={service}> <Container service={service}>
<Block label="cloudflared.status" value={statsData.result.status} /> <Block label="cloudflared.status" value={statsData.result.status.charAt(0).toUpperCase() + statsData.result.status.slice(1)} />
<Block label="cloudflared.origin_ip" value={statsData.result.connections.origin_ip} /> <Block label="cloudflared.origin_ip" value={originIP} />
</Container> </Container>
); );
} }

View File

@ -1,12 +1,16 @@
import credentialedProxyHandler from "utils/proxy/handlers/credentialed"; import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
const widget = { const widget = {
api: "https://api.cloudflare.com/client/v4/accounts/{accountid}/{endpoint}/{tunnelid}?", api: "https://api.cloudflare.com/client/v4/accounts/{accountid}/{endpoint}/{tunnelid}",
proxyHandler: credentialedProxyHandler, proxyHandler: credentialedProxyHandler,
mappings: { mappings: {
"cfd_tunnel": { "cfd_tunnel": {
endpoint: "cfd_tunnel", endpoint: "cfd_tunnel",
validate: [
"success",
"result"
]
}, },
}, },
}; };

View File

@ -37,6 +37,7 @@ const components = {
opnsense: dynamic(() => import("./opnsense/component")), opnsense: dynamic(() => import("./opnsense/component")),
overseerr: dynamic(() => import("./overseerr/component")), overseerr: dynamic(() => import("./overseerr/component")),
paperlessngx: dynamic(() => import("./paperlessngx/component")), paperlessngx: dynamic(() => import("./paperlessngx/component")),
proxmoxbackupserver: dynamic(() => import("./proxmoxbackupserver/component")),
pihole: dynamic(() => import("./pihole/component")), pihole: dynamic(() => import("./pihole/component")),
plex: dynamic(() => import("./plex/component")), plex: dynamic(() => import("./plex/component")),
portainer: dynamic(() => import("./portainer/component")), portainer: dynamic(() => import("./portainer/component")),
@ -61,6 +62,7 @@ const components = {
unifi: dynamic(() => import("./unifi/component")), unifi: dynamic(() => import("./unifi/component")),
watchtower: dynamic(() => import("./watchtower/component")), watchtower: dynamic(() => import("./watchtower/component")),
xteve: dynamic(() => import("./xteve/component")), xteve: dynamic(() => import("./xteve/component")),
immich: dynamic(() => import("./immich/component")),
}; };
export default components; export default components;

View File

@ -0,0 +1,33 @@
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 { widget } = service;
const { data: immichData, error: immichError } = useWidgetAPI(widget);
if (immichError || immichData?.statusCode === 401) {
return <Container error={immichError ?? immichData} />;
}
if (!immichData) {
return (
<Container service={service}>
<Block label="immich.users" />
<Block label="immich.photos" />
<Block label="immich.videos" />
<Block label="immich.storage" />
</Container>
);
}
return (
<Container service={service}>
<Block label="immich.users" value={immichData.usageByUser.length} />
<Block label="immich.photos" value={immichData.photos} />
<Block label="immich.videos" value={immichData.videos} />
<Block label="immich.storage" value={immichData.usage} />
</Container>
);
}

View File

@ -0,0 +1,8 @@
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
const widget = {
api: "{url}/api/server-info/stats",
proxyHandler: credentialedProxyHandler,
};
export default widget;

View File

@ -27,7 +27,7 @@ export default function Component({ service }) {
return ( return (
<Container service={service}> <Container service={service}>
<Block label="nzbget.rate" value={t("common.bitrate", { value: statusData.DownloadRate })} /> <Block label="nzbget.rate" value={t("common.byterate", { value: statusData.DownloadRate })} />
<Block <Block
label="nzbget.remaining" label="nzbget.remaining"
value={t("common.bytes", { value: statusData.RemainingSizeMB * 1024 * 1024 })} value={t("common.bytes", { value: statusData.RemainingSizeMB * 1024 * 1024 })}

View File

@ -31,8 +31,8 @@ export default function Component({ service }) {
} }
const { data } = clusterData ; const { data } = clusterData ;
const vms = data.filter(item => item.type === "qemu") || []; const vms = data.filter(item => item.type === "qemu" && item.template === 0) || [];
const lxc = data.filter(item => item.type === "lxc") || []; const lxc = data.filter(item => item.type === "lxc" && item.template === 0) || [];
const nodes = data.filter(item => item.type === "node") || []; const nodes = data.filter(item => item.type === "node") || [];
const runningVMs = vms.reduce(calcRunning, 0); const runningVMs = vms.reduce(calcRunning, 0);

View File

@ -0,0 +1,45 @@
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: datastoreData, error: datastoreError } = useWidgetAPI(widget, "status/datastore-usage");
const { data: tasksData, error: tasksError } = useWidgetAPI(widget, "nodes/localhost/tasks");
const { data: hostData, error: hostError } = useWidgetAPI(widget, "nodes/localhost/status");
if (datastoreError || tasksError || hostError) {
const finalError = tasksError ?? datastoreError ?? hostError;
return <Container error={finalError} />;
}
if (!datastoreData || !tasksData || !hostData) {
return (
<Container service={service}>
<Block label="proxmoxbackupserver.datastore_usage" />
<Block label="proxmoxbackupserver.failed_tasks" />
<Block label="proxmoxbackupserver.cpu_usage" />
<Block label="proxmoxbackupserver.memory_usage" />
</Container>
);
}
const datastoreUsage = datastoreData.data[0].used / datastoreData.data[0].total * 100;
const cpuUsage = hostData.data.cpu * 100;
const memoryUsage = hostData.data.memory.used / hostData.data.memory.total * 100;
const failedTasks = tasksData.total >= 100 ? "99+" : tasksData.total;
return (
<Container service={service}>
<Block label="proxmoxbackupserver.datastore_usage" value={t("common.percent", { value: datastoreUsage })} />
<Block label="proxmoxbackupserver.failed_tasks_24h" value={failedTasks} />
<Block label="proxmoxbackupserver.cpu_usage" value={t("common.percent", { value: cpuUsage })} />
<Block label="proxmoxbackupserver.memory_usage" value={t("common.percent", { value: memoryUsage })} />
</Container>
);
}

View File

@ -0,0 +1,22 @@
import credentialedProxyHandler from "utils/proxy/handlers/credentialed";
const since = Date.now() - (24 * 60 * 60 * 1000);
const widget = {
api: "{url}/api2/json/{endpoint}",
proxyHandler: credentialedProxyHandler,
mappings: {
"status/datastore-usage": {
endpoint: "status/datastore-usage",
},
"nodes/localhost/tasks": {
endpoint: `nodes/localhost/tasks?errors=true&limit=100&since=${since}`,
},
"nodes/localhost/status": {
endpoint: "nodes/localhost/status",
},
},
};
export default widget;

View File

@ -31,6 +31,7 @@ import ombi from "./ombi/widget";
import opnsense from "./opnsense/widget"; import opnsense from "./opnsense/widget";
import overseerr from "./overseerr/widget"; import overseerr from "./overseerr/widget";
import paperlessngx from "./paperlessngx/widget"; import paperlessngx from "./paperlessngx/widget";
import proxmoxbackupserver from "./proxmoxbackupserver/widget";
import pihole from "./pihole/widget"; import pihole from "./pihole/widget";
import plex from "./plex/widget"; import plex from "./plex/widget";
import portainer from "./portainer/widget"; import portainer from "./portainer/widget";
@ -55,6 +56,7 @@ import truenas from "./truenas/widget";
import unifi from "./unifi/widget"; import unifi from "./unifi/widget";
import watchtower from "./watchtower/widget"; import watchtower from "./watchtower/widget";
import xteve from "./xteve/widget"; import xteve from "./xteve/widget";
import immich from "./immich/widget";
const widgets = { const widgets = {
adguard, adguard,
@ -92,6 +94,7 @@ const widgets = {
opnsense, opnsense,
overseerr, overseerr,
paperlessngx, paperlessngx,
proxmoxbackupserver,
pihole, pihole,
plex, plex,
portainer, portainer,
@ -117,6 +120,7 @@ const widgets = {
unifi_console: unifi, unifi_console: unifi,
watchtower, watchtower,
xteve, xteve,
immich,
}; };
export default widgets; export default widgets;