Compare commits

...

11 Commits

56 changed files with 1072 additions and 197 deletions

View File

@@ -29,6 +29,7 @@ jobs:
# henrygd/beszel-agent:alpine # henrygd/beszel-agent:alpine
- image: henrygd/beszel-agent - image: henrygd/beszel-agent
dockerfile: ./internal/dockerfile_agent_alpine dockerfile: ./internal/dockerfile_agent_alpine
flavor: latest=false
registry: docker.io registry: docker.io
username_secret: DOCKERHUB_USERNAME username_secret: DOCKERHUB_USERNAME
password_secret: DOCKERHUB_TOKEN password_secret: DOCKERHUB_TOKEN
@@ -55,6 +56,7 @@ jobs:
# henrygd/beszel-agent-nvidia:slim # henrygd/beszel-agent-nvidia:slim
- image: henrygd/beszel-agent-nvidia - image: henrygd/beszel-agent-nvidia
dockerfile: ./internal/dockerfile_agent_nvidia_slim dockerfile: ./internal/dockerfile_agent_nvidia_slim
flavor: latest=false
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
registry: docker.io registry: docker.io
username_secret: DOCKERHUB_USERNAME username_secret: DOCKERHUB_USERNAME
@@ -123,6 +125,7 @@ jobs:
# ghcr.io/henrygd/beszel-agent-nvidia:slim # ghcr.io/henrygd/beszel-agent-nvidia:slim
- image: ghcr.io/${{ github.repository }}/beszel-agent-nvidia - image: ghcr.io/${{ github.repository }}/beszel-agent-nvidia
dockerfile: ./internal/dockerfile_agent_nvidia_slim dockerfile: ./internal/dockerfile_agent_nvidia_slim
flavor: latest=false
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
@@ -150,6 +153,7 @@ jobs:
# ghcr.io/henrygd/beszel-agent:alpine # ghcr.io/henrygd/beszel-agent:alpine
- image: ghcr.io/${{ github.repository }}/beszel-agent - image: ghcr.io/${{ github.repository }}/beszel-agent
dockerfile: ./internal/dockerfile_agent_alpine dockerfile: ./internal/dockerfile_agent_alpine
flavor: latest=false
registry: ghcr.io registry: ghcr.io
username: ${{ github.actor }} username: ${{ github.actor }}
password_secret: GITHUB_TOKEN password_secret: GITHUB_TOKEN
@@ -159,7 +163,7 @@ jobs:
type=semver,pattern={{major}}.{{minor}}-alpine type=semver,pattern={{major}}.{{minor}}-alpine
type=semver,pattern={{major}}-alpine type=semver,pattern={{major}}-alpine
# henrygd/beszel-agent (keep at bottom so it gets built after :alpine and gets the latest tag) # henrygd/beszel-agent
- image: henrygd/beszel-agent - image: henrygd/beszel-agent
dockerfile: ./internal/dockerfile_agent dockerfile: ./internal/dockerfile_agent
registry: docker.io registry: docker.io
@@ -200,6 +204,8 @@ jobs:
uses: docker/metadata-action@v6 uses: docker/metadata-action@v6
with: with:
images: ${{ matrix.image }} images: ${{ matrix.image }}
# Variant images must not overwrite the standard image's latest tag.
flavor: ${{ matrix.flavor || 'latest=auto' }}
tags: ${{ matrix.tags }} tags: ${{ matrix.tags }}
# https://github.com/docker/login-action # https://github.com/docker/login-action

View File

@@ -201,12 +201,9 @@ func mdraidSmartStatus(health mdraidHealth) string {
if health.mismatchCnt > 0 { if health.mismatchCnt > 0 {
return "WARNING" return "WARNING"
} }
// "check" scans for consistency problems without repairing mismatches. // "check" and "repair" are requested consistency scans, not evidence of
// With no mismatches, keep it green while reporting progress attributes. // array failure. With no health issues above, keep scrubbing green while
switch syncAction { // reporting the sync action and progress attributes.
case "repair":
return "WARNING"
}
switch state { switch state {
case "clean", "active", "active-idle", "write-pending", "read-auto", "readonly": case "clean", "active", "active-idle", "write-pending", "read-auto", "readonly":
return "PASSED" return "PASSED"

View File

@@ -174,8 +174,25 @@ func TestMdraidSmartStatus(t *testing.T) {
if got := mdraidSmartStatus(mdraidHealth{arrayState: "clean", mismatchCnt: 1}); got != "WARNING" { if got := mdraidSmartStatus(mdraidHealth{arrayState: "clean", mismatchCnt: 1}); got != "WARNING" {
t.Fatalf("mdraidSmartStatus(clean+mismatch) = %q, want WARNING", got) t.Fatalf("mdraidSmartStatus(clean+mismatch) = %q, want WARNING", got)
} }
if got := mdraidSmartStatus(mdraidHealth{arrayState: "clean", syncAction: "repair"}); got != "WARNING" { for _, tc := range []struct {
t.Fatalf("mdraidSmartStatus(repair) = %q, want WARNING", got) name string
health mdraidHealth
want string
}{
{"clean", mdraidHealth{arrayState: "clean"}, "PASSED"},
{"active", mdraidHealth{arrayState: "active"}, "PASSED"},
{"mismatch", mdraidHealth{arrayState: "active", mismatchCnt: 1}, "WARNING"},
{"degraded", mdraidHealth{arrayState: "active", degraded: 1}, "FAILED"},
{"faulty member", mdraidHealth{arrayState: "active", faultyDisks: 1}, "FAILED"},
{"inactive", mdraidHealth{arrayState: "inactive"}, "FAILED"},
{"unknown", mdraidHealth{arrayState: "unknown"}, "UNKNOWN"},
} {
t.Run("repair/"+tc.name, func(t *testing.T) {
tc.health.syncAction = "repair"
if got := mdraidSmartStatus(tc.health); got != tc.want {
t.Fatalf("mdraidSmartStatus(%+v) = %q, want %s", tc.health, got, tc.want)
}
})
} }
if got := mdraidSmartStatus(mdraidHealth{arrayState: "clean"}); got != "PASSED" { if got := mdraidSmartStatus(mdraidHealth{arrayState: "clean"}); got != "PASSED" {
t.Fatalf("mdraidSmartStatus(clean) = %q, want PASSED", got) t.Fatalf("mdraidSmartStatus(clean) = %q, want PASSED", got)

View File

@@ -11,6 +11,7 @@ import (
"strings" "strings"
"sync/atomic" "sync/atomic"
"testing" "testing"
"testing/synctest"
beszelTests "github.com/henrygd/beszel/internal/tests" beszelTests "github.com/henrygd/beszel/internal/tests"
pbTests "github.com/pocketbase/pocketbase/tests" pbTests "github.com/pocketbase/pocketbase/tests"
@@ -533,6 +534,20 @@ func TestSendTestNotification(t *testing.T) {
for _, url := range []string{localURL, "smtp://user:pass@127.0.0.1/?fromAddress=sender@example.com&toAddresses=recipient@example.com", "mqtt://127.0.0.1/topic"} { for _, url := range []string{localURL, "smtp://user:pass@127.0.0.1/?fromAddress=sender@example.com&toAddresses=recipient@example.com", "mqtt://127.0.0.1/topic"} {
scenarios = append(scenarios, beszelTests.ApiScenario{ scenarios = append(scenarios, beszelTests.ApiScenario{
BeforeTestFunc: func(tb testing.TB, _ *pbTests.TestApp, e *core.ServeEvent) {
if !strings.HasPrefix(url, "mqtt://") {
return
}
// Keep the real MQTT rejection path, but advance its library's
// fixed timeout using virtual time instead of waiting 10 seconds.
e.Router.BindFunc(func(re *core.RequestEvent) error {
var err error
synctest.Test(tb.(*testing.T), func(t *testing.T) {
err = re.Next()
})
return err
})
},
Name: "readonly cannot send to " + url, Name: "readonly cannot send to " + url,
Method: http.MethodPost, Method: http.MethodPost,
URL: "/api/beszel/test-notification", URL: "/api/beszel/test-notification",

View File

@@ -11,6 +11,7 @@ import (
"strings" "strings"
"sync/atomic" "sync/atomic"
"testing" "testing"
"testing/synctest"
"github.com/nicholas-fedor/shoutrrr/pkg/types" "github.com/nicholas-fedor/shoutrrr/pkg/types"
"golang.org/x/net/dns/dnsmessage" "golang.org/x/net/dns/dnsmessage"
@@ -178,39 +179,45 @@ func TestPublicNotificationTCP(t *testing.T) {
} { } {
t.Run(rawURL, func(t *testing.T) { t.Run(rawURL, func(t *testing.T) {
t.Parallel() t.Parallel()
// MQTT waits for a fixed library timeout even after a dial failure.
// Virtual time preserves the full send/cleanup path without that delay.
t.Run("internal destination", func(t *testing.T) { t.Run("internal destination", func(t *testing.T) {
err := sendPublicNotification(strings.ReplaceAll(rawURL, "HOST", "127.0.0.1"), "test") synctest.Test(t, func(t *testing.T) {
if !errors.Is(err, errInternalDestination) { err := sendPublicNotification(strings.ReplaceAll(rawURL, "HOST", "127.0.0.1"), "test")
t.Fatalf("expected blocked destination, got %v", err) if !errors.Is(err, errInternalDestination) {
} t.Fatalf("expected blocked destination, got %v", err)
}
})
}) })
t.Run("public destination uses injected dialer", func(t *testing.T) { t.Run("public destination uses injected dialer", func(t *testing.T) {
var calls atomic.Int32 synctest.Test(t, func(t *testing.T) {
stopped := errors.New("test dial stopped") var calls atomic.Int32
service, err := newPublicNotificationService(strings.ReplaceAll(rawURL, "HOST", "8.8.8.8"), types.SenderOptions{ stopped := errors.New("test dial stopped")
DialContext: func(ctx context.Context, network, address string) (net.Conn, error) { service, err := newPublicNotificationService(strings.ReplaceAll(rawURL, "HOST", "8.8.8.8"), types.SenderOptions{
calls.Add(1) DialContext: func(ctx context.Context, network, address string) (net.Conn, error) {
if network != "tcp" || !strings.HasPrefix(address, "8.8.8.8:") { calls.Add(1)
t.Errorf("unexpected dial: %s %s", network, address) if network != "tcp" || !strings.HasPrefix(address, "8.8.8.8:") {
} t.Errorf("unexpected dial: %s %s", network, address)
if err := checkNotificationAddress(address); err != nil { }
t.Error(err) if err := checkNotificationAddress(address); err != nil {
} t.Error(err)
return nil, stopped }
}, return nil, stopped
},
})
if err != nil {
t.Fatal(err)
}
if closer, ok := service.(io.Closer); ok {
defer closer.Close()
}
if err := service.Send("test", &types.Params{}); err == nil {
t.Fatal("expected dial failure")
}
if calls.Load() == 0 {
t.Fatal("custom dialer was not used")
}
}) })
if err != nil {
t.Fatal(err)
}
if closer, ok := service.(io.Closer); ok {
defer closer.Close()
}
if err := service.Send("test", &types.Params{}); err == nil {
t.Fatal("expected dial failure")
}
if calls.Load() == 0 {
t.Fatal("custom dialer was not used")
}
}) })
}) })
} }

View File

@@ -12,7 +12,7 @@ RUN apk add --no-cache ca-certificates && update-ca-certificates
# Build # Build
ARG TARGETOS TARGETARCH ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent
RUN rm -rf /tmp/* RUN rm -rf /tmp/*

View File

@@ -10,14 +10,14 @@ COPY . ./
# Build # Build
ARG TARGETOS TARGETARCH ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent
RUN rm -rf /tmp/* RUN rm -rf /tmp/*
# -------------------------- # --------------------------
# Final image: default scratch-based agent # Final image: default scratch-based agent
# -------------------------- # --------------------------
FROM alpine:3.23 FROM alpine:3.24
COPY --from=builder /agent /agent COPY --from=builder /agent /agent
# AMD GPU name lookup (used by agent on Linux when /usr/share/libdrm/amdgpu.ids is read) # AMD GPU name lookup (used by agent on Linux when /usr/share/libdrm/amdgpu.ids is read)

View File

@@ -10,13 +10,13 @@ COPY . ./
# Build # Build
ARG TARGETOS TARGETARCH ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent
# -------------------------- # --------------------------
# Final image # Final image
# Note: must cap_add: [CAP_PERFMON] and mount /dev/dri/ as volume # Note: must cap_add: [CAP_PERFMON] and mount /dev/dri/ as volume
# -------------------------- # --------------------------
FROM alpine:3.23 FROM alpine:3.24
COPY --from=builder /agent /agent COPY --from=builder /agent /agent

View File

@@ -10,7 +10,7 @@ COPY . ./
# Build # Build
ARG TARGETOS TARGETARCH ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -tags glibc -ldflags "-w -s" -o /agent ./internal/cmd/agent RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -tags glibc -ldflags "-w -s" -o /agent ./internal/cmd/agent
# -------------------------- # --------------------------
# Smartmontools builder stage # Smartmontools builder stage

View File

@@ -17,7 +17,7 @@ RUN set -eux; \
if [ "$TARGETARCH" = "arm" ] && [ -n "$TARGETVARIANT" ]; then \ if [ "$TARGETARCH" = "arm" ] && [ -n "$TARGETVARIANT" ]; then \
export GOARM="${TARGETVARIANT#v}"; \ export GOARM="${TARGETVARIANT#v}"; \
fi; \ fi; \
CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH \ CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH \
go build -tags glibc -ldflags "-w -s" -o /agent ./internal/cmd/agent go build -tags glibc -ldflags "-w -s" -o /agent ./internal/cmd/agent
# -------------------------- # --------------------------

View File

@@ -17,7 +17,7 @@ RUN update-ca-certificates
# Build # Build
ARG TARGETOS TARGETARCH ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /beszel ./internal/cmd/hub RUN CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /beszel ./internal/cmd/hub
# ? ------------------------- # ? -------------------------
FROM scratch FROM scratch

View File

@@ -978,11 +978,18 @@ func TestAgentWebSocketIntegration(t *testing.T) {
} }
} }
// Verify system status // A connected WebSocket does not mean the hub has finished verifying
updatedSystemRecord, err := testApp.FindRecordById("systems", systemRecord.Id) // the agent and updating the system. Wait for the database state rather
require.NoError(t, err) // than assuming that work completes within a fixed sleep under load.
status := updatedSystemRecord.GetString("status") var status string
assert.Equal(t, tc.expectSystemStatus, status, "System status should match expected value") require.EventuallyWithT(t, func(c *assert.CollectT) {
updatedSystemRecord, err := testApp.FindRecordById("systems", systemRecord.Id)
if !assert.NoError(c, err) {
return
}
status = updatedSystemRecord.GetString("status")
assert.Equal(c, tc.expectSystemStatus, status, "System status should match expected value")
}, 5*time.Second, 20*time.Millisecond)
t.Logf("%s - System status: %s, Fingerprint: %s", tc.description, status, finalFingerprint) t.Logf("%s - System status: %s, Fingerprint: %s", tc.description, status, finalFingerprint)
}) })
@@ -1142,42 +1149,43 @@ func TestMultipleSystemsWithSameUniversalToken(t *testing.T) {
// Verify system creation/reuse behavior // Verify system creation/reuse behavior
if tc.expectConnection { if tc.expectConnection {
// Count systems after connection expectedSystemsAfter := systemsBeforeCount
systemsAfter, err := testApp.FindRecordsByFilter("systems", "users ~ {:userId}", "", -1, 0, map[string]any{"userId": userRecord.Id})
require.NoError(t, err)
systemsAfterCount := len(systemsAfter)
if tc.expectNewSystem { if tc.expectNewSystem {
// Should have created a new system expectedSystemsAfter++
systemCount++ systemCount++
assert.Equal(t, systemsBeforeCount+1, systemsAfterCount, "Should have created a new system")
assert.Equal(t, systemCount, systemsAfterCount, "Total system count should match expected")
} else {
// Should have reused existing system
assert.Equal(t, systemsBeforeCount, systemsAfterCount, "Should not have created a new system")
assert.Equal(t, systemCount, systemsAfterCount, "Total system count should remain the same")
} }
time.Sleep(20 * time.Millisecond) // WebSocket connection precedes the hub's asynchronous system
// setup. Re-read all database state until setup is complete.
var systemId, status string
require.EventuallyWithT(t, func(c *assert.CollectT) {
systemsAfter, err := testApp.FindRecordsByFilter("systems", "users ~ {:userId}", "", -1, 0, map[string]any{"userId": userRecord.Id})
if !assert.NoError(c, err) {
return
}
assert.Len(c, systemsAfter, expectedSystemsAfter, "System creation/reuse should match expected behavior")
assert.Len(c, systemsAfter, systemCount, "Total system count should match expected")
// Verify that a fingerprint record exists for this fingerprint fingerprints, err := testApp.FindRecordsByFilter("fingerprints", "token = {:token} && fingerprint = {:fingerprint}", "", -1, 0, map[string]any{
fingerprints, err := testApp.FindRecordsByFilter("fingerprints", "token = {:token} && fingerprint = {:fingerprint}", "", -1, 0, map[string]any{ "token": universalToken,
"token": universalToken, "fingerprint": tc.agentFingerprint,
"fingerprint": tc.agentFingerprint, })
}) if !assert.NoError(c, err) || !assert.Len(c, fingerprints, 1, "Should have exactly one fingerprint record for this token+fingerprint combination") {
require.NoError(t, err) return
require.Len(t, fingerprints, 1, "Should have exactly one fingerprint record for this token+fingerprint combination") }
fingerprint := fingerprints[0] fingerprint := fingerprints[0]
assert.Equal(t, universalToken, fingerprint.GetString("token"), "Fingerprint should have the universal token") assert.Equal(c, universalToken, fingerprint.GetString("token"), "Fingerprint should have the universal token")
assert.Equal(t, tc.agentFingerprint, fingerprint.GetString("fingerprint"), "Fingerprint should match agent's fingerprint") assert.Equal(c, tc.agentFingerprint, fingerprint.GetString("fingerprint"), "Fingerprint should match agent's fingerprint")
// Verify system status systemId = fingerprint.GetString("system")
systemId := fingerprint.GetString("system") system, err := testApp.FindRecordById("systems", systemId)
system, err := testApp.FindRecordById("systems", systemId) if !assert.NoError(c, err) {
require.NoError(t, err) return
status := system.GetString("status") }
assert.Equal(t, tc.expectSystemStatus, status, "System status should match expected value") status = system.GetString("status")
assert.Equal(c, tc.expectSystemStatus, status, "System status should match expected value")
}, 5*time.Second, 20*time.Millisecond)
t.Logf("%s - System ID: %s, Status: %s, New System: %v", tc.description, systemId, status, tc.expectNewSystem) t.Logf("%s - System ID: %s, Status: %s, New System: %v", tc.description, systemId, status, tc.expectNewSystem)
} }

View File

@@ -0,0 +1,159 @@
//go:build testing
package systems
import (
"context"
"crypto/ed25519"
"crypto/rand"
"net"
"sync/atomic"
"testing"
"time"
"github.com/fxamacker/cbor/v2"
"github.com/henrygd/beszel/internal/common"
"github.com/henrygd/beszel/internal/entities/monitor"
esystem "github.com/henrygd/beszel/internal/entities/system"
"github.com/henrygd/beszel/internal/hub/expirymap"
"github.com/pocketbase/pocketbase/core"
"github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh"
)
func TestSSHNetworkMonitorReconnectSync(t *testing.T) {
sys, app := newTestSystemWithHub(t)
sys.manager.zfsFetchMap = expirymap.New[zfsFetchState](time.Hour)
t.Cleanup(sys.manager.zfsFetchMap.StopCleaner)
sys.ctx = context.Background()
sys.Status = up
_, key, err := ed25519.GenerateKey(rand.Reader)
require.NoError(t, err)
signer, err := ssh.NewSignerFromKey(key)
require.NoError(t, err)
config := &ssh.ServerConfig{NoClientAuth: true, ServerVersion: "SSH-2.0-beszel_0.20.0"}
config.AddHostKey(signer)
listener, err := net.Listen("tcp", "127.0.0.1:0")
require.NoError(t, err)
t.Cleanup(func() { _ = listener.Close() })
sys.Host, sys.Port, err = net.SplitHostPort(listener.Addr().String())
require.NoError(t, err)
sys.manager.sshConfig = &ssh.ClientConfig{User: "test", HostKeyCallback: ssh.InsecureIgnoreHostKey(), Timeout: time.Second}
t.Cleanup(sys.closeSSHConnection)
requests := make(chan monitor.SyncRequest, 10)
var failSync atomic.Bool
go func() {
for {
conn, err := listener.Accept()
if err != nil {
return
}
go func() {
server, channels, reqs, err := ssh.NewServerConn(conn, config)
if err != nil {
_ = conn.Close()
return
}
defer server.Close()
go ssh.DiscardRequests(reqs)
for channel := range channels {
ch, reqs, err := channel.Accept()
if err != nil {
return
}
go func() {
defer ch.Close()
for req := range reqs {
if req.Type != "shell" {
_ = req.Reply(false, nil)
continue
}
_ = req.Reply(true, nil)
var request common.HubRequest[cbor.RawMessage]
if cbor.NewDecoder(ch).Decode(&request) != nil {
return
}
response := common.AgentResponse{}
switch request.Action {
case common.GetData:
response.SystemData = &esystem.CombinedData{}
case common.SyncNetworkMonitors:
var syncReq monitor.SyncRequest
if cbor.Unmarshal(request.Data, &syncReq) != nil {
return
}
requests <- syncReq
if failSync.Load() {
response.Error = "test sync failure"
} else {
response.Data, _ = cbor.Marshal(monitor.SyncResponse{})
}
}
_ = cbor.NewEncoder(ch).Encode(response)
_, _ = ch.SendRequest("exit-status", false, ssh.Marshal(struct{ Status uint32 }{0}))
return
}
}()
}
}()
}
}()
collection, err := app.FindCachedCollectionByNameOrId("network_monitors")
require.NoError(t, err)
probe := core.NewRecord(collection)
probe.Load(map[string]any{"system": sys.Id, "target": "localhost", "protocol": "tcp", "port": 80, "interval": 60, "enabled": true})
require.NoError(t, app.SaveNoValidate(probe))
fetch := func() {
t.Helper()
_, err := sys.fetchDataFromAgent(common.DataRequestOptions{})
require.NoError(t, err, "monitor sync failure must not fail stats fetching")
}
receive := func() monitor.SyncRequest {
t.Helper()
select {
case req := <-requests:
require.Equal(t, monitor.SyncActionReplace, req.Action)
return req
case <-time.After(time.Second):
t.Fatal("missing full monitor sync")
return monitor.SyncRequest{}
}
}
fetch()
require.Equal(t, probe.Id, receive().Configs[0].ID)
require.False(t, sys.monitorsNeedSync.Load())
fetch()
require.Empty(t, requests, "steady-state fetch must not resync")
// Simulate loss of the agent process/connection and its in-memory monitors.
require.NoError(t, sys.client.Load().Close())
fetch()
require.Equal(t, probe.Id, receive().Configs[0].ID)
require.False(t, sys.monitorsNeedSync.Load())
// Failed replacements are retried on the next successful stats fetch.
require.NoError(t, sys.client.Load().Close())
failSync.Store(true)
fetch()
receive()
require.True(t, sys.monitorsNeedSync.Load())
failSync.Store(false)
fetch()
receive()
require.False(t, sys.monitorsNeedSync.Load())
probe.Set("enabled", false)
require.NoError(t, app.SaveNoValidate(probe))
require.NoError(t, sys.client.Load().Close())
fetch()
require.Empty(t, receive().Configs, "empty replacement must clear stale monitors")
}
func TestPendingNetworkMonitorSyncQueryFailure(t *testing.T) {
sys, app := newTestSystemWithHub(t)
_, err := app.DB().NewQuery("DROP TABLE network_monitors").Execute()
require.NoError(t, err)
sys.monitorsNeedSync.Store(true)
sys.syncPendingNetworkMonitors()
require.True(t, sys.monitorsNeedSync.Load())
}

View File

@@ -6,6 +6,7 @@ import (
"net/http" "net/http"
"net/http/httptest" "net/http/httptest"
"strings" "strings"
"sync/atomic"
"testing" "testing"
"time" "time"
@@ -13,6 +14,7 @@ import (
"github.com/fxamacker/cbor/v2" "github.com/fxamacker/cbor/v2"
"github.com/henrygd/beszel/internal/common" "github.com/henrygd/beszel/internal/common"
"github.com/henrygd/beszel/internal/entities/monitor" "github.com/henrygd/beszel/internal/entities/monitor"
esystem "github.com/henrygd/beszel/internal/entities/system"
"github.com/henrygd/beszel/internal/hub/ws" "github.com/henrygd/beszel/internal/hub/ws"
"github.com/lxzan/gws" "github.com/lxzan/gws"
"github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/core"
@@ -22,17 +24,31 @@ import (
type monitorSyncClient struct { type monitorSyncClient struct {
gws.BuiltinEventHandler gws.BuiltinEventHandler
requests chan common.HubRequest[monitor.SyncRequest] requests chan common.HubRequest[monitor.SyncRequest]
failSync atomic.Bool
} }
func (c *monitorSyncClient) OnMessage(conn *gws.Conn, message *gws.Message) { func (c *monitorSyncClient) OnMessage(conn *gws.Conn, message *gws.Message) {
defer message.Close() defer message.Close()
var req common.HubRequest[monitor.SyncRequest] var req common.HubRequest[cbor.RawMessage]
if err := cbor.Unmarshal(message.Bytes(), &req); err != nil { if err := cbor.Unmarshal(message.Bytes(), &req); err != nil {
return return
} }
c.requests <- req resp := common.AgentResponse{Id: req.Id}
data, _ := cbor.Marshal(monitor.SyncResponse{}) if req.Action == common.GetData {
response, _ := cbor.Marshal(common.AgentResponse{Id: req.Id, Data: data}) resp.SystemData = &esystem.CombinedData{}
} else {
var data monitor.SyncRequest
if err := cbor.Unmarshal(req.Data, &data); err != nil {
return
}
c.requests <- common.HubRequest[monitor.SyncRequest]{Id: req.Id, Action: req.Action, Data: data}
if c.failSync.Load() {
resp.Error = "test sync failure"
} else {
resp.Data, _ = cbor.Marshal(monitor.SyncResponse{})
}
}
response, _ := cbor.Marshal(resp)
_ = conn.WriteMessage(gws.OpcodeBinary, response) _ = conn.WriteMessage(gws.OpcodeBinary, response)
} }
@@ -57,7 +73,7 @@ func TestNetworkMonitorSyncSkipsOlderAgents(t *testing.T) {
} }
func TestNetworkMonitorReconnectSync(t *testing.T) { func TestNetworkMonitorReconnectSync(t *testing.T) {
for _, change := range []string{"delete", "disable"} { for _, change := range []string{"delete", "disable", "retry"} {
t.Run(change, func(t *testing.T) { t.Run(change, func(t *testing.T) {
sys, app := newTestSystemWithHub(t) sys, app := newTestSystemWithHub(t)
record, err := app.FindRecordById("systems", sys.Id) record, err := app.FindRecordById("systems", sys.Id)
@@ -120,9 +136,33 @@ func TestNetworkMonitorReconnectSync(t *testing.T) {
} }
} }
client.failSync.Store(change == "retry")
initial := connect() initial := connect()
require.Len(t, initial.Configs, 1) require.Len(t, initial.Configs, 1)
require.Equal(t, probe.Id, initial.Configs[0].ID) require.Equal(t, probe.Id, initial.Configs[0].ID)
if change == "retry" {
system, err := sm.GetSystem(sys.Id)
require.NoError(t, err)
require.Eventually(t, system.monitorsNeedSync.Load, time.Second, time.Millisecond)
// A second failed sync must not fail the stats fetch or clear pending state.
_, err = system.fetchDataFromAgent(common.DataRequestOptions{})
require.NoError(t, err)
require.True(t, system.monitorsNeedSync.Load())
require.Len(t, client.requests, 1)
<-client.requests
client.failSync.Store(false)
_, err = system.fetchDataFromAgent(common.DataRequestOptions{})
require.NoError(t, err)
require.False(t, system.monitorsNeedSync.Load())
require.Len(t, client.requests, 1)
retry := <-client.requests
require.Equal(t, monitor.SyncActionReplace, retry.Data.Action)
require.Equal(t, initial.Configs, retry.Data.Configs)
_, err = system.fetchDataFromAgent(common.DataRequestOptions{})
require.NoError(t, err)
require.Empty(t, client.requests, "successful sync must not repeat on every fetch")
return
}
require.NoError(t, sm.RemoveSystem(sys.Id)) require.NoError(t, sm.RemoveSystem(sys.Id))
if change == "delete" { if change == "delete" {
require.NoError(t, app.Delete(probe)) require.NoError(t, app.Delete(probe))

View File

@@ -2,6 +2,7 @@ package systems
import ( import (
"context" "context"
"fmt"
"time" "time"
"github.com/henrygd/beszel" "github.com/henrygd/beszel"
@@ -9,6 +10,27 @@ import (
"github.com/henrygd/beszel/internal/entities/monitor" "github.com/henrygd/beszel/internal/entities/monitor"
) )
// syncPendingNetworkMonitors runs on WebSocket connect and after successful stats
// fetches. Failed syncs retry on the next update without taking the system down.
func (sys *System) syncPendingNetworkMonitors() {
if !sys.monitorsNeedSync.Swap(false) {
return
}
if err := sys.syncAllNetworkMonitors(); err != nil {
sys.monitorsNeedSync.Store(true)
sys.manager.hub.Logger().Warn("failed to sync monitors to agent", "system", sys.Id, "err", err)
}
}
func (sys *System) syncAllNetworkMonitors() error {
configs, err := sys.manager.GetMonitorConfigsForSystem(sys.Id)
if err != nil {
return fmt.Errorf("failed to load monitors: %w", err)
}
// An empty set must also replace probes retained across a disconnect.
return sys.SyncNetworkMonitors(configs)
}
// SyncNetworkMonitors sends monitor configurations to the agent. // SyncNetworkMonitors sends monitor configurations to the agent.
func (sys *System) SyncNetworkMonitors(configs []monitor.Config) error { func (sys *System) SyncNetworkMonitors(configs []monitor.Config) error {
_, err := sys.syncNetworkMonitors(monitor.SyncRequest{Action: monitor.SyncActionReplace, Configs: configs}) _, err := sys.syncNetworkMonitors(monitor.SyncRequest{Action: monitor.SyncActionReplace, Configs: configs})

View File

@@ -56,6 +56,9 @@ type System struct {
smartInterval time.Duration // Interval for periodic SMART data updates smartInterval time.Duration // Interval for periodic SMART data updates
zfsFetching atomic.Bool // True if ZFS pools are currently being fetched zfsFetching atomic.Bool // True if ZFS pools are currently being fetched
zfsInterval time.Duration // Interval for periodic ZFS detail data updates zfsInterval time.Duration // Interval for periodic ZFS detail data updates
// A fresh connection needs a full monitor configuration sync.
monitorsNeedSync atomic.Bool
// Serialize persistence from scheduled updates and resumes through commit. // Serialize persistence from scheduled updates and resumes through commit.
recordsMu sync.Mutex recordsMu sync.Mutex
// Protected by recordsMu; realtime reads don't consume probes. // Protected by recordsMu; realtime reads don't consume probes.
@@ -630,7 +633,10 @@ func (sys *System) request(ctx context.Context, action common.WebSocketAction, r
err := sys.sshTransport.RequestWithRetry(ctx, action, req, dest, 1) err := sys.sshTransport.RequestWithRetry(ctx, action, req, dest, 1)
// Keep legacy SSH client/version fields in sync for other code paths. // Keep legacy SSH client/version fields in sync for other code paths.
if sys.sshTransport != nil { if sys.sshTransport != nil {
sys.client.Store(sys.sshTransport.GetClient()) client := sys.sshTransport.GetClient()
if previous := sys.client.Swap(client); client != nil && client != previous {
sys.monitorsNeedSync.Store(true)
}
sys.agentVersion = sys.sshTransport.GetAgentVersion() sys.agentVersion = sys.sshTransport.GetAgentVersion()
} }
return err return err
@@ -688,6 +694,7 @@ func (sys *System) fetchDataFromAgent(options common.DataRequestOptions) (*syste
if sys.WsConn != nil && sys.WsConn.IsConnected() { if sys.WsConn != nil && sys.WsConn.IsConnected() {
wsData, err := sys.fetchDataViaWebSocket(options) wsData, err := sys.fetchDataViaWebSocket(options)
if err == nil { if err == nil {
sys.syncPendingNetworkMonitors()
return wsData, nil return wsData, nil
} }
// close the WebSocket connection if error and try SSH // close the WebSocket connection if error and try SSH
@@ -698,6 +705,7 @@ func (sys *System) fetchDataFromAgent(options common.DataRequestOptions) (*syste
if err != nil { if err != nil {
return nil, err return nil, err
} }
sys.syncPendingNetworkMonitors()
return sshData, nil return sshData, nil
} }
@@ -932,6 +940,7 @@ func (s *System) createSSHClient() error {
return err return err
} }
s.agentVersion, _ = extractAgentVersion(string(client.Conn.ServerVersion())) s.agentVersion, _ = extractAgentVersion(string(client.Conn.ServerVersion()))
s.monitorsNeedSync.Store(true)
s.manager.resetFailedSmartFetchState(s.Id) s.manager.resetFailedSmartFetchState(s.Id)
s.manager.resetFailedZfsFetchState(s.Id) s.manager.resetFailedZfsFetchState(s.Id)
return nil return nil

View File

@@ -349,23 +349,14 @@ func (sm *SystemManager) AddWebSocketSystem(systemId string, agentVersion semver
system := sm.NewSystem(systemId) system := sm.NewSystem(systemId)
system.WsConn = wsConn system.WsConn = wsConn
system.agentVersion = agentVersion system.agentVersion = agentVersion
system.monitorsNeedSync.Store(true)
if err := sm.AddRecord(systemRecord, system); err != nil { if err := sm.AddRecord(systemRecord, system); err != nil {
return err return err
} }
// Sync network monitors to the newly connected agent // Sync network monitors to the newly connected agent
go func() { go system.syncPendingNetworkMonitors()
configs, err := sm.GetMonitorConfigsForSystem(systemId)
if err != nil {
sm.hub.Logger().Warn("failed to load monitors for agent", "system", systemId, "err", err)
return
}
// An empty set must also replace any probes retained across a disconnect.
if err := system.SyncNetworkMonitors(configs); err != nil {
sm.hub.Logger().Warn("failed to sync monitors to agent", "system", systemId, "err", err)
}
}()
return nil return nil
} }

View File

@@ -1057,6 +1057,15 @@ func init() {
"required": true, "required": true,
"system": false, "system": false,
"type": "number" "type": "number"
},
{
"hidden": false,
"id": "bool2084032502",
"name": "updatable",
"presentable": false,
"required": false,
"system": false,
"type": "bool"
} }
], ],
"indexes": [ "indexes": [

View File

@@ -1,27 +0,0 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
c, err := app.FindCollectionByNameOrId("zfs_pools")
if err != nil {
return err
}
c.Fields.Add(&core.TextField{Name: "display_name"})
c.Fields.Add(&core.BoolField{Name: "raw"})
return app.Save(c)
}, func(app core.App) error {
c, err := app.FindCollectionByNameOrId("zfs_pools")
if err != nil {
return err
}
c.Fields.RemoveByName("display_name")
c.Fields.RemoveByName("raw")
return app.Save(c)
})
}

View File

@@ -1,24 +0,0 @@
package migrations
import (
"github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations"
)
func init() {
m.Register(func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("containers")
if err != nil {
return err
}
collection.Fields.Add(&core.BoolField{Name: "updatable"})
return app.Save(collection)
}, func(app core.App) error {
collection, err := app.FindCollectionByNameOrId("containers")
if err != nil {
return err
}
collection.Fields.RemoveByName("updatable")
return app.Save(collection)
})
}

View File

@@ -59,7 +59,11 @@ export const containerChartCols: ColumnDef<ContainerRecord>[] = [
const allSystems = $allSystemsById.get() const allSystems = $allSystemsById.get()
const systemNameA = allSystems[a.original.system]?.name ?? "" const systemNameA = allSystems[a.original.system]?.name ?? ""
const systemNameB = allSystems[b.original.system]?.name ?? "" const systemNameB = allSystems[b.original.system]?.name ?? ""
return systemNameA.localeCompare(systemNameB) const primary = systemNameA.localeCompare(systemNameB)
if (primary !== 0) {
return primary
}
return a.original.name.localeCompare(b.original.name)
}, },
header: ({ column }) => <HeaderButton column={column} name={t`System`} Icon={ServerIcon} />, header: ({ column }) => <HeaderButton column={column} name={t`System`} Icon={ServerIcon} />,
cell: ({ getValue }) => { cell: ({ getValue }) => {

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ar\n" "Language: ar\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:46\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Arabic\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" "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"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: bg\n" "Language: bg\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Bulgarian\n" "Language-Team: Bulgarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: cs\n" "Language: cs\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Czech\n" "Language-Team: Czech\n"
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n" "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: da\n" "Language: da\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Danish\n" "Language-Team: Danish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n" "Language: de\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:46\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: German\n" "Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: el\n" "Language: el\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Greek\n" "Language-Team: Greek\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: es\n" "Language: es\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Spanish\n" "Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: fa\n" "Language: fa\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:46\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Persian\n" "Language-Team: Persian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: fr\n" "Language: fr\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: French\n" "Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: he\n" "Language: he\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Hebrew\n" "Language-Team: Hebrew\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n==2 ? 1 : 2);\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : n==2 ? 1 : 2);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: hr\n" "Language: hr\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:46\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Croatian\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" "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"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: hu\n" "Language: hu\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Hungarian\n" "Language-Team: Hungarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: id\n" "Language: id\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:46\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Indonesian\n" "Language-Team: Indonesian\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: it\n" "Language: it\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Italian\n" "Language-Team: Italian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ja\n" "Language: ja\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Japanese\n" "Language-Team: Japanese\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ko\n" "Language: ko\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Korean\n" "Language-Team: Korean\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: nl\n" "Language: nl\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Dutch\n" "Language-Team: Dutch\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: no\n" "Language: no\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Norwegian\n" "Language-Team: Norwegian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: pl\n" "Language: pl\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Polish\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" "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"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: pt\n" "Language: pt\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Portuguese\n" "Language-Team: Portuguese\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ro\n" "Language: ro\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 00:33\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Romanian\n" "Language-Team: Romanian\n"
"Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100>0 && n%100<20)) ? 1 : 2);\n" "Plural-Forms: nplurals=3; plural=(n==1 ? 0 : (n==0 || (n%100>0 && n%100<20)) ? 1 : 2);\n"
@@ -30,6 +30,12 @@ msgstr ""
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "{0} din {1} rând(uri) selectat(e)." msgstr "{0} din {1} rând(uri) selectat(e)."
#. placeholder {0}: selectedSystemIds.size
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "{0} selected"
msgstr ""
#: src/components/routes/system/info-bar.tsx #: src/components/routes/system/info-bar.tsx
msgid "{cores, plural, one {# core} other {# cores}}" msgid "{cores, plural, one {# core} other {# cores}}"
msgstr "" msgstr ""
@@ -61,7 +67,7 @@ msgstr "1 oră"
#. Load average #. Load average
#: src/components/routes/system/charts/load-average-chart.tsx #: src/components/routes/system/charts/load-average-chart.tsx
msgid "1 min" msgid "1 min"
msgstr "" msgstr "1 min"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 minute" msgid "1 minute"
@@ -78,7 +84,7 @@ msgstr "12 ore"
#. Load average #. Load average
#: src/components/routes/system/charts/load-average-chart.tsx #: src/components/routes/system/charts/load-average-chart.tsx
msgid "15 min" msgid "15 min"
msgstr "" msgstr "15 min"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "24 hours" msgid "24 hours"
@@ -91,7 +97,7 @@ msgstr "30 zile"
#. Load average #. Load average
#: src/components/routes/system/charts/load-average-chart.tsx #: src/components/routes/system/charts/load-average-chart.tsx
msgid "5 min" msgid "5 min"
msgstr "" msgstr "5 min"
#. Table column #. Table column
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
@@ -121,6 +127,10 @@ msgstr "Stare activă"
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Add {foo}" msgid "Add {foo}"
@@ -142,7 +152,7 @@ msgstr "Reglaţi lăţimea aspectului principal"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Admin" msgid "Admin"
msgstr "" msgstr "Admin"
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "After" msgid "After"
@@ -154,7 +164,7 @@ msgstr "După setarea variabilelor de mediu, reporniţi centrul Beszel pentru ca
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Agent" msgid "Agent"
msgstr "" msgstr "Agent"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
@@ -188,6 +198,7 @@ msgstr "Toate sistemele"
msgid "Are you sure you want to delete {name}?" msgid "Are you sure you want to delete {name}?"
msgstr "Sigur vrei să ștergi {name}?" msgstr "Sigur vrei să ștergi {name}?"
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Are you sure?" msgid "Are you sure?"
msgstr "Ești sigur?" msgstr "Ești sigur?"
@@ -245,6 +256,14 @@ msgstr "Utilizarea medie a {0}"
msgid "Average utilization of GPU engines" msgid "Average utilization of GPU engines"
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Average, minimum, and maximum response time"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Avg 1h"
msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
@@ -306,6 +325,19 @@ msgstr "Biți (Kbps, Mbps, Gbps)"
msgid "Boot state" msgid "Boot state"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Bulk Add"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Bulk Add {foo}"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Bulk copy"
msgstr ""
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)" msgid "Bytes (KB/s, MB/s, GB/s)"
@@ -327,6 +359,7 @@ msgstr ""
msgid "Can stop" msgid "Can stop"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
@@ -348,7 +381,7 @@ msgstr "Atenție - posibilă pierdere de date"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Celsius (°C)" msgid "Celsius (°C)"
msgstr "" msgstr "Celsius (°C)"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Change display units for metrics." msgid "Change display units for metrics."
@@ -396,6 +429,7 @@ msgid "Checksum errors"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
@@ -403,6 +437,14 @@ msgstr ""
msgid "Clear" msgid "Clear"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Clear all"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Clear matches"
msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
msgid "Click on a container to view more information." msgid "Click on a container to view more information."
msgstr "" msgstr ""
@@ -432,6 +474,10 @@ msgstr ""
msgid "Configure how you receive alert notifications." msgid "Configure how you receive alert notifications."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Configure response monitoring from this agent."
msgstr ""
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Confirm password" msgid "Confirm password"
@@ -457,6 +503,7 @@ msgstr ""
msgid "Containers" msgid "Containers"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
@@ -517,6 +564,10 @@ msgstr ""
msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>." msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>."
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Copy to system"
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Copy YAML" msgid "Copy YAML"
msgstr "" msgstr ""
@@ -530,7 +581,7 @@ msgstr ""
#: src/components/systemd-table/systemd-table-columns.tsx #: src/components/systemd-table/systemd-table-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "CPU" msgid "CPU"
msgstr "" msgstr "CPU"
#: src/components/routes/system/cpu-sheet.tsx #: src/components/routes/system/cpu-sheet.tsx
msgid "CPU Cores" msgid "CPU Cores"
@@ -630,6 +681,7 @@ msgstr ""
msgid "Default time period" msgid "Default time period"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
@@ -718,12 +770,14 @@ msgstr "Descarcă"
msgid "Duration" msgid "Duration"
msgstr "Durată" msgstr "Durată"
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Edit" msgid "Edit"
msgstr "Editează" msgstr "Editează"
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Edit {foo}" msgid "Edit {foo}"
msgstr "Editează {foo}" msgstr "Editează {foo}"
@@ -732,7 +786,7 @@ msgstr "Editează {foo}"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
#: src/components/login/otp-forms.tsx #: src/components/login/otp-forms.tsx
msgid "Email" msgid "Email"
msgstr "" msgstr "Email"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Email notifications" msgid "Email notifications"
@@ -772,6 +826,11 @@ msgstr ""
msgid "Ephemeral" msgid "Ephemeral"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx #: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
@@ -844,6 +903,11 @@ msgstr ""
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Failed to delete monitors."
msgstr ""
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
@@ -862,6 +926,10 @@ msgstr ""
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Failed to update monitors."
msgstr ""
#. placeholder {0}: statusTotals[ServiceStatus.Failed] #. placeholder {0}: statusTotals[ServiceStatus.Failed]
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Failed: {0}" msgid "Failed: {0}"
@@ -872,6 +940,7 @@ msgid "Fans"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system/chart-card.tsx #: src/components/routes/system/chart-card.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
@@ -924,7 +993,7 @@ msgstr ""
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Global" msgid "Global"
msgstr "" msgstr "Global"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "GPU" msgid "GPU"
@@ -1011,14 +1080,25 @@ msgctxt "Docker image"
msgid "Image" msgid "Image"
msgstr "Imagine" msgstr "Imagine"
#: src/components/containers-table/containers-table-columns.tsx
#: src/components/containers-table/containers-table-columns.tsx
msgctxt "Docker image"
msgid "Image update available"
msgstr ""
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Inactive" msgid "Inactive"
msgstr "Inactiv" msgstr "Inactiv"
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Interval" msgid "Interval"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Interval (seconds)"
msgstr ""
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Invalid email address." msgid "Invalid email address."
msgstr "" msgstr ""
@@ -1097,6 +1177,15 @@ msgstr "Jurnale"
msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table." msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table."
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgctxt "Packet loss"
msgid "Loss"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Loss 1h"
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Main PID" msgid "Main PID"
msgstr "" msgstr ""
@@ -1115,6 +1204,10 @@ msgstr ""
msgid "Max 1 min" msgid "Max 1 min"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Max 1h"
msgstr ""
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/routes/system/info-bar.tsx #: src/components/routes/system/info-bar.tsx
#: src/components/systemd-table/systemd-table-columns.tsx #: src/components/systemd-table/systemd-table-columns.tsx
@@ -1141,9 +1234,23 @@ msgstr "Memorie Utilizată"
msgid "Memory usage of containers" msgid "Memory usage of containers"
msgstr "Utilizarea memoriei de către containere" msgstr "Utilizarea memoriei de către containere"
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Min 1h"
msgstr ""
#. Device model #. Device model
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
msgid "Model" msgid "Model"
msgstr "Model"
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Monitor"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Monitors created"
msgstr "" msgstr ""
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
@@ -1163,6 +1270,29 @@ msgstr "Nume"
msgid "Net" msgid "Net"
msgstr "Rețea" msgstr "Rețea"
#: src/components/routes/system.tsx
msgid "Network"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Network Monitor"
msgstr ""
#: src/lib/alerts.ts
msgid "Network Monitor Loss"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
#: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/monitors.tsx
msgid "Network Monitors"
msgstr ""
#: src/components/routes/system/charts/network-charts.tsx #: src/components/routes/system/charts/network-charts.tsx
msgid "Network traffic of containers" msgid "Network traffic of containers"
msgstr "Traficul de rețea al containerelor" msgstr "Traficul de rețea al containerelor"
@@ -1197,6 +1327,7 @@ msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
@@ -1207,6 +1338,7 @@ msgstr ""
msgid "No S.M.A.R.T. attributes available for this device." msgid "No S.M.A.R.T. attributes available for this device."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "No systems found." msgid "No systems found."
@@ -1238,6 +1370,11 @@ msgstr ""
msgid "One or more containers are unhealthy" msgid "One or more containers are unhealthy"
msgstr "" msgstr ""
#. placeholder {0}: alert.value
#: src/components/active-alerts.tsx
msgid "One or more monitors exceed {0}% loss"
msgstr ""
#: src/lib/alerts.ts #: src/lib/alerts.ts
msgid "One or more services are in a failed state" msgid "One or more services are in a failed state"
msgstr "" msgstr ""
@@ -1251,6 +1388,7 @@ msgstr ""
msgid "One-time password" msgid "One-time password"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
@@ -1272,6 +1410,11 @@ msgstr "Altele"
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Packet loss (%)"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
@@ -1309,6 +1452,7 @@ msgstr ""
msgid "Past" msgid "Past"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Pause" msgid "Pause"
msgstr "Suspendare" msgstr "Suspendare"
@@ -1392,8 +1536,9 @@ msgid "Pool Usage"
msgstr "" msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Port" msgid "Port"
msgstr "" msgstr "Port"
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
msgctxt "Container ports" msgctxt "Container ports"
@@ -1418,6 +1563,11 @@ msgstr ""
msgid "Process started" msgid "Process started"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Protocol"
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Public key" msgid "Public key"
msgstr "" msgstr ""
@@ -1503,10 +1653,20 @@ msgstr ""
msgid "Resolved" msgid "Resolved"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Response"
msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Response time monitoring from agents."
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Restarts" msgid "Restarts"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Resume" msgid "Resume"
msgstr "" msgstr ""
@@ -1539,6 +1699,7 @@ msgid "S.M.A.R.T. Self-Test"
msgstr "" msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Save {foo}" msgid "Save {foo}"
msgstr "" msgstr ""
@@ -1575,6 +1736,11 @@ msgstr "Caută"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Search systems"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Seconds between pings (default: 60)" msgid "Seconds between pings (default: 60)"
msgstr "" msgstr ""
@@ -1587,6 +1753,27 @@ msgstr ""
msgid "Select {foo}" msgid "Select {foo}"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select a system"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Select all"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select matches"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Select row"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select systems"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Send a single heartbeat ping to verify your endpoint is working." msgid "Send a single heartbeat ping to verify your endpoint is working."
msgstr "" msgstr ""
@@ -1692,6 +1879,8 @@ msgstr ""
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
@@ -1716,6 +1905,8 @@ msgid "Systemd Services"
msgstr "" msgstr ""
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Systems" msgid "Systems"
msgstr "Sisteme" msgstr "Sisteme"
@@ -1732,6 +1923,11 @@ msgctxt "Tabs system layout option"
msgid "Tabs" msgid "Tabs"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Target"
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Tasks" msgid "Tasks"
msgstr "Sarcini" msgstr "Sarcini"
@@ -1779,6 +1975,7 @@ msgstr ""
msgid "This action cannot be undone. This will permanently delete all current records for {name} from the database." msgid "This action cannot be undone. This will permanently delete all current records for {name} from the database."
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "This will permanently delete all selected records from the database." msgid "This will permanently delete all selected records from the database."
msgstr "" msgstr ""
@@ -1821,7 +2018,7 @@ msgstr ""
#: src/components/ui/chart.tsx #: src/components/ui/chart.tsx
#: src/components/ui/chart.tsx #: src/components/ui/chart.tsx
msgid "Total" msgid "Total"
msgstr "" msgstr "Total"
#: src/components/routes/system/network-sheet.tsx #: src/components/routes/system/network-sheet.tsx
msgid "Total data received for each interface" msgid "Total data received for each interface"
@@ -1839,7 +2036,7 @@ msgstr ""
#. placeholder {0}: data.length #. placeholder {0}: data.length
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Total: {0}" msgid "Total: {0}"
msgstr "" msgstr "Total: {0}"
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Triggered by" msgid "Triggered by"
@@ -1901,6 +2098,10 @@ msgstr ""
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when one hour loss exceeds a threshold"
msgstr ""
#: src/lib/alerts.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "" msgstr ""
@@ -1960,6 +2161,7 @@ msgid "Update"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
#: src/components/systemd-table/systemd-table-columns.tsx #: src/components/systemd-table/systemd-table-columns.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ru\n" "Language: ru\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Russian\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" "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"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: sl\n" "Language: sl\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Slovenian\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" "Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: sr\n" "Language: sr\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Serbian (Cyrillic)\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" "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"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: sv\n" "Language: sv\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Swedish\n" "Language-Team: Swedish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: th\n" "Language: th\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 00:33\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Thai\n" "Language-Team: Thai\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
@@ -30,6 +30,12 @@ msgstr ""
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr ""
#. placeholder {0}: selectedSystemIds.size
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "{0} selected"
msgstr ""
#: src/components/routes/system/info-bar.tsx #: src/components/routes/system/info-bar.tsx
msgid "{cores, plural, one {# core} other {# cores}}" msgid "{cores, plural, one {# core} other {# cores}}"
msgstr "" msgstr ""
@@ -121,6 +127,10 @@ msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Add {foo}" msgid "Add {foo}"
@@ -188,6 +198,7 @@ msgstr ""
msgid "Are you sure you want to delete {name}?" msgid "Are you sure you want to delete {name}?"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Are you sure?" msgid "Are you sure?"
msgstr "" msgstr ""
@@ -245,6 +256,14 @@ msgstr ""
msgid "Average utilization of GPU engines" msgid "Average utilization of GPU engines"
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Average, minimum, and maximum response time"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Avg 1h"
msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
@@ -306,6 +325,19 @@ msgstr ""
msgid "Boot state" msgid "Boot state"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Bulk Add"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Bulk Add {foo}"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Bulk copy"
msgstr ""
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)" msgid "Bytes (KB/s, MB/s, GB/s)"
@@ -327,6 +359,7 @@ msgstr ""
msgid "Can stop" msgid "Can stop"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
@@ -396,6 +429,7 @@ msgid "Checksum errors"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
@@ -403,6 +437,14 @@ msgstr ""
msgid "Clear" msgid "Clear"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Clear all"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Clear matches"
msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
msgid "Click on a container to view more information." msgid "Click on a container to view more information."
msgstr "" msgstr ""
@@ -432,6 +474,10 @@ msgstr ""
msgid "Configure how you receive alert notifications." msgid "Configure how you receive alert notifications."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Configure response monitoring from this agent."
msgstr ""
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Confirm password" msgid "Confirm password"
@@ -457,6 +503,7 @@ msgstr ""
msgid "Containers" msgid "Containers"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
@@ -517,6 +564,10 @@ msgstr ""
msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>." msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>."
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Copy to system"
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Copy YAML" msgid "Copy YAML"
msgstr "" msgstr ""
@@ -630,6 +681,7 @@ msgstr ""
msgid "Default time period" msgid "Default time period"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
@@ -718,12 +770,14 @@ msgstr ""
msgid "Duration" msgid "Duration"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Edit {foo}" msgid "Edit {foo}"
msgstr "" msgstr ""
@@ -772,6 +826,11 @@ msgstr ""
msgid "Ephemeral" msgid "Ephemeral"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx #: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
@@ -844,6 +903,11 @@ msgstr ""
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Failed to delete monitors."
msgstr ""
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
@@ -862,6 +926,10 @@ msgstr ""
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Failed to update monitors."
msgstr ""
#. placeholder {0}: statusTotals[ServiceStatus.Failed] #. placeholder {0}: statusTotals[ServiceStatus.Failed]
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Failed: {0}" msgid "Failed: {0}"
@@ -872,6 +940,7 @@ msgid "Fans"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system/chart-card.tsx #: src/components/routes/system/chart-card.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
@@ -1011,14 +1080,25 @@ msgctxt "Docker image"
msgid "Image" msgid "Image"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table-columns.tsx
#: src/components/containers-table/containers-table-columns.tsx
msgctxt "Docker image"
msgid "Image update available"
msgstr ""
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Inactive" msgid "Inactive"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Interval" msgid "Interval"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Interval (seconds)"
msgstr ""
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Invalid email address." msgid "Invalid email address."
msgstr "" msgstr ""
@@ -1097,6 +1177,15 @@ msgstr ""
msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table." msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table."
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgctxt "Packet loss"
msgid "Loss"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Loss 1h"
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Main PID" msgid "Main PID"
msgstr "" msgstr ""
@@ -1115,6 +1204,10 @@ msgstr ""
msgid "Max 1 min" msgid "Max 1 min"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Max 1h"
msgstr ""
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/routes/system/info-bar.tsx #: src/components/routes/system/info-bar.tsx
#: src/components/systemd-table/systemd-table-columns.tsx #: src/components/systemd-table/systemd-table-columns.tsx
@@ -1141,11 +1234,25 @@ msgstr ""
msgid "Memory usage of containers" msgid "Memory usage of containers"
msgstr "การใช้หน่วยความจำของคอนเทนเนอร์" msgstr "การใช้หน่วยความจำของคอนเทนเนอร์"
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Min 1h"
msgstr ""
#. Device model #. Device model
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
msgid "Model" msgid "Model"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Monitor"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Monitors created"
msgstr ""
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
msgid "Mountpoint" msgid "Mountpoint"
msgstr "" msgstr ""
@@ -1163,6 +1270,29 @@ msgstr ""
msgid "Net" msgid "Net"
msgstr "" msgstr ""
#: src/components/routes/system.tsx
msgid "Network"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Network Monitor"
msgstr ""
#: src/lib/alerts.ts
msgid "Network Monitor Loss"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
#: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/monitors.tsx
msgid "Network Monitors"
msgstr ""
#: src/components/routes/system/charts/network-charts.tsx #: src/components/routes/system/charts/network-charts.tsx
msgid "Network traffic of containers" msgid "Network traffic of containers"
msgstr "การรับส่งข้อมูลเครือข่ายของคอนเทนเนอร์" msgstr "การรับส่งข้อมูลเครือข่ายของคอนเทนเนอร์"
@@ -1197,6 +1327,7 @@ msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
@@ -1207,6 +1338,7 @@ msgstr ""
msgid "No S.M.A.R.T. attributes available for this device." msgid "No S.M.A.R.T. attributes available for this device."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "No systems found." msgid "No systems found."
@@ -1238,6 +1370,11 @@ msgstr ""
msgid "One or more containers are unhealthy" msgid "One or more containers are unhealthy"
msgstr "" msgstr ""
#. placeholder {0}: alert.value
#: src/components/active-alerts.tsx
msgid "One or more monitors exceed {0}% loss"
msgstr ""
#: src/lib/alerts.ts #: src/lib/alerts.ts
msgid "One or more services are in a failed state" msgid "One or more services are in a failed state"
msgstr "" msgstr ""
@@ -1251,6 +1388,7 @@ msgstr ""
msgid "One-time password" msgid "One-time password"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
@@ -1272,6 +1410,11 @@ msgstr ""
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Packet loss (%)"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
@@ -1309,6 +1452,7 @@ msgstr ""
msgid "Past" msgid "Past"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Pause" msgid "Pause"
msgstr "" msgstr ""
@@ -1392,6 +1536,7 @@ msgid "Pool Usage"
msgstr "" msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Port" msgid "Port"
msgstr "" msgstr ""
@@ -1418,6 +1563,11 @@ msgstr ""
msgid "Process started" msgid "Process started"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Protocol"
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Public key" msgid "Public key"
msgstr "" msgstr ""
@@ -1503,10 +1653,20 @@ msgstr ""
msgid "Resolved" msgid "Resolved"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Response"
msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Response time monitoring from agents."
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Restarts" msgid "Restarts"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Resume" msgid "Resume"
msgstr "" msgstr ""
@@ -1539,6 +1699,7 @@ msgid "S.M.A.R.T. Self-Test"
msgstr "" msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Save {foo}" msgid "Save {foo}"
msgstr "" msgstr ""
@@ -1575,6 +1736,11 @@ msgstr ""
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Search systems"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Seconds between pings (default: 60)" msgid "Seconds between pings (default: 60)"
msgstr "" msgstr ""
@@ -1587,6 +1753,27 @@ msgstr ""
msgid "Select {foo}" msgid "Select {foo}"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select a system"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Select all"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select matches"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Select row"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select systems"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Send a single heartbeat ping to verify your endpoint is working." msgid "Send a single heartbeat ping to verify your endpoint is working."
msgstr "" msgstr ""
@@ -1692,6 +1879,8 @@ msgstr ""
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
@@ -1716,6 +1905,8 @@ msgid "Systemd Services"
msgstr "" msgstr ""
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Systems" msgid "Systems"
msgstr "" msgstr ""
@@ -1732,6 +1923,11 @@ msgctxt "Tabs system layout option"
msgid "Tabs" msgid "Tabs"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Target"
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Tasks" msgid "Tasks"
msgstr "" msgstr ""
@@ -1779,6 +1975,7 @@ msgstr ""
msgid "This action cannot be undone. This will permanently delete all current records for {name} from the database." msgid "This action cannot be undone. This will permanently delete all current records for {name} from the database."
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "This will permanently delete all selected records from the database." msgid "This will permanently delete all selected records from the database."
msgstr "" msgstr ""
@@ -1901,6 +2098,10 @@ msgstr ""
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when one hour loss exceeds a threshold"
msgstr ""
#: src/lib/alerts.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "" msgstr ""
@@ -1960,6 +2161,7 @@ msgid "Update"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
#: src/components/systemd-table/systemd-table-columns.tsx #: src/components/systemd-table/systemd-table-columns.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: tr\n" "Language: tr\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Turkish\n" "Language-Team: Turkish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ug\n" "Language: ug\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 00:33\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Uyghur\n" "Language-Team: Uyghur\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -30,6 +30,12 @@ msgstr ""
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr ""
#. placeholder {0}: selectedSystemIds.size
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "{0} selected"
msgstr ""
#: src/components/routes/system/info-bar.tsx #: src/components/routes/system/info-bar.tsx
msgid "{cores, plural, one {# core} other {# cores}}" msgid "{cores, plural, one {# core} other {# cores}}"
msgstr "" msgstr ""
@@ -121,6 +127,10 @@ msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Add {foo}" msgid "Add {foo}"
@@ -188,6 +198,7 @@ msgstr ""
msgid "Are you sure you want to delete {name}?" msgid "Are you sure you want to delete {name}?"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Are you sure?" msgid "Are you sure?"
msgstr "" msgstr ""
@@ -245,6 +256,14 @@ msgstr ""
msgid "Average utilization of GPU engines" msgid "Average utilization of GPU engines"
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Average, minimum, and maximum response time"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Avg 1h"
msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
@@ -306,6 +325,19 @@ msgstr ""
msgid "Boot state" msgid "Boot state"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Bulk Add"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Bulk Add {foo}"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Bulk copy"
msgstr ""
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)" msgid "Bytes (KB/s, MB/s, GB/s)"
@@ -327,6 +359,7 @@ msgstr ""
msgid "Can stop" msgid "Can stop"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
@@ -396,6 +429,7 @@ msgid "Checksum errors"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
@@ -403,6 +437,14 @@ msgstr ""
msgid "Clear" msgid "Clear"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Clear all"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Clear matches"
msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
msgid "Click on a container to view more information." msgid "Click on a container to view more information."
msgstr "" msgstr ""
@@ -432,6 +474,10 @@ msgstr ""
msgid "Configure how you receive alert notifications." msgid "Configure how you receive alert notifications."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Configure response monitoring from this agent."
msgstr ""
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Confirm password" msgid "Confirm password"
@@ -457,6 +503,7 @@ msgstr ""
msgid "Containers" msgid "Containers"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
@@ -517,6 +564,10 @@ msgstr ""
msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>." msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>."
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Copy to system"
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Copy YAML" msgid "Copy YAML"
msgstr "" msgstr ""
@@ -630,6 +681,7 @@ msgstr ""
msgid "Default time period" msgid "Default time period"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
@@ -718,12 +770,14 @@ msgstr ""
msgid "Duration" msgid "Duration"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Edit {foo}" msgid "Edit {foo}"
msgstr "" msgstr ""
@@ -772,6 +826,11 @@ msgstr ""
msgid "Ephemeral" msgid "Ephemeral"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx #: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
@@ -844,6 +903,11 @@ msgstr ""
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Failed to delete monitors."
msgstr ""
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
@@ -862,6 +926,10 @@ msgstr ""
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Failed to update monitors."
msgstr ""
#. placeholder {0}: statusTotals[ServiceStatus.Failed] #. placeholder {0}: statusTotals[ServiceStatus.Failed]
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Failed: {0}" msgid "Failed: {0}"
@@ -872,6 +940,7 @@ msgid "Fans"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system/chart-card.tsx #: src/components/routes/system/chart-card.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
@@ -1011,14 +1080,25 @@ msgctxt "Docker image"
msgid "Image" msgid "Image"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table-columns.tsx
#: src/components/containers-table/containers-table-columns.tsx
msgctxt "Docker image"
msgid "Image update available"
msgstr ""
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
msgid "Inactive" msgid "Inactive"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Interval" msgid "Interval"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Interval (seconds)"
msgstr ""
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Invalid email address." msgid "Invalid email address."
msgstr "" msgstr ""
@@ -1097,6 +1177,15 @@ msgstr ""
msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table." msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table."
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgctxt "Packet loss"
msgid "Loss"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Loss 1h"
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Main PID" msgid "Main PID"
msgstr "" msgstr ""
@@ -1115,6 +1204,10 @@ msgstr ""
msgid "Max 1 min" msgid "Max 1 min"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Max 1h"
msgstr ""
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/routes/system/info-bar.tsx #: src/components/routes/system/info-bar.tsx
#: src/components/systemd-table/systemd-table-columns.tsx #: src/components/systemd-table/systemd-table-columns.tsx
@@ -1141,11 +1234,25 @@ msgstr ""
msgid "Memory usage of containers" msgid "Memory usage of containers"
msgstr "كونتېينېرلارنىڭ ئەسلەك ئىشلىتىشى" msgstr "كونتېينېرلارنىڭ ئەسلەك ئىشلىتىشى"
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Min 1h"
msgstr ""
#. Device model #. Device model
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
msgid "Model" msgid "Model"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Monitor"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Monitors created"
msgstr ""
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
msgid "Mountpoint" msgid "Mountpoint"
msgstr "" msgstr ""
@@ -1163,6 +1270,29 @@ msgstr ""
msgid "Net" msgid "Net"
msgstr "" msgstr ""
#: src/components/routes/system.tsx
msgid "Network"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Network Monitor"
msgstr ""
#: src/lib/alerts.ts
msgid "Network Monitor Loss"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
#: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/monitors.tsx
msgid "Network Monitors"
msgstr ""
#: src/components/routes/system/charts/network-charts.tsx #: src/components/routes/system/charts/network-charts.tsx
msgid "Network traffic of containers" msgid "Network traffic of containers"
msgstr "كونتېينېرلارنىڭ تور ئېقىمى" msgstr "كونتېينېرلارنىڭ تور ئېقىمى"
@@ -1197,6 +1327,7 @@ msgstr ""
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/containers-table/containers-table.tsx #: src/components/containers-table/containers-table.tsx
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
@@ -1207,6 +1338,7 @@ msgstr ""
msgid "No S.M.A.R.T. attributes available for this device." msgid "No S.M.A.R.T. attributes available for this device."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "No systems found." msgid "No systems found."
@@ -1238,6 +1370,11 @@ msgstr ""
msgid "One or more containers are unhealthy" msgid "One or more containers are unhealthy"
msgstr "" msgstr ""
#. placeholder {0}: alert.value
#: src/components/active-alerts.tsx
msgid "One or more monitors exceed {0}% loss"
msgstr ""
#: src/lib/alerts.ts #: src/lib/alerts.ts
msgid "One or more services are in a failed state" msgid "One or more services are in a failed state"
msgstr "" msgstr ""
@@ -1251,6 +1388,7 @@ msgstr ""
msgid "One-time password" msgid "One-time password"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
@@ -1272,6 +1410,11 @@ msgstr ""
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "" msgstr ""
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Packet loss (%)"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
@@ -1309,6 +1452,7 @@ msgstr ""
msgid "Past" msgid "Past"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Pause" msgid "Pause"
msgstr "" msgstr ""
@@ -1392,6 +1536,7 @@ msgid "Pool Usage"
msgstr "" msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Port" msgid "Port"
msgstr "" msgstr ""
@@ -1418,6 +1563,11 @@ msgstr ""
msgid "Process started" msgid "Process started"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Protocol"
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Public key" msgid "Public key"
msgstr "" msgstr ""
@@ -1503,10 +1653,20 @@ msgstr ""
msgid "Resolved" msgid "Resolved"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/system/charts/monitors-charts.tsx
msgid "Response"
msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
msgid "Response time monitoring from agents."
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Restarts" msgid "Restarts"
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Resume" msgid "Resume"
msgstr "" msgstr ""
@@ -1539,6 +1699,7 @@ msgid "S.M.A.R.T. Self-Test"
msgstr "" msgstr ""
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Save {foo}" msgid "Save {foo}"
msgstr "" msgstr ""
@@ -1575,6 +1736,11 @@ msgstr ""
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Search systems"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Seconds between pings (default: 60)" msgid "Seconds between pings (default: 60)"
msgstr "" msgstr ""
@@ -1587,6 +1753,27 @@ msgstr ""
msgid "Select {foo}" msgid "Select {foo}"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select a system"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Select all"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select matches"
msgstr ""
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Select row"
msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Select systems"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx #: src/components/routes/settings/heartbeat.tsx
msgid "Send a single heartbeat ping to verify your endpoint is working." msgid "Send a single heartbeat ping to verify your endpoint is working."
msgstr "" msgstr ""
@@ -1692,6 +1879,8 @@ msgstr ""
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
#: src/components/routes/settings/quiet-hours.tsx #: src/components/routes/settings/quiet-hours.tsx
@@ -1716,6 +1905,8 @@ msgid "Systemd Services"
msgstr "" msgstr ""
#: src/components/navbar.tsx #: src/components/navbar.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/monitor-dialog.tsx
msgid "Systems" msgid "Systems"
msgstr "" msgstr ""
@@ -1732,6 +1923,11 @@ msgctxt "Tabs system layout option"
msgid "Tabs" msgid "Tabs"
msgstr "" msgstr ""
#: src/components/network-monitors-table/monitor-dialog.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
msgid "Target"
msgstr ""
#: src/components/systemd-table/systemd-table.tsx #: src/components/systemd-table/systemd-table.tsx
msgid "Tasks" msgid "Tasks"
msgstr "" msgstr ""
@@ -1779,6 +1975,7 @@ msgstr ""
msgid "This action cannot be undone. This will permanently delete all current records for {name} from the database." msgid "This action cannot be undone. This will permanently delete all current records for {name} from the database."
msgstr "" msgstr ""
#: src/components/network-monitors-table/network-monitors-table.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "This will permanently delete all selected records from the database." msgid "This will permanently delete all selected records from the database."
msgstr "" msgstr ""
@@ -1901,6 +2098,10 @@ msgstr ""
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when one hour loss exceeds a threshold"
msgstr ""
#: src/lib/alerts.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "" msgstr ""
@@ -1960,6 +2161,7 @@ msgid "Update"
msgstr "" msgstr ""
#: src/components/containers-table/containers-table-columns.tsx #: src/components/containers-table/containers-table-columns.tsx
#: src/components/network-monitors-table/network-monitors-columns.tsx
#: src/components/routes/system/smart-table.tsx #: src/components/routes/system/smart-table.tsx
#: src/components/routes/system/storage-pools-table.tsx #: src/components/routes/system/storage-pools-table.tsx
#: src/components/systemd-table/systemd-table-columns.tsx #: src/components/systemd-table/systemd-table-columns.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: uk\n" "Language: uk\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Ukrainian\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" "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"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: uz\n" "Language: uz\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:46\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Uzbek\n" "Language-Team: Uzbek\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: vi\n" "Language: vi\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-16 10:11\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Vietnamese\n" "Language-Team: Vietnamese\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: zh\n" "Language: zh\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Chinese Simplified\n" "Language-Team: Chinese Simplified\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: zh\n" "Language: zh\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:46\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Chinese Traditional, Hong Kong\n" "Language-Team: Chinese Traditional, Hong Kong\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: zh\n" "Language: zh\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-09-10 01:45\n" "PO-Revision-Date: 2026-09-18 19:22\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Chinese Traditional\n" "Language-Team: Chinese Traditional\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"

View File

@@ -1,3 +1,39 @@
## 0.20.0
- Add network monitoring from agents (#2266, #1911)
- Add Docker image update available flag (#2211)
- Add btrfs filesystem reporting as storage pools (#2315)
- Add persistence of view preferences and language to user settings (#1831)
- Add `TRUSTED_PROXY_IPS` allowlist for `TRUSTED_AUTH_HEADER` (#2327)
- Add ZFS utilities to Intel and NVIDIA agent images (#2288, #2311)
- Revert SMART warnings for certain attributes (#2296, #2308, #2347)
- Improve NVMe data units display as human-readable GB/TB (#2303)
- Fix agent disconnects during slow collections by extending WebSocket deadline (#2294)
- Fix missing root CA certificates in base agent image (#2291)
- Fix false RAID health warnings during healthy data scrubbing (#2109)
- Fix ZFS monitoring when /dev/zfs is unavailable (#2325)
- Fix spurious `HUB_URL` warning in SSH-only mode (#2316)
- Fix idle GPU utilization display in systems table (#2312)
- Fix session handling to clear auth store after token expiry (#2310)
- Fix chart history handling when switching to live charts (#2333)
- Update Go dependencies
## 0.19.0 ## 0.19.0
- **Potential breaking change:** Agents now verify HTTPS certificates. If an agent connects to a hub using a self-signed or otherwise untrusted certificate, configure `CA_CERT_FILE` with the appropriate CA certificate or the connection will be rejected. - **Potential breaking change:** Agents now verify HTTPS certificates. If an agent connects to a hub using a self-signed or otherwise untrusted certificate, configure `CA_CERT_FILE` with the appropriate CA certificate or the connection will be rejected.