mirror of
https://github.com/henrygd/beszel.git
synced 2026-09-14 03:54:40 +00:00
Compare commits
8
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f6142e27e | ||
|
|
8c37b93a4b | ||
|
|
201d16af05 | ||
|
|
db007176fd | ||
|
|
83fb67132b | ||
|
|
a04837f4d5 | ||
|
|
3d8db53e52 | ||
|
|
5797f8a6ad |
@@ -6,7 +6,7 @@ import "github.com/blang/semver"
|
||||
|
||||
const (
|
||||
// Version is the current version of the application.
|
||||
Version = "0.18.2"
|
||||
Version = "0.18.3"
|
||||
// AppName is the name of the application.
|
||||
AppName = "beszel"
|
||||
)
|
||||
|
||||
@@ -4,7 +4,7 @@ go 1.25.5
|
||||
|
||||
require (
|
||||
github.com/blang/semver v3.5.1+incompatible
|
||||
github.com/coreos/go-systemd/v22 v22.6.0
|
||||
github.com/coreos/go-systemd/v22 v22.7.0
|
||||
github.com/distatus/battery v0.11.0
|
||||
github.com/ebitengine/purego v0.9.1
|
||||
github.com/fxamacker/cbor/v2 v2.9.0
|
||||
@@ -13,14 +13,14 @@ require (
|
||||
github.com/lxzan/gws v1.8.9
|
||||
github.com/nicholas-fedor/shoutrrr v0.13.1
|
||||
github.com/pocketbase/dbx v1.11.0
|
||||
github.com/pocketbase/pocketbase v0.35.1
|
||||
github.com/shirou/gopsutil/v4 v4.25.12
|
||||
github.com/pocketbase/pocketbase v0.36.2
|
||||
github.com/shirou/gopsutil/v4 v4.26.1
|
||||
github.com/spf13/cast v1.10.0
|
||||
github.com/spf13/cobra v1.10.2
|
||||
github.com/spf13/pflag v1.0.10
|
||||
github.com/stretchr/testify v1.11.1
|
||||
golang.org/x/crypto v0.46.0
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93
|
||||
golang.org/x/crypto v0.47.0
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96
|
||||
golang.org/x/sys v0.40.0
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
)
|
||||
@@ -34,15 +34,15 @@ require (
|
||||
github.com/domodwyer/mailyak/v3 v3.6.2 // indirect
|
||||
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 // indirect
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 // indirect
|
||||
github.com/ganigeorgiev/fexpr v0.5.0 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
|
||||
github.com/go-sql-driver/mysql v1.9.1 // indirect
|
||||
github.com/godbus/dbus/v5 v5.2.2 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/klauspost/compress v1.18.2 // indirect
|
||||
github.com/klauspost/compress v1.18.3 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20251013123823-9fd1530e3ec3 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
@@ -54,15 +54,15 @@ require (
|
||||
github.com/tklauser/numcpus v0.11.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
golang.org/x/image v0.34.0 // indirect
|
||||
golang.org/x/net v0.48.0 // indirect
|
||||
golang.org/x/image v0.35.0 // indirect
|
||||
golang.org/x/net v0.49.0 // indirect
|
||||
golang.org/x/oauth2 v0.34.0 // indirect
|
||||
golang.org/x/sync v0.19.0 // indirect
|
||||
golang.org/x/term v0.39.0 // indirect
|
||||
golang.org/x/text v0.33.0 // indirect
|
||||
howett.net/plist v1.0.1 // indirect
|
||||
modernc.org/libc v1.66.10 // indirect
|
||||
modernc.org/libc v1.67.6 // indirect
|
||||
modernc.org/mathutil v1.7.1 // indirect
|
||||
modernc.org/memory v1.11.0 // indirect
|
||||
modernc.org/sqlite v1.43.0 // indirect
|
||||
modernc.org/sqlite v1.44.3 // indirect
|
||||
)
|
||||
|
||||
@@ -9,8 +9,8 @@ github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 h1:DklsrG3d
|
||||
github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2/go.mod h1:WaHUgvxTVq04UNunO+XhnAqY/wQc+bxr74GqbsZ/Jqw=
|
||||
github.com/blang/semver v3.5.1+incompatible h1:cQNTCjp13qL8KC3Nbxr/y2Bqb63oX6wdnnjpJbkM4JQ=
|
||||
github.com/blang/semver v3.5.1+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
|
||||
github.com/coreos/go-systemd/v22 v22.6.0 h1:aGVa/v8B7hpb0TKl0MWoAavPDmHvobFe5R5zn0bCJWo=
|
||||
github.com/coreos/go-systemd/v22 v22.6.0/go.mod h1:iG+pp635Fo7ZmV/j14KUcmEyWF+0X7Lua8rrTWzYgWU=
|
||||
github.com/coreos/go-systemd/v22 v22.7.0 h1:LAEzFkke61DFROc7zNLX/WA2i5J8gYqe0rSj9KI28KA=
|
||||
github.com/coreos/go-systemd/v22 v22.7.0/go.mod h1:xNUYtjHu2EDXbsxz1i41wouACIwT7Ybq9o0BQhMwD0w=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
@@ -33,8 +33,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
|
||||
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12 h1:e9hWvmLYvtp846tLHam2o++qitpguFiYCKbn0w9jyqw=
|
||||
github.com/gabriel-vasile/mimetype v1.4.12/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
|
||||
github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
|
||||
github.com/ganigeorgiev/fexpr v0.5.0 h1:XA9JxtTE/Xm+g/JFI6RfZEHSiQlk+1glLvRK1Lpv/Tk=
|
||||
github.com/ganigeorgiev/fexpr v0.5.0/go.mod h1:RyGiGqmeXhEQ6+mlGdnUleLHgtzzu/VGO2WtJkF5drE=
|
||||
github.com/gliderlabs/ssh v0.3.8 h1:a4YXD1V7xMF9g5nTkdfnja3Sxy1PVDCj1Zg4Wb8vY6c=
|
||||
@@ -53,13 +53,13 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
|
||||
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
|
||||
github.com/godbus/dbus/v5 v5.2.2 h1:TUR3TgtSVDmjiXOgAAyaZbYmIeP3DPkld3jgKGV8mXQ=
|
||||
github.com/godbus/dbus/v5 v5.2.2/go.mod h1:3AAv2+hPq5rdnr5txxxRwiGjPXamgoIHgz9FPBfOp3c=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1 h1:kYf81DTWFe7t+1VvL7eS+jKFVWaUnK9cB1qbwn63YCY=
|
||||
github.com/golang-jwt/jwt/v5 v5.3.1/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/pprof v0.0.0-20251114195745-4902fdda35c8 h1:3DsUAV+VNEQa2CUVLxCY3f87278uWfIDhJnbdvDjvmE=
|
||||
github.com/google/pprof v0.0.0-20251114195745-4902fdda35c8/go.mod h1:I6V7YzU0XDpsHqbsyrghnFZLO1gwK6NPTNvmetQIk9U=
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83 h1:z2ogiKUYzX5Is6zr/vP9vJGqPwcdqsWjOt+V8J7+bTc=
|
||||
github.com/google/pprof v0.0.0-20260115054156-294ebfa9ad83/go.mod h1:MxpfABSjhmINe3F1It9d+8exIHFvUqtLIRCdOGNXqiI=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
@@ -69,8 +69,8 @@ github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLf
|
||||
github.com/jarcoal/httpmock v1.4.1 h1:0Ju+VCFuARfFlhVXFc2HxlcQkfB+Xq12/EotHko+x2A=
|
||||
github.com/jarcoal/httpmock v1.4.1/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLanykgjwBXL0=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
|
||||
github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/klauspost/compress v1.18.3 h1:9PJRvfbmTabkOX8moIpXPbMMbYN60bWImDDU7L+/6zw=
|
||||
github.com/klauspost/compress v1.18.3/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
@@ -96,8 +96,8 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pocketbase/dbx v1.11.0 h1:LpZezioMfT3K4tLrqA55wWFw1EtH1pM4tzSVa7kgszU=
|
||||
github.com/pocketbase/dbx v1.11.0/go.mod h1:xXRCIAKTHMgUCyCKZm55pUOdvFziJjQfXaWKhu2vhMs=
|
||||
github.com/pocketbase/pocketbase v0.35.1 h1:Cd5ivUThTw29myY/tYa2cb0elkScBMseG6fExZsIQB8=
|
||||
github.com/pocketbase/pocketbase v0.35.1/go.mod h1:yQnh1o1Aq6wVuqcmZbRbDmIhc31AME/F5pnPR0Bdtmg=
|
||||
github.com/pocketbase/pocketbase v0.36.2 h1:mzrxnvXKc3yxKlvZdbwoYXkH8kfIETteD0hWdgj0VI4=
|
||||
github.com/pocketbase/pocketbase v0.36.2/go.mod h1:71vSF8whUDzC8mcLFE10+Qatf9JQdeOGIRWawOuLLKM=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||
@@ -105,8 +105,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qq
|
||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/shirou/gopsutil/v4 v4.25.12 h1:e7PvW/0RmJ8p8vPGJH4jvNkOyLmbkXgXW4m6ZPic6CY=
|
||||
github.com/shirou/gopsutil/v4 v4.25.12/go.mod h1:EivAfP5x2EhLp2ovdpKSozecVXn1TmuG7SMzs/Wh4PU=
|
||||
github.com/shirou/gopsutil/v4 v4.26.1 h1:TOkEyriIXk2HX9d4isZJtbjXbEjf5qyKPAzbzY0JWSo=
|
||||
github.com/shirou/gopsutil/v4 v4.26.1/go.mod h1:medLI9/UNAb0dOI9Q3/7yWSqKkj00u+1tgY8nvv41pc=
|
||||
github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY=
|
||||
github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
|
||||
github.com/spf13/cobra v1.10.2 h1:DMTTonx5m65Ic0GOoRY2c16WCbHxOOw6xxezuLaBpcU=
|
||||
@@ -129,18 +129,18 @@ github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
|
||||
go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc=
|
||||
go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.46.0 h1:cKRW/pmt1pKAfetfu+RCEvjvZkA9RimPbh7bhFjGVBU=
|
||||
golang.org/x/crypto v0.46.0/go.mod h1:Evb/oLKmMraqjZ2iQTwDwvCtJkczlDuTmdJXoZVzqU0=
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93 h1:fQsdNF2N+/YewlRZiricy4P1iimyPKZ/xwniHj8Q2a0=
|
||||
golang.org/x/exp v0.0.0-20251219203646-944ab1f22d93/go.mod h1:EPRbTFwzwjXj9NpYyyrvenVh9Y+GFeEvMNh7Xuz7xgU=
|
||||
golang.org/x/crypto v0.47.0 h1:V6e3FRj+n4dbpw86FJ8Fv7XVOql7TEwpHapKoMJ/GO8=
|
||||
golang.org/x/crypto v0.47.0/go.mod h1:ff3Y9VzzKbwSSEzWqJsJVBnWmRwRSHt/6Op5n9bQc4A=
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96 h1:Z/6YuSHTLOHfNFdb8zVZomZr7cqNgTJvA8+Qz75D8gU=
|
||||
golang.org/x/exp v0.0.0-20260112195511-716be5621a96/go.mod h1:nzimsREAkjBCIEFtHiYkrJyT+2uy9YZJB7H1k68CXZU=
|
||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||
golang.org/x/image v0.34.0 h1:33gCkyw9hmwbZJeZkct8XyR11yH889EQt/QH4VmXMn8=
|
||||
golang.org/x/image v0.34.0/go.mod h1:2RNFBZRB+vnwwFil8GkMdRvrJOFd1AzdZI6vOY+eJVU=
|
||||
golang.org/x/mod v0.31.0 h1:HaW9xtz0+kOcWKwli0ZXy79Ix+UW/vOfmWI5QVd2tgI=
|
||||
golang.org/x/mod v0.31.0/go.mod h1:43JraMp9cGx1Rx3AqioxrbrhNsLl2l/iNAvuBkrezpg=
|
||||
golang.org/x/image v0.35.0 h1:LKjiHdgMtO8z7Fh18nGY6KDcoEtVfsgLDPeLyguqb7I=
|
||||
golang.org/x/image v0.35.0/go.mod h1:MwPLTVgvxSASsxdLzKrl8BRFuyqMyGhLwmC+TO1Sybk=
|
||||
golang.org/x/mod v0.32.0 h1:9F4d3PHLljb6x//jOyokMv3eX+YDeepZSEo3mFJy93c=
|
||||
golang.org/x/mod v0.32.0/go.mod h1:SgipZ/3h2Ci89DlEtEXWUk/HteuRin+HHhN+WbNhguU=
|
||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||
golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
|
||||
golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
|
||||
golang.org/x/net v0.49.0 h1:eeHFmOGUTtaaPSGNmjBKpbng9MulQsJURQUAfUwY++o=
|
||||
golang.org/x/net v0.49.0/go.mod h1:/ysNB2EvaqvesRkuLAyjI1ycPZlQHM3q01F02UY/MV8=
|
||||
golang.org/x/oauth2 v0.34.0 h1:hqK/t4AKgbqWkdkcAeI8XLmbK+4m4G5YeQRrmiotGlw=
|
||||
golang.org/x/oauth2 v0.34.0/go.mod h1:lzm5WQJQwKZ3nwavOZ3IS5Aulzxi68dUSgRHujetwEA=
|
||||
golang.org/x/sync v0.19.0 h1:vV+1eWNmZ5geRlYjzm2adRgW2/mcpevXNg50YZtPCE4=
|
||||
@@ -159,8 +159,8 @@ golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||
golang.org/x/text v0.33.0 h1:B3njUFyqtHDUI5jMn1YIr5B0IE2U0qck04r6d4KPAxE=
|
||||
golang.org/x/text v0.33.0/go.mod h1:LuMebE6+rBincTi9+xWTY8TztLzKHc/9C1uBCG27+q8=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.40.0 h1:yLkxfA+Qnul4cs9QA3KnlFu0lVmd8JJfoq+E41uSutA=
|
||||
golang.org/x/tools v0.40.0/go.mod h1:Ik/tzLRlbscWpqqMRjyWYDisX8bG13FrdXp3o4Sr9lc=
|
||||
golang.org/x/tools v0.41.0 h1:a9b8iMweWG+S0OBnlU36rzLp20z1Rp10w+IY2czHTQc=
|
||||
golang.org/x/tools v0.41.0/go.mod h1:XSY6eDqxVNiYgezAVqqCeihT4j1U2CCsqvH3WhQpnlg=
|
||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
|
||||
google.golang.org/protobuf v1.36.10 h1:AYd7cD/uASjIL6Q9LiTjz8JLcrh/88q5UObnmY3aOOE=
|
||||
google.golang.org/protobuf v1.36.10/go.mod h1:HTf+CrKn2C3g5S8VImy6tdcUvCska2kB7j23XfzDpco=
|
||||
@@ -185,10 +185,8 @@ modernc.org/gc/v3 v3.1.1 h1:k8T3gkXWY9sEiytKhcgyiZ2L0DTyCQ/nvX+LoCljoRE=
|
||||
modernc.org/gc/v3 v3.1.1/go.mod h1:HFK/6AGESC7Ex+EZJhJ2Gni6cTaYpSMmU/cT9RmlfYY=
|
||||
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
|
||||
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
|
||||
modernc.org/libc v1.66.10 h1:yZkb3YeLx4oynyR+iUsXsybsX4Ubx7MQlSYEw4yj59A=
|
||||
modernc.org/libc v1.66.10/go.mod h1:8vGSEwvoUoltr4dlywvHqjtAqHBaw0j1jI7iFBTAr2I=
|
||||
modernc.org/libc v1.67.4 h1:zZGmCMUVPORtKv95c2ReQN5VDjvkoRm9GWPTEPuvlWg=
|
||||
modernc.org/libc v1.67.4/go.mod h1:QvvnnJ5P7aitu0ReNpVIEyesuhmDLQ8kaEoyMjIFZJA=
|
||||
modernc.org/libc v1.67.6 h1:eVOQvpModVLKOdT+LvBPjdQqfrZq+pC39BygcT+E7OI=
|
||||
modernc.org/libc v1.67.6/go.mod h1:JAhxUVlolfYDErnwiqaLvUqc8nfb2r6S6slAgZOnaiE=
|
||||
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
|
||||
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
|
||||
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=
|
||||
@@ -197,8 +195,8 @@ modernc.org/opt v0.1.4 h1:2kNGMRiUjrp4LcaPuLY2PzUfqM/w9N23quVwhKt5Qm8=
|
||||
modernc.org/opt v0.1.4/go.mod h1:03fq9lsNfvkYSfxrfUhZCWPk1lm4cq4N+Bh//bEtgns=
|
||||
modernc.org/sortutil v1.2.1 h1:+xyoGf15mM3NMlPDnFqrteY07klSFxLElE2PVuWIJ7w=
|
||||
modernc.org/sortutil v1.2.1/go.mod h1:7ZI3a3REbai7gzCLcotuw9AC4VZVpYMjDzETGsSMqJE=
|
||||
modernc.org/sqlite v1.43.0 h1:8YqiFx3G1VhHTXO2Q00bl1Wz9KhS9Q5okwfp9Y97VnA=
|
||||
modernc.org/sqlite v1.43.0/go.mod h1:+VkC6v3pLOAE0A0uVucQEcbVW0I5nHCeDaBf+DpsQT8=
|
||||
modernc.org/sqlite v1.44.3 h1:+39JvV/HWMcYslAwRxHb8067w+2zowvFOUrOWIy9PjY=
|
||||
modernc.org/sqlite v1.44.3/go.mod h1:CzbrU2lSB1DKUusvwGz7rqEKIq+NUd8GWuBBZDs9/nA=
|
||||
modernc.org/strutil v1.2.1 h1:UneZBkQA+DX2Rp35KcM69cSsNES9ly8mQWD71HKlOA0=
|
||||
modernc.org/strutil v1.2.1/go.mod h1:EHkiggD70koQxjVdSBM3JKM7k6L0FbGE5eymy9i3B9A=
|
||||
modernc.org/token v1.1.0 h1:Xl7Ap9dKaEs5kLoOQeQmPWevfnk/DM5qcLcYlA8ys6Y=
|
||||
|
||||
@@ -105,8 +105,6 @@ func NewAlertManager(app hubLike) *AlertManager {
|
||||
func (am *AlertManager) bindEvents() {
|
||||
am.hub.OnRecordAfterUpdateSuccess("alerts").BindFunc(updateHistoryOnAlertUpdate)
|
||||
am.hub.OnRecordAfterDeleteSuccess("alerts").BindFunc(resolveHistoryOnAlertDelete)
|
||||
am.hub.OnRecordAfterUpdateSuccess("container_alerts").BindFunc(updateHistoryOnContainerAlertUpdate)
|
||||
am.hub.OnRecordAfterDeleteSuccess("container_alerts").BindFunc(resolveHistoryOnContainerAlertDelete)
|
||||
am.hub.OnRecordAfterUpdateSuccess("smart_devices").BindFunc(am.handleSmartDeviceAlert)
|
||||
}
|
||||
|
||||
|
||||
@@ -117,119 +117,3 @@ func DeleteUserAlerts(e *core.RequestEvent) error {
|
||||
|
||||
return e.JSON(http.StatusOK, map[string]any{"success": true, "count": numDeleted})
|
||||
}
|
||||
|
||||
// UpsertUserContainerAlerts handles API request to create or update container alerts for a user
|
||||
// across multiple containers (POST /api/beszel/user-container-alerts)
|
||||
func UpsertUserContainerAlerts(e *core.RequestEvent) error {
|
||||
userID := e.Auth.Id
|
||||
|
||||
reqData := struct {
|
||||
Min uint8 `json:"min"`
|
||||
Value float64 `json:"value"`
|
||||
Name string `json:"name"`
|
||||
Systems []string `json:"systems"`
|
||||
Containers []string `json:"containers"`
|
||||
Overwrite bool `json:"overwrite"`
|
||||
}{}
|
||||
err := e.BindBody(&reqData)
|
||||
if err != nil || userID == "" || reqData.Name == "" || len(reqData.Systems) == 0 || len(reqData.Containers) == 0 {
|
||||
return e.BadRequestError("Bad data", err)
|
||||
}
|
||||
|
||||
containerAlertsCollection, err := e.App.FindCachedCollectionByNameOrId("container_alerts")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = e.App.RunInTransaction(func(txApp core.App) error {
|
||||
for _, systemId := range reqData.Systems {
|
||||
for _, containerId := range reqData.Containers {
|
||||
// find existing matching alert
|
||||
alertRecord, err := txApp.FindFirstRecordByFilter(containerAlertsCollection,
|
||||
"system={:system} && container={:container} && name={:name} && user={:user}",
|
||||
dbx.Params{"system": systemId, "container": containerId, "name": reqData.Name, "user": userID})
|
||||
|
||||
if err != nil && !errors.Is(err, sql.ErrNoRows) {
|
||||
return err
|
||||
}
|
||||
|
||||
// skip if alert already exists and overwrite is not set
|
||||
if !reqData.Overwrite && alertRecord != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// create new alert if it doesn't exist
|
||||
if alertRecord == nil {
|
||||
alertRecord = core.NewRecord(containerAlertsCollection)
|
||||
alertRecord.Set("user", userID)
|
||||
alertRecord.Set("system", systemId)
|
||||
alertRecord.Set("container", containerId)
|
||||
alertRecord.Set("name", reqData.Name)
|
||||
}
|
||||
|
||||
alertRecord.Set("value", reqData.Value)
|
||||
alertRecord.Set("min", reqData.Min)
|
||||
|
||||
if err := txApp.SaveNoValidate(alertRecord); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, map[string]any{"success": true})
|
||||
}
|
||||
|
||||
// DeleteUserContainerAlerts handles API request to delete container alerts for a user
|
||||
// across multiple containers (DELETE /api/beszel/user-container-alerts)
|
||||
func DeleteUserContainerAlerts(e *core.RequestEvent) error {
|
||||
userID := e.Auth.Id
|
||||
|
||||
reqData := struct {
|
||||
AlertName string `json:"name"`
|
||||
Systems []string `json:"systems"`
|
||||
Containers []string `json:"containers"`
|
||||
}{}
|
||||
err := e.BindBody(&reqData)
|
||||
if err != nil || userID == "" || reqData.AlertName == "" || len(reqData.Systems) == 0 || len(reqData.Containers) == 0 {
|
||||
return e.BadRequestError("Bad data", err)
|
||||
}
|
||||
|
||||
var numDeleted uint16
|
||||
|
||||
err = e.App.RunInTransaction(func(txApp core.App) error {
|
||||
for _, systemId := range reqData.Systems {
|
||||
for _, containerId := range reqData.Containers {
|
||||
// Find existing alert to delete
|
||||
alertRecord, err := txApp.FindFirstRecordByFilter("container_alerts",
|
||||
"system={:system} && container={:container} && name={:name} && user={:user}",
|
||||
dbx.Params{"system": systemId, "container": containerId, "name": reqData.AlertName, "user": userID})
|
||||
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
// alert doesn't exist, continue to next container
|
||||
continue
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
if err := txApp.Delete(alertRecord); err != nil {
|
||||
return err
|
||||
}
|
||||
numDeleted++
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, map[string]any{"success": true, "count": numDeleted})
|
||||
}
|
||||
|
||||
@@ -1,394 +0,0 @@
|
||||
package alerts
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/henrygd/beszel/internal/entities/container"
|
||||
"github.com/henrygd/beszel/internal/entities/system"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"github.com/pocketbase/pocketbase/tools/types"
|
||||
"github.com/spf13/cast"
|
||||
)
|
||||
|
||||
// ContainerAlertData holds the data for a container alert
|
||||
type ContainerAlertData struct {
|
||||
systemRecord *core.Record
|
||||
containerRecord *core.Record
|
||||
alertRecord *core.Record
|
||||
name string
|
||||
unit string
|
||||
val float64
|
||||
threshold float64
|
||||
triggered bool
|
||||
time time.Time
|
||||
count uint8
|
||||
min uint8
|
||||
descriptor string // override descriptor in notification body
|
||||
}
|
||||
|
||||
// ContainerAlertStats represents the stats structure for container alerts
|
||||
type ContainerAlertStats struct {
|
||||
Cpu float64 `json:"c"`
|
||||
Mem float64 `json:"m"`
|
||||
NetworkSent float64 `json:"ns"`
|
||||
NetworkRecv float64 `json:"nr"`
|
||||
Status string `json:"s"`
|
||||
Health string `json:"h"`
|
||||
}
|
||||
|
||||
// HandleContainerAlerts processes container alerts for a system
|
||||
func (am *AlertManager) HandleContainerAlerts(systemRecord *core.Record, data *system.CombinedData) error {
|
||||
containers := data.Containers
|
||||
if len(containers) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Get all container alerts for this system
|
||||
alertRecords, err := am.hub.FindAllRecords("container_alerts",
|
||||
dbx.NewExp("system={:system}", dbx.Params{"system": systemRecord.Id}),
|
||||
)
|
||||
if err != nil || len(alertRecords) == 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Group alerts by container
|
||||
containerAlerts := make(map[string][]*core.Record)
|
||||
for _, alertRecord := range alertRecords {
|
||||
containerId := alertRecord.GetString("container")
|
||||
containerAlerts[containerId] = append(containerAlerts[containerId], alertRecord)
|
||||
}
|
||||
|
||||
// Process alerts for each container
|
||||
for containerId, alerts := range containerAlerts {
|
||||
// Find the container in the current stats
|
||||
var containerStats *container.Stats
|
||||
for _, c := range containers {
|
||||
if c.Id == containerId {
|
||||
containerStats = c
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// If container not found in current stats, it might be stopped
|
||||
// We'll still process Status and Health alerts
|
||||
if containerStats == nil {
|
||||
for _, alertRecord := range alerts {
|
||||
name := alertRecord.GetString("name")
|
||||
if name == "Status" || name == "Health" {
|
||||
// Container is missing, so it's likely stopped
|
||||
go am.sendContainerStatusAlert(alertRecord, systemRecord, containerId, "stopped")
|
||||
}
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
// Process each alert for this container
|
||||
var validAlerts []ContainerAlertData
|
||||
now := time.Now().UTC()
|
||||
oldestTime := now
|
||||
|
||||
for _, alertRecord := range alerts {
|
||||
name := alertRecord.GetString("name")
|
||||
var val float64
|
||||
unit := "%"
|
||||
|
||||
switch name {
|
||||
case "CPU":
|
||||
val = containerStats.Cpu
|
||||
case "Memory":
|
||||
val = containerStats.Mem
|
||||
case "Network":
|
||||
val = containerStats.NetworkSent + containerStats.NetworkRecv
|
||||
unit = " MB/s"
|
||||
case "Status":
|
||||
// Status alert is handled differently - immediate trigger
|
||||
triggered := alertRecord.GetBool("triggered")
|
||||
isRunning := containerStats.Status == "running"
|
||||
if (!triggered && !isRunning) || (triggered && isRunning) {
|
||||
go am.sendContainerStatusAlert(alertRecord, systemRecord, containerId, containerStats.Status)
|
||||
}
|
||||
continue
|
||||
case "Health":
|
||||
// Health alert - trigger on unhealthy status
|
||||
triggered := alertRecord.GetBool("triggered")
|
||||
isHealthy := containerStats.Health == container.DockerHealthNone || containerStats.Health == container.DockerHealthHealthy
|
||||
if (!triggered && !isHealthy) || (triggered && isHealthy) {
|
||||
go am.sendContainerHealthAlert(alertRecord, systemRecord, containerId, containerStats.Health)
|
||||
}
|
||||
continue
|
||||
default:
|
||||
continue
|
||||
}
|
||||
|
||||
triggered := alertRecord.GetBool("triggered")
|
||||
threshold := alertRecord.GetFloat("value")
|
||||
min := max(1, cast.ToUint8(alertRecord.Get("min")))
|
||||
|
||||
alert := ContainerAlertData{
|
||||
systemRecord: systemRecord,
|
||||
alertRecord: alertRecord,
|
||||
name: name,
|
||||
unit: unit,
|
||||
val: val,
|
||||
threshold: threshold,
|
||||
triggered: triggered,
|
||||
min: min,
|
||||
}
|
||||
|
||||
// Send alert immediately if min is 1
|
||||
if min == 1 {
|
||||
alert.triggered = val > threshold
|
||||
go am.sendContainerAlert(alert, containerId, containerStats.Name)
|
||||
continue
|
||||
}
|
||||
|
||||
alert.time = now.Add(-time.Duration(min) * time.Minute)
|
||||
if alert.time.Before(oldestTime) {
|
||||
oldestTime = alert.time
|
||||
}
|
||||
|
||||
validAlerts = append(validAlerts, alert)
|
||||
}
|
||||
|
||||
if len(validAlerts) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Fetch historical container stats
|
||||
containerStatsRecords := []struct {
|
||||
Stats []byte `db:"stats"`
|
||||
Created types.DateTime `db:"created"`
|
||||
}{}
|
||||
|
||||
err = am.hub.DB().
|
||||
Select("stats", "created").
|
||||
From("container_stats").
|
||||
Where(dbx.NewExp(
|
||||
"system={:system} AND type='1m' AND created > {:created}",
|
||||
dbx.Params{
|
||||
"system": systemRecord.Id,
|
||||
"created": oldestTime.Add(-time.Second * 90),
|
||||
},
|
||||
)).
|
||||
OrderBy("created").
|
||||
All(&containerStatsRecords)
|
||||
|
||||
if err != nil || len(containerStatsRecords) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
oldestRecordTime := containerStatsRecords[0].Created.Time()
|
||||
|
||||
// Filter valid alerts
|
||||
filteredAlerts := make([]ContainerAlertData, 0, len(validAlerts))
|
||||
for _, alert := range validAlerts {
|
||||
if alert.time.After(oldestRecordTime) {
|
||||
filteredAlerts = append(filteredAlerts, alert)
|
||||
}
|
||||
}
|
||||
validAlerts = filteredAlerts
|
||||
|
||||
if len(validAlerts) == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
// Process historical stats
|
||||
for i := range containerStatsRecords {
|
||||
stat := containerStatsRecords[i]
|
||||
systemStatsCreation := stat.Created.Time().Add(-time.Second * 10)
|
||||
|
||||
// Parse container stats array
|
||||
var allContainerStats []*container.Stats
|
||||
if err := json.Unmarshal(stat.Stats, &allContainerStats); err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Find this container in the stats
|
||||
var thisContainerStats *container.Stats
|
||||
for _, cs := range allContainerStats {
|
||||
if cs.Id == containerId {
|
||||
thisContainerStats = cs
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
if thisContainerStats == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
for j := range validAlerts {
|
||||
alert := &validAlerts[j]
|
||||
if i == 0 {
|
||||
alert.val = 0
|
||||
}
|
||||
if systemStatsCreation.Before(alert.time) {
|
||||
continue
|
||||
}
|
||||
|
||||
switch alert.name {
|
||||
case "CPU":
|
||||
alert.val += thisContainerStats.Cpu
|
||||
case "Memory":
|
||||
alert.val += thisContainerStats.Mem
|
||||
case "Network":
|
||||
alert.val += thisContainerStats.NetworkSent + thisContainerStats.NetworkRecv
|
||||
default:
|
||||
continue
|
||||
}
|
||||
alert.count++
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate averages and send alerts
|
||||
for _, alert := range validAlerts {
|
||||
alert.val = alert.val / float64(alert.count)
|
||||
minCount := float32(alert.min) / 1.2
|
||||
|
||||
if float32(alert.count) >= minCount {
|
||||
if !alert.triggered && alert.val > alert.threshold {
|
||||
alert.triggered = true
|
||||
go am.sendContainerAlert(alert, containerId, containerStats.Name)
|
||||
} else if alert.triggered && alert.val <= alert.threshold {
|
||||
alert.triggered = false
|
||||
go am.sendContainerAlert(alert, containerId, containerStats.Name)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// sendContainerAlert sends a container alert notification
|
||||
func (am *AlertManager) sendContainerAlert(alert ContainerAlertData, containerId, containerName string) {
|
||||
systemName := alert.systemRecord.GetString("name")
|
||||
|
||||
var subject string
|
||||
if alert.triggered {
|
||||
subject = fmt.Sprintf("%s container %s %s above threshold", systemName, containerName, strings.ToLower(alert.name))
|
||||
} else {
|
||||
subject = fmt.Sprintf("%s container %s %s below threshold", systemName, containerName, strings.ToLower(alert.name))
|
||||
}
|
||||
|
||||
minutesLabel := "minute"
|
||||
if alert.min > 1 {
|
||||
minutesLabel += "s"
|
||||
}
|
||||
|
||||
descriptor := alert.name
|
||||
if alert.descriptor != "" {
|
||||
descriptor = alert.descriptor
|
||||
}
|
||||
|
||||
body := fmt.Sprintf("%s averaged %.2f%s for the previous %v %s.", descriptor, alert.val, alert.unit, alert.min, minutesLabel)
|
||||
|
||||
alert.alertRecord.Set("triggered", alert.triggered)
|
||||
if err := am.hub.Save(alert.alertRecord); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
am.SendAlert(AlertMessageData{
|
||||
UserID: alert.alertRecord.GetString("user"),
|
||||
SystemID: alert.systemRecord.Id,
|
||||
Title: subject,
|
||||
Message: body,
|
||||
Link: am.hub.MakeLink("system", alert.systemRecord.Id, "containers", containerId),
|
||||
LinkText: "View " + containerName,
|
||||
})
|
||||
}
|
||||
|
||||
// sendContainerStatusAlert sends a container status change alert
|
||||
func (am *AlertManager) sendContainerStatusAlert(alertRecord, systemRecord *core.Record, containerId, status string) {
|
||||
triggered := alertRecord.GetBool("triggered")
|
||||
isRunning := status == "running"
|
||||
|
||||
// Only send if state changed
|
||||
if (!triggered && isRunning) || (triggered && !isRunning) {
|
||||
return
|
||||
}
|
||||
|
||||
systemName := systemRecord.GetString("name")
|
||||
|
||||
// Try to get container name from containers collection
|
||||
containerName := containerId
|
||||
if containerRecord, err := am.hub.FindFirstRecordByFilter("containers", "id={:id}", dbx.Params{"id": containerId}); err == nil {
|
||||
containerName = containerRecord.GetString("name")
|
||||
}
|
||||
|
||||
var subject string
|
||||
if isRunning {
|
||||
subject = fmt.Sprintf("%s container %s is now running", systemName, containerName)
|
||||
} else {
|
||||
subject = fmt.Sprintf("%s container %s has stopped", systemName, containerName)
|
||||
}
|
||||
|
||||
body := fmt.Sprintf("Container status changed to: %s", status)
|
||||
|
||||
alertRecord.Set("triggered", !isRunning)
|
||||
if err := am.hub.Save(alertRecord); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
am.SendAlert(AlertMessageData{
|
||||
UserID: alertRecord.GetString("user"),
|
||||
SystemID: systemRecord.Id,
|
||||
Title: subject,
|
||||
Message: body,
|
||||
Link: am.hub.MakeLink("system", systemRecord.Id, "containers", containerId),
|
||||
LinkText: "View " + containerName,
|
||||
})
|
||||
}
|
||||
|
||||
// sendContainerHealthAlert sends a container health status change alert
|
||||
func (am *AlertManager) sendContainerHealthAlert(alertRecord, systemRecord *core.Record, containerId string, health container.DockerHealth) {
|
||||
triggered := alertRecord.GetBool("triggered")
|
||||
isHealthy := health == container.DockerHealthNone || health == container.DockerHealthHealthy
|
||||
|
||||
// Only send if state changed
|
||||
if (!triggered && isHealthy) || (triggered && !isHealthy) {
|
||||
return
|
||||
}
|
||||
|
||||
systemName := systemRecord.GetString("name")
|
||||
|
||||
// Try to get container name from containers collection
|
||||
containerName := containerId
|
||||
if containerRecord, err := am.hub.FindFirstRecordByFilter("containers", "id={:id}", dbx.Params{"id": containerId}); err == nil {
|
||||
containerName = containerRecord.GetString("name")
|
||||
}
|
||||
|
||||
var subject string
|
||||
if isHealthy {
|
||||
subject = fmt.Sprintf("%s container %s is now healthy", systemName, containerName)
|
||||
} else {
|
||||
subject = fmt.Sprintf("%s container %s is unhealthy", systemName, containerName)
|
||||
}
|
||||
|
||||
// Convert DockerHealth to string
|
||||
healthStatus := "unknown"
|
||||
for str, val := range container.DockerHealthStrings {
|
||||
if val == health {
|
||||
healthStatus = str
|
||||
break
|
||||
}
|
||||
}
|
||||
body := fmt.Sprintf("Container health status changed to: %s", healthStatus)
|
||||
|
||||
alertRecord.Set("triggered", !isHealthy)
|
||||
if err := am.hub.Save(alertRecord); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
am.SendAlert(AlertMessageData{
|
||||
UserID: alertRecord.GetString("user"),
|
||||
SystemID: systemRecord.Id,
|
||||
Title: subject,
|
||||
Message: body,
|
||||
Link: am.hub.MakeLink("system", systemRecord.Id, "containers", containerId),
|
||||
LinkText: "View " + containerName,
|
||||
})
|
||||
}
|
||||
@@ -72,70 +72,3 @@ func createAlertHistoryRecord(app core.App, alertRecord *core.Record) (alertHist
|
||||
}
|
||||
return alertHistoryRecord, err
|
||||
}
|
||||
|
||||
// On triggered container alert record delete, set matching alert history record to resolved
|
||||
func resolveHistoryOnContainerAlertDelete(e *core.RecordEvent) error {
|
||||
if !e.Record.GetBool("triggered") {
|
||||
return e.Next()
|
||||
}
|
||||
_ = resolveContainerAlertHistoryRecord(e.App, e.Record.Id)
|
||||
return e.Next()
|
||||
}
|
||||
|
||||
// On container alert record update, update alert history record
|
||||
func updateHistoryOnContainerAlertUpdate(e *core.RecordEvent) error {
|
||||
original := e.Record.Original()
|
||||
new := e.Record
|
||||
|
||||
originalTriggered := original.GetBool("triggered")
|
||||
newTriggered := new.GetBool("triggered")
|
||||
|
||||
// no need to update alert history if triggered state has not changed
|
||||
if originalTriggered == newTriggered {
|
||||
return e.Next()
|
||||
}
|
||||
|
||||
// if new state is triggered, create new alert history record
|
||||
if newTriggered {
|
||||
_, _ = createContainerAlertHistoryRecord(e.App, new)
|
||||
return e.Next()
|
||||
}
|
||||
|
||||
// if new state is not triggered, check for matching alert history record and set it to resolved
|
||||
_ = resolveContainerAlertHistoryRecord(e.App, new.Id)
|
||||
return e.Next()
|
||||
}
|
||||
|
||||
// resolveContainerAlertHistoryRecord sets the resolved field to the current time
|
||||
func resolveContainerAlertHistoryRecord(app core.App, alertRecordID string) error {
|
||||
alertHistoryRecord, err := app.FindFirstRecordByFilter("alerts_history", "alert_id={:alert_id} && resolved=null", dbx.Params{"alert_id": alertRecordID})
|
||||
if err != nil || alertHistoryRecord == nil {
|
||||
return err
|
||||
}
|
||||
alertHistoryRecord.Set("resolved", time.Now().UTC())
|
||||
err = app.Save(alertHistoryRecord)
|
||||
if err != nil {
|
||||
app.Logger().Error("Failed to resolve container alert history", "err", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// createContainerAlertHistoryRecord creates a new container alert history record
|
||||
func createContainerAlertHistoryRecord(app core.App, alertRecord *core.Record) (alertHistoryRecord *core.Record, err error) {
|
||||
alertHistoryCollection, err := app.FindCachedCollectionByNameOrId("alerts_history")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
alertHistoryRecord = core.NewRecord(alertHistoryCollection)
|
||||
alertHistoryRecord.Set("alert_id", alertRecord.Id)
|
||||
alertHistoryRecord.Set("user", alertRecord.GetString("user"))
|
||||
alertHistoryRecord.Set("system", alertRecord.GetString("system"))
|
||||
alertHistoryRecord.Set("container", alertRecord.GetString("container"))
|
||||
alertHistoryRecord.Set("name", alertRecord.GetString("name"))
|
||||
alertHistoryRecord.Set("value", alertRecord.GetFloat("value"))
|
||||
err = app.Save(alertHistoryRecord)
|
||||
if err != nil {
|
||||
app.Logger().Error("Failed to save container alert history", "err", err)
|
||||
}
|
||||
return alertHistoryRecord, err
|
||||
}
|
||||
|
||||
@@ -296,9 +296,6 @@ func (h *Hub) registerApiRoutes(se *core.ServeEvent) error {
|
||||
// update / delete user alerts
|
||||
apiAuth.POST("/user-alerts", alerts.UpsertUserAlerts)
|
||||
apiAuth.DELETE("/user-alerts", alerts.DeleteUserAlerts)
|
||||
// update / delete container alerts
|
||||
apiAuth.POST("/user-container-alerts", alerts.UpsertUserContainerAlerts)
|
||||
apiAuth.DELETE("/user-container-alerts", alerts.DeleteUserContainerAlerts)
|
||||
// refresh SMART devices for a system
|
||||
apiAuth.POST("/smart/refresh", h.refreshSmartData)
|
||||
// get systemd service details
|
||||
|
||||
@@ -51,7 +51,6 @@ type hubLike interface {
|
||||
core.App
|
||||
GetSSHKey(dataDir string) (ssh.Signer, error)
|
||||
HandleSystemAlerts(systemRecord *core.Record, data *system.CombinedData) error
|
||||
HandleContainerAlerts(systemRecord *core.Record, data *system.CombinedData) error
|
||||
HandleStatusAlerts(status string, systemRecord *core.Record) error
|
||||
}
|
||||
|
||||
@@ -212,10 +211,6 @@ func (sm *SystemManager) onRecordAfterUpdateSuccess(e *core.RecordEvent) error {
|
||||
if err := sm.hub.HandleSystemAlerts(e.Record, system.data); err != nil {
|
||||
e.App.Logger().Error("Error handling system alerts", "err", err)
|
||||
}
|
||||
// Trigger container alerts
|
||||
if err := sm.hub.HandleContainerAlerts(e.Record, system.data); err != nil {
|
||||
e.App.Logger().Error("Error handling container alerts", "err", err)
|
||||
}
|
||||
}
|
||||
|
||||
// Trigger status change alerts for up/down transitions
|
||||
|
||||
@@ -1,208 +0,0 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
|
||||
func init() {
|
||||
m.Register(func(app core.App) error {
|
||||
// 1. Create container_alerts collection
|
||||
// Check if collection already exists to prevent errors on restart
|
||||
if _, err := app.FindCollectionByNameOrId("container_alerts"); err == nil {
|
||||
// Collection exists, skip creation
|
||||
} else {
|
||||
jsonData := `{
|
||||
"id": "ca_container_alerts",
|
||||
"name": "container_alerts",
|
||||
"type": "base",
|
||||
"system": false,
|
||||
"listRule": "@request.auth.id != \"\" && user.id = @request.auth.id",
|
||||
"viewRule": "",
|
||||
"createRule": "@request.auth.id != \"\" && user.id = @request.auth.id",
|
||||
"updateRule": "@request.auth.id != \"\" && user.id = @request.auth.id",
|
||||
"deleteRule": "@request.auth.id != \"\" && user.id = @request.auth.id",
|
||||
"fields": [
|
||||
{
|
||||
"id": "text_id",
|
||||
"name": "id",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": true,
|
||||
"primaryKey": true,
|
||||
"autogeneratePattern": "[a-z0-9]{15}",
|
||||
"min": 15,
|
||||
"max": 15,
|
||||
"pattern": "^[a-z0-9]+$"
|
||||
},
|
||||
{
|
||||
"id": "rel_user",
|
||||
"name": "user",
|
||||
"type": "relation",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false,
|
||||
"collectionId": "_pb_users_auth_",
|
||||
"cascadeDelete": true,
|
||||
"minSelect": null,
|
||||
"maxSelect": 1,
|
||||
"displayFields": null
|
||||
},
|
||||
{
|
||||
"id": "rel_system",
|
||||
"name": "system",
|
||||
"type": "relation",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false,
|
||||
"collectionId": "2hz5ncl8tizk5nx",
|
||||
"cascadeDelete": true,
|
||||
"minSelect": null,
|
||||
"maxSelect": 1,
|
||||
"displayFields": null
|
||||
},
|
||||
{
|
||||
"id": "text_container",
|
||||
"name": "container",
|
||||
"type": "text",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false,
|
||||
"min": null,
|
||||
"max": null,
|
||||
"pattern": ""
|
||||
},
|
||||
{
|
||||
"id": "select_name",
|
||||
"name": "name",
|
||||
"type": "select",
|
||||
"required": true,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false,
|
||||
"maxSelect": 1,
|
||||
"values": [
|
||||
"Status",
|
||||
"CPU",
|
||||
"Memory",
|
||||
"Network",
|
||||
"Health"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "number_value",
|
||||
"name": "value",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false,
|
||||
"min": null,
|
||||
"max": null,
|
||||
"onlyInt": false
|
||||
},
|
||||
{
|
||||
"id": "number_min",
|
||||
"name": "min",
|
||||
"type": "number",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false,
|
||||
"min": null,
|
||||
"max": 60,
|
||||
"onlyInt": true
|
||||
},
|
||||
{
|
||||
"id": "bool_triggered",
|
||||
"name": "triggered",
|
||||
"type": "bool",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false
|
||||
},
|
||||
{
|
||||
"id": "autodate_created",
|
||||
"name": "created",
|
||||
"type": "autodate",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false,
|
||||
"onCreate": true,
|
||||
"onUpdate": false
|
||||
},
|
||||
{
|
||||
"id": "autodate_updated",
|
||||
"name": "updated",
|
||||
"type": "autodate",
|
||||
"required": false,
|
||||
"presentable": false,
|
||||
"unique": false,
|
||||
"system": false,
|
||||
"onCreate": true,
|
||||
"onUpdate": true
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE UNIQUE INDEX ` + "`" + `idx_container_alerts_unique` + "`" + ` ON ` + "`" + `container_alerts` + "`" + ` (` + "`" + `user` + "`" + `, ` + "`" + `system` + "`" + `, ` + "`" + `container` + "`" + `, ` + "`" + `name` + "`" + `)"
|
||||
]
|
||||
}`
|
||||
|
||||
collection := &core.Collection{}
|
||||
if err := json.Unmarshal([]byte(jsonData), collection); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := app.Save(collection); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// 2. Add container field to alerts_history collection
|
||||
alertsHistoryCollection, err := app.FindCollectionByNameOrId("alerts_history")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if alertsHistoryCollection.Fields.GetByName("container") == nil {
|
||||
containerField := &core.TextField{
|
||||
Name: "container",
|
||||
Required: false,
|
||||
}
|
||||
|
||||
alertsHistoryCollection.Fields.Add(containerField)
|
||||
|
||||
return app.Save(alertsHistoryCollection)
|
||||
}
|
||||
|
||||
return nil
|
||||
}, func(app core.App) error {
|
||||
// Rollback 2: remove the container field
|
||||
alertsHistoryCollection, err := app.FindCollectionByNameOrId("alerts_history")
|
||||
if err == nil {
|
||||
if field := alertsHistoryCollection.Fields.GetByName("container"); field != nil {
|
||||
alertsHistoryCollection.Fields.RemoveByName("container")
|
||||
if err := app.Save(alertsHistoryCollection); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Rollback 1: delete the container_alerts collection
|
||||
collection, err := app.FindCollectionByNameOrId("container_alerts")
|
||||
if err == nil {
|
||||
return app.Delete(collection)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
}
|
||||
@@ -190,6 +190,8 @@ func (rm *RecordManager) AverageSystemStats(db dbx.Builder, records RecordIds) *
|
||||
id := record.Id
|
||||
// clear global statsRecord for reuse
|
||||
statsRecord.Stats = statsRecord.Stats[:0]
|
||||
// reset tempStats each iteration to avoid omitzero fields retaining stale values
|
||||
*stats = system.Stats{}
|
||||
|
||||
queryParams["id"] = id
|
||||
db.NewQuery("SELECT stats FROM system_stats WHERE id = {:id}").Bind(queryParams).One(&statsRecord)
|
||||
@@ -444,9 +446,11 @@ func (rm *RecordManager) AverageContainerStats(db dbx.Builder, records RecordIds
|
||||
|
||||
for i := range records {
|
||||
id := records[i].Id
|
||||
// clear global statsRecord and containerStats for reuse
|
||||
// clear global statsRecord for reuse
|
||||
statsRecord.Stats = statsRecord.Stats[:0]
|
||||
containerStats = containerStats[:0]
|
||||
// must set to nil (not [:0]) to avoid json.Unmarshal reusing backing array
|
||||
// which causes omitzero fields to inherit stale values from previous iterations
|
||||
containerStats = nil
|
||||
|
||||
queryParams["id"] = id
|
||||
db.NewQuery("SELECT stats FROM container_stats WHERE id = {:id}").Bind(queryParams).One(&statsRecord)
|
||||
|
||||
Generated
+14
-44
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "beszel",
|
||||
"version": "0.18.2",
|
||||
"version": "0.18.3",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "beszel",
|
||||
"version": "0.18.2",
|
||||
"version": "0.18.3",
|
||||
"dependencies": {
|
||||
"@henrygd/queue": "^1.0.7",
|
||||
"@henrygd/semaphore": "^0.0.2",
|
||||
@@ -111,7 +111,6 @@
|
||||
"integrity": "sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@ampproject/remapping": "^2.2.0",
|
||||
"@babel/code-frame": "^7.27.1",
|
||||
@@ -1138,7 +1137,6 @@
|
||||
"integrity": "sha512-9IO+PDvdneY8OCI8zvI1oDXpzryTMtyRv7uq9O0U1mFCvIPVd5dWQKQDu/CpgpYAc2+JG/izn5PNl9xzPc6ckw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "^7.20.12",
|
||||
"@babel/runtime": "^7.20.13",
|
||||
@@ -1292,7 +1290,6 @@
|
||||
"resolved": "https://registry.npmjs.org/@lingui/core/-/core-5.4.1.tgz",
|
||||
"integrity": "sha512-4FeIh56PH5vziPg2BYo4XYWWOHE4XaY/XR8Jakwn0/qwtLpydWMNVpZOpGWi7nfPZtcLaJLmZKup6UNxEl1Pfw==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@babel/runtime": "^7.20.13",
|
||||
"@lingui/message-utils": "5.4.1"
|
||||
@@ -3488,7 +3485,6 @@
|
||||
"integrity": "sha512-lr3jdBw/BGj49Eps7EvqlUaoeA0xpj3pc0RoJkHpYaCHkVK7i28dKyImLQb3JVlqs3aYSXf7qYuWOW/fgZnTXQ==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"csstype": "^3.0.2"
|
||||
}
|
||||
@@ -3499,7 +3495,6 @@
|
||||
"integrity": "sha512-i5ZzwYpqjmrKenzkoLM2Ibzt6mAsM7pxB6BCIouEVVmgiqaMj1TjaK7hnA36hbW5aZv20kx7Lw6hWzPWg0Rurw==",
|
||||
"devOptional": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"peerDependencies": {
|
||||
"@types/react": "^19.0.0"
|
||||
}
|
||||
@@ -3704,7 +3699,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"caniuse-lite": "^1.0.30001726",
|
||||
"electron-to-chromium": "^1.5.173",
|
||||
@@ -5078,9 +5072,9 @@
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash": {
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"version": "4.17.23",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
|
||||
"integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/lodash.sortby": {
|
||||
@@ -5322,9 +5316,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/minizlib": {
|
||||
"version": "3.0.2",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.0.2.tgz",
|
||||
"integrity": "sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA==",
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz",
|
||||
"integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
@@ -5334,22 +5328,6 @@
|
||||
"node": ">= 18"
|
||||
}
|
||||
},
|
||||
"node_modules/mkdirp": {
|
||||
"version": "3.0.1",
|
||||
"resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-3.0.1.tgz",
|
||||
"integrity": "sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"bin": {
|
||||
"mkdirp": "dist/cjs/src/bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=10"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/moo": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
|
||||
@@ -5393,7 +5371,6 @@
|
||||
}
|
||||
],
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": "^18.0.0 || >=20.0.0"
|
||||
}
|
||||
@@ -5603,7 +5580,6 @@
|
||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
@@ -5749,7 +5725,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react/-/react-19.1.2.tgz",
|
||||
"integrity": "sha512-MdWVitvLbQULD+4DP8GYjZUrepGW7d+GQkNVqJEzNxE+e9WIa4egVFE/RDfVb1u9u/Jw7dNMmPB4IqxzbFYJ0w==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
@@ -5759,7 +5734,6 @@
|
||||
"resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.1.2.tgz",
|
||||
"integrity": "sha512-dEoydsCp50i7kS1xHOmPXq4zQYoGWedUsvqv9H6zdif2r7yLHygyfP9qou71TulRN0d6ng9EbRVsQhSqfUc19g==",
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"scheduler": "^0.26.0"
|
||||
},
|
||||
@@ -6299,8 +6273,7 @@
|
||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.12.tgz",
|
||||
"integrity": "sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.3",
|
||||
@@ -6317,17 +6290,16 @@
|
||||
}
|
||||
},
|
||||
"node_modules/tar": {
|
||||
"version": "7.4.3",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.4.3.tgz",
|
||||
"integrity": "sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw==",
|
||||
"version": "7.5.7",
|
||||
"resolved": "https://registry.npmjs.org/tar/-/tar-7.5.7.tgz",
|
||||
"integrity": "sha512-fov56fJiRuThVFXD6o6/Q354S7pnWMJIVlDBYijsTNx6jKSE4pvrDTs6lUnmGvNyfJwFQQwWy3owKz1ucIhveQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/fs-minipass": "^4.0.0",
|
||||
"chownr": "^3.0.0",
|
||||
"minipass": "^7.1.2",
|
||||
"minizlib": "^3.0.1",
|
||||
"mkdirp": "^3.0.1",
|
||||
"minizlib": "^3.1.0",
|
||||
"yallist": "^5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
@@ -6422,7 +6394,6 @@
|
||||
"integrity": "sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==",
|
||||
"devOptional": true,
|
||||
"license": "Apache-2.0",
|
||||
"peer": true,
|
||||
"bin": {
|
||||
"tsc": "bin/tsc",
|
||||
"tsserver": "bin/tsserver"
|
||||
@@ -6657,7 +6628,6 @@
|
||||
"integrity": "sha512-uzcxnSDVjAopEUjljkWh8EIrg6tlzrjFUfMcR1EVsRDGwf/ccef0qQPRyOrROwhrTDaApueq+ja+KLPlzR/zdg==",
|
||||
"dev": true,
|
||||
"license": "MIT",
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"esbuild": "^0.25.0",
|
||||
"fdir": "^6.5.0",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "beszel",
|
||||
"private": true,
|
||||
"version": "0.18.2",
|
||||
"version": "0.18.3",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
import { t } from "@lingui/core/macro"
|
||||
import { useStore } from "@nanostores/react"
|
||||
import { BellIcon } from "lucide-react"
|
||||
import { memo, useMemo, useState } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
|
||||
import { $containerAlerts } from "@/lib/stores"
|
||||
import { cn } from "@/lib/utils"
|
||||
import type { ContainerRecord } from "@/types"
|
||||
import { ContainerAlertDialogContent } from "./container-alerts-sheet"
|
||||
|
||||
export default memo(function ContainerAlertButton({
|
||||
systemId,
|
||||
container,
|
||||
}: {
|
||||
systemId: string
|
||||
container: ContainerRecord
|
||||
}) {
|
||||
const [opened, setOpened] = useState(false)
|
||||
const alerts = useStore($containerAlerts)
|
||||
|
||||
const containerAlerts = alerts[systemId]?.get(container.id)
|
||||
const hasContainerAlert = containerAlerts && containerAlerts.size > 0
|
||||
|
||||
return useMemo(
|
||||
() => (
|
||||
<Sheet>
|
||||
<SheetTrigger asChild>
|
||||
<Button variant="ghost" size="icon" aria-label={t`Alerts`} data-nolink onClick={() => setOpened(true)}>
|
||||
<BellIcon
|
||||
className={cn("h-[1.2em] w-[1.2em] pointer-events-none", {
|
||||
"fill-primary": hasContainerAlert,
|
||||
})}
|
||||
/>
|
||||
</Button>
|
||||
</SheetTrigger>
|
||||
<SheetContent className="max-h-full overflow-auto w-150 !max-w-full p-4 sm:p-6">
|
||||
{opened && <ContainerAlertDialogContent systemId={systemId} container={container} />}
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
),
|
||||
[opened, hasContainerAlert]
|
||||
)
|
||||
})
|
||||
@@ -1,327 +0,0 @@
|
||||
import { t } from "@lingui/core/macro"
|
||||
import { Plural, Trans } from "@lingui/react/macro"
|
||||
import { useStore } from "@nanostores/react"
|
||||
import { getPagePath } from "@nanostores/router"
|
||||
import { BoxIcon, GlobeIcon } from "lucide-react"
|
||||
import { lazy, memo, Suspense, useMemo, useState } from "react"
|
||||
import { $router, Link } from "@/components/router"
|
||||
import { Checkbox } from "@/components/ui/checkbox"
|
||||
import { DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
|
||||
import { Switch } from "@/components/ui/switch"
|
||||
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
|
||||
import { toast } from "@/components/ui/use-toast"
|
||||
import { containerAlertInfo } from "@/lib/container-alerts"
|
||||
import { pb } from "@/lib/api"
|
||||
import { $containerAlerts } from "@/lib/stores"
|
||||
import { cn, debounce } from "@/lib/utils"
|
||||
import type { ContainerAlertInfo, ContainerAlertRecord, ContainerRecord } from "@/types"
|
||||
|
||||
const Slider = lazy(() => import("@/components/ui/slider"))
|
||||
|
||||
const endpoint = "/api/beszel/user-container-alerts"
|
||||
|
||||
const alertDebounce = 100
|
||||
|
||||
const alertKeys = Object.keys(containerAlertInfo) as (keyof typeof containerAlertInfo)[]
|
||||
|
||||
const failedUpdateToast = (error: unknown) => {
|
||||
console.error(error)
|
||||
toast({
|
||||
title: t`Failed to update alert`,
|
||||
description: t`Please check logs for more details.`,
|
||||
variant: "destructive",
|
||||
})
|
||||
}
|
||||
|
||||
/** Create or update container alerts */
|
||||
const upsertContainerAlerts = debounce(
|
||||
async ({
|
||||
name,
|
||||
value,
|
||||
min,
|
||||
systems,
|
||||
containers,
|
||||
}: {
|
||||
name: string
|
||||
value: number
|
||||
min: number
|
||||
systems: string[]
|
||||
containers: string[]
|
||||
}) => {
|
||||
try {
|
||||
await pb.send<{ success: boolean }>(endpoint, {
|
||||
method: "POST",
|
||||
body: { name, value, min, systems, containers, overwrite: true },
|
||||
})
|
||||
} catch (error) {
|
||||
failedUpdateToast(error)
|
||||
}
|
||||
},
|
||||
alertDebounce
|
||||
)
|
||||
|
||||
/** Delete container alerts */
|
||||
const deleteContainerAlerts = debounce(
|
||||
async ({ name, systems, containers }: { name: string; systems: string[]; containers: string[] }) => {
|
||||
try {
|
||||
await pb.send<{ success: boolean }>(endpoint, {
|
||||
method: "DELETE",
|
||||
body: { name, systems, containers },
|
||||
})
|
||||
} catch (error) {
|
||||
failedUpdateToast(error)
|
||||
}
|
||||
},
|
||||
alertDebounce
|
||||
)
|
||||
|
||||
export const ContainerAlertDialogContent = memo(function ContainerAlertDialogContent({
|
||||
systemId,
|
||||
container,
|
||||
}: {
|
||||
systemId: string
|
||||
container: ContainerRecord
|
||||
}) {
|
||||
const alerts = useStore($containerAlerts)
|
||||
const [overwriteExisting, setOverwriteExisting] = useState<boolean | "indeterminate">(false)
|
||||
const [currentTab, setCurrentTab] = useState("container")
|
||||
|
||||
const containerAlerts = alerts[systemId]?.get(container.id) ?? new Map()
|
||||
|
||||
// Keep a copy of alerts when we switch to global tab
|
||||
const alertsWhenGlobalSelected = useMemo(() => {
|
||||
return currentTab === "global" ? structuredClone(alerts) : alerts
|
||||
}, [currentTab])
|
||||
|
||||
return (
|
||||
<>
|
||||
<DialogHeader>
|
||||
<DialogTitle className="text-xl">
|
||||
<Trans>Container Alerts</Trans>
|
||||
</DialogTitle>
|
||||
<DialogDescription>
|
||||
<Trans>
|
||||
See{" "}
|
||||
<Link href={getPagePath($router, "settings", { name: "notifications" })} className="link">
|
||||
notification settings
|
||||
</Link>{" "}
|
||||
to configure how you receive alerts.
|
||||
</Trans>
|
||||
</DialogDescription>
|
||||
</DialogHeader>
|
||||
<Tabs defaultValue="container" onValueChange={setCurrentTab}>
|
||||
<TabsList className="mb-1 -mt-0.5">
|
||||
<TabsTrigger value="container">
|
||||
<BoxIcon className="me-2 h-3.5 w-3.5" />
|
||||
<span className="truncate max-w-60">{container.name}</span>
|
||||
</TabsTrigger>
|
||||
<TabsTrigger value="global">
|
||||
<GlobeIcon className="me-1.5 h-3.5 w-3.5" />
|
||||
<Trans>All Containers</Trans>
|
||||
</TabsTrigger>
|
||||
</TabsList>
|
||||
<TabsContent value="container">
|
||||
<div className="grid gap-3">
|
||||
{alertKeys.map((name) => (
|
||||
<ContainerAlertContent
|
||||
key={name}
|
||||
alertKey={name}
|
||||
data={containerAlertInfo[name as keyof typeof containerAlertInfo]}
|
||||
alert={containerAlerts.get(name)}
|
||||
systemId={systemId}
|
||||
container={container}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
<TabsContent value="global">
|
||||
<label
|
||||
htmlFor="ovw"
|
||||
className="mb-3 flex gap-2 items-center justify-center cursor-pointer border rounded-sm py-3 px-4 border-destructive text-destructive font-semibold text-sm"
|
||||
>
|
||||
<Checkbox
|
||||
id="ovw"
|
||||
className="text-destructive border-destructive data-[state=checked]:bg-destructive"
|
||||
checked={overwriteExisting}
|
||||
onCheckedChange={setOverwriteExisting}
|
||||
/>
|
||||
<Trans>Overwrite existing alerts</Trans>
|
||||
</label>
|
||||
<div className="grid gap-3">
|
||||
{alertKeys.map((name) => (
|
||||
<ContainerAlertContent
|
||||
key={name}
|
||||
alertKey={name}
|
||||
systemId={systemId}
|
||||
container={container}
|
||||
alert={containerAlerts.get(name)}
|
||||
data={containerAlertInfo[name as keyof typeof containerAlertInfo]}
|
||||
global={true}
|
||||
overwriteExisting={!!overwriteExisting}
|
||||
initialAlertsState={alertsWhenGlobalSelected}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</TabsContent>
|
||||
</Tabs>
|
||||
</>
|
||||
)
|
||||
})
|
||||
|
||||
export function ContainerAlertContent({
|
||||
alertKey,
|
||||
data: alertData,
|
||||
systemId,
|
||||
container,
|
||||
alert,
|
||||
global = false,
|
||||
overwriteExisting = false,
|
||||
initialAlertsState = {},
|
||||
}: {
|
||||
alertKey: string
|
||||
data: ContainerAlertInfo
|
||||
systemId: string
|
||||
container: ContainerRecord
|
||||
alert?: ContainerAlertRecord
|
||||
global?: boolean
|
||||
overwriteExisting?: boolean
|
||||
initialAlertsState?: Record<string, Map<string, Map<string, ContainerAlertRecord>>>
|
||||
}) {
|
||||
const { name } = alertData
|
||||
|
||||
const singleDescription = alertData.singleDesc?.()
|
||||
|
||||
const [checked, setChecked] = useState(global ? false : !!alert)
|
||||
const [min, setMin] = useState(alert?.min || 10)
|
||||
const [value, setValue] = useState(alert?.value || (singleDescription ? 0 : alertData.start ?? 80))
|
||||
|
||||
const Icon = alertData.icon
|
||||
|
||||
/** Get container ids to update */
|
||||
function getContainerIds(): string[] {
|
||||
// if not global, update only the current container
|
||||
if (!global) {
|
||||
return [container.id]
|
||||
}
|
||||
// if global, we need to get all containers for this system
|
||||
// For now, we'll just use the current container
|
||||
// In a real implementation, you'd fetch all containers for the system
|
||||
return [container.id]
|
||||
}
|
||||
|
||||
function sendUpsert(min: number, value: number) {
|
||||
const containers = getContainerIds()
|
||||
containers.length &&
|
||||
upsertContainerAlerts({
|
||||
name: alertKey,
|
||||
value,
|
||||
min,
|
||||
systems: [systemId],
|
||||
containers,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="rounded-lg border border-muted-foreground/15 hover:border-muted-foreground/20 transition-colors duration-100 group">
|
||||
<label
|
||||
htmlFor={`c${name}`}
|
||||
className={cn("flex flex-row items-center justify-between gap-4 cursor-pointer p-4", {
|
||||
"pb-0": checked,
|
||||
})}
|
||||
>
|
||||
<div className="grid gap-1 select-none">
|
||||
<p className="font-semibold flex gap-3 items-center">
|
||||
<Icon className="h-4 w-4 opacity-85" /> {alertData.name()}
|
||||
</p>
|
||||
{!checked && <span className="block text-sm text-muted-foreground">{alertData.desc()}</span>}
|
||||
</div>
|
||||
<Switch
|
||||
id={`c${name}`}
|
||||
checked={checked}
|
||||
onCheckedChange={(newChecked) => {
|
||||
setChecked(newChecked)
|
||||
if (newChecked) {
|
||||
// if alert checked, create or update alert
|
||||
sendUpsert(min, value)
|
||||
} else {
|
||||
// if unchecked, delete alert
|
||||
deleteContainerAlerts({ name: alertKey, systems: [systemId], containers: getContainerIds() })
|
||||
// when force deleting all alerts of a type, also remove them from initialAlertsState
|
||||
if (overwriteExisting) {
|
||||
for (const systemAlerts of Object.values(initialAlertsState)) {
|
||||
for (const containerAlerts of systemAlerts.values()) {
|
||||
containerAlerts.delete(alertKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
/>
|
||||
</label>
|
||||
{checked && (
|
||||
<div className="grid sm:grid-cols-2 mt-1.5 gap-5 px-4 pb-5 tabular-nums text-muted-foreground">
|
||||
<Suspense fallback={<div className="h-10" />}>
|
||||
{!singleDescription && (
|
||||
<div>
|
||||
<p id={`v${name}`} className="text-sm block h-8">
|
||||
{alertData.invert ? (
|
||||
<Trans>
|
||||
Average drops below{" "}
|
||||
<strong className="text-foreground">
|
||||
{value}
|
||||
{alertData.unit}
|
||||
</strong>
|
||||
</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
Average exceeds{" "}
|
||||
<strong className="text-foreground">
|
||||
{value}
|
||||
{alertData.unit}
|
||||
</strong>
|
||||
</Trans>
|
||||
)}
|
||||
</p>
|
||||
<div className="flex gap-3">
|
||||
<Slider
|
||||
aria-labelledby={`v${name}`}
|
||||
defaultValue={[value]}
|
||||
onValueCommit={(val) => sendUpsert(min, val[0])}
|
||||
onValueChange={(val) => setValue(val[0])}
|
||||
step={alertData.step ?? 1}
|
||||
min={alertData.min ?? 1}
|
||||
max={alertData.max ?? 99}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className={cn(singleDescription && "col-span-full lowercase")}>
|
||||
<p id={`t${name}`} className="text-sm block h-8 first-letter:uppercase">
|
||||
{singleDescription && (
|
||||
<>
|
||||
{singleDescription}
|
||||
{` `}
|
||||
</>
|
||||
)}
|
||||
<Trans>
|
||||
For <strong className="text-foreground">{min}</strong>{" "}
|
||||
<Plural value={min} one="minute" other="minutes" />
|
||||
</Trans>
|
||||
</p>
|
||||
<div className="flex gap-3">
|
||||
<Slider
|
||||
aria-labelledby={`v${name}`}
|
||||
defaultValue={[min]}
|
||||
onValueCommit={(minVal) => sendUpsert(minVal[0], value)}
|
||||
onValueChange={(val) => setMin(val[0])}
|
||||
min={1}
|
||||
max={60}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</Suspense>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -38,6 +38,23 @@ export default memo(function ContainerChart({
|
||||
|
||||
const isNetChart = chartType === ChartType.Network
|
||||
|
||||
// Filter with set lookup
|
||||
const filteredKeys = useMemo(() => {
|
||||
if (!filter) {
|
||||
return new Set<string>()
|
||||
}
|
||||
const filterTerms = filter
|
||||
.toLowerCase()
|
||||
.split(" ")
|
||||
.filter((term) => term.length > 0)
|
||||
return new Set(
|
||||
Object.keys(chartConfig).filter((key) => {
|
||||
const keyLower = key.toLowerCase()
|
||||
return !filterTerms.some((term) => keyLower.includes(term))
|
||||
})
|
||||
)
|
||||
}, [chartConfig, filter])
|
||||
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: not necessary
|
||||
const { toolTipFormatter, dataFunction, tickFormatter } = useMemo(() => {
|
||||
const obj = {} as {
|
||||
@@ -85,10 +102,14 @@ export default memo(function ContainerChart({
|
||||
let totalSent = 0
|
||||
let totalRecv = 0
|
||||
const payloadData = item?.payload && typeof item.payload === "object" ? item.payload : {}
|
||||
for (const value of Object.values(payloadData)) {
|
||||
for (const [containerKey, value] of Object.entries(payloadData)) {
|
||||
if (!value || typeof value !== "object") {
|
||||
continue
|
||||
}
|
||||
// Skip filtered out containers
|
||||
if (filteredKeys.has(containerKey)) {
|
||||
continue
|
||||
}
|
||||
const [sent, recv] = getRxTxBytes(value as { b?: [number, number]; ns?: number; nr?: number })
|
||||
totalSent += sent
|
||||
totalRecv += recv
|
||||
@@ -124,24 +145,7 @@ export default memo(function ContainerChart({
|
||||
obj.dataFunction = (key: string, data: any) => data[key]?.[dataKey] ?? null
|
||||
}
|
||||
return obj
|
||||
}, [])
|
||||
|
||||
// Filter with set lookup
|
||||
const filteredKeys = useMemo(() => {
|
||||
if (!filter) {
|
||||
return new Set<string>()
|
||||
}
|
||||
const filterTerms = filter
|
||||
.toLowerCase()
|
||||
.split(" ")
|
||||
.filter((term) => term.length > 0)
|
||||
return new Set(
|
||||
Object.keys(chartConfig).filter((key) => {
|
||||
const keyLower = key.toLowerCase()
|
||||
return !filterTerms.some((term) => keyLower.includes(term))
|
||||
})
|
||||
)
|
||||
}, [chartConfig, filter])
|
||||
}, [filteredKeys])
|
||||
|
||||
// console.log('rendered at', new Date())
|
||||
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import type { Column, ColumnDef } from "@tanstack/react-table"
|
||||
import { lazy, Suspense } from "react"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { cn, decimalString, formatBytes, hourWithSeconds } from "@/lib/utils"
|
||||
import type { ContainerRecord } from "@/types"
|
||||
@@ -32,7 +31,8 @@ const unitSeconds = [
|
||||
// Convert docker status string to number of seconds ("Up X minutes", "Up X hours", etc.)
|
||||
function getStatusValue(status: string): number {
|
||||
const [_, num, unit] = status.split(" ")
|
||||
const numValue = Number(num)
|
||||
// Docker uses "a" or "an" instead of "1" for singular units (e.g., "Up a minute", "Up an hour")
|
||||
const numValue = num === "a" || num === "an" ? 1 : Number(num)
|
||||
for (const [unitName, value] of unitSeconds) {
|
||||
if (unit.startsWith(unitName)) {
|
||||
return numValue * value
|
||||
@@ -41,9 +41,6 @@ function getStatusValue(status: string): number {
|
||||
return 0
|
||||
}
|
||||
|
||||
// Lazy load the alert button component
|
||||
const ContainerAlertButton = lazy(() => import("@/components/alerts/container-alert-button"))
|
||||
|
||||
export const containerChartCols: ColumnDef<ContainerRecord>[] = [
|
||||
{
|
||||
id: "name",
|
||||
@@ -66,7 +63,7 @@ export const containerChartCols: ColumnDef<ContainerRecord>[] = [
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`System`} Icon={ServerIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
const allSystems = useStore($allSystemsById)
|
||||
return <span className="ms-1.5 xl:w-30 block truncate">{allSystems[getValue() as string]?.name ?? ""}</span>
|
||||
return <span className="ms-1.5 xl:w-34 block truncate">{allSystems[getValue() as string]?.name ?? ""}</span>
|
||||
},
|
||||
},
|
||||
// {
|
||||
@@ -141,17 +138,17 @@ export const containerChartCols: ColumnDef<ContainerRecord>[] = [
|
||||
id: "image",
|
||||
sortingFn: (a, b) => a.original.image.localeCompare(b.original.image),
|
||||
accessorFn: (record) => record.image,
|
||||
enableHiding: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t({ message: "Image", context: "Docker image" })} Icon={LayersIcon} />,
|
||||
header: ({ column }) => (
|
||||
<HeaderButton column={column} name={t({ message: "Image", context: "Docker image" })} Icon={LayersIcon} />
|
||||
),
|
||||
cell: ({ getValue }) => {
|
||||
return <span className="ms-1.5 xl:w-30 block truncate">{getValue() as string}</span>
|
||||
return <span className="ms-1.5 xl:w-40 block truncate">{getValue() as string}</span>
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "status",
|
||||
accessorFn: (record) => record.status,
|
||||
invertSorting: true,
|
||||
enableHiding: true,
|
||||
sortingFn: (a, b) => getStatusValue(a.original.status) - getStatusValue(b.original.status),
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Status`} Icon={HourglassIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
@@ -168,21 +165,6 @@ export const containerChartCols: ColumnDef<ContainerRecord>[] = [
|
||||
return <span className="ms-1.5 tabular-nums">{hourWithSeconds(new Date(timestamp).toISOString())}</span>
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "actions",
|
||||
header: () => <div className="text-center">{t`Actions`}</div>,
|
||||
cell: ({ row }) => {
|
||||
// Lazy load the alert button component
|
||||
const ContainerAlertButton = lazy(() => import("@/components/alerts/container-alert-button"))
|
||||
return (
|
||||
<div className="flex justify-center" onClick={(e) => e.stopPropagation()}>
|
||||
<Suspense fallback={<div className="h-8 w-8" />}>
|
||||
<ContainerAlertButton systemId={row.original.system} container={row.original} />
|
||||
</Suspense>
|
||||
</div>
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
function HeaderButton({
|
||||
|
||||
@@ -231,7 +231,7 @@ const AllContainersTable = memo(function AllContainersTable({
|
||||
>
|
||||
{/* add header height to table size */}
|
||||
<div style={{ height: `${virtualizer.getTotalSize() + 48}px`, paddingTop, paddingBottom }}>
|
||||
<table className="text-sm w-full h-full">
|
||||
<table className="text-sm w-full h-full text-nowrap">
|
||||
<ContainersTableHead table={table} />
|
||||
<TableBody>
|
||||
{rows.length ? (
|
||||
|
||||
@@ -75,9 +75,7 @@ export default function Navbar() {
|
||||
<HardDriveIcon className="h-[1.2rem] w-[1.2rem]" strokeWidth={1.5} />
|
||||
</Link>
|
||||
</TooltipTrigger>
|
||||
<TooltipContent>
|
||||
<Trans>S.M.A.R.T.</Trans>
|
||||
</TooltipContent>
|
||||
<TooltipContent>S.M.A.R.T.</TooltipContent>
|
||||
</Tooltip>
|
||||
<LangToggle />
|
||||
<ModeToggle />
|
||||
|
||||
@@ -363,7 +363,8 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
e.target instanceof HTMLTextAreaElement ||
|
||||
e.shiftKey ||
|
||||
e.ctrlKey ||
|
||||
e.metaKey
|
||||
e.metaKey ||
|
||||
e.altKey
|
||||
) {
|
||||
return
|
||||
}
|
||||
|
||||
@@ -3,7 +3,7 @@ import PocketBase from "pocketbase"
|
||||
import { basePath } from "@/components/router"
|
||||
import { toast } from "@/components/ui/use-toast"
|
||||
import type { ChartTimes, UserSettings } from "@/types"
|
||||
import { $alerts, $allSystemsById, $allSystemsByName, $containerAlerts, $userSettings } from "./stores"
|
||||
import { $alerts, $allSystemsById, $allSystemsByName, $userSettings } from "./stores"
|
||||
import { chartTimeData } from "./utils"
|
||||
|
||||
/** PocketBase JS Client */
|
||||
@@ -30,7 +30,6 @@ export function logOut() {
|
||||
$allSystemsByName.set({})
|
||||
$allSystemsById.set({})
|
||||
$alerts.set({})
|
||||
$containerAlerts.set({})
|
||||
$userSettings.set({} as UserSettings)
|
||||
sessionStorage.setItem("lo", "t") // prevent auto login on logout
|
||||
pb.authStore.clear()
|
||||
|
||||
@@ -1,180 +0,0 @@
|
||||
import { t } from "@lingui/core/macro"
|
||||
import { CpuIcon, HeartPulseIcon, MemoryStickIcon, ServerIcon } from "lucide-react"
|
||||
import type { RecordSubscription } from "pocketbase"
|
||||
import { EthernetIcon } from "@/components/ui/icons"
|
||||
import { $containerAlerts } from "@/lib/stores"
|
||||
import type { ContainerAlertInfo, ContainerAlertRecord } from "@/types"
|
||||
import { pb } from "./api"
|
||||
|
||||
/** Container alert info for each alert type */
|
||||
export const containerAlertInfo: Record<string, ContainerAlertInfo> = {
|
||||
Status: {
|
||||
name: () => t`Status`,
|
||||
unit: "",
|
||||
icon: ServerIcon,
|
||||
desc: () => t`Triggers when container status changes`,
|
||||
singleDesc: () => `${t`Container`} ${t`Stopped`}`,
|
||||
},
|
||||
CPU: {
|
||||
name: () => t`CPU Usage`,
|
||||
unit: "%",
|
||||
icon: CpuIcon,
|
||||
desc: () => t`Triggers when CPU usage exceeds a threshold`,
|
||||
},
|
||||
Memory: {
|
||||
name: () => t`Memory Usage`,
|
||||
unit: "%",
|
||||
icon: MemoryStickIcon,
|
||||
desc: () => t`Triggers when memory usage exceeds a threshold`,
|
||||
},
|
||||
Network: {
|
||||
name: () => t`Network`,
|
||||
unit: " MB/s",
|
||||
icon: EthernetIcon,
|
||||
desc: () => t`Triggers when combined up/down exceeds a threshold`,
|
||||
max: 125,
|
||||
},
|
||||
Health: {
|
||||
name: () => t`Health Status`,
|
||||
unit: "",
|
||||
icon: HeartPulseIcon,
|
||||
desc: () => t`Triggers when container health status changes`,
|
||||
singleDesc: () => `${t`Container`} ${t`Unhealthy`}`,
|
||||
},
|
||||
}
|
||||
|
||||
class ContainerAlertManager {
|
||||
private unsubscribeFn?: () => void
|
||||
|
||||
/**
|
||||
* Subscribe to container alert updates
|
||||
*/
|
||||
async subscribe() {
|
||||
if (this.unsubscribeFn) {
|
||||
return
|
||||
}
|
||||
|
||||
// Fetch initial container alerts
|
||||
try {
|
||||
const alerts = await pb.collection("container_alerts").getFullList<ContainerAlertRecord>()
|
||||
this.updateStore(alerts)
|
||||
} catch (e) {
|
||||
console.error("Failed to fetch container alerts:", e)
|
||||
}
|
||||
|
||||
// Subscribe to real-time updates
|
||||
this.unsubscribeFn = await pb
|
||||
.collection("container_alerts")
|
||||
.subscribe<ContainerAlertRecord>("*", this.handleAlertUpdate)
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsubscribe from container alert updates
|
||||
*/
|
||||
unsubscribe() {
|
||||
if (this.unsubscribeFn) {
|
||||
this.unsubscribeFn()
|
||||
this.unsubscribeFn = undefined
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle real-time alert updates
|
||||
*/
|
||||
private handleAlertUpdate = (e: RecordSubscription<ContainerAlertRecord>) => {
|
||||
const { action, record } = e
|
||||
|
||||
if (action === "delete") {
|
||||
this.deleteFromStore(record)
|
||||
} else {
|
||||
this.updateStore([record])
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Update store with alert records
|
||||
*/
|
||||
private updateStore(alerts: ContainerAlertRecord[]) {
|
||||
const currentAlerts = $containerAlerts.get()
|
||||
|
||||
for (const alert of alerts) {
|
||||
if (!currentAlerts[alert.system]) {
|
||||
currentAlerts[alert.system] = new Map()
|
||||
}
|
||||
if (!currentAlerts[alert.system].get(alert.container)) {
|
||||
currentAlerts[alert.system].set(alert.container, new Map())
|
||||
}
|
||||
currentAlerts[alert.system].get(alert.container)!.set(alert.name, alert)
|
||||
}
|
||||
|
||||
$containerAlerts.set(currentAlerts)
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete alert from store
|
||||
*/
|
||||
private deleteFromStore(alert: ContainerAlertRecord) {
|
||||
const currentAlerts = $containerAlerts.get()
|
||||
|
||||
if (currentAlerts[alert.system]?.get(alert.container)?.has(alert.name)) {
|
||||
currentAlerts[alert.system].get(alert.container)!.delete(alert.name)
|
||||
|
||||
// Clean up empty maps
|
||||
if (currentAlerts[alert.system].get(alert.container)!.size === 0) {
|
||||
currentAlerts[alert.system].delete(alert.container)
|
||||
}
|
||||
if (currentAlerts[alert.system].size === 0) {
|
||||
delete currentAlerts[alert.system]
|
||||
}
|
||||
|
||||
$containerAlerts.set(currentAlerts)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create or update container alerts
|
||||
*/
|
||||
async upsert(
|
||||
systems: string[],
|
||||
containers: string[],
|
||||
name: string,
|
||||
value: number,
|
||||
min: number,
|
||||
overwrite = false
|
||||
) {
|
||||
return pb.send("/api/beszel/user-container-alerts", {
|
||||
method: "POST",
|
||||
body: {
|
||||
systems,
|
||||
containers,
|
||||
name,
|
||||
value,
|
||||
min,
|
||||
overwrite,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete container alerts
|
||||
*/
|
||||
async delete(systems: string[], containers: string[], name: string) {
|
||||
return pb.send("/api/beszel/user-container-alerts", {
|
||||
method: "DELETE",
|
||||
body: {
|
||||
systems,
|
||||
containers,
|
||||
name,
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all container alerts from store
|
||||
*/
|
||||
clear() {
|
||||
$containerAlerts.set({})
|
||||
}
|
||||
}
|
||||
|
||||
export const containerAlertManager = new ContainerAlertManager()
|
||||
@@ -1,5 +1,5 @@
|
||||
import { atom, computed, listenKeys, map, type ReadableAtom } from "nanostores"
|
||||
import type { AlertMap, ChartTimes, ContainerAlertMap, SystemRecord, UserSettings } from "@/types"
|
||||
import type { AlertMap, ChartTimes, SystemRecord, UserSettings } from "@/types"
|
||||
import { pb } from "./api"
|
||||
import { Unit } from "./enums"
|
||||
|
||||
@@ -22,9 +22,6 @@ export const $systems: ReadableAtom<SystemRecord[]> = computed($allSystemsById,
|
||||
/** Map of alert records by system id and alert name */
|
||||
export const $alerts = map<AlertMap>({})
|
||||
|
||||
/** Map of container alert records by system id, container id, and alert name */
|
||||
export const $containerAlerts = map<ContainerAlertMap>({})
|
||||
|
||||
/** SSH public key */
|
||||
export const $publicKey = atom("")
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ar\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-25 19:15\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Arabic\n"
|
||||
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "التنبيهات"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "جميع الحاويات"
|
||||
@@ -837,6 +838,7 @@ msgstr "غير نشط"
|
||||
msgid "Invalid email address."
|
||||
msgstr "عنوان البريد الإشباكي غير صالح."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "اللغة"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "تعيين عتبات النسبة المئوية لألوان العد
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "إلى البريد الإشباكي"
|
||||
msgid "Toggle grid"
|
||||
msgstr "تبديل الشبكة"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "تبديل السمة"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: bg\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:17\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Bulgarian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Тревоги"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Всички контейнери"
|
||||
@@ -230,7 +231,7 @@ msgstr "Bandwidth на мрежата"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Неактивен"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Невалиден имейл адрес."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Език"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Задайте процентни прагове за цветовете
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "До имейл(ите)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Превключване на мрежа"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Включи тема"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: cs\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-05 20:24\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Czech\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Výstrahy"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Všechny kontejnery"
|
||||
@@ -230,7 +231,7 @@ msgstr "Přenos"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Neaktivní"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Neplatná e-mailová adresa."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Jazyk"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Nastavte procentuální prahové hodnoty pro barvy měřičů."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Na email(y)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Přepnout mřížku"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Přepnout motiv"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: da\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-19 10:55\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Danish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Alarmer"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alle containere"
|
||||
@@ -198,7 +199,7 @@ msgstr "Gennemsnit falder under <0>{value}{0}</0>"
|
||||
#. placeholder {0}: alertData.unit
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Average exceeds <0>{value}{0}</0>"
|
||||
msgstr "Gennemsnit overstiger <0>{value}{0}</0>"
|
||||
msgstr "Gennemsnittet overstiger <0>{value}{0}</0>"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average power consumption of GPUs"
|
||||
@@ -230,7 +231,7 @@ msgstr "Båndbredde"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -400,7 +401,7 @@ msgstr "Forbindelsen er nede"
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Continue"
|
||||
msgstr "Forsæt"
|
||||
msgstr "Fortsæt"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "Copied to clipboard"
|
||||
@@ -425,7 +426,7 @@ msgstr "Kopier miljø"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Copy host"
|
||||
msgstr "Kopier host"
|
||||
msgstr "Kopier vært"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
@@ -626,7 +627,7 @@ msgstr "Rediger {foo}"
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
#: src/components/login/otp-forms.tsx
|
||||
msgid "Email"
|
||||
msgstr "E-mail"
|
||||
msgstr "Email"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Email notifications"
|
||||
@@ -644,11 +645,11 @@ msgstr "Sluttid"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Enter email address to reset password"
|
||||
msgstr "Indtast e-mailadresse for at nulstille adgangskoden"
|
||||
msgstr "Indtast emailadresse for at nulstille adgangskoden"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Enter email address..."
|
||||
msgstr "Indtast e-mailadresse..."
|
||||
msgstr "Indtast emailadresse..."
|
||||
|
||||
#: src/components/login/otp-forms.tsx
|
||||
msgid "Enter your one-time password."
|
||||
@@ -791,7 +792,7 @@ msgstr "GPU-enheder"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "GPU Power Draw"
|
||||
msgstr "Gpu Strøm Træk"
|
||||
msgstr "GPU Strøm Træk"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "GPU Usage"
|
||||
@@ -837,6 +838,7 @@ msgstr "Inaktiv"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ugyldig email adresse."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Sprog"
|
||||
@@ -1119,7 +1121,7 @@ msgstr "Procentdel af tid brugt i hver tilstand"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Permanent"
|
||||
msgstr "Permanent"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Persistence"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Indstil procentvise tærskler for målerfarver."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Til email(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Slå gitter til/fra"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Skift tema"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: de\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-05 20:24\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: German\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Warnungen"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alle Container"
|
||||
@@ -230,7 +231,7 @@ msgstr "Bandbreite"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -598,11 +599,11 @@ msgstr "Dokumentation"
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Down"
|
||||
msgstr "Offline"
|
||||
msgstr "Inaktiv"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Down ({downSystemsLength})"
|
||||
msgstr "Offline ({downSystemsLength})"
|
||||
msgstr "Inaktiv ({downSystemsLength})"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Download"
|
||||
@@ -837,6 +838,7 @@ msgstr "Inaktiv"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ungültige E-Mail-Adresse."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Sprache"
|
||||
@@ -969,7 +971,7 @@ msgstr "Name"
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Netz"
|
||||
msgstr "Netzwerk"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Network traffic of docker containers"
|
||||
@@ -1119,7 +1121,7 @@ msgstr "Prozentsatz der Zeit in jedem Zustand"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Permanent"
|
||||
msgstr "Permanent"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Persistence"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Prozentuale Schwellenwerte für Zählerfarben festlegen."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "An E-Mail(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Raster umschalten"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Darstellung umschalten"
|
||||
@@ -1613,11 +1617,11 @@ msgstr "Unbegrenzt"
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Up"
|
||||
msgstr "aktiv"
|
||||
msgstr "Aktiv"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "aktiv ({upSystemsLength})"
|
||||
msgstr "Aktiv ({upSystemsLength})"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Update"
|
||||
|
||||
@@ -152,6 +152,7 @@ msgstr "Alerts"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "All Containers"
|
||||
@@ -832,6 +833,7 @@ msgstr "Inactive"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Invalid email address."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Language"
|
||||
@@ -1330,6 +1332,7 @@ msgstr "Set percentage thresholds for meter colors."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1481,6 +1484,7 @@ msgstr "To email(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Toggle grid"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Toggle theme"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: es\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-14 09:39\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Spanish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Alertas"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Todos los contenedores"
|
||||
@@ -837,6 +838,7 @@ msgstr "Inactivo"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Dirección de correo electrónico no válida."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Idioma"
|
||||
@@ -1307,7 +1309,7 @@ msgstr "Buscar sistemas o configuraciones..."
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "See <0>notification settings</0> to configure how you receive alerts."
|
||||
msgstr "Consulta <0>configuración de notificaciones</0> para configurar cómo recibe alertas."
|
||||
msgstr "Consulta la <0>configuración de notificaciones</0> para configurar cómo recibes alertas."
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Select {foo}"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Establecer umbrales de porcentaje para los colores de los medidores."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "A correo(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Alternar cuadrícula"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Alternar tema"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: fa\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Persian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "هشدارها"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "همه کانتینرها"
|
||||
@@ -837,6 +838,7 @@ msgstr "غیرفعال"
|
||||
msgid "Invalid email address."
|
||||
msgstr "آدرس ایمیل نامعتبر است."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "زبان"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "آستانه های درصدی را برای رنگ های متر تنظ
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "به ایمیل(ها)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "تغییر نمایش جدول"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "تغییر تم"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: fr\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-01-09 21:08\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Alertes"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Tous les conteneurs"
|
||||
@@ -230,7 +231,7 @@ msgstr "Bande passante"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Inactif"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Adresse email invalide."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Langue"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Définir des seuils de pourcentage pour les couleurs des compteurs."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Aux email(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Basculer la grille"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Changer le thème"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: he\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hebrew\n"
|
||||
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "התראות"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "כל הקונטיינרים"
|
||||
@@ -837,6 +838,7 @@ msgstr "לא פעיל"
|
||||
msgid "Invalid email address."
|
||||
msgstr "כתובת אימייל לא תקינה."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "שפה"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "הגדר סף אחוזים עבור צבעי מד."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "לאימייל(ים)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "החלף רשת"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "החלף ערכת נושא"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: hr\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Croatian\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
@@ -99,7 +99,7 @@ msgstr "Aktivan"
|
||||
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktivna upozorenja"
|
||||
msgstr "Aktivna Upozorenja"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Active state"
|
||||
@@ -113,11 +113,11 @@ msgstr "Dodaj {foo}"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Add <0>System</0>"
|
||||
msgstr "Dodaj <0>Sistem</0>"
|
||||
msgstr "Dodaj <0>Sustav</0>"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Add system"
|
||||
msgstr "Dodaj sistem"
|
||||
msgstr "Dodaj sustav"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Add URL"
|
||||
@@ -125,7 +125,7 @@ msgstr "Dodaj URL"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Adjust display options for charts."
|
||||
msgstr "Podesite opcije prikaza za grafikone."
|
||||
msgstr "Podesite opcije prikaza grafikona."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Adjust the width of the main layout"
|
||||
@@ -157,6 +157,7 @@ msgstr "Upozorenja"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Svi spremnici"
|
||||
@@ -168,7 +169,7 @@ msgstr "Svi spremnici"
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
msgstr "Svi Sistemi"
|
||||
msgstr "Svi Sustavi"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Are you sure you want to delete {name}?"
|
||||
@@ -206,7 +207,7 @@ msgstr "Prosječna potrošnja energije grafičkog procesora"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average system-wide CPU utilization"
|
||||
msgstr "Prosječna iskorištenost procesora na cijelom sustavu"
|
||||
msgstr "Prosječna iskorištenost procesora u cijelom sustavu"
|
||||
|
||||
#. placeholder {0}: gpu.n
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -215,7 +216,7 @@ msgstr "Prosječna iskorištenost {0}"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average utilization of GPU engines"
|
||||
msgstr "Prosječna iskorištenost GPU motora"
|
||||
msgstr "Prosječna iskorištenost grafičkih procesora"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
@@ -225,12 +226,12 @@ msgstr "Sigurnosne kopije"
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Bandwidth"
|
||||
msgstr "Propusnost"
|
||||
msgstr "Mrežna Propusnost"
|
||||
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -258,11 +259,11 @@ msgstr "Ispod {0}{1} u posljednjih {2, plural, one {# minuti} few {# minute} oth
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
|
||||
msgstr "Beszel podržava OpenID Connect i mnoge druge OAuth2 davatalje autentifikacije."
|
||||
msgstr "Beszel podržava OpenID Connect i mnoge druge pružatelje OAuth2 autentifikacije."
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Beszel uses <0>Shoutrrr</0> to integrate with popular notification services."
|
||||
msgstr "Beszel koristi <0>Shoutrrr</0> za integraciju sa popularnim servisima za notifikacije."
|
||||
msgstr "Beszel koristi <0>Shoutrrr</0> za integraciju s popularnim obavještajnim uslugama."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Binary"
|
||||
@@ -339,19 +340,19 @@ msgstr "Puni se"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Chart options"
|
||||
msgstr "Opcije grafikona"
|
||||
msgstr "Postavke grafikona"
|
||||
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "Check {email} for a reset link."
|
||||
msgstr "Provjerite {email} za vezu za resetiranje."
|
||||
msgstr "Provjerite {email} za pristup poveznici za resetiranje."
|
||||
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Check logs for more details."
|
||||
msgstr "Provjerite logove za više detalja."
|
||||
msgstr "Provjerite zapise (logove) za više detalja."
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Check your notification service"
|
||||
msgstr "Provjerite Vaš servis notifikacija"
|
||||
msgstr "Provjerite svoju obavještajnu uslugu"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
@@ -387,7 +388,7 @@ msgstr "Konfigurirajte način primanja obavijesti upozorenja."
|
||||
#: src/components/login/auth-form.tsx
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Confirm password"
|
||||
msgstr "Potvrdite lozinku"
|
||||
msgstr "Potvrdi lozinku"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Conflicts"
|
||||
@@ -400,7 +401,7 @@ msgstr "Veza je pala"
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Continue"
|
||||
msgstr "Nastavite"
|
||||
msgstr "Nastavi"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "Copied to clipboard"
|
||||
@@ -577,15 +578,15 @@ msgstr "Iskorištenost diska od {extraFsName}"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Docker CPU Usage"
|
||||
msgstr "Iskorištenost Docker Procesora"
|
||||
msgstr "Iskorištenost Docker procesora"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Docker Memory Usage"
|
||||
msgstr "Iskorištenost Docker Memorije"
|
||||
msgstr "Iskorištenost Docker memorije"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Docker Network I/O"
|
||||
msgstr "Docker Mrežni I/O"
|
||||
msgstr "Docker mrežni I/O"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
@@ -630,12 +631,12 @@ msgstr "Email"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Email notifications"
|
||||
msgstr "Email notifikacije"
|
||||
msgstr "Email obavijesti"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Empty"
|
||||
msgstr "Prazna"
|
||||
msgstr "Prazno"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
@@ -644,7 +645,7 @@ msgstr "Vrijeme završetka"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Enter email address to reset password"
|
||||
msgstr "Unesite email adresu za resetiranje lozinke"
|
||||
msgstr "Unesite email adresu kako biste resetirali lozinku"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Enter email address..."
|
||||
@@ -652,7 +653,7 @@ msgstr "Unesite email adresu..."
|
||||
|
||||
#: src/components/login/otp-forms.tsx
|
||||
msgid "Enter your one-time password."
|
||||
msgstr "Unesite Vašu jednokratnu lozinku."
|
||||
msgstr "Unesite jednokratnu lozinku."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Ephemeral"
|
||||
@@ -682,7 +683,7 @@ msgstr "Glavni PID izvršavanja"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Existing systems not defined in <0>config.yml</0> will be deleted. Please make regular backups."
|
||||
msgstr "Postojeći sistemi koji nisu definirani u <0>config.yml</0> će biti izbrisani. Molimo Vas napravite redovite sigurnosne kopije."
|
||||
msgstr "Postojeći sustavi koji nisu definirani u <0>config.yml</0> datoteci bit će izbrisani. Molimo Vas da spremate redovite sigurnosne kopije."
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Exited active"
|
||||
@@ -694,7 +695,7 @@ msgstr "Istječe nakon jednog sata ili ponovnog pokretanja huba."
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Export"
|
||||
msgstr "Izvezi"
|
||||
msgstr "Izvoz"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Export configuration"
|
||||
@@ -718,21 +719,21 @@ msgstr "Neuspjeli atributi:"
|
||||
|
||||
#: src/lib/api.ts
|
||||
msgid "Failed to authenticate"
|
||||
msgstr "Provjera autentičnosti nije uspjela"
|
||||
msgstr "Neuspješna provjera autentičnosti"
|
||||
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Failed to save settings"
|
||||
msgstr "Neuspješno snimanje postavki"
|
||||
msgstr "Neuspješno spremanje postavki"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Failed to send test notification"
|
||||
msgstr "Neuspješno slanje testne notifikacije"
|
||||
msgstr "Neuspješno slanje probne obavijesti"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Ažuriranje upozorenja nije uspjelo"
|
||||
msgstr "Neuspješno ažuriranje upozorenja"
|
||||
|
||||
#. placeholder {0}: statusTotals[ServiceStatus.Failed]
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
@@ -750,7 +751,7 @@ msgstr "Filtriraj..."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Fingerprint"
|
||||
msgstr "Otisak prsta"
|
||||
msgstr "Otisak"
|
||||
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Firmware"
|
||||
@@ -773,7 +774,7 @@ msgstr "FreeBSD naredba"
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Full"
|
||||
msgstr "Puna"
|
||||
msgstr "Puno"
|
||||
|
||||
#. Context: General settings
|
||||
#: src/components/routes/settings/general.tsx
|
||||
@@ -787,7 +788,7 @@ msgstr "Globalno"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "GPU Engines"
|
||||
msgstr "GPU motori"
|
||||
msgstr "Grafički procesori"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "GPU Power Draw"
|
||||
@@ -799,7 +800,7 @@ msgstr "Iskorištenost GPU-a"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Grid"
|
||||
msgstr "Mreža"
|
||||
msgstr "Rešetka"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
@@ -818,7 +819,7 @@ msgstr "Host / IP"
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Idle"
|
||||
msgstr "Neaktivna"
|
||||
msgstr "Neaktivno"
|
||||
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
@@ -835,8 +836,9 @@ msgstr "Neaktivno"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Nevažeća adresa e-pošte."
|
||||
msgstr "Nevažeća email adresa."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Jezik"
|
||||
@@ -877,7 +879,7 @@ msgstr "Prosječno Opterećenje 5m"
|
||||
#. Short label for load average
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Load Avg"
|
||||
msgstr "Prosječno opterećenje"
|
||||
msgstr "Prosječno Opterećenje"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Load state"
|
||||
@@ -898,13 +900,13 @@ msgstr "Prijava"
|
||||
#: src/components/login/auth-form.tsx
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "Login attempt failed"
|
||||
msgstr "Pokušaj prijave nije uspio"
|
||||
msgstr "Neuspješno pokušaj prijave"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logovi"
|
||||
msgstr "Zapisi"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table."
|
||||
@@ -948,15 +950,15 @@ msgstr "Vrhunac memorije"
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Memory Usage"
|
||||
msgstr "Upotreba memorije"
|
||||
msgstr "Iskorištenost memorije"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Memory usage of docker containers"
|
||||
msgstr "Upotreba memorije Docker spremnika"
|
||||
msgstr "Iskorištenost memorije Docker spremnika"
|
||||
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Model"
|
||||
msgstr "Model"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
@@ -1028,7 +1030,7 @@ msgstr "Podrška za OAuth 2 / OIDC"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
|
||||
msgstr "Prilikom svakog ponovnog pokretanja, sustavi u bazi podataka biti će ažurirani kako bi odgovarali sustavima definiranim u datoteci."
|
||||
msgstr "Prilikom svakog ponovnog pokretanja, sustavi u bazi podataka bit će ažurirani kako bi odgovarali sustavima definiranim u datoteci."
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
@@ -1045,11 +1047,11 @@ msgstr "Jednokratna lozinka"
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Open menu"
|
||||
msgstr "Otvori menu"
|
||||
msgstr "Otvori meni"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Or continue with"
|
||||
msgstr "Ili nastavi sa"
|
||||
msgstr "Ili nastavi s"
|
||||
|
||||
#: src/components/routes/system/cpu-sheet.tsx
|
||||
msgid "Other"
|
||||
@@ -1057,7 +1059,7 @@ msgstr "Ostalo"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Prebrišite postojeća upozorenja"
|
||||
msgstr "Prebriši postojeća upozorenja"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
@@ -1090,7 +1092,7 @@ msgstr "Lozinka mora biti kraća od 72 bajta."
|
||||
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "Password reset request received"
|
||||
msgstr "Zahtjev za ponovno postavljanje lozinke primljen"
|
||||
msgstr "Zahtjev za ponovno postavljanje lozinke zaprimljen"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Past"
|
||||
@@ -1131,20 +1133,20 @@ msgstr "Molimo <0>konfigurirajte SMTP server</0> kako biste osigurali isporuku u
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Please check logs for more details."
|
||||
msgstr "Za više detalja provjerite logove."
|
||||
msgstr "Za više detalja provjerite zapise (logove)."
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "Please check your credentials and try again"
|
||||
msgstr "Provjerite svoje podatke i pokušajte ponovno"
|
||||
msgstr "Provjerite svoje vjerodajnice i pokušajte ponovno"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Please create an admin account"
|
||||
msgstr "Molimo kreirajte administratorski račun"
|
||||
msgstr "Molimo kreirajte administrativan račun"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Please enable pop-ups for this site"
|
||||
msgstr "Omogućite skočne prozore za ovu stranicu"
|
||||
msgstr "Molimo omogućite skočne prozore za ovu stranicu"
|
||||
|
||||
#: src/lib/api.ts
|
||||
msgid "Please log in again"
|
||||
@@ -1152,7 +1154,7 @@ msgstr "Molimo prijavite se ponovno"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Please see <0>the documentation</0> for instructions."
|
||||
msgstr "Molimo pogledajte <0>dokumentaciju</0> za instrukcije."
|
||||
msgstr "Molimo provjerite <0>dokumentaciju</0> za upute."
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Please sign in to your account"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Postavite pragove postotka za boje mjerača."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1412,7 +1415,7 @@ msgstr "Systemd servisi"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Systems"
|
||||
msgstr "Sistemi"
|
||||
msgstr "Sustavi"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Systems may be managed in a <0>config.yml</0> file inside your data directory."
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Primaoci e-pošte"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Uključi/isključi rešetku"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Uključi/isključi temu"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: hu\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Hungarian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -113,7 +113,7 @@ msgstr "Hozzáadás {foo}"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Add <0>System</0>"
|
||||
msgstr "Hozzáadás <0>System</0>"
|
||||
msgstr "<0>Rendszer</0> Hozzáadása"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Add system"
|
||||
@@ -125,7 +125,7 @@ msgstr "URL hozzáadása"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Adjust display options for charts."
|
||||
msgstr "Állítsa be a diagram megjelenítését."
|
||||
msgstr "A diagramok megjelenítésének beállítása."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Adjust the width of the main layout"
|
||||
@@ -157,9 +157,10 @@ msgstr "Riasztások"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Összes konténer"
|
||||
msgstr "Minden konténer"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
@@ -230,7 +231,7 @@ msgstr "Sávszélesség"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Akk"
|
||||
msgstr "Akku"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -656,7 +657,7 @@ msgstr "Adja meg az egyszeri jelszavát."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Ephemeral"
|
||||
msgstr "Átmeneti"
|
||||
msgstr "Ideiglenes"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
@@ -758,7 +759,7 @@ msgstr "Firmware"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
|
||||
msgstr "A <0>{min}</0> {min, plural, one {perc} other {percek}}"
|
||||
msgstr "<0>{min}</0> {min, plural, one {percig} other {percig}}"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Forgot password?"
|
||||
@@ -837,6 +838,7 @@ msgstr "Inaktív"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Érvénytelen e-mail cím."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Nyelv"
|
||||
@@ -1123,7 +1125,7 @@ msgstr "Állandó"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Persistence"
|
||||
msgstr "Kitartás"
|
||||
msgstr "Tartósság"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
|
||||
@@ -1311,7 +1313,7 @@ msgstr "Lásd <0>az értesítési beállításokat</0>, hogy konfigurálja, hogy
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Select {foo}"
|
||||
msgstr ""
|
||||
msgstr "{foo} kiválasztása"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Sent"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Százalékos küszöbértékek beállítása a mérőszínekhez."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "E-mailben"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Rács ki- és bekapcsolása"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Téma váltása"
|
||||
@@ -1549,19 +1553,19 @@ msgstr "Riaszt, ha az 5 perces terhelési átlag túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when any sensor exceeds a threshold"
|
||||
msgstr "Bekapcsol, ha bármelyik érzékelő túllép egy küszöbértéket"
|
||||
msgstr "Riaszt, ha bármelyik hőmérséklet érzékelő túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when battery charge drops below a threshold"
|
||||
msgstr ""
|
||||
msgstr "Riaszt, ha az akkumulátor töltöttségi szintje egy küszöbérték alá esik"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when combined up/down exceeds a threshold"
|
||||
msgstr "Bekapcsol, ha bármelyik érzékelő túllép egy küszöbértéket"
|
||||
msgstr "Riaszt, ha a sávszélesség-használat túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when CPU usage exceeds a threshold"
|
||||
msgstr "Bekapcsol, ha a CPU érzékelő túllép egy küszöbértéket"
|
||||
msgstr "Riaszt, ha a CPU használat túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when GPU usage exceeds a threshold"
|
||||
@@ -1569,15 +1573,15 @@ msgstr "Riaszt, ha a GPU használat túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when memory usage exceeds a threshold"
|
||||
msgstr "Bekapcsol, ha a Ram érzékelő túllép egy küszöbértéket"
|
||||
msgstr "Riaszt, ha a memóriahasználat túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when status switches between up and down"
|
||||
msgstr "Bekapcsol, amikor az állapot fel és le között változik"
|
||||
msgstr "Riaszt, amikor a rendszer online állapota változik"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when usage of any disk exceeds a threshold"
|
||||
msgstr "Bekapcsol, ha a lemez érzékelő túllép egy küszöbértéket"
|
||||
msgstr "Riaszt, ha a lemezhasználat túllép egy küszöbértéket"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
@@ -1710,7 +1714,7 @@ msgstr "Webhook / Push értesítések"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "When enabled, this token allows agents to self-register without prior system creation."
|
||||
msgstr "Ha engedélyezve van, ez a token lehetővé teszi az ügynökök számára az önregisztrációt rendszer előzetes létrehozása nélkül."
|
||||
msgstr "Ha engedélyezve van, ez a token lehetővé teszi az ügynökök számára a regisztrációt a rendszer előzetes létrehozása nélkül."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: id\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-25 10:45\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Indonesian\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Peringatan"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Semua Container"
|
||||
@@ -456,7 +457,7 @@ msgstr "Salin YAML"
|
||||
#: src/components/systemd-table/systemd-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system/cpu-sheet.tsx
|
||||
msgid "CPU Cores"
|
||||
@@ -542,7 +543,7 @@ msgstr "Deskripsi"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detail"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Device"
|
||||
@@ -555,11 +556,11 @@ msgstr "Sedang tidak di charge"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Disk"
|
||||
msgstr "Disk"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Disk I/O"
|
||||
msgstr "Disk I/O"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Disk unit"
|
||||
@@ -585,7 +586,7 @@ msgstr "Penggunaan Memori Docker"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Docker Network I/O"
|
||||
msgstr "Docker Network I/O"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
@@ -606,7 +607,7 @@ msgstr "Mati ({downSystemsLength})"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Download"
|
||||
msgstr "Download"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Duration"
|
||||
@@ -626,7 +627,7 @@ msgstr "Ubah {foo}"
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
#: src/components/login/otp-forms.tsx
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Email notifications"
|
||||
@@ -667,7 +668,7 @@ msgstr "Sementara"
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Error"
|
||||
msgstr "Error"
|
||||
msgstr ""
|
||||
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
@@ -694,7 +695,7 @@ msgstr "Kedaluwarsa setelah satu jam atau saat restart hub."
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Export"
|
||||
msgstr "Export"
|
||||
msgstr "Ekspor"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Export configuration"
|
||||
@@ -706,7 +707,7 @@ msgstr "Export konfigurasi sistem anda saat ini."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Fahrenheit (°F)"
|
||||
msgstr "Fahrenheit (°F)"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Failed"
|
||||
@@ -746,15 +747,15 @@ msgstr "Gagal: {0}"
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Filter..."
|
||||
msgstr "Filter..."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Fingerprint"
|
||||
msgstr "Fingerprint"
|
||||
msgstr "Sidik jari"
|
||||
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Firmware"
|
||||
msgstr "Firmware"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
|
||||
@@ -783,7 +784,7 @@ msgstr "Umum"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Global"
|
||||
msgstr "Global"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "GPU Engines"
|
||||
@@ -813,12 +814,12 @@ msgstr "Perintah Homebrew"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Host / IP"
|
||||
msgstr "Host / IP"
|
||||
msgstr ""
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Idle"
|
||||
msgstr "Idle"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
@@ -827,7 +828,7 @@ msgstr "Jika anda kehilangan kata sandi untuk akun admin anda, anda dapat merese
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Inactive"
|
||||
@@ -837,6 +838,7 @@ msgstr "Tidak aktif"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Alamat email tidak valid."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Bahasa"
|
||||
@@ -889,7 +891,7 @@ msgstr "Memuat..."
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Log Out"
|
||||
msgstr "Log Out"
|
||||
msgstr "Keluar"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Login"
|
||||
@@ -956,7 +958,7 @@ msgstr "Penggunaan memori kontainer docker"
|
||||
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Model"
|
||||
msgstr "Model"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
@@ -1160,7 +1162,7 @@ msgstr "Silakan masuk ke akun anda"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Port"
|
||||
msgstr "Port"
|
||||
msgstr ""
|
||||
|
||||
#. Power On Time
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
@@ -1246,7 +1248,7 @@ msgstr "Lanjutkan"
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgctxt "Root disk label"
|
||||
msgid "Root"
|
||||
msgstr "Root"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Rotate token"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Tetapkan ambang persentase untuk warna meter."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1374,7 +1377,7 @@ msgstr "Status"
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
msgstr "Status"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/systemd-table/systemd-table-columns.tsx
|
||||
msgid "Sub State"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Ke email"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Ganti tampilan"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Ganti tema"
|
||||
@@ -1493,7 +1497,7 @@ msgstr "Ganti tema"
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Token"
|
||||
msgstr "Token"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
@@ -1512,7 +1516,7 @@ msgstr "Token dan Fingerprint digunakan untuk mengautentikasi koneksi WebSocket
|
||||
#: src/components/ui/chart.tsx
|
||||
#: src/components/ui/chart.tsx
|
||||
msgid "Total"
|
||||
msgstr "Total"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Total data received for each interface"
|
||||
@@ -1525,7 +1529,7 @@ msgstr "Total data yang dikirim untuk setiap antarmuka"
|
||||
#. placeholder {0}: data.length
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Total: {0}"
|
||||
msgstr "Total: {0}"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Triggered by"
|
||||
@@ -1635,7 +1639,7 @@ msgstr "Diperbarui setiap 10 menit."
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Upload"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
msgid "Uptime"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: it\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:17\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Italian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Avvisi"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Tutti i contenitori"
|
||||
@@ -230,7 +231,7 @@ msgstr "Larghezza di banda"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Inattivo"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Indirizzo email non valido."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Lingua"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Imposta le soglie percentuali per i colori dei contatori."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "A email(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Attiva/disattiva griglia"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Attiva/disattiva tema"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ja\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Japanese\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "アラート"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "すべてのコンテナ"
|
||||
@@ -837,6 +838,7 @@ msgstr "非アクティブ"
|
||||
msgid "Invalid email address."
|
||||
msgstr "無効なメールアドレスです。"
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "言語"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "メーターの色を変更するしきい値(パーセンテージ)
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "宛先メールアドレス"
|
||||
msgid "Toggle grid"
|
||||
msgstr "グリッドを切り替え"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "テーマを切り替え"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ko\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Korean\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "알림"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "모든 컨테이너"
|
||||
@@ -837,6 +838,7 @@ msgstr "비활성"
|
||||
msgid "Invalid email address."
|
||||
msgstr "잘못된 이메일 주소입니다."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "언어"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "그래프 미터 색상의 백분율 임계값을 설정합니다."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "받는사람(들)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "그리드 전환"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "테마 전환"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: nl\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-17 12:02\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Dutch\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -59,7 +59,7 @@ msgstr "1 minuut"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 week"
|
||||
msgstr ""
|
||||
msgstr "1 week"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "12 hours"
|
||||
@@ -134,7 +134,7 @@ msgstr "Breedte van het hoofdlayout aanpassen"
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Admin"
|
||||
msgstr ""
|
||||
msgstr "Administrator"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "After"
|
||||
@@ -142,7 +142,7 @@ msgstr "Na"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Agent"
|
||||
msgstr ""
|
||||
msgstr "Agent"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
@@ -157,6 +157,7 @@ msgstr "Waarschuwingen"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alle containers"
|
||||
@@ -271,7 +272,7 @@ msgstr "Binair"
|
||||
#: src/components/routes/settings/general.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Bits (Kbps, Mbps, Gbps)"
|
||||
msgstr ""
|
||||
msgstr "Bits (Kbps, Mbps, Gbps)"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Boot state"
|
||||
@@ -280,11 +281,11 @@ msgstr "Opstartstatus"
|
||||
#: src/components/routes/settings/general.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Bytes (KB/s, MB/s, GB/s)"
|
||||
msgstr ""
|
||||
msgstr "Bytes (KB/s, MB/s, GB/s)"
|
||||
|
||||
#: src/components/charts/mem-chart.tsx
|
||||
msgid "Cache / Buffers"
|
||||
msgstr ""
|
||||
msgstr "Cache / Buffers"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Can reload"
|
||||
@@ -318,7 +319,7 @@ msgstr "Opgelet - potentieel gegevensverlies"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Celsius (°C)"
|
||||
msgstr ""
|
||||
msgstr "Celsius (°C)"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Change display units for metrics."
|
||||
@@ -456,7 +457,7 @@ msgstr "YAML kopiëren"
|
||||
#: src/components/systemd-table/systemd-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr ""
|
||||
msgstr "CPU"
|
||||
|
||||
#: src/components/routes/system/cpu-sheet.tsx
|
||||
msgid "CPU Cores"
|
||||
@@ -706,7 +707,7 @@ msgstr "Exporteer je huidige systeemconfiguratie."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Fahrenheit (°F)"
|
||||
msgstr ""
|
||||
msgstr "Fahrenheit (°F)"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Failed"
|
||||
@@ -837,6 +838,7 @@ msgstr "Inactief"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ongeldig e-mailadres."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Taal"
|
||||
@@ -926,7 +928,7 @@ msgstr "Handmatige installatie-instructies"
|
||||
#. Chart select field. Please try to keep this short.
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Max 1 min"
|
||||
msgstr ""
|
||||
msgstr "Max 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
@@ -1119,7 +1121,7 @@ msgstr "Percentage tijd besteed in elke status"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Permanent"
|
||||
msgstr "Permanent"
|
||||
msgstr "Blijvend"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Persistence"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Stel percentagedrempels in voor meterkleuren."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1374,7 +1377,7 @@ msgstr "Status"
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
msgstr ""
|
||||
msgstr "Status"
|
||||
|
||||
#: src/components/systemd-table/systemd-table-columns.tsx
|
||||
msgid "Sub State"
|
||||
@@ -1447,7 +1450,7 @@ msgstr "Temperatuur van systeem sensoren"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Test <0>URL</0>"
|
||||
msgstr ""
|
||||
msgstr "Test <0>URL</0>"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Test notification sent"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Naar e-mail(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Schakel raster"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Schakel thema"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: no\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-05 20:24\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Norwegian\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Alarmer"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alle containere"
|
||||
@@ -230,7 +231,7 @@ msgstr "Båndbredde"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr ""
|
||||
msgstr "Batteri"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Inaktiv"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ugyldig e-postadresse."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Språk"
|
||||
@@ -908,7 +910,7 @@ msgstr "Logger"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table."
|
||||
msgstr "Ser du etter hvor du kan opprette alarmer? Klikk på bjelle-ikonene <0/> i systemtabellen."
|
||||
msgstr "Ser du etter hvor du kan opprette alarmer? Klikk på bjelle-ikonet <0/> for systemet i systemoversikten."
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Main PID"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Angi prosentvise terskler for målerfarger."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Til e-postadresse(r)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Rutenett av/på"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Tema av/på"
|
||||
@@ -1549,7 +1553,7 @@ msgstr "Slår inn når gjennomsnittsbelastningen over 5 minutter overstiger en g
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when any sensor exceeds a threshold"
|
||||
msgstr "Slår inn når enhver sensor overstiger en grenseverdi"
|
||||
msgstr "Slår inn når hvilken som helst sensor overstiger en grenseverdi"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when battery charge drops below a threshold"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: pl\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-18 19:21\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Polish\n"
|
||||
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
|
||||
@@ -129,7 +129,7 @@ msgstr "Dostosuj opcje wyświetlania wykresów."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Adjust the width of the main layout"
|
||||
msgstr "Dostosuj szerokość głównego układu"
|
||||
msgstr "Dostosuj szerokość widoku"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
@@ -157,6 +157,7 @@ msgstr "Alerty"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Wszystkie kontenery"
|
||||
@@ -188,12 +189,12 @@ msgstr "Średnia"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average CPU utilization of containers"
|
||||
msgstr "Średnie wykorzystanie procesora przez kontenery"
|
||||
msgstr "Średnie wykorzystanie CPU przez kontenery"
|
||||
|
||||
#. placeholder {0}: alertData.unit
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Average drops below <0>{value}{0}</0>"
|
||||
msgstr ""
|
||||
msgstr "Średnia spada poniżej <0>{value}{0}</0>"
|
||||
|
||||
#. placeholder {0}: alertData.unit
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
@@ -206,7 +207,7 @@ msgstr "Średnie zużycie energii przez GPU"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average system-wide CPU utilization"
|
||||
msgstr "Średnie wykorzystanie procesora w całym systemie"
|
||||
msgstr "Średnie wykorzystanie CPU w całym systemie"
|
||||
|
||||
#. placeholder {0}: gpu.n
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -220,7 +221,7 @@ msgstr "Średnie wykorzystanie silników GPU"
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Backups"
|
||||
msgstr "Kopie"
|
||||
msgstr "Kopie zapasowe"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -230,7 +231,7 @@ msgstr "Przepustowość"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr ""
|
||||
msgstr "Bateria"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -254,7 +255,7 @@ msgstr "Przed"
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Below {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr ""
|
||||
msgstr "Poniżej {0}{1} w ciągu ostatnich {2, plural, one {# minuty} other {# minut}}"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
|
||||
@@ -262,7 +263,7 @@ msgstr "Beszel obsługuje OpenID Connect i wielu dostawców uwierzytelniania OAu
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Beszel uses <0>Shoutrrr</0> to integrate with popular notification services."
|
||||
msgstr "Beszel używa <0>Shoutrrr</0> do integracji z popularnych serwisów powiadomień."
|
||||
msgstr "Beszel używa <0>Shoutrrr</0> do integracji z popularnymi serwisami powiadomień."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Binary"
|
||||
@@ -314,7 +315,7 @@ msgstr "Pojemność"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Caution - potential data loss"
|
||||
msgstr "Uwaga- potencjalna utrata danych."
|
||||
msgstr "Uwaga - ryzyko utraty danych"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Celsius (°C)"
|
||||
@@ -326,7 +327,7 @@ msgstr "Zmień jednostki wyświetlania dla metryk."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Change general application options."
|
||||
msgstr "Zmiana ogólnych ustawień aplikacji."
|
||||
msgstr "Zmień ogólne ustawienia aplikacji."
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Charge"
|
||||
@@ -339,7 +340,7 @@ msgstr "Ładuje się"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Chart options"
|
||||
msgstr "Opcje wykresu"
|
||||
msgstr "Wykresy"
|
||||
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "Check {email} for a reset link."
|
||||
@@ -361,15 +362,15 @@ msgstr "Wyczyść"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Kliknij na kontener, aby wyświetlić więcej informacji."
|
||||
msgstr "Wybierz kontener, aby wyświetlić więcej informacji."
|
||||
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Click on a device to view more information."
|
||||
msgstr "Kliknij na urządzenie, aby wyświetlić więcej informacji."
|
||||
msgstr "Wybierz urządzenie, aby wyświetlić więcej informacji."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Kliknij na system, aby zobaczyć więcej informacji."
|
||||
msgstr "Wybierz system, aby wyświetlić więcej informacji."
|
||||
|
||||
#: src/components/ui/input-copy.tsx
|
||||
msgid "Click to copy"
|
||||
@@ -500,11 +501,11 @@ msgstr "Krytyczny (%)"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Cumulative Download"
|
||||
msgstr "Pobieranie skumulowane"
|
||||
msgstr "Pobieranie łącznie"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Cumulative Upload"
|
||||
msgstr "Wysyłanie skumulowane"
|
||||
msgstr "Wysyłanie łącznie"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -577,11 +578,11 @@ msgstr "Wykorzystanie dysku {extraFsName}"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Docker CPU Usage"
|
||||
msgstr "Wykorzystanie procesora przez Docker"
|
||||
msgstr "Użycie CPU przez Docker"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Docker Memory Usage"
|
||||
msgstr "Wykorzystanie pamięci przez Docker"
|
||||
msgstr "Użycie pamięci przez Docker"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Docker Network I/O"
|
||||
@@ -656,7 +657,7 @@ msgstr "Wprowadź swoje jednorazowe hasło."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Ephemeral"
|
||||
msgstr "Efemeryczny"
|
||||
msgstr "Tymczasowy"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
@@ -682,7 +683,7 @@ msgstr "Główny PID wykonania"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Existing systems not defined in <0>config.yml</0> will be deleted. Please make regular backups."
|
||||
msgstr "Istniejące systemy, które nie są zdefiniowane w <0>config.yml</0>, zostaną usunięte. Proszę regularnie tworzyć kopie zapasowe."
|
||||
msgstr "Istniejące systemy, które nie są zdefiniowane w <0>config.yml</0>, zostaną usunięte. Pamiętaj aby regularnie tworzyć kopie zapasowe."
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Exited active"
|
||||
@@ -728,7 +729,7 @@ msgstr "Nie udało się zapisać ustawień"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Failed to send test notification"
|
||||
msgstr "Nie udało się wysłać testowego powiadomienia"
|
||||
msgstr "Nie udało się wysłać powiadomienia testowego"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Failed to update alert"
|
||||
@@ -803,7 +804,7 @@ msgstr "Siatka"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Zdrowie"
|
||||
msgstr "Kondycja"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
@@ -837,6 +838,7 @@ msgstr "Nieaktywny"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Nieprawidłowy adres e-mail."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Język"
|
||||
@@ -864,15 +866,15 @@ msgstr "Średnie obciążenie"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 15m"
|
||||
msgstr "Średnie obciążenie 15 m"
|
||||
msgstr "Średnie obciążenie 15 min"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 1m"
|
||||
msgstr "Średnie obciążenie 1 m"
|
||||
msgstr "Średnie obciążenie 1 min"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 5m"
|
||||
msgstr "Średnie obciążenie 5 m"
|
||||
msgstr "Średnie obciążenie 5 min"
|
||||
|
||||
#. Short label for load average
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
@@ -948,7 +950,7 @@ msgstr "Szczyt pamięci"
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Memory Usage"
|
||||
msgstr "Wykorzystanie pamięci"
|
||||
msgstr "Użycie pamięci"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Memory usage of docker containers"
|
||||
@@ -996,7 +998,7 @@ msgstr "Nie"
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "No results found."
|
||||
msgstr "Brak wyników."
|
||||
msgstr "Nie znaleziono wyników."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
@@ -1082,7 +1084,7 @@ msgstr "Hasło"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Password must be at least 8 characters."
|
||||
msgstr "Hasło musi mieć co najmniej 8 znaków."
|
||||
msgstr "Hasło musi zawierać co najmniej 8 znaków."
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Password must be less than 72 bytes."
|
||||
@@ -1090,11 +1092,11 @@ msgstr "Hasło musi być mniejsze niż 72 bajty."
|
||||
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "Password reset request received"
|
||||
msgstr "Otrzymane żądanie resetowania hasła"
|
||||
msgstr "Otrzymano żądanie resetowania hasła"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Past"
|
||||
msgstr "Przeszłe"
|
||||
msgstr "Poprzednie"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Pause"
|
||||
@@ -1237,7 +1239,7 @@ msgstr "Rozwiązany"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Restarts"
|
||||
msgstr "Ponowne uruchomienia"
|
||||
msgstr "Uruchamia ponownie"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Resume"
|
||||
@@ -1283,7 +1285,7 @@ msgstr "Zapisz system"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Saved in the database and does not expire until you disable it."
|
||||
msgstr "Zapisane w bazie danych i nie wygasa, dopóki go nie wyłączysz."
|
||||
msgstr "Zapisany w bazie danych. Nie wygasa, dopóki go nie wyłączysz."
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Schedule"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Ustaw progi procentowe dla kolorów mierników."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1342,7 +1345,7 @@ msgstr "Ustawienia"
|
||||
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings saved"
|
||||
msgstr "Ustawienia zapisane"
|
||||
msgstr "Ustawienia zostały zapisane"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Sign in"
|
||||
@@ -1484,8 +1487,9 @@ msgstr "Do e-mail(ów)"
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
msgid "Toggle grid"
|
||||
msgstr "Przełącz siatkę"
|
||||
msgstr "Przełącz widok"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Zmień motyw"
|
||||
@@ -1553,7 +1557,7 @@ msgstr "Wyzwalane, gdy jakikolwiek czujnik przekroczy ustalony próg."
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when battery charge drops below a threshold"
|
||||
msgstr ""
|
||||
msgstr "Uruchamia się, gdy poziom baterii spadnie poniżej wybranej wartości"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when combined up/down exceeds a threshold"
|
||||
@@ -1569,7 +1573,7 @@ msgstr "Wyzwalane, gdy użycie GPU przekroczy próg"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when memory usage exceeds a threshold"
|
||||
msgstr "Wyzwalane, wykorzystanie pamięci przekroczy ustalony próg."
|
||||
msgstr "Wyzwalane, wykorzystanie pamięci przekroczy ustalony próg"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when status switches between up and down"
|
||||
@@ -1690,7 +1694,7 @@ msgstr "Oczekiwanie na wystarczającą liczbę rekordów do wyświetlenia"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Want to help improve our translations? Check <0>Crowdin</0> for details."
|
||||
msgstr "Chcesz pomóc nam uczynić nasze tłumaczenia jeszcze lepszymi? Sprawdź <0>Crowdin</0> po więcej szczegółów."
|
||||
msgstr "Chcesz pomóc ulepszyć nasze tłumaczenie? Sprawdź <0>Crowdin</0> po szczegóły."
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Wants"
|
||||
@@ -1722,7 +1726,7 @@ msgstr "Polecenie Windows"
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Write"
|
||||
msgstr "Napisz"
|
||||
msgstr "Zapis"
|
||||
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "YAML Config"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: pt\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-05 20:24\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -42,7 +42,7 @@ msgstr "{count, plural, one {{countString} minuto} other {{countString} minutos}
|
||||
|
||||
#: src/components/routes/system/info-bar.tsx
|
||||
msgid "{threads, plural, one {# thread} other {# threads}}"
|
||||
msgstr "{threads, plural, one {# thread} other {# threads}}"
|
||||
msgstr ""
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 hour"
|
||||
@@ -157,6 +157,7 @@ msgstr "Alertas"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Todos os Contêineres"
|
||||
@@ -230,7 +231,7 @@ msgstr "Largura de Banda"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -284,7 +285,7 @@ msgstr "Bytes (KB/s, MB/s, GB/s)"
|
||||
|
||||
#: src/components/charts/mem-chart.tsx
|
||||
msgid "Cache / Buffers"
|
||||
msgstr ""
|
||||
msgstr "Cache / Buffers"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Can reload"
|
||||
@@ -813,7 +814,7 @@ msgstr "Comando Homebrew"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Host / IP"
|
||||
msgstr ""
|
||||
msgstr "Host / IP"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Inativo"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Endereço de email inválido."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Idioma"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Defina os limiares de porcentagem para as cores do medidor."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1430,7 +1433,7 @@ msgstr "Tarefas"
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Temp"
|
||||
msgstr ""
|
||||
msgstr "Temp"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Para email(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Alternar grade"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Alternar tema"
|
||||
@@ -1493,7 +1497,7 @@ msgstr "Alternar tema"
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Token"
|
||||
msgstr ""
|
||||
msgstr "Token"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: ru\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:17\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Russian\n"
|
||||
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Оповещения"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Все контейнеры"
|
||||
@@ -230,7 +231,7 @@ msgstr "Пропускная способность"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr "Батарея"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Неактивно"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Неверный адрес электронной почты."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Язык"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Установите процентные пороги для цвето
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "На электронную почту"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Переключить сетку"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Переключить тему"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: sl\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-05 20:24\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Slovenian\n"
|
||||
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n"
|
||||
@@ -142,7 +142,7 @@ msgstr "Po"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Agent"
|
||||
msgstr "Agent"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
@@ -157,6 +157,7 @@ msgstr "Opozorila"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Vsi kontejnerji"
|
||||
@@ -230,7 +231,7 @@ msgstr "Pasovna širina"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -456,7 +457,7 @@ msgstr "Kopiraj YAML"
|
||||
#: src/components/systemd-table/systemd-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system/cpu-sheet.tsx
|
||||
msgid "CPU Cores"
|
||||
@@ -706,7 +707,7 @@ msgstr "Izvozi trenutne nastavitve sistema."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Fahrenheit (°F)"
|
||||
msgstr "Fahrenheit (°F)"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Failed"
|
||||
@@ -837,6 +838,7 @@ msgstr "Neaktivno"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Napačen e-poštni naslov."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Jezik"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Nastavite odstotne pragove za barve merilnikov."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "E-pošta za"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Preklopi način mreže"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Obrni temo"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: sr\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-08 18:22\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Serbian (Cyrillic)\n"
|
||||
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Упозорења"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Сви контејнери"
|
||||
@@ -230,7 +231,7 @@ msgstr "Пропусни опсег"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Неактивно"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Неважећа имејл адреса."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Језик"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Подесите процентуалне прагове за боје
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "На е-пошту(е)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Укључи/искључи мрежу"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Промени тему"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: sv\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-05 20:24\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Swedish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Larm"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alla behållare"
|
||||
@@ -230,7 +231,7 @@ msgstr "Bandbredd"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Inaktiv"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ogiltig e-postadress."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Språk"
|
||||
@@ -1119,7 +1121,7 @@ msgstr "Procentandel av tid spenderad i varje tillstånd"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Permanent"
|
||||
msgstr "Permanent"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Persistence"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Ställ in procentuella tröskelvärden för mätarfärger."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Till e-postadress(er)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Växla rutnät"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Växla tema"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: tr\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Turkish\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Uyarılar"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Tüm Konteynerler"
|
||||
@@ -837,6 +838,7 @@ msgstr "Pasif"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Geçersiz e-posta adresi."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Dil"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Sayaç renkleri için yüzde eşiklerini ayarlayın."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "E-posta(lar)a"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Izgarayı değiştir"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Temayı değiştir"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: uk\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Ukrainian\n"
|
||||
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Сповіщення"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Всі контейнери"
|
||||
@@ -230,7 +231,7 @@ msgstr "Пропускна здатність"
|
||||
#. Battery label in systems table header
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Bat"
|
||||
msgstr "Bat"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -837,6 +838,7 @@ msgstr "Неактивне"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Неправильна адреса електронної пошти."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Мова"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Встановіть відсоткові пороги для кольо
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "На електронну пошту"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Перемкнути сітку"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Перемкнути тему"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: vi\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Vietnamese\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "Cảnh báo"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Tất cả container"
|
||||
@@ -456,7 +457,7 @@ msgstr "Sao chép YAML"
|
||||
#: src/components/systemd-table/systemd-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/system/cpu-sheet.tsx
|
||||
msgid "CPU Cores"
|
||||
@@ -626,7 +627,7 @@ msgstr "Chỉnh sửa {foo}"
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
#: src/components/login/otp-forms.tsx
|
||||
msgid "Email"
|
||||
msgstr "Email"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Email notifications"
|
||||
@@ -837,6 +838,7 @@ msgstr "Không hoạt động"
|
||||
msgid "Invalid email address."
|
||||
msgstr "Địa chỉ email không hợp lệ."
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "Ngôn ngữ"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "Đặt ngưỡng cho màu sắc đồng hồ."
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "Đến email(s)"
|
||||
msgid "Toggle grid"
|
||||
msgstr "Chuyển đổi lưới"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "Chuyển đổi chủ đề"
|
||||
@@ -1493,7 +1497,7 @@ msgstr "Chuyển đổi chủ đề"
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Token"
|
||||
msgstr "Token"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: zh\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Simplified\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -113,7 +113,7 @@ msgstr "添加 {foo}"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Add <0>System</0>"
|
||||
msgstr "<0>添加客户端</0>"
|
||||
msgstr "添加<0>客户端</0>"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Add system"
|
||||
@@ -157,6 +157,7 @@ msgstr "警报"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "所有容器"
|
||||
@@ -837,6 +838,7 @@ msgstr "非活跃"
|
||||
msgid "Invalid email address."
|
||||
msgstr "无效的电子邮件地址。"
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "语言"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "设置仪表颜色的百分比阈值。"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "发送到电子邮件"
|
||||
msgid "Toggle grid"
|
||||
msgstr "切换网格"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "切换主题"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: zh\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-12-02 23:18\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Traditional, Hong Kong\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -157,6 +157,7 @@ msgstr "警報"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "所有容器"
|
||||
@@ -837,6 +838,7 @@ msgstr "未啟用"
|
||||
msgid "Invalid email address."
|
||||
msgstr "無效的電子郵件地址。"
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "語言"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "設定儀表顏色的百分比閾值。"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "發送到電子郵件"
|
||||
msgid "Toggle grid"
|
||||
msgstr "切換網格"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "切換主題"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: zh\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2026-01-10 17:34\n"
|
||||
"PO-Revision-Date: 2026-01-31 21:16\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Chinese Traditional\n"
|
||||
"Plural-Forms: nplurals=1; plural=0;\n"
|
||||
@@ -142,7 +142,7 @@ msgstr "之後"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Agent"
|
||||
msgstr "代理"
|
||||
msgstr "Agent"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
@@ -157,6 +157,7 @@ msgstr "警報"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "所有容器"
|
||||
@@ -442,11 +443,11 @@ msgstr "複製文字"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Copy the installation command for the agent below, or register agents automatically with a <0>universal token</0>."
|
||||
msgstr "複製下面的代理程式安裝指令,或使用<0>通用令牌</0>自動註冊代理程式。"
|
||||
msgstr "以下方指令安裝 Agent ,或使用<0>通用 Token</0>進行自動註冊。"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>."
|
||||
msgstr "複製下面的代理程式<0>docker-compose.yml</0>內容,或使用<1>通用令牌</1>自動註冊代理程式。"
|
||||
msgstr "以下方<0>docker-compose.yml</0>執行 Agent,或使用<1>通用 Token</1>進行自動註冊。"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Copy YAML"
|
||||
@@ -534,7 +535,7 @@ msgstr "刪除"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "刪除指紋"
|
||||
msgstr "刪除 Fingerprint"
|
||||
|
||||
#: src/components/systemd-table/systemd-table.tsx
|
||||
msgid "Description"
|
||||
@@ -690,7 +691,7 @@ msgstr "結束"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Expires after one hour or on hub restart."
|
||||
msgstr "一小時後或重新啟動集線器時過期。"
|
||||
msgstr "在一個小時後或者重新啟動 Hub 時過期。"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Export"
|
||||
@@ -750,7 +751,7 @@ msgstr "篩選..."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Fingerprint"
|
||||
msgstr "指紋"
|
||||
msgstr "Fingerprint"
|
||||
|
||||
#: src/components/routes/system/smart-table.tsx
|
||||
msgid "Firmware"
|
||||
@@ -837,6 +838,7 @@ msgstr "未啟用"
|
||||
msgid "Invalid email address."
|
||||
msgstr "無效的電子郵件地址。"
|
||||
|
||||
#: src/components/lang-toggle.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
msgstr "語言"
|
||||
@@ -1250,7 +1252,7 @@ msgstr "Root"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Rotate token"
|
||||
msgstr "輪替令牌"
|
||||
msgstr "重設 Token"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Rows per page"
|
||||
@@ -1283,7 +1285,7 @@ msgstr "儲存系統"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Saved in the database and does not expire until you disable it."
|
||||
msgstr "保存在資料庫中,在您停用之前不會過期。"
|
||||
msgstr "儲存在資料庫中,在您停用之前不會過期。"
|
||||
|
||||
#: src/components/routes/settings/quiet-hours.tsx
|
||||
msgid "Schedule"
|
||||
@@ -1335,6 +1337,7 @@ msgstr "設定儀表顏色的百分比閾值。"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Settings"
|
||||
@@ -1486,6 +1489,7 @@ msgstr "發送到電子郵件"
|
||||
msgid "Toggle grid"
|
||||
msgstr "切換網格"
|
||||
|
||||
#: src/components/mode-toggle.tsx
|
||||
#: src/components/mode-toggle.tsx
|
||||
msgid "Toggle theme"
|
||||
msgstr "切換主題"
|
||||
@@ -1493,21 +1497,21 @@ msgstr "切換主題"
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Token"
|
||||
msgstr "令牌"
|
||||
msgstr "Token"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens & Fingerprints"
|
||||
msgstr "令牌和指紋"
|
||||
msgstr "Token & Fingerprint"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens allow agents to connect and register. Fingerprints are stable identifiers unique to each system, set on first connection."
|
||||
msgstr "令牌允許代理程式連線和註冊。指紋是每個系統的唯一穩定識別符,在首次連線時產生。"
|
||||
msgstr "Token 用於 Agent 的連線和註冊。Fingerprint 則是每個系統唯一的穩定識別碼,於初次連線時設定。"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
|
||||
msgstr "令牌和指紋被用於驗證到 Hub 的 WebSocket 連線。"
|
||||
msgstr "Token 與 Fingerprint 用於驗證連往 Hub 的 WebSocket 連線。"
|
||||
|
||||
#: src/components/ui/chart.tsx
|
||||
#: src/components/ui/chart.tsx
|
||||
@@ -1597,7 +1601,7 @@ msgstr "單位偏好"
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Universal token"
|
||||
msgstr "通用令牌"
|
||||
msgstr "通用 Token"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -1710,7 +1714,7 @@ msgstr "Webhook / 推送通知"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "When enabled, this token allows agents to self-register without prior system creation."
|
||||
msgstr "啟用後,此令牌允許代理無需事先建立系統即可自行註冊。"
|
||||
msgstr "啟用後,此 Token 可讓 Agent 自行註冊,無需預先在系統中建立項目。"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
|
||||
@@ -12,7 +12,6 @@ import Settings from "@/components/routes/settings/layout.tsx"
|
||||
import { ThemeProvider } from "@/components/theme-provider.tsx"
|
||||
import { Toaster } from "@/components/ui/toaster.tsx"
|
||||
import { alertManager } from "@/lib/alerts"
|
||||
import { containerAlertManager } from "@/lib/container-alerts"
|
||||
import { pb, updateUserSettings } from "@/lib/api.ts"
|
||||
import { dynamicActivate, getLocale } from "@/lib/i18n"
|
||||
import { $authenticated, $copyContent, $direction, $publicKey, $userSettings } from "@/lib/stores.ts"
|
||||
@@ -50,11 +49,8 @@ const App = memo(() => {
|
||||
.then(alertManager.refresh)
|
||||
// subscribe to new alert updates
|
||||
.then(alertManager.subscribe)
|
||||
// subscribe to container alerts
|
||||
.then(() => containerAlertManager.subscribe())
|
||||
return () => {
|
||||
alertManager.unsubscribe()
|
||||
containerAlertManager.unsubscribe()
|
||||
systemsManager.unsubscribe()
|
||||
}
|
||||
}, [])
|
||||
|
||||
Vendored
-27
@@ -340,33 +340,6 @@ export interface AlertInfo {
|
||||
|
||||
export type AlertMap = Record<string, Map<string, AlertRecord>>
|
||||
|
||||
export interface ContainerAlertRecord extends RecordModel {
|
||||
id: string
|
||||
system: string
|
||||
container: string
|
||||
name: string
|
||||
triggered: boolean
|
||||
value: number
|
||||
min: number
|
||||
}
|
||||
|
||||
export interface ContainerAlertInfo {
|
||||
name: () => string
|
||||
unit: string
|
||||
icon: any
|
||||
desc: () => string
|
||||
max?: number
|
||||
min?: number
|
||||
step?: number
|
||||
start?: number
|
||||
/** Single value description (when there's only one value, like status) */
|
||||
singleDesc?: () => string
|
||||
invert?: boolean
|
||||
}
|
||||
|
||||
export type ContainerAlertMap = Record<string, Map<string, Map<string, ContainerAlertRecord>>>
|
||||
|
||||
|
||||
export interface SmartData {
|
||||
/** model family */
|
||||
// mf?: string
|
||||
|
||||
@@ -1,3 +1,49 @@
|
||||
## 0.18.3
|
||||
|
||||
- Add experimental sysfs AMD GPU collector. (#737, #1569)
|
||||
|
||||
- Update LibreHardwareMonitorLib to 0.9.5. (#1697)
|
||||
|
||||
- Improve container network stats accuracy.
|
||||
|
||||
- Fix `SHARE_ALL_SYSTEMS` for system_details, smart_devices, and systemd_services. (#1660)
|
||||
|
||||
- Parse ATA device statistics for temperature and future metrics. (#1689)
|
||||
|
||||
- Add `SMART_DEVICES_SEPARATOR` environment variable and allow drives with the same name to be added with different types (e.g. RAID controllers). (#1655)
|
||||
|
||||
- Add tooltips for navbar buttons. (#1636)
|
||||
|
||||
- Add icon button for mobile use. (#1687)
|
||||
|
||||
- Add tooltip to system name in systems table. (#1640)
|
||||
|
||||
- Improve CJK truncation in UI.
|
||||
|
||||
- Fix container uptime sorting edge case. (#1696)
|
||||
|
||||
- Remove stale systemd services from tracking after deletion. (#1594)
|
||||
|
||||
- Apply SELinux context after binary replacement. (#1678)
|
||||
|
||||
- Update honeypot field name and autofill ignores. (#1011)
|
||||
|
||||
- Write health_file to `/dev/shm` instead of `/tmp` if available. (#1455)
|
||||
|
||||
- Don't force lowercase text for active alerts. (#1682)
|
||||
|
||||
- Ensure battery current charge doesn't exceed full capacity. (#1668)
|
||||
|
||||
- Increase `smartctl --scan` timeout to 10 seconds. (#1465)
|
||||
|
||||
- Use name-only matching for unique S.M.A.R.T. devices. (#1655)
|
||||
|
||||
- Fix smartctlArgs call to use hasExistingData flag. (#1645)
|
||||
|
||||
- Ignore alt key combinations when navigating systems with arrow keys. (#1698)
|
||||
|
||||
- Update Go dependencies
|
||||
|
||||
## 0.18.2
|
||||
|
||||
- Add separate dynamically linked glibc build for Linux. (#1618)
|
||||
|
||||
Reference in New Issue
Block a user