Compare commits

..

14 Commits

Author SHA1 Message Date
henrygd
49976c6f61 fix nvidia agent dockerfile after project reorganization 2025-09-17 14:10:02 -04:00
henrygd
d68f1f0985 0.12.8 release :) 2025-09-17 14:02:17 -04:00
henrygd
273a090200 update translations 2025-09-17 14:01:20 -04:00
henrygd
59057a2ba4 add check for status alerts which are not properly resolved (#1052) 2025-09-17 13:31:49 -04:00
henrygd
1b9e781d45 refactor deltatracker
- embed mutex
- add example function
2025-09-16 22:09:46 -04:00
henrygd
4e0ca7c2ba formatting (biome) 2025-09-15 18:04:13 -04:00
henrygd
a9e7bcd37f add per-interface and cumulative network traffic charts (#926)
Co-authored-by: Sven van Ginkel <svenvanginkel@icloud.com>
2025-09-15 17:59:21 -04:00
henrygd
4635f24fb2 fix entre arg in makefile dev server 2025-09-15 17:26:07 -04:00
henrygd
3e73399b87 fix battery detection on newer macs (#1170) 2025-09-15 12:02:50 -04:00
Ryan W
e149366451 Fixing service name in helm chart and making default values unopinionated (#1166) 2025-09-13 12:09:36 -04:00
henrygd
8da1ded73e strip whitespace from TOKEN_FILE (#984) 2025-09-12 12:59:53 -04:00
henrygd
efa37b2312 web: extra check for valid system before adding (#1063) 2025-09-11 15:37:11 -04:00
henrygd
bcdb4c92b5 add freebsd to list of copyable commands 2025-09-11 15:07:37 -04:00
henrygd
a7d07310b6 Add AUTO_LOGIN environment variable for automatic login. (#399) 2025-09-11 14:01:09 -04:00
92 changed files with 2029 additions and 3882 deletions

View File

@@ -77,7 +77,7 @@ dev-hub: export ENV=dev
dev-hub:
mkdir -p ./internal/site/dist && touch ./internal/site/dist/index.html
@if command -v entr >/dev/null 2>&1; then \
find ./internal/cmd/hub/*.go ./internal/{alerts,hub,records,users}/*.go | entr -r -s "cd ./internal/cmd/hub && go run -tags development . serve --http 0.0.0.0:8090"; \
find ./internal -type f -name '*.go' | entr -r -s "cd ./internal/cmd/hub && go run -tags development . serve --http 0.0.0.0:8090"; \
else \
cd ./internal/cmd/hub && go run -tags development . serve --http 0.0.0.0:8090; \
fi

View File

@@ -20,9 +20,8 @@ func HasReadableBattery() bool {
}
haveCheckedBattery = true
bat, err := battery.Get(0)
if err == nil && bat != nil {
systemHasBattery = true
} else {
systemHasBattery = err == nil && bat != nil && bat.Design != 0 && bat.Full != 0
if !systemHasBattery {
slog.Debug("No battery found", "err", err)
}
return systemHasBattery

View File

@@ -85,7 +85,7 @@ func getToken() (string, error) {
if err != nil {
return "", err
}
return string(tokenBytes), nil
return strings.TrimSpace(string(tokenBytes)), nil
}
// getOptions returns the WebSocket client options, creating them if necessary.

View File

@@ -537,4 +537,25 @@ func TestGetToken(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "", token, "Empty file should return empty string")
})
t.Run("strips whitespace from TOKEN_FILE", func(t *testing.T) {
unsetEnvVars()
tokenWithWhitespace := " test-token-with-whitespace \n\t"
expectedToken := "test-token-with-whitespace"
tokenFile, err := os.CreateTemp("", "token-test-*.txt")
require.NoError(t, err)
defer os.Remove(tokenFile.Name())
_, err = tokenFile.WriteString(tokenWithWhitespace)
require.NoError(t, err)
tokenFile.Close()
os.Setenv("TOKEN_FILE", tokenFile.Name())
defer os.Unsetenv("TOKEN_FILE")
token, err := getToken()
assert.NoError(t, err)
assert.Equal(t, expectedToken, token, "Whitespace should be stripped from token file content")
})
}

View File

@@ -0,0 +1,81 @@
// Package deltatracker provides a tracker for calculating differences in numeric values over time.
package deltatracker
import (
"sync"
"golang.org/x/exp/constraints"
)
// Numeric is a constraint that permits any integer or floating-point type.
type Numeric interface {
constraints.Integer | constraints.Float
}
// DeltaTracker is a generic, thread-safe tracker for calculating differences
// in numeric values over time.
// K is the key type (e.g., int, string).
// V is the value type (e.g., int, int64, float32, float64).
type DeltaTracker[K comparable, V Numeric] struct {
sync.RWMutex
current map[K]V
previous map[K]V
}
// NewDeltaTracker creates a new generic tracker.
func NewDeltaTracker[K comparable, V Numeric]() *DeltaTracker[K, V] {
return &DeltaTracker[K, V]{
current: make(map[K]V),
previous: make(map[K]V),
}
}
// Set records the current value for a given ID.
func (t *DeltaTracker[K, V]) Set(id K, value V) {
t.Lock()
defer t.Unlock()
t.current[id] = value
}
// Deltas returns a map of all calculated deltas for the current interval.
func (t *DeltaTracker[K, V]) Deltas() map[K]V {
t.RLock()
defer t.RUnlock()
deltas := make(map[K]V)
for id, currentVal := range t.current {
if previousVal, ok := t.previous[id]; ok {
deltas[id] = currentVal - previousVal
} else {
deltas[id] = 0
}
}
return deltas
}
// Delta returns the delta for a single key.
// Returns 0 if the key doesn't exist or has no previous value.
func (t *DeltaTracker[K, V]) Delta(id K) V {
t.RLock()
defer t.RUnlock()
currentVal, currentOk := t.current[id]
if !currentOk {
return 0
}
previousVal, previousOk := t.previous[id]
if !previousOk {
return 0
}
return currentVal - previousVal
}
// Cycle prepares the tracker for the next interval.
func (t *DeltaTracker[K, V]) Cycle() {
t.Lock()
defer t.Unlock()
t.previous = t.current
t.current = make(map[K]V)
}

View File

@@ -0,0 +1,217 @@
package deltatracker
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
func ExampleDeltaTracker() {
tracker := NewDeltaTracker[string, int]()
tracker.Set("key1", 10)
tracker.Set("key2", 20)
tracker.Cycle()
tracker.Set("key1", 15)
tracker.Set("key2", 30)
fmt.Println(tracker.Delta("key1"))
fmt.Println(tracker.Delta("key2"))
fmt.Println(tracker.Deltas())
// Output: 5
// 10
// map[key1:5 key2:10]
}
func TestNewDeltaTracker(t *testing.T) {
tracker := NewDeltaTracker[string, int]()
assert.NotNil(t, tracker)
assert.Empty(t, tracker.current)
assert.Empty(t, tracker.previous)
}
func TestSet(t *testing.T) {
tracker := NewDeltaTracker[string, int]()
tracker.Set("key1", 10)
tracker.RLock()
defer tracker.RUnlock()
assert.Equal(t, 10, tracker.current["key1"])
}
func TestDeltas(t *testing.T) {
tracker := NewDeltaTracker[string, int]()
// Test with no previous values
tracker.Set("key1", 10)
tracker.Set("key2", 20)
deltas := tracker.Deltas()
assert.Equal(t, 0, deltas["key1"])
assert.Equal(t, 0, deltas["key2"])
// Cycle to move current to previous
tracker.Cycle()
// Set new values and check deltas
tracker.Set("key1", 15) // Delta should be 5 (15-10)
tracker.Set("key2", 25) // Delta should be 5 (25-20)
tracker.Set("key3", 30) // New key, delta should be 0
deltas = tracker.Deltas()
assert.Equal(t, 5, deltas["key1"])
assert.Equal(t, 5, deltas["key2"])
assert.Equal(t, 0, deltas["key3"])
}
func TestCycle(t *testing.T) {
tracker := NewDeltaTracker[string, int]()
tracker.Set("key1", 10)
tracker.Set("key2", 20)
// Verify current has values
tracker.RLock()
assert.Equal(t, 10, tracker.current["key1"])
assert.Equal(t, 20, tracker.current["key2"])
assert.Empty(t, tracker.previous)
tracker.RUnlock()
tracker.Cycle()
// After cycle, previous should have the old current values
// and current should be empty
tracker.RLock()
assert.Empty(t, tracker.current)
assert.Equal(t, 10, tracker.previous["key1"])
assert.Equal(t, 20, tracker.previous["key2"])
tracker.RUnlock()
}
func TestCompleteWorkflow(t *testing.T) {
tracker := NewDeltaTracker[string, int]()
// First interval
tracker.Set("server1", 100)
tracker.Set("server2", 200)
// Get deltas for first interval (should be zero)
firstDeltas := tracker.Deltas()
assert.Equal(t, 0, firstDeltas["server1"])
assert.Equal(t, 0, firstDeltas["server2"])
// Cycle to next interval
tracker.Cycle()
// Second interval
tracker.Set("server1", 150) // Delta: 50
tracker.Set("server2", 180) // Delta: -20
tracker.Set("server3", 300) // New server, delta: 300
secondDeltas := tracker.Deltas()
assert.Equal(t, 50, secondDeltas["server1"])
assert.Equal(t, -20, secondDeltas["server2"])
assert.Equal(t, 0, secondDeltas["server3"])
}
func TestDeltaTrackerWithDifferentTypes(t *testing.T) {
// Test with int64
intTracker := NewDeltaTracker[string, int64]()
intTracker.Set("pid1", 1000)
intTracker.Cycle()
intTracker.Set("pid1", 1200)
intDeltas := intTracker.Deltas()
assert.Equal(t, int64(200), intDeltas["pid1"])
// Test with float64
floatTracker := NewDeltaTracker[string, float64]()
floatTracker.Set("cpu1", 1.5)
floatTracker.Cycle()
floatTracker.Set("cpu1", 2.7)
floatDeltas := floatTracker.Deltas()
assert.InDelta(t, 1.2, floatDeltas["cpu1"], 0.0001)
// Test with int keys
pidTracker := NewDeltaTracker[int, int64]()
pidTracker.Set(101, 20000)
pidTracker.Cycle()
pidTracker.Set(101, 22500)
pidDeltas := pidTracker.Deltas()
assert.Equal(t, int64(2500), pidDeltas[101])
}
func TestDelta(t *testing.T) {
tracker := NewDeltaTracker[string, int]()
// Test getting delta for non-existent key
result := tracker.Delta("nonexistent")
assert.Equal(t, 0, result)
// Test getting delta for key with no previous value
tracker.Set("key1", 10)
result = tracker.Delta("key1")
assert.Equal(t, 0, result)
// Cycle to move current to previous
tracker.Cycle()
// Test getting delta for key with previous value
tracker.Set("key1", 15)
result = tracker.Delta("key1")
assert.Equal(t, 5, result)
// Test getting delta for key that exists in previous but not current
result = tracker.Delta("key1")
assert.Equal(t, 5, result) // Should still return 5
// Test getting delta for key that exists in current but not previous
tracker.Set("key2", 20)
result = tracker.Delta("key2")
assert.Equal(t, 0, result)
}
func TestDeltaWithDifferentTypes(t *testing.T) {
// Test with int64
intTracker := NewDeltaTracker[string, int64]()
intTracker.Set("pid1", 1000)
intTracker.Cycle()
intTracker.Set("pid1", 1200)
result := intTracker.Delta("pid1")
assert.Equal(t, int64(200), result)
// Test with float64
floatTracker := NewDeltaTracker[string, float64]()
floatTracker.Set("cpu1", 1.5)
floatTracker.Cycle()
floatTracker.Set("cpu1", 2.7)
floatResult := floatTracker.Delta("cpu1")
assert.InDelta(t, 1.2, floatResult, 0.0001)
// Test with int keys
pidTracker := NewDeltaTracker[int, int64]()
pidTracker.Set(101, 20000)
pidTracker.Cycle()
pidTracker.Set(101, 22500)
pidResult := pidTracker.Delta(101)
assert.Equal(t, int64(2500), pidResult)
}
func TestDeltaConcurrentAccess(t *testing.T) {
tracker := NewDeltaTracker[string, int]()
// Set initial values
tracker.Set("key1", 10)
tracker.Set("key2", 20)
tracker.Cycle()
// Set new values
tracker.Set("key1", 15)
tracker.Set("key2", 25)
// Test concurrent access safety
result1 := tracker.Delta("key1")
result2 := tracker.Delta("key2")
assert.Equal(t, 5, result1)
assert.Equal(t, 5, result2)
}

View File

@@ -1,13 +1,83 @@
package agent
import (
"fmt"
"log/slog"
"strings"
"time"
"github.com/henrygd/beszel/internal/entities/system"
psutilNet "github.com/shirou/gopsutil/v4/net"
)
func (a *Agent) updateNetworkStats(systemStats *system.Stats) {
// network stats
if len(a.netInterfaces) == 0 {
// if no network interfaces, initialize again
// this is a fix if agent started before network is online (#466)
// maybe refactor this in the future to not cache interface names at all so we
// don't miss an interface that's been added after agent started in any circumstance
a.initializeNetIoStats()
}
if systemStats.NetworkInterfaces == nil {
systemStats.NetworkInterfaces = make(map[string][4]uint64, 0)
}
if netIO, err := psutilNet.IOCounters(true); err == nil {
msElapsed := uint64(time.Since(a.netIoStats.Time).Milliseconds())
a.netIoStats.Time = time.Now()
totalBytesSent := uint64(0)
totalBytesRecv := uint64(0)
netInterfaceDeltaTracker.Cycle()
// sum all bytes sent and received
for _, v := range netIO {
// skip if not in valid network interfaces list
if _, exists := a.netInterfaces[v.Name]; !exists {
continue
}
totalBytesSent += v.BytesSent
totalBytesRecv += v.BytesRecv
// track deltas for each network interface
netInterfaceDeltaTracker.Set(fmt.Sprintf("%sdown", v.Name), v.BytesRecv)
netInterfaceDeltaTracker.Set(fmt.Sprintf("%sup", v.Name), v.BytesSent)
upDelta := netInterfaceDeltaTracker.Delta(fmt.Sprintf("%sup", v.Name)) * 1000 / msElapsed
downDelta := netInterfaceDeltaTracker.Delta(fmt.Sprintf("%sdown", v.Name)) * 1000 / msElapsed
// add interface to systemStats
systemStats.NetworkInterfaces[v.Name] = [4]uint64{upDelta, downDelta, v.BytesSent, v.BytesRecv}
}
// add to systemStats
var bytesSentPerSecond, bytesRecvPerSecond uint64
if msElapsed > 0 {
bytesSentPerSecond = (totalBytesSent - a.netIoStats.BytesSent) * 1000 / msElapsed
bytesRecvPerSecond = (totalBytesRecv - a.netIoStats.BytesRecv) * 1000 / msElapsed
}
networkSentPs := bytesToMegabytes(float64(bytesSentPerSecond))
networkRecvPs := bytesToMegabytes(float64(bytesRecvPerSecond))
// add check for issue (#150) where sent is a massive number
if networkSentPs > 10_000 || networkRecvPs > 10_000 {
slog.Warn("Invalid net stats. Resetting.", "sent", networkSentPs, "recv", networkRecvPs)
for _, v := range netIO {
if _, exists := a.netInterfaces[v.Name]; !exists {
continue
}
slog.Info(v.Name, "recv", v.BytesRecv, "sent", v.BytesSent)
}
// reset network I/O stats
a.initializeNetIoStats()
} else {
systemStats.NetworkSent = networkSentPs
systemStats.NetworkRecv = networkRecvPs
systemStats.Bandwidth[0], systemStats.Bandwidth[1] = bytesSentPerSecond, bytesRecvPerSecond
// update netIoStats
a.netIoStats.BytesSent = totalBytesSent
a.netIoStats.BytesRecv = totalBytesRecv
}
}
}
func (a *Agent) initializeNetIoStats() {
// reset valid network interfaces
a.netInterfaces = make(map[string]struct{}, 0)

View File

@@ -11,6 +11,7 @@ import (
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/agent/battery"
"github.com/henrygd/beszel/agent/deltatracker"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/shirou/gopsutil/v4/cpu"
@@ -18,9 +19,10 @@ import (
"github.com/shirou/gopsutil/v4/host"
"github.com/shirou/gopsutil/v4/load"
"github.com/shirou/gopsutil/v4/mem"
psutilNet "github.com/shirou/gopsutil/v4/net"
)
var netInterfaceDeltaTracker = deltatracker.NewDeltaTracker[string, uint64]()
// Sets initial / non-changing values about the host system
func (a *Agent) initializeSystemInfo() {
a.systemInfo.AgentVersion = beszel.Version
@@ -70,7 +72,7 @@ func (a *Agent) initializeSystemInfo() {
// Returns current info, stats about the host system
func (a *Agent) getSystemStats() system.Stats {
systemStats := system.Stats{}
var systemStats system.Stats
// battery
if battery.HasReadableBattery() {
@@ -173,55 +175,7 @@ func (a *Agent) getSystemStats() system.Stats {
}
// network stats
if len(a.netInterfaces) == 0 {
// if no network interfaces, initialize again
// this is a fix if agent started before network is online (#466)
// maybe refactor this in the future to not cache interface names at all so we
// don't miss an interface that's been added after agent started in any circumstance
a.initializeNetIoStats()
}
if netIO, err := psutilNet.IOCounters(true); err == nil {
msElapsed := uint64(time.Since(a.netIoStats.Time).Milliseconds())
a.netIoStats.Time = time.Now()
totalBytesSent := uint64(0)
totalBytesRecv := uint64(0)
// sum all bytes sent and received
for _, v := range netIO {
// skip if not in valid network interfaces list
if _, exists := a.netInterfaces[v.Name]; !exists {
continue
}
totalBytesSent += v.BytesSent
totalBytesRecv += v.BytesRecv
}
// add to systemStats
var bytesSentPerSecond, bytesRecvPerSecond uint64
if msElapsed > 0 {
bytesSentPerSecond = (totalBytesSent - a.netIoStats.BytesSent) * 1000 / msElapsed
bytesRecvPerSecond = (totalBytesRecv - a.netIoStats.BytesRecv) * 1000 / msElapsed
}
networkSentPs := bytesToMegabytes(float64(bytesSentPerSecond))
networkRecvPs := bytesToMegabytes(float64(bytesRecvPerSecond))
// add check for issue (#150) where sent is a massive number
if networkSentPs > 10_000 || networkRecvPs > 10_000 {
slog.Warn("Invalid net stats. Resetting.", "sent", networkSentPs, "recv", networkRecvPs)
for _, v := range netIO {
if _, exists := a.netInterfaces[v.Name]; !exists {
continue
}
slog.Info(v.Name, "recv", v.BytesRecv, "sent", v.BytesSent)
}
// reset network I/O stats
a.initializeNetIoStats()
} else {
systemStats.NetworkSent = networkSentPs
systemStats.NetworkRecv = networkRecvPs
systemStats.Bandwidth[0], systemStats.Bandwidth[1] = bytesSentPerSecond, bytesRecvPerSecond
// update netIoStats
a.netIoStats.BytesSent = totalBytesSent
a.netIoStats.BytesRecv = totalBytesRecv
}
}
a.updateNetworkStats(&systemStats)
// temperatures
// TODO: maybe refactor to methods on systemStats

View File

@@ -6,7 +6,7 @@ import "github.com/blang/semver"
const (
// Version is the current version of the application.
Version = "0.12.7"
Version = "0.12.8"
// AppName is the name of the application.
AppName = "beszel"
)

View File

@@ -25,7 +25,12 @@ type alertInfo struct {
// startWorker is a long-running goroutine that processes alert tasks
// every x seconds. It must be running to process status alerts.
func (am *AlertManager) startWorker() {
tick := time.Tick(15 * time.Second)
processPendingAlerts := time.Tick(15 * time.Second)
// check for status alerts that are not resolved when system comes up
// (can be removed if we figure out core bug in #1052)
checkStatusAlerts := time.Tick(561 * time.Second)
for {
select {
case <-am.stopChan:
@@ -41,7 +46,9 @@ func (am *AlertManager) startWorker() {
case "cancel":
am.pendingAlerts.Delete(task.alertRecord.Id)
}
case <-tick:
case <-checkStatusAlerts:
resolveStatusAlerts(am.hub)
case <-processPendingAlerts:
// Check for expired alerts every tick
now := time.Now()
for key, value := range am.pendingAlerts.Range {
@@ -170,3 +177,35 @@ func (am *AlertManager) sendStatusAlert(alertStatus string, systemName string, a
LinkText: "View " + systemName,
})
}
// resolveStatusAlerts resolves any status alerts that weren't resolved
// when system came up (https://github.com/henrygd/beszel/issues/1052)
func resolveStatusAlerts(app core.App) error {
db := app.DB()
// Find all active status alerts where the system is actually up
var alertIds []string
err := db.NewQuery(`
SELECT a.id
FROM alerts a
JOIN systems s ON a.system = s.id
WHERE a.name = 'Status'
AND a.triggered = true
AND s.status = 'up'
`).Column(&alertIds)
if err != nil {
return err
}
// resolve all matching alert records
for _, alertId := range alertIds {
alert, err := app.FindRecordById("alerts", alertId)
if err != nil {
return err
}
alert.Set("triggered", false)
err = app.Save(alert)
if err != nil {
return err
}
}
return nil
}

View File

@@ -13,6 +13,7 @@ import (
"testing/synctest"
"time"
"github.com/henrygd/beszel/internal/alerts"
beszelTests "github.com/henrygd/beszel/internal/tests"
"github.com/pocketbase/dbx"
@@ -369,33 +370,9 @@ func TestUserAlertsApi(t *testing.T) {
}
}
func getHubWithUser(t *testing.T) (*beszelTests.TestHub, *core.Record) {
hub, err := beszelTests.NewTestHub(t.TempDir())
assert.NoError(t, err)
hub.StartHub()
// Manually initialize the system manager to bind event hooks
err = hub.GetSystemManager().Initialize()
assert.NoError(t, err)
// Create a test user
user, err := beszelTests.CreateUser(hub, "test@example.com", "password")
assert.NoError(t, err)
// Create user settings for the test user (required for alert notifications)
userSettingsData := map[string]any{
"user": user.Id,
"settings": `{"emails":[test@example.com],"webhooks":[]}`,
}
_, err = beszelTests.CreateRecord(hub, "user_settings", userSettingsData)
assert.NoError(t, err)
return hub, user
}
func TestStatusAlerts(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
hub, user := getHubWithUser(t)
hub, user := beszelTests.GetHubWithUser(t)
defer hub.Cleanup()
systems, err := beszelTests.CreateSystems(hub, 4, user.Id, "paused")
@@ -476,7 +453,7 @@ func TestStatusAlerts(t *testing.T) {
func TestAlertsHistory(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
hub, user := getHubWithUser(t)
hub, user := beszelTests.GetHubWithUser(t)
defer hub.Cleanup()
// Create systems and alerts
@@ -602,3 +579,102 @@ func TestAlertsHistory(t *testing.T) {
assert.EqualValues(t, 2, totalHistoryCount, "Should have 2 total alert history records")
})
}
func TestResolveStatusAlerts(t *testing.T) {
hub, user := beszelTests.GetHubWithUser(t)
defer hub.Cleanup()
// Create a systemUp
systemUp, err := beszelTests.CreateRecord(hub, "systems", map[string]any{
"name": "test-system",
"users": []string{user.Id},
"host": "127.0.0.1",
"status": "up",
})
assert.NoError(t, err)
systemDown, err := beszelTests.CreateRecord(hub, "systems", map[string]any{
"name": "test-system-2",
"users": []string{user.Id},
"host": "127.0.0.2",
"status": "up",
})
assert.NoError(t, err)
// Create a status alertUp for the system
alertUp, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
"name": "Status",
"system": systemUp.Id,
"user": user.Id,
"min": 1,
})
assert.NoError(t, err)
alertDown, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
"name": "Status",
"system": systemDown.Id,
"user": user.Id,
"min": 1,
})
assert.NoError(t, err)
// Verify alert is not triggered initially
assert.False(t, alertUp.GetBool("triggered"), "Alert should not be triggered initially")
// Set the system to 'up' (this should not trigger the alert)
systemUp.Set("status", "up")
err = hub.SaveNoValidate(systemUp)
assert.NoError(t, err)
systemDown.Set("status", "down")
err = hub.SaveNoValidate(systemDown)
assert.NoError(t, err)
// Wait a moment for any processing
time.Sleep(10 * time.Millisecond)
// Verify alertUp is still not triggered after setting system to up
alertUp, err = hub.FindFirstRecordByFilter("alerts", "id={:id}", dbx.Params{"id": alertUp.Id})
assert.NoError(t, err)
assert.False(t, alertUp.GetBool("triggered"), "Alert should not be triggered when system is up")
// Manually set both alerts triggered to true
alertUp.Set("triggered", true)
err = hub.SaveNoValidate(alertUp)
assert.NoError(t, err)
alertDown.Set("triggered", true)
err = hub.SaveNoValidate(alertDown)
assert.NoError(t, err)
// Verify we have exactly one alert with triggered true
triggeredCount, err := hub.CountRecords("alerts", dbx.HashExp{"triggered": true})
assert.NoError(t, err)
assert.EqualValues(t, 2, triggeredCount, "Should have exactly two alerts with triggered true")
// Verify the specific alertUp is triggered
alertUp, err = hub.FindFirstRecordByFilter("alerts", "id={:id}", dbx.Params{"id": alertUp.Id})
assert.NoError(t, err)
assert.True(t, alertUp.GetBool("triggered"), "Alert should be triggered")
// Verify we have two unresolved alert history records
alertHistoryCount, err := hub.CountRecords("alerts_history", dbx.HashExp{"resolved": ""})
assert.NoError(t, err)
assert.EqualValues(t, 2, alertHistoryCount, "Should have exactly two unresolved alert history records")
err = alerts.ResolveStatusAlerts(hub)
assert.NoError(t, err)
// Verify alertUp is not triggered after resolving
alertUp, err = hub.FindFirstRecordByFilter("alerts", "id={:id}", dbx.Params{"id": alertUp.Id})
assert.NoError(t, err)
assert.False(t, alertUp.GetBool("triggered"), "Alert should not be triggered after resolving")
// Verify alertDown is still triggered
alertDown, err = hub.FindFirstRecordByFilter("alerts", "id={:id}", dbx.Params{"id": alertDown.Id})
assert.NoError(t, err)
assert.True(t, alertDown.GetBool("triggered"), "Alert should still be triggered after resolving")
// Verify we have one unresolved alert history record
alertHistoryCount, err = hub.CountRecords("alerts_history", dbx.HashExp{"resolved": ""})
assert.NoError(t, err)
assert.EqualValues(t, 1, alertHistoryCount, "Should have exactly one unresolved alert history record")
}

View File

@@ -1,3 +1,6 @@
//go:build testing
// +build testing
package alerts
import (
@@ -53,3 +56,7 @@ func (am *AlertManager) ForceExpirePendingAlerts() {
return true
})
}
func ResolveStatusAlerts(app core.App) error {
return resolveStatusAlerts(app)
}

View File

@@ -2,15 +2,18 @@ FROM --platform=$BUILDPLATFORM golang:alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
# RUN go mod download
COPY *.go ./
COPY cmd ./cmd
COPY internal ./internal
COPY ../go.mod ../go.sum ./
RUN go mod download
# Copy source files
COPY . ./
# Build
ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./cmd/agent
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent
RUN rm -rf /tmp/*
# --------------------------
# Final image: GPU-enabled agent with nvidia-smi
@@ -18,4 +21,7 @@ RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-
FROM nvidia/cuda:12.2.2-base-ubuntu22.04
COPY --from=builder /agent /agent
# this is so we don't need to create the /tmp directory in the scratch container
COPY --from=builder /tmp /tmp
ENTRYPOINT ["/agent"]

View File

@@ -38,9 +38,10 @@ type Stats struct {
Bandwidth [2]uint64 `json:"b,omitzero" cbor:"26,keyasint,omitzero"` // [sent bytes, recv bytes]
MaxBandwidth [2]uint64 `json:"bm,omitzero" cbor:"27,keyasint,omitzero"` // [sent bytes, recv bytes]
// TODO: remove other load fields in future release in favor of load avg array
LoadAvg [3]float64 `json:"la,omitempty" cbor:"28,keyasint"`
Battery [2]uint8 `json:"bat,omitzero" cbor:"29,keyasint,omitzero"` // [percent, charge state, current]
MaxMem float64 `json:"mm,omitempty" cbor:"30,keyasint,omitempty"`
LoadAvg [3]float64 `json:"la,omitempty" cbor:"28,keyasint"`
Battery [2]uint8 `json:"bat,omitzero" cbor:"29,keyasint,omitzero"` // [percent, charge state, current]
MaxMem float64 `json:"mm,omitempty" cbor:"30,keyasint,omitempty"`
NetworkInterfaces map[string][4]uint64 `json:"ni,omitempty" cbor:"31,keyasint,omitempty"` // [upload bytes, download bytes, total upload, total download]
}
type GPUData struct {

View File

@@ -175,35 +175,31 @@ func (h *Hub) registerCronJobs(_ *core.ServeEvent) error {
// custom middlewares
func (h *Hub) registerMiddlewares(se *core.ServeEvent) {
// authorizes request with user matching the provided email
authorizeRequestWithEmail := func(e *core.RequestEvent, email string) (err error) {
if e.Auth != nil || email == "" {
return e.Next()
}
isAuthRefresh := e.Request.URL.Path == "/api/collections/users/auth-refresh" && e.Request.Method == http.MethodPost
e.Auth, err = e.App.FindFirstRecordByData("users", "email", email)
if err != nil || !isAuthRefresh {
return e.Next()
}
// auth refresh endpoint, make sure token is set in header
token, _ := e.Auth.NewAuthToken()
e.Request.Header.Set("Authorization", token)
return e.Next()
}
// authenticate with trusted header
if autoLogin, _ := GetEnv("AUTO_LOGIN"); autoLogin != "" {
se.Router.BindFunc(func(e *core.RequestEvent) error {
return authorizeRequestWithEmail(e, autoLogin)
})
}
// authenticate with trusted header
if trustedHeader, _ := GetEnv("TRUSTED_AUTH_HEADER"); trustedHeader != "" {
se.Router.BindFunc(func(e *core.RequestEvent) error {
if e.Auth != nil {
return e.Next()
}
trustedEmail := e.Request.Header.Get(trustedHeader)
if trustedEmail == "" {
return e.Next()
}
isAuthRefresh := e.Request.URL.Path == "/api/collections/users/auth-refresh" && e.Request.Method == http.MethodPost
if !isAuthRefresh {
authRecord, err := e.App.FindAuthRecordByEmail("users", trustedEmail)
if err == nil {
e.Auth = authRecord
}
return e.Next()
}
// if auth refresh endpoint, find user record directly and generate token
user, err := e.App.FindFirstRecordByData("users", "email", trustedEmail)
if err != nil {
return e.Next()
}
e.Auth = user
// need to set the authorization header for the client sdk to pick up the token
if token, err := user.NewAuthToken(); err == nil {
e.Request.Header.Set("Authorization", token)
}
return e.Next()
return authorizeRequestWithEmail(e, e.Request.Header.Get(trustedHeader))
})
}
}

View File

@@ -712,6 +712,60 @@ func TestCreateUserEndpointAvailability(t *testing.T) {
})
}
func TestAutoLoginMiddleware(t *testing.T) {
var hubs []*beszelTests.TestHub
defer func() {
defer os.Unsetenv("AUTO_LOGIN")
for _, hub := range hubs {
hub.Cleanup()
}
}()
os.Setenv("AUTO_LOGIN", "user@test.com")
testAppFactory := func(t testing.TB) *pbTests.TestApp {
hub, _ := beszelTests.NewTestHub(t.TempDir())
hubs = append(hubs, hub)
hub.StartHub()
return hub.TestApp
}
scenarios := []beszelTests.ApiScenario{
{
Name: "GET /getkey - without auto login should fail",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
ExpectedStatus: 401,
ExpectedContent: []string{"requires valid"},
TestAppFactory: testAppFactory,
},
{
Name: "GET /getkey - with auto login should fail if no matching user",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
ExpectedStatus: 401,
ExpectedContent: []string{"requires valid"},
TestAppFactory: testAppFactory,
},
{
Name: "GET /getkey - with auto login should succeed",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
ExpectedStatus: 200,
ExpectedContent: []string{"\"key\":", "\"v\":"},
TestAppFactory: testAppFactory,
BeforeTestFunc: func(t testing.TB, app *pbTests.TestApp, e *core.ServeEvent) {
beszelTests.CreateUser(app, "user@test.com", "password123")
},
},
}
for _, scenario := range scenarios {
scenario.Test(t)
}
}
func TestTrustedHeaderMiddleware(t *testing.T) {
var hubs []*beszelTests.TestHub

View File

@@ -225,6 +225,19 @@ func (rm *RecordManager) AverageSystemStats(db dbx.Builder, records RecordIds) *
sum.MaxBandwidth[0] = max(sum.MaxBandwidth[0], stats.MaxBandwidth[0], stats.Bandwidth[0])
sum.MaxBandwidth[1] = max(sum.MaxBandwidth[1], stats.MaxBandwidth[1], stats.Bandwidth[1])
// Accumulate network interfaces
if sum.NetworkInterfaces == nil {
sum.NetworkInterfaces = make(map[string][4]uint64, len(stats.NetworkInterfaces))
}
for key, value := range stats.NetworkInterfaces {
sum.NetworkInterfaces[key] = [4]uint64{
sum.NetworkInterfaces[key][0] + value[0],
sum.NetworkInterfaces[key][1] + value[1],
max(sum.NetworkInterfaces[key][2], value[2]),
max(sum.NetworkInterfaces[key][3], value[3]),
}
}
// Accumulate temperatures
if stats.Temperatures != nil {
if sum.Temperatures == nil {
@@ -299,6 +312,19 @@ func (rm *RecordManager) AverageSystemStats(db dbx.Builder, records RecordIds) *
sum.Bandwidth[0] = sum.Bandwidth[0] / uint64(count)
sum.Bandwidth[1] = sum.Bandwidth[1] / uint64(count)
sum.Battery[0] = uint8(batterySum / int(count))
// Average network interfaces
if sum.NetworkInterfaces != nil {
for key := range sum.NetworkInterfaces {
sum.NetworkInterfaces[key] = [4]uint64{
sum.NetworkInterfaces[key][0] / uint64(count),
sum.NetworkInterfaces[key][1] / uint64(count),
sum.NetworkInterfaces[key][2],
sum.NetworkInterfaces[key][3],
}
}
}
// Average temperatures
if sum.Temperatures != nil && tempCount > 0 {
for key := range sum.Temperatures {

View File

@@ -175,7 +175,7 @@ func TestDeleteOldSystemStats(t *testing.T) {
}
// Run deletion
err = records.TestDeleteOldSystemStats(hub)
err = records.DeleteOldSystemStats(hub)
require.NoError(t, err)
// Verify results
@@ -268,7 +268,7 @@ func TestDeleteOldAlertsHistory(t *testing.T) {
assert.Equal(t, int64(tc.alertCount), countBefore, "Initial count should match")
// Run deletion
err = records.TestDeleteOldAlertsHistory(hub, tc.countToKeep, tc.countBeforeDeletion)
err = records.DeleteOldAlertsHistory(hub, tc.countToKeep, tc.countBeforeDeletion)
require.NoError(t, err)
// Count after deletion
@@ -332,7 +332,7 @@ func TestDeleteOldAlertsHistoryEdgeCases(t *testing.T) {
}
// Should not error and should not delete anything
err = records.TestDeleteOldAlertsHistory(hub, 10, 20)
err = records.DeleteOldAlertsHistory(hub, 10, 20)
require.NoError(t, err)
count, err := hub.CountRecords("alerts_history")
@@ -346,7 +346,7 @@ func TestDeleteOldAlertsHistoryEdgeCases(t *testing.T) {
require.NoError(t, err)
// Should not error with empty table
err = records.TestDeleteOldAlertsHistory(hub, 10, 20)
err = records.DeleteOldAlertsHistory(hub, 10, 20)
require.NoError(t, err)
})
}
@@ -376,7 +376,7 @@ func TestTwoDecimals(t *testing.T) {
}
for _, tc := range testCases {
result := records.TestTwoDecimals(tc.input)
result := records.TwoDecimals(tc.input)
assert.InDelta(t, tc.expected, result, 0.02, "twoDecimals(%f) should equal %f", tc.input, tc.expected)
}
}

View File

@@ -7,17 +7,17 @@ import (
"github.com/pocketbase/pocketbase/core"
)
// TestDeleteOldSystemStats exposes deleteOldSystemStats for testing
func TestDeleteOldSystemStats(app core.App) error {
// DeleteOldSystemStats exposes deleteOldSystemStats for testing
func DeleteOldSystemStats(app core.App) error {
return deleteOldSystemStats(app)
}
// TestDeleteOldAlertsHistory exposes deleteOldAlertsHistory for testing
func TestDeleteOldAlertsHistory(app core.App, countToKeep, countBeforeDeletion int) error {
// DeleteOldAlertsHistory exposes deleteOldAlertsHistory for testing
func DeleteOldAlertsHistory(app core.App, countToKeep, countBeforeDeletion int) error {
return deleteOldAlertsHistory(app, countToKeep, countBeforeDeletion)
}
// TestTwoDecimals exposes twoDecimals for testing
func TestTwoDecimals(value float64) float64 {
// TwoDecimals exposes twoDecimals for testing
func TwoDecimals(value float64) float64 {
return twoDecimals(value)
}

View File

@@ -17,7 +17,10 @@
"linter": {
"enabled": true,
"rules": {
"recommended": true
"recommended": true,
"correctness": {
"useUniqueElementIds": "off"
}
}
},
"javascript": {
@@ -35,4 +38,4 @@
}
}
}
}
}

View File

@@ -1,12 +1,12 @@
{
"name": "beszel",
"version": "0.12.7",
"version": "0.12.8",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "beszel",
"version": "0.12.7",
"version": "0.12.8",
"dependencies": {
"@henrygd/queue": "^1.0.7",
"@henrygd/semaphore": "^0.0.2",
@@ -46,6 +46,7 @@
"valibot": "^0.42.1"
},
"devDependencies": {
"@biomejs/biome": "2.2.3",
"@lingui/cli": "^5.4.1",
"@lingui/swc-plugin": "^5.6.1",
"@lingui/vite-plugin": "^5.4.1",
@@ -330,6 +331,169 @@
"node": ">=6.9.0"
}
},
"node_modules/@biomejs/biome": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/biome/-/biome-2.2.3.tgz",
"integrity": "sha512-9w0uMTvPrIdvUrxazZ42Ib7t8Y2yoGLKLdNne93RLICmaHw7mcLv4PPb5LvZLJF3141gQHiCColOh/v6VWlWmg==",
"dev": true,
"license": "MIT OR Apache-2.0",
"bin": {
"biome": "bin/biome"
},
"engines": {
"node": ">=14.21.3"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/biome"
},
"optionalDependencies": {
"@biomejs/cli-darwin-arm64": "2.2.3",
"@biomejs/cli-darwin-x64": "2.2.3",
"@biomejs/cli-linux-arm64": "2.2.3",
"@biomejs/cli-linux-arm64-musl": "2.2.3",
"@biomejs/cli-linux-x64": "2.2.3",
"@biomejs/cli-linux-x64-musl": "2.2.3",
"@biomejs/cli-win32-arm64": "2.2.3",
"@biomejs/cli-win32-x64": "2.2.3"
}
},
"node_modules/@biomejs/cli-darwin-arm64": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-arm64/-/cli-darwin-arm64-2.2.3.tgz",
"integrity": "sha512-OrqQVBpadB5eqzinXN4+Q6honBz+tTlKVCsbEuEpljK8ASSItzIRZUA02mTikl3H/1nO2BMPFiJ0nkEZNy3B1w==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=14.21.3"
}
},
"node_modules/@biomejs/cli-darwin-x64": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-darwin-x64/-/cli-darwin-x64-2.2.3.tgz",
"integrity": "sha512-OCdBpb1TmyfsTgBAM1kPMXyYKTohQ48WpiN9tkt9xvU6gKVKHY4oVwteBebiOqyfyzCNaSiuKIPjmHjUZ2ZNMg==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=14.21.3"
}
},
"node_modules/@biomejs/cli-linux-arm64": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64/-/cli-linux-arm64-2.2.3.tgz",
"integrity": "sha512-g/Uta2DqYpECxG+vUmTAmUKlVhnGEcY7DXWgKP8ruLRa8Si1QHsWknPY3B/wCo0KgYiFIOAZ9hjsHfNb9L85+g==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.21.3"
}
},
"node_modules/@biomejs/cli-linux-arm64-musl": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-arm64-musl/-/cli-linux-arm64-musl-2.2.3.tgz",
"integrity": "sha512-q3w9jJ6JFPZPeqyvwwPeaiS/6NEszZ+pXKF+IczNo8Xj6fsii45a4gEEicKyKIytalV+s829ACZujQlXAiVLBQ==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.21.3"
}
},
"node_modules/@biomejs/cli-linux-x64": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64/-/cli-linux-x64-2.2.3.tgz",
"integrity": "sha512-LEtyYL1fJsvw35CxrbQ0gZoxOG3oZsAjzfRdvRBRHxOpQ91Q5doRVjvWW/wepgSdgk5hlaNzfeqpyGmfSD0Eyw==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.21.3"
}
},
"node_modules/@biomejs/cli-linux-x64-musl": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-linux-x64-musl/-/cli-linux-x64-musl-2.2.3.tgz",
"integrity": "sha512-y76Dn4vkP1sMRGPFlNc+OTETBhGPJ90jY3il6jAfur8XWrYBQV3swZ1Jo0R2g+JpOeeoA0cOwM7mJG6svDz79w==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=14.21.3"
}
},
"node_modules/@biomejs/cli-win32-arm64": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-arm64/-/cli-win32-arm64-2.2.3.tgz",
"integrity": "sha512-Ms9zFYzjcJK7LV+AOMYnjN3pV3xL8Prxf9aWdDVL74onLn5kcvZ1ZMQswE5XHtnd/r/0bnUd928Rpbs14BzVmA==",
"cpu": [
"arm64"
],
"dev": true,
"license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=14.21.3"
}
},
"node_modules/@biomejs/cli-win32-x64": {
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/@biomejs/cli-win32-x64/-/cli-win32-x64-2.2.3.tgz",
"integrity": "sha512-gvCpewE7mBwBIpqk1YrUqNR4mCiyJm6UI3YWQQXkedSSEwzRdodRpaKhbdbHw1/hmTWOVXQ+Eih5Qctf4TCVOQ==",
"cpu": [
"x64"
],
"dev": true,
"license": "MIT OR Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=14.21.3"
}
},
"node_modules/@esbuild/aix-ppc64": {
"version": "0.25.6",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.6.tgz",
@@ -5763,14 +5927,14 @@
"license": "MIT"
},
"node_modules/tinyglobby": {
"version": "0.2.14",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.14.tgz",
"integrity": "sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ==",
"version": "0.2.15",
"resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
"integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
"dev": true,
"license": "MIT",
"dependencies": {
"fdir": "^6.4.4",
"picomatch": "^4.0.2"
"fdir": "^6.5.0",
"picomatch": "^4.0.3"
},
"engines": {
"node": ">=12.0.0"
@@ -5957,9 +6121,9 @@
}
},
"node_modules/vite": {
"version": "7.1.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz",
"integrity": "sha512-OOUi5zjkDxYrKhTV3V7iKsoS37VUM7v40+HuwEmcrsf11Cdx9y3DIr2Px6liIcZFwt3XSRpQvFpL3WVy7ApkGw==",
"version": "7.1.5",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.5.tgz",
"integrity": "sha512-4cKBO9wR75r0BeIWWWId9XK9Lj6La5X846Zw9dFfzMRw38IlTk2iCcUt6hsyiDRcPidc55ZParFYDXi0nXOeLQ==",
"dev": true,
"license": "MIT",
"dependencies": {
@@ -5968,7 +6132,7 @@
"picomatch": "^4.0.3",
"postcss": "^8.5.6",
"rollup": "^4.43.0",
"tinyglobby": "^0.2.14"
"tinyglobby": "^0.2.15"
},
"bin": {
"vite": "bin/vite.js"

View File

@@ -1,7 +1,7 @@
{
"name": "beszel",
"private": true,
"version": "0.12.7",
"version": "0.12.8",
"type": "module",
"scripts": {
"dev": "vite --host",
@@ -76,4 +76,4 @@
"optionalDependencies": {
"@esbuild/linux-arm64": "^0.21.5"
}
}
}

View File

@@ -1,5 +1,9 @@
import { Trans } from "@lingui/react/macro"
import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro"
import { useStore } from "@nanostores/react"
import { getPagePath } from "@nanostores/router"
import { ChevronDownIcon, ExternalLinkIcon, PlusIcon } from "lucide-react"
import { memo, useEffect, useRef, useState } from "react"
import { Button } from "@/components/ui/button"
import {
Dialog,
@@ -10,34 +14,30 @@ import {
DialogTitle,
DialogTrigger,
} from "@/components/ui/dialog"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { isReadOnlyUser, pb } from "@/lib/api"
import { SystemStatus } from "@/lib/enums"
import { $publicKey } from "@/lib/stores"
import { cn, generateToken, tokenMap, useBrowserStorage } from "@/lib/utils"
import { pb, isReadOnlyUser } from "@/lib/api"
import { useStore } from "@nanostores/react"
import { ChevronDownIcon, ExternalLinkIcon, PlusIcon } from "lucide-react"
import { memo, useEffect, useRef, useState } from "react"
import { $router, basePath, Link, navigate } from "./router"
import { SystemRecord } from "@/types"
import { SystemStatus } from "@/lib/enums"
import { AppleIcon, DockerIcon, TuxIcon, WindowsIcon } from "./ui/icons"
import { InputCopy } from "./ui/input-copy"
import { getPagePath } from "@nanostores/router"
import type { SystemRecord } from "@/types"
import {
copyDockerCompose,
copyDockerRun,
copyLinuxCommand,
copyWindowsCommand,
DropdownItem,
type DropdownItem,
InstallDropdown,
} from "./install-dropdowns"
import { $router, basePath, Link, navigate } from "./router"
import { DropdownMenu, DropdownMenuTrigger } from "./ui/dropdown-menu"
import { AppleIcon, DockerIcon, FreeBsdIcon, TuxIcon, WindowsIcon } from "./ui/icons"
import { InputCopy } from "./ui/input-copy"
export function AddSystemButton({ className }: { className?: string }) {
const [open, setOpen] = useState(false)
let opened = useRef(false)
const opened = useRef(false)
if (open) {
opened.current = true
}
@@ -253,6 +253,12 @@ export const SystemDialog = ({ setOpen, system }: { setOpen: (open: boolean) =>
copyWindowsCommand(isUnixSocket ? hostValue : port.current?.value, publicKey, token),
icons: [WindowsIcon],
},
{
text: t({ message: "FreeBSD command", context: "Button to copy install command" }),
onClick: async () =>
copyLinuxCommand(isUnixSocket ? hostValue : port.current?.value, publicKey, token),
icons: [FreeBsdIcon],
},
{
text: t`Manual setup instructions`,
url: "https://beszel.dev/guide/agent-installation#binary",

View File

@@ -1,11 +1,11 @@
import { ColumnDef } from "@tanstack/react-table"
import { AlertsHistoryRecord } from "@/types"
import { Button } from "@/components/ui/button"
import { Badge } from "@/components/ui/badge"
import { formatShortDate, toFixedFloat, formatDuration, cn } from "@/lib/utils"
import { alertInfo } from "@/lib/alerts"
import { Trans } from "@lingui/react/macro"
import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro"
import type { ColumnDef } from "@tanstack/react-table"
import { Badge } from "@/components/ui/badge"
import { Button } from "@/components/ui/button"
import { alertInfo } from "@/lib/alerts"
import { cn, formatDuration, formatShortDate, toFixedFloat } from "@/lib/utils"
import type { AlertsHistoryRecord } from "@/types"
export const alertsHistoryColumns: ColumnDef<AlertsHistoryRecord>[] = [
{
@@ -38,7 +38,7 @@ export const alertsHistoryColumns: ColumnDef<AlertsHistoryRecord>[] = [
</Button>
),
cell: ({ getValue, row }) => {
let name = getValue() as string
const name = getValue() as string
const info = alertInfo[row.original.name]
const Icon = info?.icon

View File

@@ -1,13 +1,13 @@
import { t } from "@lingui/core/macro"
import { memo, useMemo, useState } from "react"
import { useStore } from "@nanostores/react"
import { $alerts } from "@/lib/stores"
import { BellIcon } from "lucide-react"
import { cn } from "@/lib/utils"
import { memo, useMemo, useState } from "react"
import { Button } from "@/components/ui/button"
import { SystemRecord } from "@/types"
import { AlertDialogContent } from "./alerts-sheet"
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
import { $alerts } from "@/lib/stores"
import { cn } from "@/lib/utils"
import type { SystemRecord } from "@/types"
import { AlertDialogContent } from "./alerts-sheet"
export default memo(function AlertsButton({ system }: { system: SystemRecord }) {
const [opened, setOpened] = useState(false)

View File

@@ -1,21 +1,20 @@
import { t } from "@lingui/core/macro"
import { Trans, Plural } from "@lingui/react/macro"
import { $alerts, $systems } from "@/lib/stores"
import { cn, debounce } from "@/lib/utils"
import { alertInfo } from "@/lib/alerts"
import { Switch } from "@/components/ui/switch"
import { AlertInfo, AlertRecord, SystemRecord } from "@/types"
import { lazy, memo, Suspense, useMemo, useState } from "react"
import { toast } from "@/components/ui/use-toast"
import { Plural, Trans } from "@lingui/react/macro"
import { useStore } from "@nanostores/react"
import { getPagePath } from "@nanostores/router"
import { Checkbox } from "@/components/ui/checkbox"
import { DialogTitle, DialogDescription } from "@/components/ui/dialog"
import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"
import { ServerIcon, GlobeIcon } from "lucide-react"
import { GlobeIcon, ServerIcon } from "lucide-react"
import { lazy, memo, Suspense, useMemo, useState } from "react"
import { $router, Link } from "@/components/router"
import { DialogHeader } from "@/components/ui/dialog"
import { Checkbox } from "@/components/ui/checkbox"
import { DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { Switch } from "@/components/ui/switch"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { toast } from "@/components/ui/use-toast"
import { alertInfo } from "@/lib/alerts"
import { pb } from "@/lib/api"
import { $alerts, $systems } from "@/lib/stores"
import { cn, debounce } from "@/lib/utils"
import type { AlertInfo, AlertRecord, SystemRecord } from "@/types"
const Slider = lazy(() => import("@/components/ui/slider"))
@@ -172,7 +171,7 @@ export function AlertContent({
const [checked, setChecked] = useState(global ? false : !!alert)
const [min, setMin] = useState(alert?.min || 10)
const [value, setValue] = useState(alert?.value || (singleDescription ? 0 : alertData.start ?? 80))
const [value, setValue] = useState(alert?.value || (singleDescription ? 0 : (alertData.start ?? 80)))
const Icon = alertData.icon

View File

@@ -1,9 +1,16 @@
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { cn, formatShortDate, chartMargin } from "@/lib/utils"
import { useYAxisWidth } from "./hooks"
import { ChartData, SystemStatsRecord } from "@/types"
import { useMemo } from "react"
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import {
ChartContainer,
ChartLegend,
ChartLegendContent,
ChartTooltip,
ChartTooltipContent,
xAxis,
} from "@/components/ui/chart"
import { chartMargin, cn, formatShortDate } from "@/lib/utils"
import type { ChartData, SystemStatsRecord } from "@/types"
import { useYAxisWidth } from "./hooks"
export type DataPoint = {
label: string
@@ -20,6 +27,8 @@ export default function AreaChartDefault({
contentFormatter,
dataPoints,
domain,
legend,
itemSorter,
}: // logRender = false,
{
chartData: ChartData
@@ -29,10 +38,13 @@ export default function AreaChartDefault({
contentFormatter: ({ value, payload }: { value: number; payload: SystemStatsRecord }) => string
dataPoints?: DataPoint[]
domain?: [number, number]
legend?: boolean
itemSorter?: (a: any, b: any) => number
// logRender?: boolean
}) {
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()
// biome-ignore lint/correctness/useExhaustiveDependencies: ignore
return useMemo(() => {
if (chartData.systemStats.length === 0) {
return null
@@ -63,6 +75,8 @@ export default function AreaChartDefault({
<ChartTooltip
animationEasing="ease-out"
animationDuration={150}
// @ts-expect-error
itemSorter={itemSorter}
content={
<ChartTooltipContent
labelFormatter={(_, data) => formatShortDate(data[0].payload.created)}
@@ -70,11 +84,14 @@ export default function AreaChartDefault({
/>
}
/>
{dataPoints?.map((dataPoint, i) => {
const color = `var(--chart-${dataPoint.color})`
{dataPoints?.map((dataPoint) => {
let { color } = dataPoint
if (typeof color === "number") {
color = `var(--chart-${color})`
}
return (
<Area
key={i}
key={dataPoint.label}
dataKey={dataPoint.dataKey}
name={dataPoint.label}
type="monotoneX"
@@ -85,7 +102,7 @@ export default function AreaChartDefault({
/>
)
})}
{/* <ChartLegend content={<ChartLegendContent />} /> */}
{legend && <ChartLegend content={<ChartLegendContent />} />}
</AreaChart>
</ChartContainer>
</div>

View File

@@ -1,9 +1,9 @@
import { useStore } from "@nanostores/react"
import { HistoryIcon } from "lucide-react"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"
import { $chartTime } from "@/lib/stores"
import { chartTimeData, cn } from "@/lib/utils"
import { ChartTimes } from "@/types"
import { useStore } from "@nanostores/react"
import { HistoryIcon } from "lucide-react"
import type { ChartTimes } from "@/types"
export default function ChartTimeSelect({ className }: { className?: string }) {
const chartTime = useStore($chartTime)

View File

@@ -1,13 +1,13 @@
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { memo, useMemo } from "react"
import { cn, formatShortDate, chartMargin, toFixedFloat, formatBytes, decimalString } from "@/lib/utils"
// import Spinner from '../spinner'
import { useStore } from "@nanostores/react"
import { memo, useMemo } from "react"
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { ChartType, Unit } from "@/lib/enums"
import { $containerFilter, $userSettings } from "@/lib/stores"
import { chartMargin, cn, decimalString, formatBytes, formatShortDate, toFixedFloat } from "@/lib/utils"
import type { ChartData } from "@/types"
import { Separator } from "../ui/separator"
import { ChartType, Unit } from "@/lib/enums"
import { useYAxisWidth } from "./hooks"
export default memo(function ContainerChart({

View File

@@ -1,10 +1,10 @@
import { useLingui } from "@lingui/react/macro"
import { memo } from "react"
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { cn, formatShortDate, decimalString, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils"
import { ChartData } from "@/types"
import { memo } from "react"
import { useLingui } from "@lingui/react/macro"
import { Unit } from "@/lib/enums"
import { chartMargin, cn, decimalString, formatBytes, formatShortDate, toFixedFloat } from "@/lib/utils"
import type { ChartData } from "@/types"
import { useYAxisWidth } from "./hooks"
export default memo(function DiskChart({

View File

@@ -1,5 +1,5 @@
import { memo, useMemo } from "react"
import { CartesianGrid, Line, LineChart, YAxis } from "recharts"
import {
ChartContainer,
ChartLegend,
@@ -8,9 +8,8 @@ import {
ChartTooltipContent,
xAxis,
} from "@/components/ui/chart"
import { cn, formatShortDate, toFixedFloat, decimalString, chartMargin } from "@/lib/utils"
import { ChartData } from "@/types"
import { memo, useMemo } from "react"
import { chartMargin, cn, decimalString, formatShortDate, toFixedFloat } from "@/lib/utils"
import type { ChartData } from "@/types"
import { useYAxisWidth } from "./hooks"
export default memo(function GpuPowerChart({ chartData }: { chartData: ChartData }) {
@@ -27,10 +26,10 @@ export default memo(function GpuPowerChart({ chartData }: { chartData: ChartData
colors: Record<string, string>
}
const powerSums = {} as Record<string, number>
for (let data of chartData.systemStats) {
let newData = { created: data.created } as Record<string, number | string>
for (const data of chartData.systemStats) {
const newData = { created: data.created } as Record<string, number | string>
for (let gpu of Object.values(data.stats?.g ?? {})) {
for (const gpu of Object.values(data.stats?.g ?? {})) {
if (gpu.p) {
const name = gpu.n
newData[name] = gpu.p
@@ -40,7 +39,7 @@ export default memo(function GpuPowerChart({ chartData }: { chartData: ChartData
newChartData.data.push(newData)
}
const keys = Object.keys(powerSums).sort((a, b) => powerSums[b] - powerSums[a])
for (let key of keys) {
for (const key of keys) {
newChartData.colors[key] = `hsl(${((keys.indexOf(key) * 360) / keys.length) % 360}, 60%, 55%)`
}
return newChartData
@@ -67,7 +66,7 @@ export default memo(function GpuPowerChart({ chartData }: { chartData: ChartData
width={yAxisWidth}
tickFormatter={(value) => {
const val = toFixedFloat(value, 2)
return updateYAxisWidth(val + "W")
return updateYAxisWidth(`${val}W`)
}}
tickLine={false}
axisLine={false}
@@ -76,12 +75,12 @@ export default memo(function GpuPowerChart({ chartData }: { chartData: ChartData
<ChartTooltip
animationEasing="ease-out"
animationDuration={150}
// @ts-ignore
// @ts-expect-error
itemSorter={(a, b) => b.value - a.value}
content={
<ChartTooltipContent
labelFormatter={(_, data) => formatShortDate(data[0].payload.created)}
contentFormatter={(item) => decimalString(item.value) + "W"}
contentFormatter={(item) => `${decimalString(item.value)}W`}
// indicator="line"
/>
}

View File

@@ -1,6 +1,6 @@
import { useMemo, useState } from "react"
import { ChartConfig } from "@/components/ui/chart"
import { ChartData } from "@/types"
import type { ChartConfig } from "@/components/ui/chart"
import type { ChartData, SystemStats, SystemStatsRecord } from "@/types"
/** Chart configurations for CPU, memory, and network usage charts */
export interface ContainerChartConfigs {
@@ -105,3 +105,21 @@ export function useYAxisWidth() {
}
return { yAxisWidth, updateYAxisWidth }
}
// Assures consistent colors for network interfaces
export function useNetworkInterfaces(interfaces: SystemStats["ni"]) {
const keys = Object.keys(interfaces ?? {})
const sortedKeys = keys.sort((a, b) => (interfaces?.[b]?.[3] ?? 0) - (interfaces?.[a]?.[3] ?? 0))
return {
length: sortedKeys.length,
data: (index = 3) => {
return sortedKeys.map((key) => ({
label: key,
dataKey: (stats: SystemStatsRecord) => stats.stats?.ni?.[key]?.[index],
color: `hsl(${220 + (((sortedKeys.indexOf(key) * 360) / sortedKeys.length) % 360)}, 70%, 50%)`,
opacity: 0.3,
}))
},
}
}

View File

@@ -0,0 +1,110 @@
import { useMemo } from "react"
import { CartesianGrid, Line, LineChart, YAxis } from "recharts"
import {
ChartContainer,
ChartLegend,
ChartLegendContent,
ChartTooltip,
ChartTooltipContent,
xAxis,
} from "@/components/ui/chart"
import { chartMargin, cn, formatShortDate } from "@/lib/utils"
import type { ChartData, SystemStatsRecord } from "@/types"
import { useYAxisWidth } from "./hooks"
export type DataPoint = {
label: string
dataKey: (data: SystemStatsRecord) => number | undefined
color: number | string
}
export default function LineChartDefault({
chartData,
max,
maxToggled,
tickFormatter,
contentFormatter,
dataPoints,
domain,
legend,
itemSorter,
}: // logRender = false,
{
chartData: ChartData
max?: number
maxToggled?: boolean
tickFormatter: (value: number, index: number) => string
contentFormatter: ({ value, payload }: { value: number; payload: SystemStatsRecord }) => string
dataPoints?: DataPoint[]
domain?: [number, number]
legend?: boolean
itemSorter?: (a: any, b: any) => number
// logRender?: boolean
}) {
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()
// biome-ignore lint/correctness/useExhaustiveDependencies: ignore
return useMemo(() => {
if (chartData.systemStats.length === 0) {
return null
}
// if (logRender) {
// console.log("Rendered at", new Date())
// }
return (
<div>
<ChartContainer
className={cn("h-full w-full absolute aspect-auto bg-card opacity-0 transition-opacity", {
"opacity-100": yAxisWidth,
})}
>
<LineChart accessibilityLayer data={chartData.systemStats} margin={chartMargin}>
<CartesianGrid vertical={false} />
<YAxis
direction="ltr"
orientation={chartData.orientation}
className="tracking-tighter"
width={yAxisWidth}
domain={domain ?? [0, max ?? "auto"]}
tickFormatter={(value, index) => updateYAxisWidth(tickFormatter(value, index))}
tickLine={false}
axisLine={false}
/>
{xAxis(chartData)}
<ChartTooltip
animationEasing="ease-out"
animationDuration={150}
// @ts-expect-error
itemSorter={itemSorter}
content={
<ChartTooltipContent
labelFormatter={(_, data) => formatShortDate(data[0].payload.created)}
contentFormatter={contentFormatter}
/>
}
/>
{dataPoints?.map((dataPoint) => {
let { color } = dataPoint
if (typeof color === "number") {
color = `var(--chart-${color})`
}
return (
<Line
key={dataPoint.label}
dataKey={dataPoint.dataKey}
name={dataPoint.label}
type="monotoneX"
dot={false}
strokeWidth={1.5}
stroke={color}
isAnimationActive={false}
/>
)
})}
{legend && <ChartLegend content={<ChartLegendContent />} />}
</LineChart>
</ChartContainer>
</div>
)
}, [chartData.systemStats.at(-1), yAxisWidth, maxToggled])
}

View File

@@ -1,5 +1,6 @@
import { t } from "@lingui/core/macro"
import { memo } from "react"
import { CartesianGrid, Line, LineChart, YAxis } from "recharts"
import {
ChartContainer,
ChartLegend,
@@ -8,10 +9,8 @@ import {
ChartTooltipContent,
xAxis,
} from "@/components/ui/chart"
import { cn, formatShortDate, toFixedFloat, decimalString, chartMargin } from "@/lib/utils"
import { ChartData, SystemStats } from "@/types"
import { memo } from "react"
import { t } from "@lingui/core/macro"
import { chartMargin, cn, decimalString, formatShortDate, toFixedFloat } from "@/lib/utils"
import type { ChartData, SystemStats } from "@/types"
import { useYAxisWidth } from "./hooks"
export default memo(function LoadAverageChart({ chartData }: { chartData: ChartData }) {
@@ -60,7 +59,7 @@ export default memo(function LoadAverageChart({ chartData }: { chartData: ChartD
<ChartTooltip
animationEasing="ease-out"
animationDuration={150}
// @ts-ignore
// @ts-expect-error
// itemSorter={(a, b) => b.value - a.value}
content={
<ChartTooltipContent

View File

@@ -1,10 +1,10 @@
import { useLingui } from "@lingui/react/macro"
import { memo } from "react"
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { cn, decimalString, formatShortDate, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils"
import { memo } from "react"
import { ChartData } from "@/types"
import { useLingui } from "@lingui/react/macro"
import { Unit } from "@/lib/enums"
import { chartMargin, cn, decimalString, formatBytes, formatShortDate, toFixedFloat } from "@/lib/utils"
import type { ChartData } from "@/types"
import { useYAxisWidth } from "./hooks"
export default memo(function MemChart({ chartData, showMax }: { chartData: ChartData; showMax: boolean }) {
@@ -53,7 +53,7 @@ export default memo(function MemChart({ chartData, showMax }: { chartData: Chart
animationDuration={150}
content={
<ChartTooltipContent
// @ts-ignore
// @ts-expect-error
itemSorter={(a, b) => a.order - b.order}
labelFormatter={(_, data) => formatShortDate(data[0].payload.created)}
contentFormatter={({ value }) => {

View File

@@ -1,12 +1,11 @@
import { t } from "@lingui/core/macro"
import { useStore } from "@nanostores/react"
import { memo } from "react"
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { cn, formatShortDate, decimalString, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils"
import { ChartData } from "@/types"
import { memo } from "react"
import { $userSettings } from "@/lib/stores"
import { useStore } from "@nanostores/react"
import { chartMargin, cn, decimalString, formatBytes, formatShortDate, toFixedFloat } from "@/lib/utils"
import type { ChartData } from "@/types"
import { useYAxisWidth } from "./hooks"
export default memo(function SwapChart({ chartData }: { chartData: ChartData }) {

View File

@@ -1,5 +1,6 @@
import { useStore } from "@nanostores/react"
import { memo, useMemo } from "react"
import { CartesianGrid, Line, LineChart, YAxis } from "recharts"
import {
ChartContainer,
ChartLegend,
@@ -8,11 +9,9 @@ import {
ChartTooltipContent,
xAxis,
} from "@/components/ui/chart"
import { cn, formatShortDate, toFixedFloat, chartMargin, formatTemperature, decimalString } from "@/lib/utils"
import { ChartData } from "@/types"
import { memo, useMemo } from "react"
import { $temperatureFilter, $userSettings } from "@/lib/stores"
import { useStore } from "@nanostores/react"
import { chartMargin, cn, decimalString, formatShortDate, formatTemperature, toFixedFloat } from "@/lib/utils"
import type { ChartData } from "@/types"
import { useYAxisWidth } from "./hooks"
export default memo(function TemperatureChart({ chartData }: { chartData: ChartData }) {
@@ -31,18 +30,18 @@ export default memo(function TemperatureChart({ chartData }: { chartData: ChartD
colors: Record<string, string>
}
const tempSums = {} as Record<string, number>
for (let data of chartData.systemStats) {
let newData = { created: data.created } as Record<string, number | string>
let keys = Object.keys(data.stats?.t ?? {})
for (const data of chartData.systemStats) {
const newData = { created: data.created } as Record<string, number | string>
const keys = Object.keys(data.stats?.t ?? {})
for (let i = 0; i < keys.length; i++) {
let key = keys[i]
const key = keys[i]
newData[key] = data.stats.t![key]
tempSums[key] = (tempSums[key] ?? 0) + newData[key]
}
newChartData.data.push(newData)
}
const keys = Object.keys(tempSums).sort((a, b) => tempSums[b] - tempSums[a])
for (let key of keys) {
for (const key of keys) {
newChartData.colors[key] = `hsl(${((keys.indexOf(key) * 360) / keys.length) % 360}, 60%, 55%)`
}
return newChartData
@@ -78,7 +77,7 @@ export default memo(function TemperatureChart({ chartData }: { chartData: ChartD
<ChartTooltip
animationEasing="ease-out"
animationDuration={150}
// @ts-ignore
// @ts-expect-error
itemSorter={(a, b) => b.value - a.value}
content={
<ChartTooltipContent
@@ -93,7 +92,7 @@ export default memo(function TemperatureChart({ chartData }: { chartData: ChartD
/>
{colors.map((key) => {
const filtered = filter && !key.toLowerCase().includes(filter.toLowerCase())
let strokeOpacity = filtered ? 0.1 : 1
const strokeOpacity = filtered ? 0.1 : 1
return (
<Line
key={key}

View File

@@ -1,3 +1,7 @@
import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro"
import { getPagePath } from "@nanostores/router"
import { DialogDescription } from "@radix-ui/react-dialog"
import {
AlertOctagonIcon,
BookIcon,
@@ -10,7 +14,7 @@ import {
SettingsIcon,
UsersIcon,
} from "lucide-react"
import { memo, useEffect, useMemo } from "react"
import {
CommandDialog,
CommandEmpty,
@@ -21,15 +25,10 @@ import {
CommandSeparator,
CommandShortcut,
} from "@/components/ui/command"
import { memo, useEffect, useMemo } from "react"
import { isAdmin } from "@/lib/api"
import { $systems } from "@/lib/stores"
import { getHostDisplayValue, listen } from "@/lib/utils"
import { $router, basePath, navigate, prependBasePath } from "./router"
import { Trans } from "@lingui/react/macro"
import { t } from "@lingui/core/macro"
import { getPagePath } from "@nanostores/router"
import { DialogDescription } from "@radix-ui/react-dialog"
import { isAdmin } from "@/lib/api"
export default memo(function CommandPalette({ open, setOpen }: { open: boolean; setOpen: (open: boolean) => void }) {
useEffect(() => {

View File

@@ -1,8 +1,8 @@
import { Trans } from "@lingui/react/macro";
import { Trans } from "@lingui/react/macro"
import { useEffect, useMemo, useRef } from "react"
import { $copyContent } from "@/lib/stores"
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "./ui/dialog"
import { Textarea } from "./ui/textarea"
import { $copyContent } from "@/lib/stores"
export default function CopyToClipboard({ content }: { content: string }) {
return (

View File

@@ -1,7 +1,7 @@
import { memo } from "react"
import { DropdownMenuContent, DropdownMenuItem } from "./ui/dropdown-menu"
import { copyToClipboard, getHubURL } from "@/lib/utils"
import { i18n } from "@lingui/core"
import { memo } from "react"
import { copyToClipboard, getHubURL } from "@/lib/utils"
import { DropdownMenuContent, DropdownMenuItem } from "./ui/dropdown-menu"
// const isbeta = beszel.hub_version.includes("beta")
// const imagetag = isbeta ? ":edge" : ""

View File

@@ -1,11 +1,10 @@
import { useLingui } from "@lingui/react/macro"
import { LanguagesIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
import { dynamicActivate } from "@/lib/i18n"
import languages from "@/lib/languages"
import { cn } from "@/lib/utils"
import { useLingui } from "@lingui/react/macro"
import { dynamicActivate } from "@/lib/i18n"
export function LangToggle() {
const { i18n } = useLingui()

View File

@@ -1,19 +1,19 @@
import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro"
import { cn } from "@/lib/utils"
import { getPagePath } from "@nanostores/router"
import { KeyIcon, LoaderCircle, LockIcon, LogInIcon, MailIcon } from "lucide-react"
import type { AuthMethodsList, AuthProviderInfo, OAuth2AuthConfig } from "pocketbase"
import { useCallback, useEffect, useState } from "react"
import * as v from "valibot"
import { buttonVariants } from "@/components/ui/button"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "@/components/ui/dialog"
import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label"
import { KeyIcon, LoaderCircle, LockIcon, LogInIcon, MailIcon } from "lucide-react"
import { $authenticated } from "@/lib/stores"
import * as v from "valibot"
import { toast } from "../ui/use-toast"
import { Dialog, DialogContent, DialogTrigger, DialogHeader, DialogTitle } from "@/components/ui/dialog"
import { useCallback, useEffect, useState } from "react"
import { AuthMethodsList, AuthProviderInfo, OAuth2AuthConfig } from "pocketbase"
import { $router, Link, prependBasePath } from "../router"
import { getPagePath } from "@nanostores/router"
import { pb } from "@/lib/api"
import { $authenticated } from "@/lib/stores"
import { cn } from "@/lib/utils"
import { $router, Link, prependBasePath } from "../router"
import { toast } from "../ui/use-toast"
import { OtpInputForm } from "./otp-forms"
const honeypot = v.literal("")
@@ -83,9 +83,9 @@ export function UserAuthForm({
const result = v.safeParse(Schema, data)
if (!result.success) {
console.log(result)
let errors = {}
const errors = {}
for (const issue of result.issues) {
// @ts-ignore
// @ts-expect-error
errors[issue.path[0].key] = issue.message
}
setErrors(errors)
@@ -96,7 +96,7 @@ export function UserAuthForm({
if (isFirstRun) {
// check that passwords match
if (password !== passwordConfirm) {
let msg = "Passwords do not match"
const msg = "Passwords do not match"
setErrors({ passwordConfirm: msg })
return
}

View File

@@ -1,15 +1,14 @@
import { Trans } from "@lingui/react/macro"
import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro"
import { LoaderCircle, MailIcon, SendHorizonalIcon } from "lucide-react"
import { useCallback, useState } from "react"
import { pb } from "@/lib/api"
import { cn } from "@/lib/utils"
import { buttonVariants } from "../ui/button"
import { Dialog, DialogContent, DialogHeader, DialogTitle, DialogTrigger } from "../ui/dialog"
import { Input } from "../ui/input"
import { Label } from "../ui/label"
import { useCallback, useState } from "react"
import { toast } from "../ui/use-toast"
import { buttonVariants } from "../ui/button"
import { cn } from "@/lib/utils"
import { Dialog, DialogHeader } from "../ui/dialog"
import { DialogContent, DialogTrigger, DialogTitle } from "../ui/dialog"
import { pb } from "@/lib/api"
const showLoginFaliedToast = () => {
toast({

View File

@@ -1,14 +1,14 @@
import { t } from "@lingui/core/macro"
import { UserAuthForm } from "@/components/login/auth-form"
import { Logo } from "../logo"
import { useEffect, useMemo, useState } from "react"
import { useStore } from "@nanostores/react"
import ForgotPassword from "./forgot-pass-form"
import { $router } from "../router"
import { AuthMethodsList } from "pocketbase"
import { useTheme } from "../theme-provider"
import type { AuthMethodsList } from "pocketbase"
import { useEffect, useMemo, useState } from "react"
import { UserAuthForm } from "@/components/login/auth-form"
import { pb } from "@/lib/api"
import { Logo } from "../logo"
import { ModeToggle } from "../mode-toggle"
import { $router } from "../router"
import { useTheme } from "../theme-provider"
import ForgotPassword from "./forgot-pass-form"
import { OtpRequestForm } from "./otp-forms"
export default function () {
@@ -53,7 +53,7 @@ export default function () {
<div className="min-h-svh grid items-center py-12">
<div
className="grid gap-5 w-full px-4 mx-auto"
// @ts-ignore
// @ts-expect-error
style={{ maxWidth: "21.5em", "--border": theme == "light" ? "hsl(30, 8%, 70%)" : "hsl(220, 3%, 25%)" }}
>
<div className="absolute top-3 right-3">

View File

@@ -1,15 +1,15 @@
import { Trans } from "@lingui/react/macro"
import { LoaderCircle, MailIcon, SendHorizonalIcon } from "lucide-react"
import { useCallback, useState } from "react"
import { InputOTP, InputOTPGroup, InputOTPSlot } from "@/components/ui/otp"
import { pb } from "@/lib/api"
import { $authenticated } from "@/lib/stores"
import { InputOTP, InputOTPGroup, InputOTPSlot } from "@/components/ui/otp"
import { Trans } from "@lingui/react/macro"
import { showLoginFaliedToast } from "./auth-form"
import { cn } from "@/lib/utils"
import { MailIcon, LoaderCircle, SendHorizonalIcon } from "lucide-react"
import { Label } from "../ui/label"
import { $router } from "../router"
import { buttonVariants } from "../ui/button"
import { Input } from "../ui/input"
import { $router } from "../router"
import { Label } from "../ui/label"
import { showLoginFaliedToast } from "./auth-form"
export function OtpInputForm({ otpId, mfaId }: { otpId: string; mfaId: string }) {
const [value, setValue] = useState("")

View File

@@ -1,8 +1,7 @@
import { t } from "@lingui/core/macro"
import { MoonStarIcon, SunIcon } from "lucide-react"
import { Button } from "@/components/ui/button"
import { useTheme } from "@/components/theme-provider"
import { Button } from "@/components/ui/button"
export function ModeToggle() {
const { theme, setTheme } = useTheme()

View File

@@ -1,6 +1,5 @@
import { Trans } from "@lingui/react/macro"
import { useState, lazy, Suspense } from "react"
import { Button, buttonVariants } from "@/components/ui/button"
import { getPagePath } from "@nanostores/router"
import {
DatabaseBackupIcon,
LogOutIcon,
@@ -11,23 +10,24 @@ import {
UserIcon,
UsersIcon,
} from "lucide-react"
import { $router, basePath, Link, prependBasePath } from "./router"
import { LangToggle } from "./lang-toggle"
import { ModeToggle } from "./mode-toggle"
import { Logo } from "./logo"
import { cn, runOnce } from "@/lib/utils"
import { isReadOnlyUser, isAdmin, logOut, pb } from "@/lib/api"
import { lazy, Suspense, useState } from "react"
import { Button, buttonVariants } from "@/components/ui/button"
import {
DropdownMenu,
DropdownMenuTrigger,
DropdownMenuContent,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuGroup,
DropdownMenuItem,
DropdownMenuLabel,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { isAdmin, isReadOnlyUser, logOut, pb } from "@/lib/api"
import { cn, runOnce } from "@/lib/utils"
import { AddSystemButton } from "./add-system"
import { getPagePath } from "@nanostores/router"
import { LangToggle } from "./lang-toggle"
import { Logo } from "./logo"
import { ModeToggle } from "./mode-toggle"
import { $router, basePath, Link, prependBasePath } from "./router"
const CommandPalette = lazy(() => import("./command-palette"))

View File

@@ -23,7 +23,7 @@ export const prependBasePath = (path: string) => (basePath + path).replaceAll("/
// prepend base path to routes
for (const route in routes) {
// @ts-ignore need as const above to get nanostores to parse types properly
// @ts-expect-error need as const above to get nanostores to parse types properly
routes[route] = prependBasePath(routes[route])
}

View File

@@ -3,6 +3,7 @@ import { Trans, useLingui } from "@lingui/react/macro"
import { redirectPage } from "@nanostores/router"
import {
CopyIcon,
ExternalLinkIcon,
FingerprintIcon,
KeyIcon,
MoreHorizontalIcon,
@@ -28,7 +29,7 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { AppleIcon, DockerIcon, TuxIcon, WindowsIcon } from "@/components/ui/icons"
import { AppleIcon, DockerIcon, FreeBsdIcon, TuxIcon, WindowsIcon } from "@/components/ui/icons"
import { Separator } from "@/components/ui/separator"
import { Switch } from "@/components/ui/switch"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
@@ -150,6 +151,7 @@ const SectionUniversalToken = memo(() => {
setIsLoading(false)
}
// biome-ignore lint/correctness/useExhaustiveDependencies: only on mount
useEffect(() => {
updateToken()
}, [])
@@ -221,6 +223,16 @@ const ActionsButtonUniversalToken = memo(({ token, checked }: { token: string; c
onClick: () => copyWindowsCommand(port, publicKey, token),
icons: [WindowsIcon],
},
{
text: t({ message: "FreeBSD command", context: "Button to copy install command" }),
onClick: () => copyLinuxCommand(port, publicKey, token),
icons: [FreeBsdIcon],
},
{
text: t`Manual setup instructions`,
url: "https://beszel.dev/guide/agent-installation#binary",
icons: [ExternalLinkIcon],
},
]
return (
<div className="flex items-center gap-2">
@@ -291,8 +303,8 @@ const SectionTable = memo(({ fingerprints = [] }: { fingerprints: FingerprintRec
</tr>
</TableHeader>
<TableBody className="whitespace-pre">
{fingerprints.map((fingerprint, i) => (
<TableRow key={i}>
{fingerprints.map((fingerprint) => (
<TableRow key={fingerprint.id}>
<TableCell className="font-medium ps-5 py-2 max-w-60 truncate">
{fingerprint.expand.system.name}
</TableCell>
@@ -317,10 +329,10 @@ async function updateFingerprint(fingerprint: FingerprintRecord, rotateToken = f
fingerprint: "",
token: rotateToken ? generateToken() : fingerprint.token,
})
} catch (error: any) {
} catch (error: unknown) {
toast({
title: t`Error`,
description: error.message,
description: (error as Error).message,
})
}
}

View File

@@ -52,6 +52,7 @@ import { Input } from "../ui/input"
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "../ui/select"
import { Separator } from "../ui/separator"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip"
import NetworkSheet from "./system/network-sheet"
type ChartTimeData = {
time: number
@@ -564,13 +565,13 @@ export default memo(function SystemDetail({ name }: { name: string }) {
dataPoints={[
{
label: t({ message: "Write", comment: "Disk write" }),
dataKey: ({ stats }) => (showMax ? stats?.dwm : stats?.dw),
dataKey: ({ stats }: SystemStatsRecord) => (showMax ? stats?.dwm : stats?.dw),
color: 3,
opacity: 0.3,
},
{
label: t({ message: "Read", comment: "Disk read" }),
dataKey: ({ stats }) => (showMax ? stats?.drm : stats?.dr),
dataKey: ({ stats }: SystemStatsRecord) => (showMax ? stats?.drm : stats?.dr),
color: 1,
opacity: 0.3,
},
@@ -590,7 +591,12 @@ export default memo(function SystemDetail({ name }: { name: string }) {
empty={dataEmpty}
grid={grid}
title={t`Bandwidth`}
cornerEl={maxValSelect}
cornerEl={
<div className="flex gap-2">
{maxValSelect}
<NetworkSheet chartData={chartData} dataEmpty={dataEmpty} grid={grid} maxValues={maxValues} />
</div>
}
description={t`Network traffic of public interfaces`}
>
<AreaChartDefault
@@ -600,7 +606,7 @@ export default memo(function SystemDetail({ name }: { name: string }) {
{
label: t`Sent`,
// use bytes if available, otherwise multiply old MB (can remove in future)
dataKey(data) {
dataKey(data: SystemStatsRecord) {
if (showMax) {
return data?.stats?.bm?.[0] ?? (data?.stats?.nsm ?? 0) * 1024 * 1024
}
@@ -611,7 +617,7 @@ export default memo(function SystemDetail({ name }: { name: string }) {
},
{
label: t`Received`,
dataKey(data) {
dataKey(data: SystemStatsRecord) {
if (showMax) {
return data?.stats?.bm?.[1] ?? (data?.stats?.nrm ?? 0) * 1024 * 1024
}
@@ -620,7 +626,9 @@ export default memo(function SystemDetail({ name }: { name: string }) {
color: 2,
opacity: 0.2,
},
]}
]
// try to place the lesser number in front for better visibility
.sort(() => (systemStats.at(-1)?.stats.b?.[1] ?? 0) - (systemStats.at(-1)?.stats.b?.[0] ?? 0))}
tickFormatter={(val) => {
const { value, unit } = formatBytes(val, true, userSettings.unitNet, false)
return `${toFixedFloat(value, value >= 10 ? 0 : 1)} ${unit}`
@@ -674,6 +682,7 @@ export default memo(function SystemDetail({ name }: { name: string }) {
grid={grid}
title={t`Load Average`}
description={t`System load averages over time`}
legend={true}
>
<LoadAverageChart chartData={chartData} />
</ChartCard>
@@ -687,6 +696,7 @@ export default memo(function SystemDetail({ name }: { name: string }) {
title={t`Temperature`}
description={t`Temperatures of system sensors`}
cornerEl={<FilterBar store={$temperatureFilter} />}
legend={Object.keys(systemStats.at(-1)?.stats.t ?? {}).length < 12}
>
<TemperatureChart chartData={chartData} />
</ChartCard>
@@ -879,7 +889,7 @@ function FilterBar({ store = $containerFilter }: { store?: typeof $containerFilt
return (
<>
<Input placeholder={t`Filter...`} className="ps-4 pe-8" onChange={handleChange} ref={inputRef} />
<Input placeholder={t`Filter...`} className="ps-4 pe-8 w-full sm:w-44" onChange={handleChange} ref={inputRef} />
{containerFilter && (
<Button
type="button"
@@ -905,7 +915,7 @@ const SelectAvgMax = memo(({ max }: { max: boolean }) => {
const Icon = max ? ChartMax : ChartAverage
return (
<Select value={max ? "max" : "avg"} onValueChange={(e) => $maxValues.set(e === "max")}>
<SelectTrigger className="relative ps-10 pe-5">
<SelectTrigger className="relative ps-10 pe-5 w-full sm:w-44">
<Icon className="h-4 w-4 absolute start-4 top-1/2 -translate-y-1/2 opacity-85" />
<SelectValue />
</SelectTrigger>
@@ -921,13 +931,15 @@ const SelectAvgMax = memo(({ max }: { max: boolean }) => {
)
})
function ChartCard({
export function ChartCard({
title,
description,
children,
grid,
empty,
cornerEl,
legend,
className,
}: {
title: string
description: string
@@ -935,17 +947,24 @@ function ChartCard({
grid?: boolean
empty?: boolean
cornerEl?: JSX.Element | null
legend?: boolean
className?: string
}) {
const { isIntersecting, ref } = useIntersectionObserver()
return (
<Card className={cn("pb-2 sm:pb-4 odd:last-of-type:col-span-full", { "col-span-full": !grid })} ref={ref}>
<Card
className={cn("pb-2 sm:pb-4 odd:last-of-type:col-span-full min-h-full", { "col-span-full": !grid }, className)}
ref={ref}
>
<CardHeader className="pb-5 pt-4 gap-1 relative max-sm:py-3 max-sm:px-4">
<CardTitle className="text-xl sm:text-2xl">{title}</CardTitle>
<CardDescription>{description}</CardDescription>
{cornerEl && <div className="relative py-1 block sm:w-44 sm:absolute sm:top-3.5 sm:end-3.5">{cornerEl}</div>}
{cornerEl && (
<div className="relative py-1 grid sm:justify-end sm:absolute sm:top-3.5 sm:end-3.5">{cornerEl}</div>
)}
</CardHeader>
<div className="ps-0 w-[calc(100%-1.5em)] h-48 md:h-52 relative group">
<div className={cn("ps-0 w-[calc(100%-1.5em)] relative group", legend ? "h-54 md:h-56" : "h-48 md:h-52")}>
{
<Spinner
msg={empty ? t`Waiting for enough records to display` : undefined}

View File

@@ -0,0 +1,149 @@
import { t } from "@lingui/core/macro"
import { useStore } from "@nanostores/react"
import { MoreHorizontalIcon } from "lucide-react"
import { memo, useRef, useState } from "react"
import AreaChartDefault from "@/components/charts/area-chart"
import ChartTimeSelect from "@/components/charts/chart-time-select"
import { useNetworkInterfaces } from "@/components/charts/hooks"
import { Button } from "@/components/ui/button"
import { Sheet, SheetContent, SheetTrigger } from "@/components/ui/sheet"
import { $userSettings } from "@/lib/stores"
import { decimalString, formatBytes, toFixedFloat } from "@/lib/utils"
import type { ChartData } from "@/types"
import { ChartCard } from "../system"
export default memo(function NetworkSheet({
chartData,
dataEmpty,
grid,
maxValues,
}: {
chartData: ChartData
dataEmpty: boolean
grid: boolean
maxValues: boolean
}) {
const [netInterfacesOpen, setNetInterfacesOpen] = useState(false)
const userSettings = useStore($userSettings)
const netInterfaces = useNetworkInterfaces(chartData.systemStats.at(-1)?.stats?.ni ?? {})
const showNetLegend = netInterfaces.length > 0
const hasOpened = useRef(false)
if (netInterfacesOpen && !hasOpened.current) {
hasOpened.current = true
}
if (!netInterfaces.length) {
return null
}
return (
<Sheet open={netInterfacesOpen} onOpenChange={setNetInterfacesOpen}>
<SheetTrigger asChild>
<Button variant="outline" size="icon" className="shrink-0">
<MoreHorizontalIcon />
</Button>
</SheetTrigger>
{hasOpened.current && (
<SheetContent className="overflow-auto w-200 !max-w-full p-4 sm:p-6">
<ChartTimeSelect className="w-[calc(100%-1.5em)]" />
<ChartCard
empty={dataEmpty}
grid={grid}
title={t`Download`}
description={t`Network traffic of public interfaces`}
legend={showNetLegend}
className="min-h-auto"
>
<AreaChartDefault
chartData={chartData}
maxToggled={maxValues}
itemSorter={(a, b) => b.value - a.value}
dataPoints={netInterfaces.data(1)}
legend={showNetLegend}
tickFormatter={(val) => {
const { value, unit } = formatBytes(val, true, userSettings.unitNet, false)
return `${toFixedFloat(value, value >= 10 ? 0 : 1)} ${unit}`
}}
contentFormatter={({ value }) => {
const { value: convertedValue, unit } = formatBytes(value, true, userSettings.unitNet, false)
return `${decimalString(convertedValue, convertedValue >= 100 ? 1 : 2)} ${unit}`
}}
/>
</ChartCard>
<ChartCard
empty={dataEmpty}
grid={grid}
title={t`Upload`}
description={t`Network traffic of public interfaces`}
legend={showNetLegend}
className="min-h-auto"
>
<AreaChartDefault
chartData={chartData}
maxToggled={maxValues}
itemSorter={(a, b) => b.value - a.value}
legend={showNetLegend}
dataPoints={netInterfaces.data(0)}
tickFormatter={(val) => {
const { value, unit } = formatBytes(val, true, userSettings.unitNet, false)
return `${toFixedFloat(value, value >= 10 ? 0 : 1)} ${unit}`
}}
contentFormatter={({ value }) => {
const { value: convertedValue, unit } = formatBytes(value, true, userSettings.unitNet, false)
return `${decimalString(convertedValue, convertedValue >= 100 ? 1 : 2)} ${unit}`
}}
/>
</ChartCard>
<ChartCard
empty={dataEmpty}
grid={grid}
title={t`Cumulative Download`}
description={t`Total data received for each interface`}
legend={showNetLegend}
className="min-h-auto"
>
<AreaChartDefault
chartData={chartData}
legend={showNetLegend}
dataPoints={netInterfaces.data(3)}
tickFormatter={(val) => {
const { value, unit } = formatBytes(val, false, userSettings.unitNet, false)
return `${toFixedFloat(value, value >= 10 ? 0 : 1)} ${unit}`
}}
contentFormatter={({ value }) => {
const { value: convertedValue, unit } = formatBytes(value, false, userSettings.unitNet, false)
return `${decimalString(convertedValue, convertedValue >= 100 ? 1 : 2)} ${unit}`
}}
/>
</ChartCard>
<ChartCard
empty={dataEmpty}
grid={grid}
title={t`Cumulative Upload`}
description={t`Total data sent for each interface`}
legend={showNetLegend}
className="min-h-auto"
>
<AreaChartDefault
chartData={chartData}
legend={showNetLegend}
dataPoints={netInterfaces.data(2)}
tickFormatter={(val) => {
const { value, unit } = formatBytes(val, false, userSettings.unitNet, false)
return `${toFixedFloat(value, value >= 10 ? 0 : 1)} ${unit}`
}}
contentFormatter={({ value }) => {
const { value: convertedValue, unit } = formatBytes(value, false, userSettings.unitNet, false)
return `${decimalString(convertedValue, convertedValue >= 100 ? 1 : 2)} ${unit}`
}}
/>
</ChartCard>
</SheetContent>
)}
</Sheet>
)
})

View File

@@ -1,5 +1,5 @@
import { cn } from "@/lib/utils"
import { LoaderCircleIcon } from "lucide-react"
import { cn } from "@/lib/utils"
export default function ({ msg, className }: { msg?: string; className?: string }) {
return (

View File

@@ -1,6 +1,9 @@
import { SystemRecord } from "@/types"
import { CellContext, ColumnDef, HeaderContext } from "@tanstack/react-table"
import { ClassValue } from "clsx"
import { t } from "@lingui/core/macro"
import { Trans, useLingui } from "@lingui/react/macro"
import { useStore } from "@nanostores/react"
import { getPagePath } from "@nanostores/router"
import type { CellContext, ColumnDef, HeaderContext } from "@tanstack/react-table"
import type { ClassValue } from "clsx"
import {
ArrowUpDownIcon,
CopyIcon,
@@ -15,7 +18,10 @@ import {
Trash2Icon,
WifiIcon,
} from "lucide-react"
import { Button } from "../ui/button"
import { memo, useMemo, useRef, useState } from "react"
import { isReadOnlyUser, pb } from "@/lib/api"
import { MeterState, SystemStatus } from "@/lib/enums"
import { $longestSystemNameLen, $userSettings } from "@/lib/stores"
import {
cn,
copyToClipboard,
@@ -25,24 +31,12 @@ import {
getMeterState,
parseSemVer,
} from "@/lib/utils"
import { EthernetIcon, GpuIcon, HourglassIcon, ThermometerIcon } from "../ui/icons"
import { useStore } from "@nanostores/react"
import { $longestSystemNameLen, $userSettings } from "@/lib/stores"
import { Trans, useLingui } from "@lingui/react/macro"
import { useMemo, useRef, useState } from "react"
import { memo } from "react"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "../ui/dropdown-menu"
import AlertButton from "../alerts/alert-button"
import { Dialog } from "../ui/dialog"
import type { SystemRecord } from "@/types"
import { SystemDialog } from "../add-system"
import { AlertDialog } from "../ui/alert-dialog"
import AlertButton from "../alerts/alert-button"
import { $router, Link } from "../router"
import {
AlertDialog,
AlertDialogAction,
AlertDialogCancel,
AlertDialogContent,
@@ -51,12 +45,16 @@ import {
AlertDialogHeader,
AlertDialogTitle,
} from "../ui/alert-dialog"
import { buttonVariants } from "../ui/button"
import { t } from "@lingui/core/macro"
import { MeterState, SystemStatus } from "@/lib/enums"
import { $router, Link } from "../router"
import { getPagePath } from "@nanostores/router"
import { isReadOnlyUser, pb } from "@/lib/api"
import { Button, buttonVariants } from "../ui/button"
import { Dialog } from "../ui/dialog"
import {
DropdownMenu,
DropdownMenuContent,
DropdownMenuItem,
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "../ui/dropdown-menu"
import { EthernetIcon, GpuIcon, HourglassIcon, ThermometerIcon } from "../ui/icons"
const STATUS_COLORS = {
[SystemStatus.Up]: "bg-green-500",
@@ -290,7 +288,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
},
{
id: "actions",
// @ts-ignore
// @ts-expect-error
name: () => t({ message: "Actions", comment: "Table column" }),
size: 50,
cell: ({ row }) => (
@@ -305,7 +303,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
function sortableHeader(context: HeaderContext<SystemRecord, unknown>) {
const { column } = context
// @ts-ignore
// @ts-expect-error
const { Icon, hideSort, name }: { Icon: React.ElementType; name: () => string; hideSort: boolean } = column.columnDef
return (
<Button
@@ -353,7 +351,7 @@ export function IndicatorDot({ system, className }: { system: SystemRecord; clas
export const ActionsButton = memo(({ system }: { system: SystemRecord }) => {
const [deleteOpen, setDeleteOpen] = useState(false)
const [editOpen, setEditOpen] = useState(false)
let editOpened = useRef(false)
const editOpened = useRef(false)
const { t } = useLingui()
const { id, status, host, name } = system

View File

@@ -1,17 +1,31 @@
import { Trans, useLingui } from "@lingui/react/macro"
import { useStore } from "@nanostores/react"
import { getPagePath } from "@nanostores/router"
import {
ColumnDef,
ColumnFiltersState,
getFilteredRowModel,
SortingState,
getSortedRowModel,
type ColumnDef,
type ColumnFiltersState,
flexRender,
VisibilityState,
getCoreRowModel,
getFilteredRowModel,
getSortedRowModel,
type Row,
type SortingState,
type Table as TableType,
useReactTable,
Row,
Table as TableType,
type VisibilityState,
} from "@tanstack/react-table"
import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { useVirtualizer, type VirtualItem } from "@tanstack/react-virtual"
import {
ArrowDownIcon,
ArrowUpDownIcon,
ArrowUpIcon,
EyeIcon,
FilterIcon,
LayoutGridIcon,
LayoutListIcon,
Settings2Icon,
} from "lucide-react"
import { memo, useEffect, useMemo, useRef, useState } from "react"
import { Button } from "@/components/ui/button"
import {
DropdownMenu,
@@ -24,30 +38,16 @@ import {
DropdownMenuSeparator,
DropdownMenuTrigger,
} from "@/components/ui/dropdown-menu"
import { SystemRecord } from "@/types"
import {
ArrowUpDownIcon,
LayoutGridIcon,
LayoutListIcon,
ArrowDownIcon,
ArrowUpIcon,
Settings2Icon,
EyeIcon,
FilterIcon,
} from "lucide-react"
import { memo, useEffect, useMemo, useRef, useState } from "react"
import { $pausedSystems, $downSystems, $upSystems, $systems } from "@/lib/stores"
import { useStore } from "@nanostores/react"
import { cn, runOnce, useBrowserStorage } from "@/lib/utils"
import { $router, Link } from "../router"
import { useLingui, Trans } from "@lingui/react/macro"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"
import { Input } from "@/components/ui/input"
import { getPagePath } from "@nanostores/router"
import SystemsTableColumns, { ActionsButton, IndicatorDot } from "./systems-table-columns"
import AlertButton from "../alerts/alert-button"
import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { SystemStatus } from "@/lib/enums"
import { useVirtualizer, VirtualItem } from "@tanstack/react-virtual"
import { $downSystems, $pausedSystems, $systems, $upSystems } from "@/lib/stores"
import { cn, runOnce, useBrowserStorage } from "@/lib/utils"
import type { SystemRecord } from "@/types"
import AlertButton from "../alerts/alert-button"
import { $router, Link } from "../router"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"
import SystemsTableColumns, { ActionsButton, IndicatorDot } from "./systems-table-columns"
type ViewMode = "table" | "grid"
type StatusFilter = "all" | SystemRecord["status"]
@@ -309,69 +309,63 @@ export default function SystemsTable() {
)
}
const AllSystemsTable = memo(function ({
table,
rows,
colLength,
}: {
table: TableType<SystemRecord>
rows: Row<SystemRecord>[]
colLength: number
}) {
// The virtualizer will need a reference to the scrollable container element
const scrollRef = useRef<HTMLDivElement>(null)
const AllSystemsTable = memo(
({ table, rows, colLength }: { table: TableType<SystemRecord>; rows: Row<SystemRecord>[]; colLength: number }) => {
// The virtualizer will need a reference to the scrollable container element
const scrollRef = useRef<HTMLDivElement>(null)
const virtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({
count: rows.length,
estimateSize: () => (rows.length > 10 ? 56 : 60),
getScrollElement: () => scrollRef.current,
overscan: 5,
})
const virtualRows = virtualizer.getVirtualItems()
const virtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({
count: rows.length,
estimateSize: () => (rows.length > 10 ? 56 : 60),
getScrollElement: () => scrollRef.current,
overscan: 5,
})
const virtualRows = virtualizer.getVirtualItems()
const paddingTop = Math.max(0, virtualRows[0]?.start ?? 0 - virtualizer.options.scrollMargin)
const paddingBottom = Math.max(0, virtualizer.getTotalSize() - (virtualRows[virtualRows.length - 1]?.end ?? 0))
const paddingTop = Math.max(0, virtualRows[0]?.start ?? 0 - virtualizer.options.scrollMargin)
const paddingBottom = Math.max(0, virtualizer.getTotalSize() - (virtualRows[virtualRows.length - 1]?.end ?? 0))
return (
<div
className={cn(
"h-min max-h-[calc(100dvh-17rem)] max-w-full relative overflow-auto border rounded-md",
// don't set min height if there are less than 2 rows, do set if we need to display the empty state
(!rows.length || rows.length > 2) && "min-h-50"
)}
ref={scrollRef}
>
{/* add header height to table size */}
<div style={{ height: `${virtualizer.getTotalSize() + 50}px`, paddingTop, paddingBottom }}>
<table className="text-sm w-full h-full">
<SystemsTableHead table={table} colLength={colLength} />
<TableBody onMouseEnter={preloadSystemDetail}>
{rows.length ? (
virtualRows.map((virtualRow) => {
const row = rows[virtualRow.index] as Row<SystemRecord>
return (
<SystemTableRow
key={row.id}
row={row}
virtualRow={virtualRow}
length={rows.length}
colLength={colLength}
/>
)
})
) : (
<TableRow>
<TableCell colSpan={colLength} className="h-37 text-center pointer-events-none">
<Trans>No systems found.</Trans>
</TableCell>
</TableRow>
)}
</TableBody>
</table>
return (
<div
className={cn(
"h-min max-h-[calc(100dvh-17rem)] max-w-full relative overflow-auto border rounded-md",
// don't set min height if there are less than 2 rows, do set if we need to display the empty state
(!rows.length || rows.length > 2) && "min-h-50"
)}
ref={scrollRef}
>
{/* add header height to table size */}
<div style={{ height: `${virtualizer.getTotalSize() + 50}px`, paddingTop, paddingBottom }}>
<table className="text-sm w-full h-full">
<SystemsTableHead table={table} colLength={colLength} />
<TableBody onMouseEnter={preloadSystemDetail}>
{rows.length ? (
virtualRows.map((virtualRow) => {
const row = rows[virtualRow.index] as Row<SystemRecord>
return (
<SystemTableRow
key={row.id}
row={row}
virtualRow={virtualRow}
length={rows.length}
colLength={colLength}
/>
)
})
) : (
<TableRow>
<TableCell colSpan={colLength} className="h-37 text-center pointer-events-none">
<Trans>No systems found.</Trans>
</TableCell>
</TableRow>
)}
</TableBody>
</table>
</div>
</div>
</div>
)
})
)
}
)
function SystemsTableHead({ table, colLength }: { table: TableType<SystemRecord>; colLength: number }) {
const { i18n } = useLingui()
@@ -395,42 +389,44 @@ function SystemsTableHead({ table, colLength }: { table: TableType<SystemRecord>
}, [i18n.locale, colLength])
}
const SystemTableRow = memo(function ({
row,
virtualRow,
colLength,
}: {
row: Row<SystemRecord>
virtualRow: VirtualItem
length: number
colLength: number
}) {
const system = row.original
const { t } = useLingui()
return useMemo(() => {
return (
<TableRow
// data-state={row.getIsSelected() && "selected"}
className={cn("cursor-pointer transition-opacity relative safari:transform-3d", {
"opacity-50": system.status === SystemStatus.Paused,
})}
>
{row.getVisibleCells().map((cell) => (
<TableCell
key={cell.id}
style={{
width: cell.column.getSize(),
height: virtualRow.size,
}}
className="py-0"
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
)
}, [system, system.status, colLength, t])
})
const SystemTableRow = memo(
({
row,
virtualRow,
colLength,
}: {
row: Row<SystemRecord>
virtualRow: VirtualItem
length: number
colLength: number
}) => {
const system = row.original
const { t } = useLingui()
return useMemo(() => {
return (
<TableRow
// data-state={row.getIsSelected() && "selected"}
className={cn("cursor-pointer transition-opacity relative safari:transform-3d", {
"opacity-50": system.status === SystemStatus.Paused,
})}
>
{row.getVisibleCells().map((cell) => (
<TableCell
key={cell.id}
style={{
width: cell.column.getSize(),
height: virtualRow.size,
}}
className="py-0"
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
)
}, [system, system.status, colLength, t])
}
)
const SystemCard = memo(
({ row, table, colLength }: { row: Row<SystemRecord>; table: TableType<SystemRecord>; colLength: number }) => {
@@ -471,7 +467,7 @@ const SystemCard = memo(
if (!column.getIsVisible() || column.id === "system" || column.id === "actions") return null
const cell = row.getAllCells().find((cell) => cell.column.id === column.id)
if (!cell) return null
// @ts-ignore
// @ts-expect-error
const { Icon, name } = column.columnDef as ColumnDef<SystemRecord, unknown>
return (
<>

View File

@@ -1,3 +1,4 @@
/** biome-ignore-all lint/suspicious/noAssignInExpressions: it's fine :) */
import type { PreinitializedMapStore } from "nanostores"
import { pb, verifyAuth } from "@/lib/api"
import {
@@ -16,9 +17,10 @@ const COLLECTION = pb.collection<SystemRecord>("systems")
const FIELDS_DEFAULT = "id,name,host,port,info,status"
/** Maximum system name length for display purposes */
const MAX_SYSTEM_NAME_LENGTH = 20
const MAX_SYSTEM_NAME_LENGTH = 22
let initialized = false
// biome-ignore lint/suspicious/noConfusingVoidType: typescript rocks
let unsub: (() => void) | undefined | void
/** Initialize the systems manager and set up listeners */
@@ -104,20 +106,37 @@ async function fetchSystems(): Promise<SystemRecord[]> {
}
}
/** Makes sure the system has valid info object and throws if not */
function validateSystemInfo(system: SystemRecord) {
if (!("cpu" in system.info)) {
throw new Error(`${system.name} has no CPU info`)
}
}
/** Add system to both name and ID stores */
export function add(system: SystemRecord) {
$allSystemsByName.setKey(system.name, system)
$allSystemsById.setKey(system.id, system)
try {
validateSystemInfo(system)
$allSystemsByName.setKey(system.name, system)
$allSystemsById.setKey(system.id, system)
} catch (error) {
console.error(error)
}
}
/** Update system in stores */
export function update(system: SystemRecord) {
// if name changed, make sure old name is removed from the name store
const oldName = $allSystemsById.get()[system.id]?.name
if (oldName !== system.name) {
$allSystemsByName.setKey(oldName, undefined as any)
try {
validateSystemInfo(system)
// if name changed, make sure old name is removed from the name store
const oldName = $allSystemsById.get()[system.id]?.name
if (oldName !== system.name) {
$allSystemsByName.setKey(oldName, undefined as unknown as SystemRecord)
}
add(system)
} catch (error) {
console.error(error)
}
add(system)
}
/** Remove system from stores */
@@ -132,7 +151,7 @@ export function remove(system: SystemRecord) {
/** Remove system from specific store */
function removeFromStore(system: SystemRecord, store: PreinitializedMapStore<Record<string, SystemRecord>>) {
const key = store === $allSystemsByName ? system.name : system.id
store.setKey(key, undefined as any)
store.setKey(key, undefined as unknown as SystemRecord)
}
/** Action functions for subscription */

View File

@@ -1,6 +1,7 @@
import { t } from "@lingui/core/macro"
import { type ClassValue, clsx } from "clsx"
import { timeDay, timeHour } from "d3-time"
import { listenKeys } from "nanostores"
import { useEffect, useState } from "react"
import { twMerge } from "tailwind-merge"
import { prependBasePath } from "@/components/router"
@@ -8,7 +9,6 @@ import { toast } from "@/components/ui/use-toast"
import type { ChartTimeData, FingerprintRecord, SemVer, SystemRecord } from "@/types"
import { HourFormat, MeterState, Unit } from "./enums"
import { $copyContent, $userSettings } from "./stores"
import { listenKeys } from "nanostores"
export const FAVICON_DEFAULT = "favicon.svg"
export const FAVICON_GREEN = "favicon-green.svg"

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: ar\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Arabic\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: ar\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 ساعة"
msgid "1 min"
msgstr "دقيقة واحدة"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 دقيقة"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 أسبوع"
@@ -177,10 +173,6 @@ msgstr "متوسط استخدام وحدة المعالجة المركزية ع
msgid "Average utilization of {0}"
msgstr "متوسط ​​استخدام {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "متوسط استغلال محركات GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -584,10 +576,6 @@ msgstr "ممتلئة"
msgid "General"
msgstr "عام"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "محركات GPU"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "استهلاك طاقة وحدة معالجة الرسوميات"
@@ -718,7 +706,6 @@ msgstr "حركة مرور الشبكة لحاويات الدوكر"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "حركة مرور الشبكة للواجهات العامة"
@@ -1107,7 +1094,7 @@ msgstr "يتم التفعيل عندما يتجاوز متوسط التحميل
#: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold"
msgstr "يتم التفعيل عندما <EFBFBD><EFBFBD>تجاوز أي مستشعر عتبة معينة"
msgstr "يتم التفعيل عندما يتجاوز أي مستشعر عتبة معينة"
#: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold"
@@ -1191,10 +1178,6 @@ msgstr "القيمة"
msgid "View"
msgstr "عرض"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "عرض المزيد"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "عرض أحدث 200 تنبيه."
@@ -1250,4 +1233,3 @@ msgstr "تكوين YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "تم تحديث إعدادات المستخدم الخاصة بك."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: bg\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Bulgarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: bg\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 час"
msgid "1 min"
msgstr "1 минута"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 минута"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 седмица"
@@ -177,10 +173,6 @@ msgstr "Средно използване на процесора на цяла
msgid "Average utilization of {0}"
msgstr "Средно използване на {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Средно използване на GPU двигатели"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -584,10 +576,6 @@ msgstr "Пълна"
msgid "General"
msgstr "Общо"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU двигатели"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Консумация на ток от графична карта"
@@ -718,7 +706,6 @@ msgstr "Мрежов трафик на docker контейнери"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Мрежов трафик на публични интерфейси"
@@ -1191,10 +1178,6 @@ msgstr "Стойност"
msgid "View"
msgstr "Изглед"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Виж повече"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Прегледайте последните си 200 сигнала."
@@ -1250,4 +1233,3 @@ msgstr "YAML конфигурация"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Настройките за потребителя ти са обновени."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: cs\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Czech\n"
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: cs\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -46,11 +46,7 @@ msgstr "1 hodina"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "1 min"
msgstr ""
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minuta"
msgstr "1 min"
#: src/lib/utils.ts
msgid "1 week"
@@ -63,7 +59,7 @@ msgstr "12 hodin"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "15 min"
msgstr ""
msgstr "15 min"
#: src/lib/utils.ts
msgid "24 hours"
@@ -76,7 +72,7 @@ msgstr "30 dní"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "5 min"
msgstr ""
msgstr "5 min"
#. Table column
#: src/components/routes/settings/tokens-fingerprints.tsx
@@ -116,11 +112,11 @@ msgstr "Upravit možnosti zobrazení pro grafy."
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
msgid "Admin"
msgstr ""
msgstr "Admin"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
msgstr ""
msgstr "Agent"
#: src/components/command-palette.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
@@ -177,10 +173,6 @@ msgstr "Průměrné využití CPU v celém systému"
msgid "Average utilization of {0}"
msgstr "Průměrné využití {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Průměrné využití GPU engine"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -205,17 +197,17 @@ msgstr "Beszel používá <0>Shoutrrr</0> k integraci s populárními notifikač
#: src/components/add-system.tsx
msgid "Binary"
msgstr ""
msgstr "Binary"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)"
msgstr ""
msgstr "Bits (Kbps, Mbps, Gbps)"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)"
msgstr ""
msgstr "Bytes (KB/s, MB/s, GB/s)"
#: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers"
@@ -409,11 +401,11 @@ msgstr "Vybíjení"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Disk"
msgstr ""
msgstr "Disk"
#: src/components/routes/system.tsx
msgid "Disk I/O"
msgstr ""
msgstr "Disk I/O"
#: src/components/routes/settings/general.tsx
msgid "Disk unit"
@@ -474,7 +466,7 @@ msgstr "Upravit"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/otp-forms.tsx
msgid "Email"
msgstr ""
msgstr "Email"
#: src/components/routes/settings/notifications.tsx
msgid "Email notifications"
@@ -518,7 +510,7 @@ msgstr "Stávající systémy, které nejsou definovány v <0>config.yml</0>, bu
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Export"
msgstr ""
msgstr "Export"
#: src/components/routes/settings/config-yaml.tsx
msgid "Export configuration"
@@ -584,10 +576,6 @@ msgstr "Plná"
msgid "General"
msgstr "Obecné"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU enginy"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Spotřeba energie GPU"
@@ -622,7 +610,7 @@ msgstr "Neplatná e-mailová adresa."
#. Linux kernel
#: src/components/routes/system.tsx
msgid "Kernel"
msgstr ""
msgstr "Kernel"
#: src/components/routes/settings/general.tsx
msgid "Language"
@@ -718,7 +706,6 @@ msgstr "Síťový provoz kontejnerů docker"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Síťový provoz veřejných rozhraní"
@@ -850,7 +837,7 @@ msgstr "Přihlaste se prosím k vašemu účtu"
#: src/components/add-system.tsx
msgid "Port"
msgstr ""
msgstr "Port"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -1023,7 +1010,7 @@ msgstr "Teploty systémových senzorů"
#: src/components/routes/settings/notifications.tsx
msgid "Test <0>URL</0>"
msgstr ""
msgstr "Test <0>URL</0>"
#: src/components/routes/settings/notifications.tsx
msgid "Test notification sent"
@@ -1069,7 +1056,7 @@ msgstr "Přepnout motiv"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr ""
msgstr "Token"
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
@@ -1191,10 +1178,6 @@ msgstr "Hodnota"
msgid "View"
msgstr "Zobrazení"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Zobrazit více"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Zobrazit vašich 200 nejnovějších upozornění."
@@ -1250,4 +1233,3 @@ msgstr "YAML konfigurace"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Vaše uživatelská nastavení byla aktualizována."

View File

@@ -8,25 +8,25 @@ msgstr ""
"Language: da\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Danish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: da\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# day} other {# days}}"
msgstr ""
msgstr "{0, plural, one {# day} other {# days}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr ""
msgstr "{0, plural, one {# hour} other {# hours}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 time"
msgid "1 min"
msgstr ""
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minut"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 uge"
@@ -116,11 +112,11 @@ msgstr "Juster visningsindstillinger for diagrammer."
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
msgid "Admin"
msgstr ""
msgstr "Admin"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
msgstr ""
msgstr "Agent"
#: src/components/command-palette.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
@@ -177,10 +173,6 @@ msgstr "Gennemsnitlig systembaseret CPU-udnyttelse"
msgid "Average utilization of {0}"
msgstr "Gennemsnitlig udnyttelse af {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Gennemsnitlig udnyttelse af GPU-motorer"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -350,7 +342,7 @@ msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -409,11 +401,11 @@ msgstr "Aflader"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Disk"
msgstr ""
msgstr "Disk"
#: src/components/routes/system.tsx
msgid "Disk I/O"
msgstr ""
msgstr "Disk I/O"
#: src/components/routes/settings/general.tsx
msgid "Disk unit"
@@ -459,7 +451,7 @@ msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Download"
msgstr ""
msgstr "Download"
#: src/components/alerts-history-columns.tsx
msgid "Duration"
@@ -553,7 +545,7 @@ msgstr "Kunne ikke opdatere alarm"
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..."
msgstr ""
msgstr "Filter..."
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Fingerprint"
@@ -584,10 +576,6 @@ msgstr "Fuldt opladt"
msgid "General"
msgstr "Generelt"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU-motorer"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Gpu Strøm Træk"
@@ -622,7 +610,7 @@ msgstr "Ugyldig email adresse."
#. Linux kernel
#: src/components/routes/system.tsx
msgid "Kernel"
msgstr ""
msgstr "Kernel"
#: src/components/routes/settings/general.tsx
msgid "Language"
@@ -630,7 +618,7 @@ msgstr "Sprog"
#: src/components/systems-table/systems-table.tsx
msgid "Layout"
msgstr ""
msgstr "Layout"
#: src/components/routes/system.tsx
msgid "Load Average"
@@ -669,7 +657,7 @@ msgstr "Loginforsøg mislykkedes"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs"
msgstr ""
msgstr "Logs"
#: src/components/routes/settings/notifications.tsx
msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table."
@@ -709,7 +697,7 @@ msgstr "Navn"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Net"
msgstr ""
msgstr "Net"
#: src/components/routes/system.tsx
msgid "Network traffic of docker containers"
@@ -718,7 +706,6 @@ msgstr "Netværkstrafik af dockercontainere"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Netværkstrafik af offentlige grænseflader"
@@ -805,7 +792,7 @@ msgstr "Anmodning om nulstilling af adgangskode modtaget"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Pause"
msgstr ""
msgstr "Pause"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Paused"
@@ -850,7 +837,7 @@ msgstr "Log venligst ind på din konto"
#: src/components/add-system.tsx
msgid "Port"
msgstr ""
msgstr "Port"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -970,7 +957,7 @@ msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr ""
msgstr "Status"
#: src/components/routes/system.tsx
msgid "Swap space used by the system"
@@ -985,7 +972,7 @@ msgstr "Swap forbrug"
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System"
msgstr ""
msgstr "System"
#: src/components/routes/system.tsx
msgid "System load averages over time"
@@ -1023,7 +1010,7 @@ msgstr "Temperaturer i systemsensorer"
#: src/components/routes/settings/notifications.tsx
msgid "Test <0>URL</0>"
msgstr ""
msgstr "Test <0>URL</0>"
#: src/components/routes/settings/notifications.tsx
msgid "Test notification sent"
@@ -1156,7 +1143,7 @@ msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Upload"
msgstr ""
msgstr "Upload"
#: src/components/routes/system.tsx
msgid "Uptime"
@@ -1191,10 +1178,6 @@ msgstr ""
msgid "View"
msgstr "Vis"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Se mere"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr ""
@@ -1250,4 +1233,3 @@ msgstr "YAML Konfiguration"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Dine brugerindstillinger er opdateret."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: de\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-05 16:13\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: de\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 Stunde"
msgid "1 min"
msgstr "1 Min"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 Minute"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 Woche"
@@ -177,10 +173,6 @@ msgstr "Durchschnittliche systemweite CPU-Auslastung"
msgid "Average utilization of {0}"
msgstr "Durchschnittliche Auslastung von {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Durchschnittliche Auslastung der GPU-Engines"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -459,7 +451,7 @@ msgstr "Offline ({downSystemsLength})"
#: src/components/routes/system/network-sheet.tsx
msgid "Download"
msgstr "Herunterladen"
msgstr "Download"
#: src/components/alerts-history-columns.tsx
msgid "Duration"
@@ -584,10 +576,6 @@ msgstr "Voll"
msgid "General"
msgstr "Allgemein"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU-Engines"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU-Leistungsaufnahme"
@@ -718,7 +706,6 @@ msgstr "Netzwerkverkehr der Docker-Container"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Netzwerkverkehr der öffentlichen Schnittstellen"
@@ -1156,7 +1143,7 @@ msgstr "aktiv ({upSystemsLength})"
#: src/components/routes/system/network-sheet.tsx
msgid "Upload"
msgstr "Hochladen"
msgstr "Upload"
#: src/components/routes/system.tsx
msgid "Uptime"
@@ -1191,10 +1178,6 @@ msgstr "Wert"
msgid "View"
msgstr "Ansicht"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Mehr anzeigen"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Sieh dir die neusten 200 Alarme an."
@@ -1250,4 +1233,3 @@ msgstr "YAML-Konfiguration"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Deine Benutzereinstellungen wurden aktualisiert."

File diff suppressed because it is too large Load Diff

View File

@@ -358,6 +358,14 @@ msgstr "Created"
msgid "Critical (%)"
msgstr "Critical (%)"
#: src/components/routes/system/network-sheet.tsx
msgid "Cumulative Download"
msgstr "Cumulative Download"
#: src/components/routes/system/network-sheet.tsx
msgid "Cumulative Upload"
msgstr "Cumulative Upload"
#. Context: Battery state
#: src/components/routes/system.tsx
msgid "Current state"
@@ -436,6 +444,10 @@ msgstr "Down"
msgid "Down ({downSystemsLength})"
msgstr "Down ({downSystemsLength})"
#: src/components/routes/system/network-sheet.tsx
msgid "Download"
msgstr "Download"
#: src/components/alerts-history-columns.tsx
msgid "Duration"
msgstr "Duration"
@@ -447,6 +459,7 @@ msgstr "Edit"
#: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/otp-forms.tsx
msgid "Email"
msgstr "Email"
@@ -467,6 +480,10 @@ msgstr "Enter email address to reset password"
msgid "Enter email address..."
msgstr "Enter email address..."
#: src/components/login/otp-forms.tsx
msgid "Enter your one-time password."
msgstr "Enter your one-time password."
#: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
@@ -537,6 +554,12 @@ msgstr "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgid "Forgot password?"
msgstr "Forgot password?"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgctxt "Button to copy install command"
msgid "FreeBSD command"
msgstr "FreeBSD command"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
@@ -640,6 +663,7 @@ msgid "Manage display and notification preferences."
msgstr "Manage display and notification preferences."
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Manual setup instructions"
msgstr "Manual setup instructions"
@@ -675,6 +699,8 @@ msgid "Network traffic of docker containers"
msgstr "Network traffic of docker containers"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Network traffic of public interfaces"
@@ -710,6 +736,10 @@ msgstr "OAuth 2 / OIDC support"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "On each restart, systems in the database will be updated to match the systems defined in the file."
#: src/components/login/auth-form.tsx
msgid "One-time password"
msgstr "One-time password"
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
@@ -828,6 +858,14 @@ msgstr "Read"
msgid "Received"
msgstr "Received"
#: src/components/login/login.tsx
msgid "Request a one-time password"
msgstr "Request a one-time password"
#: src/components/login/otp-forms.tsx
msgid "Request OTP"
msgstr "Request OTP"
#: src/components/login/forgot-pass-form.tsx
msgid "Reset Password"
msgstr "Reset Password"
@@ -883,10 +921,6 @@ msgstr "Sent"
msgid "Set percentage thresholds for meter colors."
msgstr "Set percentage thresholds for meter colors."
#: src/components/routes/settings/general.tsx
msgid "Sets the default time range for charts when a system is viewed."
msgstr "Sets the default time range for charts when a system is viewed."
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
@@ -997,6 +1031,10 @@ msgstr "Throughput of {extraFsName}"
msgid "Throughput of root filesystem"
msgstr "Throughput of root filesystem"
#: src/components/routes/settings/general.tsx
msgid "Time format"
msgstr "Time format"
#: src/components/routes/settings/notifications.tsx
msgid "To email(s)"
msgstr "To email(s)"
@@ -1029,6 +1067,14 @@ msgstr "Tokens allow agents to connect and register. Fingerprints are stable ide
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
#: src/components/routes/system/network-sheet.tsx
msgid "Total data received for each interface"
msgstr "Total data received for each interface"
#: src/components/routes/system/network-sheet.tsx
msgid "Total data sent for each interface"
msgstr "Total data sent for each interface"
#: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "Triggers when 1 minute load average exceeds a threshold"
@@ -1090,6 +1136,10 @@ msgstr "Up"
msgid "Up ({upSystemsLength})"
msgstr "Up ({upSystemsLength})"
#: src/components/routes/system/network-sheet.tsx
msgid "Upload"
msgstr "Upload"
#: src/components/routes/system.tsx
msgid "Uptime"
msgstr "Uptime"

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: es\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: es-ES\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -46,11 +46,7 @@ msgstr "1 hora"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "1 min"
msgstr ""
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minuto"
msgstr "1 min"
#: src/lib/utils.ts
msgid "1 week"
@@ -63,7 +59,7 @@ msgstr "12 horas"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "15 min"
msgstr ""
msgstr "15 min"
#: src/lib/utils.ts
msgid "24 hours"
@@ -76,7 +72,7 @@ msgstr "30 días"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "5 min"
msgstr ""
msgstr "5 min"
#. Table column
#: src/components/routes/settings/tokens-fingerprints.tsx
@@ -177,10 +173,6 @@ msgstr "Utilización promedio de CPU del sistema"
msgid "Average utilization of {0}"
msgstr "Uso promedio de {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Utilización promedio de motores GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -210,12 +202,12 @@ msgstr "Binario"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)"
msgstr ""
msgstr "Bits (Kbps, Mbps, Gbps)"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)"
msgstr ""
msgstr "Bytes (KB/s, MB/s, GB/s)"
#: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers"
@@ -232,7 +224,7 @@ msgstr "Precaución - posible pérdida de datos"
#: src/components/routes/settings/general.tsx
msgid "Celsius (°C)"
msgstr ""
msgstr "Celsius (°C)"
#: src/components/routes/settings/general.tsx
msgid "Change display units for metrics."
@@ -350,7 +342,7 @@ msgstr "Copiar YAML"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -503,7 +495,7 @@ msgstr "Ingrese su contraseña de un solo uso."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error"
msgstr ""
msgstr "Error"
#. placeholder {0}: alert.value
#. placeholder {1}: info.unit
@@ -530,7 +522,7 @@ msgstr "Exporte la configuración actual de sus sistemas."
#: src/components/routes/settings/general.tsx
msgid "Fahrenheit (°F)"
msgstr ""
msgstr "Fahrenheit (°F)"
#: src/lib/api.ts
msgid "Failed to authenticate"
@@ -582,11 +574,7 @@ msgstr "Llena"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General"
msgstr ""
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "Motores GPU"
msgstr "General"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
@@ -604,7 +592,7 @@ msgstr "Comando Homebrew"
#: src/components/add-system.tsx
msgid "Host / IP"
msgstr ""
msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
@@ -622,7 +610,7 @@ msgstr "Dirección de correo electrónico no válida."
#. Linux kernel
#: src/components/routes/system.tsx
msgid "Kernel"
msgstr ""
msgstr "Kernel"
#: src/components/routes/settings/general.tsx
msgid "Language"
@@ -718,7 +706,6 @@ msgstr "Tráfico de red de los contenedores de Docker"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Tráfico de red de interfaces públicas"
@@ -1069,7 +1056,7 @@ msgstr "Alternar tema"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr ""
msgstr "Token"
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
@@ -1191,10 +1178,6 @@ msgstr "Valor"
msgid "View"
msgstr "Vista"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Ver más"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Ver sus 200 alertas más recientes."
@@ -1250,4 +1233,3 @@ msgstr "Configuración YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Su configuración de usuario ha sido actualizada."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: fa\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Persian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: fa\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "۱ ساعت"
msgid "1 min"
msgstr "۱ دقیقه"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 دقیقه"
#: src/lib/utils.ts
msgid "1 week"
msgstr "۱ هفته"
@@ -177,10 +173,6 @@ msgstr "میانگین استفاده از CPU در کل سیستم"
msgid "Average utilization of {0}"
msgstr "میانگین استفاده از {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "میانگین استفاده از موتورهای GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -584,10 +576,6 @@ msgstr "پر"
msgid "General"
msgstr "عمومی"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "موتورهای GPU"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "مصرف برق پردازنده گرافیکی"
@@ -718,7 +706,6 @@ msgstr "ترافیک شبکه کانتینرهای داکر"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "ترافیک شبکه رابط‌های عمومی"
@@ -1191,10 +1178,6 @@ msgstr "مقدار"
msgid "View"
msgstr "مشاهده"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "مشاهده بیشتر"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "۲۰۰ هشدار اخیر خود را مشاهده کنید."
@@ -1250,4 +1233,3 @@ msgstr "پیکربندی YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "تنظیمات کاربری شما به‌روزرسانی شد."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: fr\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-09 22:25\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: fr\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 heure"
msgid "1 min"
msgstr ""
#: src/lib/utils.ts
msgid "1 minute"
msgstr ""
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 semaine"
@@ -82,7 +78,7 @@ msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions"
msgstr ""
msgstr "Actions"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
@@ -116,11 +112,11 @@ msgstr "Ajuster les options d'affichage pour les graphiques."
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
msgid "Admin"
msgstr ""
msgstr "Admin"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
msgstr ""
msgstr "Agent"
#: src/components/command-palette.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
@@ -177,10 +173,6 @@ msgstr "Utilisation moyenne du CPU à l'échelle du système"
msgid "Average utilization of {0}"
msgstr "Utilisation moyenne de {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Utilisation moyenne des moteurs GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -244,7 +236,7 @@ msgstr "Modifier les options générales de l'application."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr ""
msgstr "Charge"
#. Context: Battery state
#: src/lib/i18n.ts
@@ -350,7 +342,7 @@ msgstr "Copier YAML"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -443,7 +435,7 @@ msgstr "Entrée/Sortie réseau Docker"
#: src/components/command-palette.tsx
msgid "Documentation"
msgstr ""
msgstr "Documentation"
#. Context: System is down
#: src/components/alerts-history-columns.tsx
@@ -474,7 +466,7 @@ msgstr "Éditer"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/otp-forms.tsx
msgid "Email"
msgstr ""
msgstr "Email"
#: src/components/routes/settings/notifications.tsx
msgid "Email notifications"
@@ -584,10 +576,6 @@ msgstr "Pleine"
msgid "General"
msgstr "Général"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "Moteurs GPU"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Consommation du GPU"
@@ -687,7 +675,7 @@ msgstr "Guide pour une installation manuelle"
#. Chart select field. Please try to keep this short.
#: src/components/routes/system.tsx
msgid "Max 1 min"
msgstr ""
msgstr "Max 1 min"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Memory"
@@ -709,7 +697,7 @@ msgstr "Nom"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Net"
msgstr ""
msgstr "Net"
#: src/components/routes/system.tsx
msgid "Network traffic of docker containers"
@@ -718,7 +706,6 @@ msgstr "Trafic réseau des conteneurs Docker"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Trafic réseau des interfaces publiques"
@@ -744,7 +731,7 @@ msgstr "Aucun système trouvé."
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications"
msgstr ""
msgstr "Notifications"
#: src/components/login/auth-form.tsx
msgid "OAuth 2 / OIDC support"
@@ -774,7 +761,7 @@ msgstr "Écraser les alertes existantes"
#: src/components/command-palette.tsx
msgid "Page"
msgstr ""
msgstr "Page"
#. placeholder {0}: table.getState().pagination.pageIndex + 1
#. placeholder {1}: table.getPageCount()
@@ -805,7 +792,7 @@ msgstr "Demande de réinitialisation du mot de passe reçue"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Pause"
msgstr ""
msgstr "Pause"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Paused"
@@ -850,7 +837,7 @@ msgstr "Veuillez vous connecter à votre compte"
#: src/components/add-system.tsx
msgid "Port"
msgstr ""
msgstr "Port"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -1015,7 +1002,7 @@ msgstr "Température"
#: src/components/routes/settings/general.tsx
msgid "Temperature unit"
msgstr "Unité de température"
msgstr ""
#: src/components/routes/system.tsx
msgid "Temperatures of system sensors"
@@ -1095,7 +1082,7 @@ msgstr "Données totales envoyées pour chaque interface"
#: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "Se déclenche lorsque la charge moyenne sur 1 minute dépasse un seuil"
msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold"
@@ -1191,10 +1178,6 @@ msgstr ""
msgid "View"
msgstr "Vue"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Voir plus"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr ""
@@ -1250,4 +1233,3 @@ msgstr "Configuration YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Vos paramètres utilisateur ont été mis à jour."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: hr\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Croatian\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: hr\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -46,11 +46,7 @@ msgstr "1 sat"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "1 min"
msgstr "1 minut"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minuta"
msgstr ""
#: src/lib/utils.ts
msgid "1 week"
@@ -63,7 +59,7 @@ msgstr "12 sati"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "15 min"
msgstr "15 minuta"
msgstr ""
#: src/lib/utils.ts
msgid "24 hours"
@@ -87,7 +83,7 @@ msgstr "Akcije"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Active"
msgstr "Aktivan"
msgstr ""
#: src/components/routes/home.tsx
msgid "Active Alerts"
@@ -145,7 +141,7 @@ msgstr "Jeste li sigurni da želite izbrisati {name}?"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Are you sure?"
msgstr "Jeste li sigurni?"
msgstr ""
#: src/components/copy-to-clipboard.tsx
msgid "Automatic copy requires a secure context."
@@ -177,10 +173,6 @@ msgstr "Prosječna iskorištenost procesora na cijelom sustavu"
msgid "Average utilization of {0}"
msgstr ""
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Prosječna iskorištenost GPU motora"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -317,7 +309,7 @@ msgstr "Kopiraj docker run"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgctxt "Environment variables"
msgid "Copy env"
msgstr "Kopiraj env"
msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "Copy host"
@@ -365,7 +357,7 @@ msgstr "Napravite račun"
#. Context: date created
#: src/components/alerts-history-columns.tsx
msgid "Created"
msgstr "Kreiran"
msgstr ""
#: src/components/routes/settings/general.tsx
msgid "Critical (%)"
@@ -463,12 +455,12 @@ msgstr "Preuzmi"
#: src/components/alerts-history-columns.tsx
msgid "Duration"
msgstr "Trajanje"
msgstr ""
#: src/components/add-system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Edit"
msgstr "Uredi"
msgstr ""
#: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
@@ -518,7 +510,7 @@ msgstr "Postojeći sistemi koji nisu definirani u <0>config.yml</0> će biti izb
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Export"
msgstr "Izvezi"
msgstr ""
#: src/components/routes/settings/config-yaml.tsx
msgid "Export configuration"
@@ -553,11 +545,11 @@ msgstr "Ažuriranje upozorenja nije uspjelo"
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..."
msgstr "Filtriraj..."
msgstr "Filter..."
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Fingerprint"
msgstr "Otisak prsta"
msgstr ""
#: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
@@ -584,10 +576,6 @@ msgstr "Puna"
msgid "General"
msgstr "Općenito"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU motori"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr ""
@@ -604,7 +592,7 @@ msgstr "Homebrew naredba"
#: src/components/add-system.tsx
msgid "Host / IP"
msgstr ""
msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
@@ -622,7 +610,7 @@ msgstr "Nevažeća adresa e-pošte."
#. Linux kernel
#: src/components/routes/system.tsx
msgid "Kernel"
msgstr ""
msgstr "Kernel"
#: src/components/routes/settings/general.tsx
msgid "Language"
@@ -651,7 +639,7 @@ msgstr ""
#. Short label for load average
#: src/components/systems-table/systems-table-columns.tsx
msgid "Load Avg"
msgstr "Prosječno opterećenje"
msgstr ""
#: src/components/navbar.tsx
msgid "Log Out"
@@ -718,7 +706,6 @@ msgstr "Mrežni promet Docker spremnika"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Mrežni promet javnih sučelja"
@@ -733,7 +720,7 @@ msgstr "Nema rezultata."
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "No results."
msgstr "Nema rezultata."
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
@@ -780,7 +767,7 @@ msgstr "Stranica"
#. placeholder {1}: table.getPageCount()
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Page {0} of {1}"
msgstr "Stranica {0} od {1}"
msgstr ""
#: src/components/command-palette.tsx
msgid "Pages / Settings"
@@ -797,7 +784,7 @@ msgstr "Lozinka mora imati najmanje 8 znakova."
#: src/components/login/auth-form.tsx
msgid "Password must be less than 72 bytes."
msgstr "Lozinka mora biti kraća od 72 bajta."
msgstr ""
#: src/components/login/forgot-pass-form.tsx
msgid "Password reset request received"
@@ -813,7 +800,7 @@ msgstr "Pauzirano"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Pauzirano ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
@@ -850,7 +837,7 @@ msgstr "Molimo prijavite se u svoj račun"
#: src/components/add-system.tsx
msgid "Port"
msgstr ""
msgstr "Port"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -970,7 +957,7 @@ msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr ""
msgstr "Status"
#: src/components/routes/system.tsx
msgid "Swap space used by the system"
@@ -1185,16 +1172,12 @@ msgstr "Korisnici"
#: src/components/alerts-history-columns.tsx
msgid "Value"
msgstr "Vrijednost"
msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "View"
msgstr "Prikaz"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Prikaži više"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr ""
@@ -1241,7 +1224,7 @@ msgstr "Piši"
#: src/components/routes/settings/layout.tsx
msgid "YAML Config"
msgstr "YAML konfiguracija"
msgstr "YAML Config"
#: src/components/routes/settings/config-yaml.tsx
msgid "YAML Configuration"
@@ -1250,4 +1233,3 @@ msgstr "YAML Konfiguracija"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Vaše korisničke postavke su ažurirane."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: hu\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-14 20:31\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Hungarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: hu\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -31,13 +31,13 @@ msgstr "{0, plural, one {# óra} other {# óra}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# perc} few {# perc} many {# perc} other {# perc}}"
msgstr ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected."
msgstr "{0} a(z) {1} sorból kiválasztva."
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
@@ -46,11 +46,7 @@ msgstr "1 óra"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "1 min"
msgstr "1 perc"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 perc"
msgstr ""
#: src/lib/utils.ts
msgid "1 week"
@@ -63,7 +59,7 @@ msgstr "12 óra"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "15 min"
msgstr "15 perc"
msgstr ""
#: src/lib/utils.ts
msgid "24 hours"
@@ -76,7 +72,7 @@ msgstr "30 nap"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "5 min"
msgstr "5 perc"
msgstr ""
#. Table column
#: src/components/routes/settings/tokens-fingerprints.tsx
@@ -87,7 +83,7 @@ msgstr "Műveletek"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Active"
msgstr "Aktív"
msgstr ""
#: src/components/routes/home.tsx
msgid "Active Alerts"
@@ -116,7 +112,7 @@ msgstr "Állítsa be a diagram megjelenítését."
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
msgid "Admin"
msgstr "Adminisztráció"
msgstr "Admin"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
@@ -126,7 +122,7 @@ msgstr "Ügynök"
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History"
msgstr "Riasztási előzmények"
msgstr ""
#: src/components/alerts/alert-button.tsx
#: src/components/alerts/alerts-sheet.tsx
@@ -145,7 +141,7 @@ msgstr "Biztosan törölni szeretnéd {name}-t?"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Are you sure?"
msgstr "Biztos vagy benne?"
msgstr ""
#: src/components/copy-to-clipboard.tsx
msgid "Automatic copy requires a secure context."
@@ -177,10 +173,6 @@ msgstr "Rendszerszintű CPU átlagos kihasználtság"
msgid "Average utilization of {0}"
msgstr "{0} átlagos kihasználtsága"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "GPU motorok átlagos kihasználtsága"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -210,12 +202,12 @@ msgstr "Bináris"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)"
msgstr "Bitek (Kbps, Mbps, Gbps)"
msgstr ""
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)"
msgstr "Byte-ok (KB/s, MB/s, GB/s)"
msgstr ""
#: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers"
@@ -232,11 +224,11 @@ msgstr "Figyelem - potenciális adatvesztés"
#: src/components/routes/settings/general.tsx
msgid "Celsius (°C)"
msgstr "Celsius (°C)"
msgstr ""
#: src/components/routes/settings/general.tsx
msgid "Change display units for metrics."
msgstr "A mértékegységek megjelenítésének megváltoztatása."
msgstr ""
#: src/components/routes/settings/general.tsx
msgid "Change general application options."
@@ -269,7 +261,7 @@ msgstr "Ellenőrizd az értesítési szolgáltatásodat"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr "További információkért kattints egy rendszerre."
msgstr ""
#: src/components/ui/input-copy.tsx
msgid "Click to copy"
@@ -291,7 +283,7 @@ msgstr "Jelszó megerősítése"
#: src/components/routes/home.tsx
msgid "Connection is down"
msgstr "Kapcsolat megszakadt"
msgstr ""
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
@@ -317,7 +309,7 @@ msgstr "Docker run másolása"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgctxt "Environment variables"
msgid "Copy env"
msgstr "Környezet másolása"
msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "Copy host"
@@ -346,7 +338,7 @@ msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Copy YAML"
msgstr "YAML másolása"
msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
@@ -365,7 +357,7 @@ msgstr "Fiók létrehozása"
#. Context: date created
#: src/components/alerts-history-columns.tsx
msgid "Created"
msgstr "Létrehozva"
msgstr ""
#: src/components/routes/settings/general.tsx
msgid "Critical (%)"
@@ -400,7 +392,7 @@ msgstr "Törlés"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Delete fingerprint"
msgstr "Ujjlenyomat törlése"
msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
@@ -417,7 +409,7 @@ msgstr "Lemez I/O"
#: src/components/routes/settings/general.tsx
msgid "Disk unit"
msgstr "Lemez mértékegysége"
msgstr ""
#: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
@@ -451,11 +443,11 @@ msgstr "Dokumentáció"
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down"
msgstr "Offline"
msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Offline ({downSystemsLength})"
msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Download"
@@ -463,12 +455,12 @@ msgstr "Letöltés"
#: src/components/alerts-history-columns.tsx
msgid "Duration"
msgstr "Időtartam"
msgstr ""
#: src/components/add-system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Edit"
msgstr "Szerkesztés"
msgstr ""
#: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
@@ -518,7 +510,7 @@ msgstr "A <0>config.yml</0> fájlban nem definiált meglévő rendszerek törlé
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Export"
msgstr "Exportálás"
msgstr ""
#: src/components/routes/settings/config-yaml.tsx
msgid "Export configuration"
@@ -530,7 +522,7 @@ msgstr "Exportálja a jelenlegi rendszerkonfigurációt."
#: src/components/routes/settings/general.tsx
msgid "Fahrenheit (°F)"
msgstr "Fahrenheit (°F)"
msgstr ""
#: src/lib/api.ts
msgid "Failed to authenticate"
@@ -557,7 +549,7 @@ msgstr "Szűrő..."
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Fingerprint"
msgstr "Ujjlenyomat"
msgstr ""
#: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
@@ -584,10 +576,6 @@ msgstr "Tele"
msgid "General"
msgstr "Általános"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU motorok"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU áramfelvétele"
@@ -634,24 +622,24 @@ msgstr "Elrendezés"
#: src/components/routes/system.tsx
msgid "Load Average"
msgstr "Terhelési átlag"
msgstr ""
#: src/lib/alerts.ts
msgid "Load Average 15m"
msgstr "Terhelési átlag 15p"
msgstr ""
#: src/lib/alerts.ts
msgid "Load Average 1m"
msgstr "Terhelési átlag 1p"
msgstr ""
#: src/lib/alerts.ts
msgid "Load Average 5m"
msgstr "Terhelési átlag 5p"
msgstr ""
#. Short label for load average
#: src/components/systems-table/systems-table-columns.tsx
msgid "Load Avg"
msgstr "Terhelési átlag"
msgstr ""
#: src/components/navbar.tsx
msgid "Log Out"
@@ -682,7 +670,7 @@ msgstr "A megjelenítési és értesítési beállítások kezelése."
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Manual setup instructions"
msgstr "Manuális beállítási lépések"
msgstr ""
#. Chart select field. Please try to keep this short.
#: src/components/routes/system.tsx
@@ -718,14 +706,13 @@ msgstr "Docker konténerek hálózati forgalma"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Nyilvános interfészek hálózati forgalma"
#. Context: Bytes or bits
#: src/components/routes/settings/general.tsx
msgid "Network unit"
msgstr "Sávszélesség mértékegysége"
msgstr ""
#: src/components/command-palette.tsx
msgid "No results found."
@@ -733,7 +720,7 @@ msgstr "Nincs találat."
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "No results."
msgstr "Nincs találat."
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
@@ -780,7 +767,7 @@ msgstr "Oldal"
#. placeholder {1}: table.getPageCount()
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Page {0} of {1}"
msgstr "{0}/{1} oldal"
msgstr ""
#: src/components/command-palette.tsx
msgid "Pages / Settings"
@@ -797,7 +784,7 @@ msgstr "A jelszónak legalább 8 karakternek kell lennie."
#: src/components/login/auth-form.tsx
msgid "Password must be less than 72 bytes."
msgstr "A jelszó legfeljebb 72 byte lehet."
msgstr ""
#: src/components/login/forgot-pass-form.tsx
msgid "Password reset request received"
@@ -813,7 +800,7 @@ msgstr "Szüneteltetve"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Szüneteltetve ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
@@ -892,7 +879,7 @@ msgstr "Jelszó visszaállítása"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Resolved"
msgstr "Megoldva"
msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "Resume"
@@ -900,11 +887,11 @@ msgstr "Folytatás"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Rotate token"
msgstr "Tokenváltás"
msgstr ""
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Rows per page"
msgstr "Sorok száma oldalanként"
msgstr ""
#: src/components/routes/settings/notifications.tsx
msgid "Save address using enter key or comma. Leave blank to disable email notifications."
@@ -917,7 +904,7 @@ msgstr "Beállítások mentése"
#: src/components/add-system.tsx
msgid "Save system"
msgstr "Rendszer mentése"
msgstr ""
#: src/components/navbar.tsx
msgid "Search"
@@ -965,7 +952,7 @@ msgstr "Rendezés"
#. Context: alert state (active or resolved)
#: src/components/alerts-history-columns.tsx
msgid "State"
msgstr "Állapot"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
@@ -989,7 +976,7 @@ msgstr "Rendszer"
#: src/components/routes/system.tsx
msgid "System load averages over time"
msgstr "Rendszer terhelési átlaga"
msgstr ""
#: src/components/navbar.tsx
msgid "Systems"
@@ -1006,7 +993,7 @@ msgstr "Tábla"
#. Temperature label in systems table
#: src/components/systems-table/systems-table-columns.tsx
msgid "Temp"
msgstr "Hőmérséklet"
msgstr ""
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
@@ -1015,7 +1002,7 @@ msgstr "Hőmérséklet"
#: src/components/routes/settings/general.tsx
msgid "Temperature unit"
msgstr "Hőmérséklet mértékegysége"
msgstr ""
#: src/components/routes/system.tsx
msgid "Temperatures of system sensors"
@@ -1039,7 +1026,7 @@ msgstr "Ezt a műveletet nem lehet visszavonni! Véglegesen törli a {name} öss
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "This will permanently delete all selected records from the database."
msgstr "Ez véglegesen törli az összes kijelölt bejegyzést az adatbázisból."
msgstr ""
#: src/components/routes/system.tsx
msgid "Throughput of {extraFsName}"
@@ -1069,13 +1056,13 @@ msgstr "Téma váltása"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr "Token"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints"
msgstr "Tokenek & Ujjlenyomatok"
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens allow agents to connect and register. Fingerprints are stable identifiers unique to each system, set on first connection."
@@ -1095,15 +1082,15 @@ msgstr "Összes elküldött adat minden interfészenként"
#: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "Riaszt, ha az 1 perces terhelési átlag túllép egy küszöbértéket"
msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "Riaszt, ha a 15 perces terhelési átlag túllép egy küszöbértéket"
msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "Riaszt, ha az 5 perces terhelési átlag túllép egy küszöbértéket"
msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold"
@@ -1132,12 +1119,12 @@ msgstr "Bekapcsol, ha a lemez érzékelő túllép egy küszöbértéket"
#. Temperature / network units
#: src/components/routes/settings/general.tsx
msgid "Unit preferences"
msgstr "Mértékegység beállítások"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token"
msgstr "Univerzális token"
msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
@@ -1148,11 +1135,11 @@ msgstr "Ismeretlen"
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up"
msgstr "Online"
msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "Up ({upSystemsLength})"
msgstr "Online ({upSystemsLength})"
msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Upload"
@@ -1185,19 +1172,15 @@ msgstr "Felhasználók"
#: src/components/alerts-history-columns.tsx
msgid "Value"
msgstr "Érték"
msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "View"
msgstr "Nézet"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Továbbiak megjelenítése"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Legfrissebb 200 riasztásod áttekintése."
msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "Visible Fields"
@@ -1250,4 +1233,3 @@ msgstr "YAML konfiguráció"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "A felhasználói beállítások frissítésre kerültek."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: is\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-09-22 23:10\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Icelandic\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: is\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -112,7 +112,7 @@ msgstr ""
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
msgid "Admin"
msgstr ""
msgstr "Admin"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
@@ -173,10 +173,6 @@ msgstr "Meðal nýting örgjörva yfir allt kerfið"
msgid "Average utilization of {0}"
msgstr "Meðal notkun af {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -201,7 +197,7 @@ msgstr "Beszel notar <0>Shoutrrr</0> til að tengjast vinsælum tilkynningaþjó
#: src/components/add-system.tsx
msgid "Binary"
msgstr ""
msgstr "Binary"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
@@ -572,7 +568,7 @@ msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr ""
msgstr "Full"
#. Context: General settings
#: src/components/routes/settings/general.tsx
@@ -580,10 +576,6 @@ msgstr ""
msgid "General"
msgstr "Almennt"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr ""
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Skjákorts rafmagnsnotkun"
@@ -600,7 +592,7 @@ msgstr "Homebrew skipun"
#: src/components/add-system.tsx
msgid "Host / IP"
msgstr ""
msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
@@ -705,7 +697,7 @@ msgstr "Nafn"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Net"
msgstr ""
msgstr "Net"
#: src/components/routes/system.tsx
msgid "Network traffic of docker containers"
@@ -845,7 +837,7 @@ msgstr "Vinsamlegast skráðu þig inn á aðganginn þinn"
#: src/components/add-system.tsx
msgid "Port"
msgstr ""
msgstr "Port"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -928,7 +920,7 @@ msgstr ""
#: src/components/routes/system.tsx
msgid "Sent"
msgstr ""
msgstr "Sent"
#: src/components/routes/settings/general.tsx
msgid "Set percentage thresholds for meter colors."
@@ -1186,10 +1178,6 @@ msgstr ""
msgid "View"
msgstr "Skoða"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr ""
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr ""
@@ -1245,4 +1233,3 @@ msgstr ""
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Notenda stillingar vistaðar."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: it\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Italian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: it\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -46,11 +46,7 @@ msgstr "1 ora"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "1 min"
msgstr ""
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minuto"
msgstr "1 min"
#: src/lib/utils.ts
msgid "1 week"
@@ -63,7 +59,7 @@ msgstr "12 ore"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "15 min"
msgstr ""
msgstr "15 min"
#: src/lib/utils.ts
msgid "24 hours"
@@ -76,7 +72,7 @@ msgstr "30 giorni"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "5 min"
msgstr ""
msgstr "5 min"
#. Table column
#: src/components/routes/settings/tokens-fingerprints.tsx
@@ -177,10 +173,6 @@ msgstr "Utilizzo medio della CPU a livello di sistema"
msgid "Average utilization of {0}"
msgstr "Utilizzo medio di {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Utilizzo medio dei motori GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -232,7 +224,7 @@ msgstr "Attenzione - possibile perdita di dati"
#: src/components/routes/settings/general.tsx
msgid "Celsius (°C)"
msgstr ""
msgstr "Celsius (°C)"
#: src/components/routes/settings/general.tsx
msgid "Change display units for metrics."
@@ -350,7 +342,7 @@ msgstr "Copia YAML"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -474,7 +466,7 @@ msgstr "Modifica"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/otp-forms.tsx
msgid "Email"
msgstr ""
msgstr "Email"
#: src/components/routes/settings/notifications.tsx
msgid "Email notifications"
@@ -530,7 +522,7 @@ msgstr "Esporta la configurazione attuale dei tuoi sistemi."
#: src/components/routes/settings/general.tsx
msgid "Fahrenheit (°F)"
msgstr ""
msgstr "Fahrenheit (°F)"
#: src/lib/api.ts
msgid "Failed to authenticate"
@@ -584,10 +576,6 @@ msgstr "Piena"
msgid "General"
msgstr "Generale"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "Motori GPU"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Consumo della GPU"
@@ -604,7 +592,7 @@ msgstr "Comando Homebrew"
#: src/components/add-system.tsx
msgid "Host / IP"
msgstr ""
msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
@@ -622,7 +610,7 @@ msgstr "Indirizzo email non valido."
#. Linux kernel
#: src/components/routes/system.tsx
msgid "Kernel"
msgstr ""
msgstr "Kernel"
#: src/components/routes/settings/general.tsx
msgid "Language"
@@ -687,7 +675,7 @@ msgstr "Istruzioni di configurazione manuale"
#. Chart select field. Please try to keep this short.
#: src/components/routes/system.tsx
msgid "Max 1 min"
msgstr ""
msgstr "Max 1 min"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Memory"
@@ -718,7 +706,6 @@ msgstr "Traffico di rete dei container Docker"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Traffico di rete delle interfacce pubbliche"
@@ -789,7 +776,7 @@ msgstr "Pagine / Impostazioni"
#: src/components/login/auth-form.tsx
#: src/components/login/auth-form.tsx
msgid "Password"
msgstr ""
msgstr "Password"
#: src/components/login/auth-form.tsx
msgid "Password must be at least 8 characters."
@@ -1023,7 +1010,7 @@ msgstr "Temperature dei sensori di sistema"
#: src/components/routes/settings/notifications.tsx
msgid "Test <0>URL</0>"
msgstr ""
msgstr "Test <0>URL</0>"
#: src/components/routes/settings/notifications.tsx
msgid "Test notification sent"
@@ -1069,7 +1056,7 @@ msgstr "Attiva/disattiva tema"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr ""
msgstr "Token"
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
@@ -1191,10 +1178,6 @@ msgstr "Valore"
msgid "View"
msgstr "Vista"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Visualizza altro"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Visualizza i tuoi 200 avvisi più recenti."
@@ -1250,4 +1233,3 @@ msgstr "Configurazione YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Le impostazioni utente sono state aggiornate."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: ja\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Japanese\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: ja\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1時間"
msgid "1 min"
msgstr "1分"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1分"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1週間"
@@ -177,10 +173,6 @@ msgstr "システム全体の平均CPU使用率"
msgid "Average utilization of {0}"
msgstr "{0}の平均使用率"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "GPUエンジンの平均使用率"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -350,7 +342,7 @@ msgstr "YAMLをコピー"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -584,10 +576,6 @@ msgstr "満充電"
msgid "General"
msgstr "一般"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPUエンジン"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPUの消費電力"
@@ -718,7 +706,6 @@ msgstr "Dockerコンテナのネットワークトラフィック"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "パブリックインターフェースのネットワークトラフィック"
@@ -1191,10 +1178,6 @@ msgstr "値"
msgid "View"
msgstr "表示"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "もっと見る"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "直近200件のアラートを表示します。"
@@ -1250,4 +1233,3 @@ msgstr "YAML設定"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "ユーザー設定が更新されました。"

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: ko\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-31 15:44\n"
"Last-Translator: \n"
"Language-Team: Korean\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: ko\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1시간"
msgid "1 min"
msgstr "1분"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1분"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1주"
@@ -177,10 +173,6 @@ msgstr "시스템 전체의 평균 CPU 사용량"
msgid "Average utilization of {0}"
msgstr "평균 {0} 사용량"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "GPU 엔진 평균 사용량"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -495,7 +487,7 @@ msgstr "이메일 주소 입력..."
#: src/components/login/otp-forms.tsx
msgid "Enter your one-time password."
msgstr "OTP를 입력하세요."
msgstr "일회용 비밀번호를 입력하세요."
#: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
@@ -584,10 +576,6 @@ msgstr "가득"
msgid "General"
msgstr "일반"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU 엔진들"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU 전원 사용량"
@@ -718,7 +706,6 @@ msgstr "Docker 컨테이너의 네트워크 트래픽"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "공용 인터페이스의 네트워크 트래픽"
@@ -756,7 +743,7 @@ msgstr "매 시작 시, 데이터베이스가 파일에 정의된 시스템과
#: src/components/login/auth-form.tsx
msgid "One-time password"
msgstr "OTP"
msgstr "일회용 비밀번호"
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
@@ -878,7 +865,7 @@ msgstr "수신됨"
#: src/components/login/login.tsx
msgid "Request a one-time password"
msgstr "OTP 요청"
msgstr "일회용 비밀번호 요청"
#: src/components/login/otp-forms.tsx
msgid "Request OTP"
@@ -1087,11 +1074,11 @@ msgstr "토큰과 지문은 허브에 대한 WebSocket 연결을 인증하는
#: src/components/routes/system/network-sheet.tsx
msgid "Total data received for each interface"
msgstr "각 인터페이스별 총합 다운로드 데이터량"
msgstr "각 인터페이스별 총 수신 데이터량"
#: src/components/routes/system/network-sheet.tsx
msgid "Total data sent for each interface"
msgstr "각 인터페이스별 총합 업로드 데이터량"
msgstr "각 인터페이스별 총 발신 데이터량"
#: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold"
@@ -1191,10 +1178,6 @@ msgstr "값"
msgid "View"
msgstr "보기"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "더 보기"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "최근 200개의 알림을 봅니다."
@@ -1250,4 +1233,3 @@ msgstr "YAML 구성"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "사용자 설정이 업데이트되었습니다."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: nl\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Dutch\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: nl\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,13 +48,9 @@ msgstr "1 uur"
msgid "1 min"
msgstr "1 minuut"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minuut"
#: src/lib/utils.ts
msgid "1 week"
msgstr ""
msgstr "1 week"
#: src/lib/utils.ts
msgid "12 hours"
@@ -116,11 +112,11 @@ msgstr "Weergaveopties voor grafieken aanpassen."
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
msgid "Admin"
msgstr ""
msgstr "Admin"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
msgstr ""
msgstr "Agent"
#: src/components/command-palette.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
@@ -177,10 +173,6 @@ msgstr "Gemiddeld systeembrede CPU-gebruik"
msgid "Average utilization of {0}"
msgstr "Gemiddeld gebruik van {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Gemiddeld gebruik van GPU-engines"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -210,16 +202,16 @@ msgstr "Binair"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)"
msgstr ""
msgstr "Bits (Kbps, Mbps, Gbps)"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)"
msgstr ""
msgstr "Bytes (KB/s, MB/s, GB/s)"
#: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers"
msgstr ""
msgstr "Cache / Buffers"
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
@@ -232,7 +224,7 @@ msgstr "Opgelet - potentieel gegevensverlies"
#: src/components/routes/settings/general.tsx
msgid "Celsius (°C)"
msgstr ""
msgstr "Celsius (°C)"
#: src/components/routes/settings/general.tsx
msgid "Change display units for metrics."
@@ -350,7 +342,7 @@ msgstr "YAML kopiëren"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -387,7 +379,7 @@ msgstr "Huidige status"
#: src/components/command-palette.tsx
#: src/components/routes/home.tsx
msgid "Dashboard"
msgstr ""
msgstr "Dashboard"
#: src/components/routes/settings/general.tsx
msgid "Default time period"
@@ -530,7 +522,7 @@ msgstr "Exporteer je huidige systeemconfiguratie."
#: src/components/routes/settings/general.tsx
msgid "Fahrenheit (°F)"
msgstr ""
msgstr "Fahrenheit (°F)"
#: src/lib/api.ts
msgid "Failed to authenticate"
@@ -553,7 +545,7 @@ msgstr "Bijwerken waarschuwing mislukt"
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..."
msgstr ""
msgstr "Filter..."
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Fingerprint"
@@ -584,10 +576,6 @@ msgstr "Vol"
msgid "General"
msgstr "Algemeen"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU-engines"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU stroomverbruik"
@@ -622,7 +610,7 @@ msgstr "Ongeldig e-mailadres."
#. Linux kernel
#: src/components/routes/system.tsx
msgid "Kernel"
msgstr ""
msgstr "Kernel"
#: src/components/routes/settings/general.tsx
msgid "Language"
@@ -669,7 +657,7 @@ msgstr "Aanmelding mislukt"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs"
msgstr ""
msgstr "Logs"
#: src/components/routes/settings/notifications.tsx
msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table."
@@ -687,7 +675,7 @@ msgstr "Handmatige installatie-instructies"
#. Chart select field. Please try to keep this short.
#: src/components/routes/system.tsx
msgid "Max 1 min"
msgstr ""
msgstr "Max 1 min"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Memory"
@@ -709,7 +697,7 @@ msgstr "Naam"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Net"
msgstr ""
msgstr "Net"
#: src/components/routes/system.tsx
msgid "Network traffic of docker containers"
@@ -718,7 +706,6 @@ msgstr "Netwerkverkeer van docker containers"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Netwerkverkeer van publieke interfaces"
@@ -762,7 +749,7 @@ msgstr "Eenmalig wachtwoord"
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Open menu"
msgstr ""
msgstr "Open menu"
#: src/components/login/auth-form.tsx
msgid "Or continue with"
@@ -970,7 +957,7 @@ msgstr "Status"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr ""
msgstr "Status"
#: src/components/routes/system.tsx
msgid "Swap space used by the system"
@@ -1023,7 +1010,7 @@ msgstr "Temperatuur van systeem sensoren"
#: src/components/routes/settings/notifications.tsx
msgid "Test <0>URL</0>"
msgstr ""
msgstr "Test <0>URL</0>"
#: src/components/routes/settings/notifications.tsx
msgid "Test notification sent"
@@ -1191,10 +1178,6 @@ msgstr "Waarde"
msgid "View"
msgstr "Weergave"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Meer weergeven"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Bekijk je 200 meest recente meldingen."
@@ -1250,4 +1233,3 @@ msgstr "YAML Configuratie"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Je gebruikersinstellingen zijn bijgewerkt."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: no\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-13 17:31\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Norwegian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: no\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -31,13 +31,13 @@ msgstr "{0, plural, one {# time} other {# timer}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# minutt} other {# minutter}}"
msgstr ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected."
msgstr "{0} av {1} rad(er) valgt."
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
@@ -46,11 +46,7 @@ msgstr "1 time"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "1 min"
msgstr "1 min"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minutt"
msgstr ""
#: src/lib/utils.ts
msgid "1 week"
@@ -63,7 +59,7 @@ msgstr "12 timer"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "15 min"
msgstr "15 min"
msgstr ""
#: src/lib/utils.ts
msgid "24 hours"
@@ -76,7 +72,7 @@ msgstr "30 dager"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "5 min"
msgstr "5 min"
msgstr ""
#. Table column
#: src/components/routes/settings/tokens-fingerprints.tsx
@@ -87,7 +83,7 @@ msgstr "Handlinger"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Active"
msgstr "Aktiv"
msgstr ""
#: src/components/routes/home.tsx
msgid "Active Alerts"
@@ -126,7 +122,7 @@ msgstr "Agent"
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History"
msgstr "Varselhistorikk"
msgstr ""
#: src/components/alerts/alert-button.tsx
#: src/components/alerts/alerts-sheet.tsx
@@ -145,7 +141,7 @@ msgstr "Er du sikker på at du vil slette {name}?"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Are you sure?"
msgstr "Er du sikker?"
msgstr ""
#: src/components/copy-to-clipboard.tsx
msgid "Automatic copy requires a secure context."
@@ -177,10 +173,6 @@ msgstr "Gjennomsnittlig CPU-utnyttelse for hele systemet"
msgid "Average utilization of {0}"
msgstr "Gjennomsnittlig utnyttelse av {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Gjennomsnittlig utnyttelse av GPU-motorer"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -210,12 +202,12 @@ msgstr "Binær"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)"
msgstr "Bits (Kbps, Mbps, Gbps)"
msgstr ""
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)"
msgstr "Bytes (KB/s, MB/s, GB/s)"
msgstr ""
#: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers"
@@ -232,11 +224,11 @@ msgstr "Advarsel - potensielt tap av data"
#: src/components/routes/settings/general.tsx
msgid "Celsius (°C)"
msgstr "Celsius (°C)"
msgstr ""
#: src/components/routes/settings/general.tsx
msgid "Change display units for metrics."
msgstr "Endre måleenheter for målinger."
msgstr ""
#: src/components/routes/settings/general.tsx
msgid "Change general application options."
@@ -269,7 +261,7 @@ msgstr "Sjekk din meldingstjeneste"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr "Klikk på et system for å se mer informasjon."
msgstr ""
#: src/components/ui/input-copy.tsx
msgid "Click to copy"
@@ -291,7 +283,7 @@ msgstr "Bekreft passord"
#: src/components/routes/home.tsx
msgid "Connection is down"
msgstr "Tilkoblingen er nede"
msgstr ""
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
@@ -317,7 +309,7 @@ msgstr "Kopier docker run"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgctxt "Environment variables"
msgid "Copy env"
msgstr "Kopier env"
msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "Copy host"
@@ -338,15 +330,15 @@ msgstr "Kopier tekst"
#: src/components/add-system.tsx
msgid "Copy the installation command for the agent below, or register agents automatically with a <0>universal token</0>."
msgstr "Kopier installasjonskommandoen for agenten nedenfor, eller registrer agenter automatisk med en <0>universal token</0>."
msgstr ""
#: src/components/add-system.tsx
msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>."
msgstr "Kopier <0>docker-compose.yml</0> for agenten nedenfor, eller registrer agenter automatisk med en <0>universal token</0>."
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Copy YAML"
msgstr "Kopier YAML"
msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
@@ -365,7 +357,7 @@ msgstr "Opprett konto"
#. Context: date created
#: src/components/alerts-history-columns.tsx
msgid "Created"
msgstr "Opprettet"
msgstr ""
#: src/components/routes/settings/general.tsx
msgid "Critical (%)"
@@ -400,7 +392,7 @@ msgstr "Slett"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Delete fingerprint"
msgstr "Slett fingeravtrykk"
msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
@@ -417,7 +409,7 @@ msgstr "Disk I/O"
#: src/components/routes/settings/general.tsx
msgid "Disk unit"
msgstr "Diskenhet"
msgstr ""
#: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
@@ -455,7 +447,7 @@ msgstr "Nede"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Nede ({downSystemsLength})"
msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Download"
@@ -463,7 +455,7 @@ msgstr "Last ned"
#: src/components/alerts-history-columns.tsx
msgid "Duration"
msgstr "Varighet"
msgstr ""
#: src/components/add-system.tsx
#: src/components/systems-table/systems-table-columns.tsx
@@ -518,7 +510,7 @@ msgstr "Eksisterende systemer som ikke er er definert i <0>config.yml</0> vil bl
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Export"
msgstr "Eksporter"
msgstr ""
#: src/components/routes/settings/config-yaml.tsx
msgid "Export configuration"
@@ -530,7 +522,7 @@ msgstr "Eksporter din nåværende systemkonfigurasjon"
#: src/components/routes/settings/general.tsx
msgid "Fahrenheit (°F)"
msgstr "Fahrenheit (°F)"
msgstr ""
#: src/lib/api.ts
msgid "Failed to authenticate"
@@ -557,7 +549,7 @@ msgstr "Filter..."
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Fingerprint"
msgstr "Fingeravtrykk"
msgstr ""
#: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
@@ -576,7 +568,7 @@ msgstr "FreeBSD kommando"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Fullt"
msgstr "Full"
#. Context: General settings
#: src/components/routes/settings/general.tsx
@@ -584,10 +576,6 @@ msgstr "Fullt"
msgid "General"
msgstr "Generelt"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU-motorer"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU Effektforbruk"
@@ -630,28 +618,28 @@ msgstr "Språk"
#: src/components/systems-table/systems-table.tsx
msgid "Layout"
msgstr "Oppsett"
msgstr "Layout"
#: src/components/routes/system.tsx
msgid "Load Average"
msgstr "Snittbelastning Last"
msgstr ""
#: src/lib/alerts.ts
msgid "Load Average 15m"
msgstr "Snittbelastning 15m"
msgstr ""
#: src/lib/alerts.ts
msgid "Load Average 1m"
msgstr "Snittbelastning 1m"
msgstr ""
#: src/lib/alerts.ts
msgid "Load Average 5m"
msgstr "Snittbelastning 5m"
msgstr ""
#. Short label for load average
#: src/components/systems-table/systems-table-columns.tsx
msgid "Load Avg"
msgstr "Snittbelastning"
msgstr ""
#: src/components/navbar.tsx
msgid "Log Out"
@@ -718,14 +706,13 @@ msgstr "Nettverkstrafikk av docker-konteinere"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Nettverkstrafikk av eksterne nettverksgrensesnitt"
#. Context: Bytes or bits
#: src/components/routes/settings/general.tsx
msgid "Network unit"
msgstr "Nettverksenhet"
msgstr ""
#: src/components/command-palette.tsx
msgid "No results found."
@@ -733,7 +720,7 @@ msgstr "Ingen resultater funnet."
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "No results."
msgstr "Ingen resultater."
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx
@@ -780,7 +767,7 @@ msgstr "Side"
#. placeholder {1}: table.getPageCount()
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Page {0} of {1}"
msgstr "Side {0} av {1}"
msgstr ""
#: src/components/command-palette.tsx
msgid "Pages / Settings"
@@ -813,7 +800,7 @@ msgstr "Satt på Pause"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Pauset ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
@@ -892,7 +879,7 @@ msgstr "Nullstill Passord"
#: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Resolved"
msgstr "Løst"
msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "Resume"
@@ -900,11 +887,11 @@ msgstr "Gjenoppta"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Rotate token"
msgstr "Forny token"
msgstr ""
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Rows per page"
msgstr "Rader per side"
msgstr ""
#: src/components/routes/settings/notifications.tsx
msgid "Save address using enter key or comma. Leave blank to disable email notifications."
@@ -965,7 +952,7 @@ msgstr "Sorter Etter"
#. Context: alert state (active or resolved)
#: src/components/alerts-history-columns.tsx
msgid "State"
msgstr "Tilstand"
msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
@@ -989,7 +976,7 @@ msgstr "System"
#: src/components/routes/system.tsx
msgid "System load averages over time"
msgstr "Systembelastning gjennomsnitt over tid"
msgstr ""
#: src/components/navbar.tsx
msgid "Systems"
@@ -1015,7 +1002,7 @@ msgstr "Temperatur"
#: src/components/routes/settings/general.tsx
msgid "Temperature unit"
msgstr "Temperaturenhet"
msgstr ""
#: src/components/routes/system.tsx
msgid "Temperatures of system sensors"
@@ -1039,7 +1026,7 @@ msgstr "Denne handlingen kan ikke omgjøres. Dette vil slette alle poster for {n
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "This will permanently delete all selected records from the database."
msgstr "Dette vil permanent slette alle valgte oppføringer fra databasen."
msgstr ""
#: src/components/routes/system.tsx
msgid "Throughput of {extraFsName}"
@@ -1069,21 +1056,21 @@ msgstr "Tema av/på"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr "Token"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints"
msgstr "Tokens & Fingeravtrykk"
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens allow agents to connect and register. Fingerprints are stable identifiers unique to each system, set on first connection."
msgstr "Tokens lar agenter koble til og registrere seg selv. Fingeravtrykk er stabile identifikatorer som er unike for hvert system, og blir satt ved første tilkobling."
msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "Tokens og fingeravtrykk blir brukt for å autentisere WebSocket-tilkoblinger til huben."
msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Total data received for each interface"
@@ -1095,15 +1082,15 @@ msgstr "Totalt sendt data for hvert grensesnitt"
#: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "Slår inn når gjennomsnittsbelastningen over 1 minutt overstiger en grenseverdi"
msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "Slår inn når gjennomsnittsbelastningen over 15 minutter overstiger en grenseverdi"
msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "Slår inn når gjennomsnittsbelastningen over 5 minutter overstiger en grenseverdi"
msgstr ""
#: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold"
@@ -1132,12 +1119,12 @@ msgstr "Slår inn når forbruk av hvilken som helst disk overstiger en grensever
#. Temperature / network units
#: src/components/routes/settings/general.tsx
msgid "Unit preferences"
msgstr "Enhetspreferanser"
msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token"
msgstr "Universal token"
msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
@@ -1152,7 +1139,7 @@ msgstr "Oppe"
#: src/components/systems-table/systems-table.tsx
msgid "Up ({upSystemsLength})"
msgstr "Oppe ({upSystemsLength})"
msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Upload"
@@ -1185,19 +1172,15 @@ msgstr "Brukere"
#: src/components/alerts-history-columns.tsx
msgid "Value"
msgstr "Verdi"
msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "View"
msgstr "Visning"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Se mer"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Vis de 200 siste varslene."
msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "Visible Fields"
@@ -1225,7 +1208,7 @@ msgstr "Webhook / Push-varslinger"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "When enabled, this token allows agents to self-register without prior system creation. Expires after one hour or on hub restart."
msgstr "Når aktivert lar denne tokenen agenter registrere seg selv uten å opprettes på systemet først. Utløper etter én time eller når huben starter på nytt."
msgstr ""
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
@@ -1250,4 +1233,3 @@ msgstr "YAML Konfigurasjon"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Dine brukerinnstillinger har blitt oppdatert."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: pl\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-09-03 18:54\n"
"Last-Translator: \n"
"Language-Team: Polish\n"
"Plural-Forms: nplurals=4; plural=(n==1 ? 0 : (n%10>=2 && n%10<=4) && (n%100<12 || n%100>14) ? 1 : n!=1 && (n%10>=0 && n%10<=1) || (n%10>=5 && n%10<=9) || (n%100>=12 && n%100<=14) ? 2 : 3);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: pl\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 godzina"
msgid "1 min"
msgstr "1 min"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minuta"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 tydzień"
@@ -177,10 +173,6 @@ msgstr "Średnie wykorzystanie procesora w całym systemie"
msgid "Average utilization of {0}"
msgstr "Średnie użycie {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Średnie wykorzystanie silników GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -459,7 +451,7 @@ msgstr "Nie działa ({downSystemsLength})"
#: src/components/routes/system/network-sheet.tsx
msgid "Download"
msgstr "Pobieranie"
msgstr "Pobierz"
#: src/components/alerts-history-columns.tsx
msgid "Duration"
@@ -584,10 +576,6 @@ msgstr "Pełna"
msgid "General"
msgstr "Ogólne"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "Silniki GPU"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Moc GPU"
@@ -718,7 +706,6 @@ msgstr "Ruch sieciowy kontenerów Docker."
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Ruch sieciowy interfejsów publicznych"
@@ -870,7 +857,7 @@ msgstr "Klucz publiczny"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
msgid "Read"
msgstr "Odczyt"
msgstr "Czytaj"
#: src/components/routes/system.tsx
msgid "Received"
@@ -1156,7 +1143,7 @@ msgstr "Działa ({upSystemsLength})"
#: src/components/routes/system/network-sheet.tsx
msgid "Upload"
msgstr "Wysyłanie"
msgstr "Wyślij"
#: src/components/routes/system.tsx
msgid "Uptime"
@@ -1191,10 +1178,6 @@ msgstr "Wartość"
msgid "View"
msgstr "Widok"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Zobacz więcej"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Wyświetl 200 ostatnich alertów."
@@ -1250,4 +1233,3 @@ msgstr "Konfiguracja YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Twoje ustawienia użytkownika zostały zaktualizowane."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: pt\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-09 12:03\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Portuguese\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: pt-PT\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 hora"
msgid "1 min"
msgstr "1 min"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minuto"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 semana"
@@ -177,14 +173,10 @@ msgstr "Utilização média de CPU em todo o sistema"
msgid "Average utilization of {0}"
msgstr "Utilização média de {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Utilização média dos motores GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
msgstr "Cópias de segurança"
msgstr "Backups"
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
@@ -219,7 +211,7 @@ msgstr "Bytes (KB/s, MB/s, GB/s)"
#: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers"
msgstr ""
msgstr "Cache / Buffers"
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
@@ -584,10 +576,6 @@ msgstr "Cheia"
msgid "General"
msgstr "Geral"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "Motores GPU"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Consumo de Energia da GPU"
@@ -604,7 +592,7 @@ msgstr "Comando Homebrew"
#: src/components/add-system.tsx
msgid "Host / IP"
msgstr ""
msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
@@ -622,7 +610,7 @@ msgstr "Endereço de email inválido."
#. Linux kernel
#: src/components/routes/system.tsx
msgid "Kernel"
msgstr ""
msgstr "Kernel"
#: src/components/routes/settings/general.tsx
msgid "Language"
@@ -669,7 +657,7 @@ msgstr "Tentativa de login falhou"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs"
msgstr ""
msgstr "Logs"
#: src/components/routes/settings/notifications.tsx
msgid "Looking instead for where to create alerts? Click the bell <0/> icons in the systems table."
@@ -718,7 +706,6 @@ msgstr "Tráfego de rede dos contêineres Docker"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Tráfego de rede das interfaces públicas"
@@ -970,7 +957,7 @@ msgstr "Estado"
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr ""
msgstr "Status"
#: src/components/routes/system.tsx
msgid "Swap space used by the system"
@@ -1006,7 +993,7 @@ msgstr "Tabela"
#. Temperature label in systems table
#: src/components/systems-table/systems-table-columns.tsx
msgid "Temp"
msgstr ""
msgstr "Temp"
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
@@ -1069,7 +1056,7 @@ msgstr "Alternar tema"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr ""
msgstr "Token"
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
@@ -1148,7 +1135,7 @@ msgstr "Desconhecida"
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up"
msgstr "Ligado"
msgstr "Ligado"
#: src/components/systems-table/systems-table.tsx
msgid "Up ({upSystemsLength})"
@@ -1191,10 +1178,6 @@ msgstr "Valor"
msgid "View"
msgstr "Visual"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Ver mais"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Veja os seus 200 alertas mais recentes."
@@ -1250,4 +1233,3 @@ msgstr "Configuração YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "As configurações do seu usuário foram atualizadas."

File diff suppressed because it is too large Load Diff

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: ru\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Russian\n"
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: ru\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -31,7 +31,7 @@ msgstr "{0, plural, one {# час} other {# часов}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# минута} few {# минут} many {# минут} other {# минуты}}"
msgstr ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length
@@ -48,10 +48,6 @@ msgstr "1 час"
msgid "1 min"
msgstr "1 мин"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 минута"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 неделя"
@@ -177,10 +173,6 @@ msgstr "Среднее использование CPU по всей систем
msgid "Average utilization of {0}"
msgstr "Среднее использование {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Средняя загрузка GPU движков"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -269,7 +261,7 @@ msgstr "Проверьте ваш сервис уведомлений"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr "Нажмите на систему для просмотра дополнительной информации."
msgstr ""
#: src/components/ui/input-copy.tsx
msgid "Click to copy"
@@ -350,7 +342,7 @@ msgstr "Скопировать YAML"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr "ЦП"
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -455,7 +447,7 @@ msgstr "Не в сети"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Не в сети ({downSystemsLength})"
msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Download"
@@ -584,10 +576,6 @@ msgstr "Полная"
msgid "General"
msgstr "Общие"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU движки"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Потребляемая мощность GPU"
@@ -718,7 +706,6 @@ msgstr "Сетевой трафик контейнеров Docker"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Сетевой трафик публичных интерфейсов"
@@ -813,7 +800,7 @@ msgstr "Пауза"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Пауза ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
@@ -1152,7 +1139,7 @@ msgstr "В сети"
#: src/components/systems-table/systems-table.tsx
msgid "Up ({upSystemsLength})"
msgstr "В сети ({upSystemsLength})"
msgstr ""
#: src/components/routes/system/network-sheet.tsx
msgid "Upload"
@@ -1191,10 +1178,6 @@ msgstr "Значение"
msgid "View"
msgstr "Вид"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Показать больше"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Просмотреть 200 последних оповещений."
@@ -1250,4 +1233,3 @@ msgstr "YAML конфигурация"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Ваши настройки пользователя были обновлены."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: sl\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Slovenian\n"
"Plural-Forms: nplurals=4; plural=n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3;\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: sl\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -31,13 +31,13 @@ msgstr "{0, plural, one {# ura} two {# uri} few {# ur} other {# ur}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# minuta} few {# minuti} many {# minut} other {# minut}}"
msgstr ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected."
msgstr "{0} od {1} vrstic izbranih."
msgstr ""
#: src/lib/utils.ts
msgid "1 hour"
@@ -46,11 +46,7 @@ msgstr "1 ura"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "1 min"
msgstr "1 min"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minuta"
msgstr ""
#: src/lib/utils.ts
msgid "1 week"
@@ -120,7 +116,7 @@ msgstr "Administrator"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
msgstr ""
msgstr "Agent"
#: src/components/command-palette.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
@@ -177,10 +173,6 @@ msgstr "Povprečna CPU izkoriščenost v celotnem sistemu"
msgid "Average utilization of {0}"
msgstr "Povprečna poraba {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Povprečna uporaba GPU motorjev"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -210,7 +202,7 @@ msgstr "Binarno"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)"
msgstr "Biti (Kbps, Mbps, Gbps)"
msgstr ""
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
@@ -350,7 +342,7 @@ msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -409,11 +401,11 @@ msgstr "Prazni se"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Disk"
msgstr ""
msgstr "Disk"
#: src/components/routes/system.tsx
msgid "Disk I/O"
msgstr ""
msgstr "Disk I/O"
#: src/components/routes/settings/general.tsx
msgid "Disk unit"
@@ -553,7 +545,7 @@ msgstr "Opozorila ni bilo mogoče posodobiti"
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..."
msgstr ""
msgstr "Filter..."
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Fingerprint"
@@ -584,10 +576,6 @@ msgstr "Polna"
msgid "General"
msgstr "Splošno"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU motorji"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU poraba moči"
@@ -718,7 +706,6 @@ msgstr "Omrežni promet docker kontejnerjev"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Omrežni promet javnih vmesnikov"
@@ -813,7 +800,7 @@ msgstr "Zaustavljeno"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Pavzirano za {pausedSystemsLength}"
msgstr ""
#: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
@@ -970,7 +957,7 @@ msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr ""
msgstr "Status"
#: src/components/routes/system.tsx
msgid "Swap space used by the system"
@@ -1191,10 +1178,6 @@ msgstr ""
msgid "View"
msgstr "Pogled"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Prikaži več"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr ""
@@ -1250,4 +1233,3 @@ msgstr "YAML nastavitev"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Vaše uporabniške nastavitve so posodobljene."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: sv\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Swedish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: sv-SE\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -46,11 +46,7 @@ msgstr "1 timme"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "1 min"
msgstr ""
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 minut"
msgstr "1 min"
#: src/lib/utils.ts
msgid "1 week"
@@ -63,7 +59,7 @@ msgstr "12 timmar"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "15 min"
msgstr ""
msgstr "15 min"
#: src/lib/utils.ts
msgid "24 hours"
@@ -76,7 +72,7 @@ msgstr "30 dagar"
#. Load average
#: src/components/charts/load-average-chart.tsx
msgid "5 min"
msgstr ""
msgstr "5 min"
#. Table column
#: src/components/routes/settings/tokens-fingerprints.tsx
@@ -116,11 +112,11 @@ msgstr "Justera visningsalternativ för diagram."
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
msgid "Admin"
msgstr ""
msgstr "Admin"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
msgstr ""
msgstr "Agent"
#: src/components/command-palette.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
@@ -177,10 +173,6 @@ msgstr "Genomsnittlig systemomfattande CPU-användning"
msgid "Average utilization of {0}"
msgstr "Genomsnittlig användning av {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Genomsnittlig användning av GPU-motorer"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -210,7 +202,7 @@ msgstr "Binär"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)"
msgstr ""
msgstr "Bits (Kbps, Mbps, Gbps)"
#: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx
@@ -232,7 +224,7 @@ msgstr "Varning - potentiell dataförlust"
#: src/components/routes/settings/general.tsx
msgid "Celsius (°C)"
msgstr ""
msgstr "Celsius (°C)"
#: src/components/routes/settings/general.tsx
msgid "Change display units for metrics."
@@ -350,7 +342,7 @@ msgstr "Kopiera YAML"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -387,7 +379,7 @@ msgstr "Aktuellt tillstånd"
#: src/components/command-palette.tsx
#: src/components/routes/home.tsx
msgid "Dashboard"
msgstr ""
msgstr "Dashboard"
#: src/components/routes/settings/general.tsx
msgid "Default time period"
@@ -409,11 +401,11 @@ msgstr "Urladdar"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Disk"
msgstr ""
msgstr "Disk"
#: src/components/routes/system.tsx
msgid "Disk I/O"
msgstr ""
msgstr "Disk I/O"
#: src/components/routes/settings/general.tsx
msgid "Disk unit"
@@ -576,7 +568,7 @@ msgstr "FreeBSD kommando"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr ""
msgstr "Full"
#. Context: General settings
#: src/components/routes/settings/general.tsx
@@ -584,10 +576,6 @@ msgstr ""
msgid "General"
msgstr "Allmänt"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU-motorer"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU-strömförbrukning"
@@ -630,7 +618,7 @@ msgstr "Språk"
#: src/components/systems-table/systems-table.tsx
msgid "Layout"
msgstr ""
msgstr "Layout"
#: src/components/routes/system.tsx
msgid "Load Average"
@@ -687,7 +675,7 @@ msgstr ""
#. Chart select field. Please try to keep this short.
#: src/components/routes/system.tsx
msgid "Max 1 min"
msgstr ""
msgstr "Max 1 min"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Memory"
@@ -718,7 +706,6 @@ msgstr "Nätverkstrafik för dockercontainrar"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Nätverkstrafik för publika gränssnitt"
@@ -850,7 +837,7 @@ msgstr "Vänligen logga in på ditt konto"
#: src/components/add-system.tsx
msgid "Port"
msgstr ""
msgstr "Port"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -970,7 +957,7 @@ msgstr ""
#: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status"
msgstr ""
msgstr "Status"
#: src/components/routes/system.tsx
msgid "Swap space used by the system"
@@ -985,7 +972,7 @@ msgstr "Swap-användning"
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System"
msgstr ""
msgstr "System"
#: src/components/routes/system.tsx
msgid "System load averages over time"
@@ -1191,10 +1178,6 @@ msgstr ""
msgid "View"
msgstr "Visa"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Visa mer"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr ""
@@ -1250,4 +1233,3 @@ msgstr "YAML-konfiguration"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Dina användarinställningar har uppdaterats."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: tr\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Turkish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: tr\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 saat"
msgid "1 min"
msgstr "1 dk"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 dakika"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 hafta"
@@ -177,10 +173,6 @@ msgstr "Sistem genelinde ortalama CPU kullanımı"
msgid "Average utilization of {0}"
msgstr "{0} ortalama kullanımı"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "GPU motorlarının ortalama kullanımı"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -350,7 +342,7 @@ msgstr "YAML'ı kopyala"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -409,7 +401,7 @@ msgstr "Boşalıyor"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Disk"
msgstr ""
msgstr "Disk"
#: src/components/routes/system.tsx
msgid "Disk I/O"
@@ -584,10 +576,6 @@ msgstr "Dolu"
msgid "General"
msgstr "Genel"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU motorları"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU Güç Çekimi"
@@ -604,7 +592,7 @@ msgstr "Homebrew komutu"
#: src/components/add-system.tsx
msgid "Host / IP"
msgstr ""
msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
@@ -718,7 +706,6 @@ msgstr "Docker konteynerlerinin ağ trafiği"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Genel arayüzlerin ağ trafiği"
@@ -850,7 +837,7 @@ msgstr "Lütfen hesabınıza giriş yapın"
#: src/components/add-system.tsx
msgid "Port"
msgstr ""
msgstr "Port"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -1023,7 +1010,7 @@ msgstr "Sistem sensörlerinin sıcaklıkları"
#: src/components/routes/settings/notifications.tsx
msgid "Test <0>URL</0>"
msgstr ""
msgstr "Test <0>URL</0>"
#: src/components/routes/settings/notifications.tsx
msgid "Test notification sent"
@@ -1069,7 +1056,7 @@ msgstr "Temayı değiştir"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr ""
msgstr "Token"
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
@@ -1191,10 +1178,6 @@ msgstr "Değer"
msgid "View"
msgstr "Görüntüle"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Daha fazla göster"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "En son 200 uyarınızı görüntüleyin."
@@ -1250,4 +1233,3 @@ msgstr "YAML Yapılandırması"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Kullanıcı ayarlarınız güncellendi."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: uk\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-30 16:20\n"
"Last-Translator: \n"
"Language-Team: Ukrainian\n"
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: uk\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 година"
msgid "1 min"
msgstr "1 хв"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 хвилина"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 тиждень"
@@ -177,10 +173,6 @@ msgstr "Середнє використання CPU по всій системі
msgid "Average utilization of {0}"
msgstr "Середнє використання {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Середнє використання рушіїв GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -584,10 +576,6 @@ msgstr "Повна"
msgid "General"
msgstr "Загальні"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "Рушії GPU"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Енергоспоживання GPU"
@@ -718,7 +706,6 @@ msgstr "Мережевий трафік контейнерів Docker"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Мережевий трафік публічних інтерфейсів"
@@ -1191,10 +1178,6 @@ msgstr "Значення"
msgid "View"
msgstr "Вигляд"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Переглянути більше"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Переглянути 200 останніх сповіщень."
@@ -1250,4 +1233,3 @@ msgstr "Конфігурація YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Ваші налаштування користувача були оновлені."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: vi\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Vietnamese\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: vi\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 giờ"
msgid "1 min"
msgstr "1 phút"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 phút"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 tuần"
@@ -177,10 +173,6 @@ msgstr "Sử dụng CPU trung bình toàn hệ thống"
msgid "Average utilization of {0}"
msgstr "Mức sử dụng trung bình của {0}"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "Mức sử dụng trung bình của động cơ GPU"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -350,7 +342,7 @@ msgstr "Sao chép YAML"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -474,7 +466,7 @@ msgstr "Chỉnh sửa"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/otp-forms.tsx
msgid "Email"
msgstr ""
msgstr "Email"
#: src/components/routes/settings/notifications.tsx
msgid "Email notifications"
@@ -584,10 +576,6 @@ msgstr "Đầy pin"
msgid "General"
msgstr "Chung"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "Động cơ GPU"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "Mức tiêu thụ điện của GPU"
@@ -718,7 +706,6 @@ msgstr "Lưu lượng mạng của các container Docker"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "Lưu lượng mạng của các giao diện công cộng"
@@ -1069,7 +1056,7 @@ msgstr "Chuyển đổi chủ đề"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr ""
msgstr "Token"
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
@@ -1191,10 +1178,6 @@ msgstr "Giá trị"
msgid "View"
msgstr "Xem"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "Xem thêm"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "Xem 200 cảnh báo gần đây nhất của bạn."
@@ -1250,4 +1233,3 @@ msgstr "Cấu hình YAML"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Cài đặt người dùng của bạn đã được cập nhật."

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: zh\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-09-05 08:15\n"
"Last-Translator: \n"
"Language-Team: Chinese Simplified\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: zh-CN\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1 小时"
msgid "1 min"
msgstr "1 分钟"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 分钟"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1 周"
@@ -177,10 +173,6 @@ msgstr "系统范围内的平均 CPU 使用率"
msgid "Average utilization of {0}"
msgstr "{0} 平均利用率"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "GPU 引擎的平均利用率"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -584,10 +576,6 @@ msgstr "满电"
msgid "General"
msgstr "常规"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU 引擎"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU 功耗"
@@ -718,7 +706,6 @@ msgstr "Docker 容器的网络流量"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "公共接口的网络流量"
@@ -1191,10 +1178,6 @@ msgstr "值"
msgid "View"
msgstr "视图"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "查看更多"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "查看您最近的200个警报。"
@@ -1250,4 +1233,3 @@ msgstr "YAML 配置"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "您的用户设置已更新。"

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: zh\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-03 18:42\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Chinese Traditional, Hong Kong\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: zh-HK\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1小時"
msgid "1 min"
msgstr "1 分鐘"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 分鐘"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1週"
@@ -177,10 +173,6 @@ msgstr "系統的平均 CPU 使用率"
msgid "Average utilization of {0}"
msgstr "{0} 的平均使用率"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "GPU 引擎的平均利用率"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -350,7 +342,7 @@ msgstr "複製YAML"
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr ""
msgstr "CPU"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx
@@ -584,10 +576,6 @@ msgstr "滿電"
msgid "General"
msgstr "一般"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU 引擎"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU 功耗"
@@ -622,7 +610,7 @@ msgstr "無效的電子郵件地址。"
#. Linux kernel
#: src/components/routes/system.tsx
msgid "Kernel"
msgstr ""
msgstr "Kernel"
#: src/components/routes/settings/general.tsx
msgid "Language"
@@ -718,7 +706,6 @@ msgstr "Docker 容器的網絡流量"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "公共接口的網絡流量"
@@ -1191,10 +1178,6 @@ msgstr "值"
msgid "View"
msgstr "檢視"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "查看更多"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "檢視最近 200 則警報。"
@@ -1250,4 +1233,3 @@ msgstr "YAML配置"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "您的用戶設置已更新。"

View File

@@ -8,15 +8,15 @@ msgstr ""
"Language: zh\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-10-12 03:15\n"
"PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n"
"Language-Team: Chinese Traditional\n"
"Plural-Forms: nplurals=1; plural=0;\n"
"X-Crowdin-Project: beszel\n"
"X-Crowdin-Project-ID: 733311\n"
"X-Crowdin-Language: zh-TW\n"
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 32\n"
"X-Crowdin-File: /main/beszel/site/src/locales/en/en.po\n"
"X-Crowdin-File-ID: 16\n"
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
#: src/components/routes/system.tsx
@@ -48,10 +48,6 @@ msgstr "1小時"
msgid "1 min"
msgstr "1 分鐘"
#: src/lib/utils.ts
msgid "1 minute"
msgstr "1 分鐘"
#: src/lib/utils.ts
msgid "1 week"
msgstr "1週"
@@ -177,10 +173,6 @@ msgstr "系統的平均 CPU 使用率"
msgid "Average utilization of {0}"
msgstr "{0} 的平均使用率"
#: src/components/routes/system.tsx
msgid "Average utilization of GPU engines"
msgstr "GPU 引擎的平均利用率"
#: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups"
@@ -584,10 +576,6 @@ msgstr "滿電"
msgid "General"
msgstr "一般"
#: src/components/routes/system.tsx
msgid "GPU Engines"
msgstr "GPU 引擎"
#: src/components/routes/system.tsx
msgid "GPU Power Draw"
msgstr "GPU 功耗"
@@ -718,7 +706,6 @@ msgstr "Docker 容器的網路流量"
#: src/components/routes/system.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
#: src/components/routes/system/network-sheet.tsx
msgid "Network traffic of public interfaces"
msgstr "公開介面的網路流量"
@@ -1191,10 +1178,6 @@ msgstr "值"
msgid "View"
msgstr "檢視"
#: src/components/routes/system/network-sheet.tsx
msgid "View more"
msgstr "查看更多"
#: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts."
msgstr "檢視最近 200 則警報。"
@@ -1250,4 +1233,3 @@ msgstr "YAML 設定檔"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "已更新您的使用者設定"

View File

@@ -141,6 +141,8 @@ export interface SystemStats {
g?: Record<string, GPUData>
/** battery percent and state */
bat?: [number, BatteryState]
/** network interfaces [upload bytes, download bytes, total upload bytes, total download bytes] */
ni?: Record<string, [number, number, number, number]>
}
export interface GPUData {

View File

View File

@@ -125,3 +125,28 @@ func CreateSystems(app core.App, count int, userId string, status string) ([]*co
}
return systems, nil
}
// GetHubWithUser creates a test hub with a test user and user settings
func GetHubWithUser(t *testing.T) (*TestHub, *core.Record) {
hub, err := NewTestHub(t.TempDir())
assert.NoError(t, err)
hub.StartHub()
// Manually initialize the system manager to bind event hooks
err = hub.GetSystemManager().Initialize()
assert.NoError(t, err)
// Create a test user
user, err := CreateUser(hub, "test@example.com", "password")
assert.NoError(t, err)
// Create user settings for the test user (required for alert notifications)
userSettingsData := map[string]any{
"user": user.Id,
"settings": `{"emails":[test@example.com],"webhooks":[]}`,
}
_, err = CreateRecord(hub, "user_settings", userSettingsData)
assert.NoError(t, err)
return hub, user
}

View File

@@ -1,5 +1,17 @@
## 0.12.8
- Add per-interface network traffic charts. (#926)
- Add cumulative network traffic charts. (#926)
- Add setting for time format (12h / 24h). (#424)
- Add experimental one-time password (OTP) support.
- Add `TRUSTED_AUTH_HEADER` environment variable for authentication forwarding. (#399)
- Add `AUTO_LOGIN` environment variable for automatic login. (#399)
- Add FreeBSD support for agent install script and update command.
## 0.12.7

View File

@@ -1,7 +1,7 @@
apiVersion: v1
kind: Service
metadata:
name: {{ include "beszel.fullname" . }}-web
name: {{ include "beszel.fullname" . }}
labels:
{{- include "beszel.labels" . | nindent 4 }}
{{- if .Values.service.annotations }}

View File

@@ -30,14 +30,10 @@ securityContext: {}
service:
enabled: true
type: LoadBalancer
loadBalancerIP: "10.0.10.251"
annotations: {}
type: ClusterIP
loadBalancerIP: ""
port: 8090
# -- Annotations for the DHCP service
annotations:
metallb.universe.tf/address-pool: pool
metallb.universe.tf/allow-shared-ip: beszel-hub-web
# -- Labels for the DHCP service
ingress:
enabled: false
@@ -96,7 +92,7 @@ persistentVolumeClaim:
accessModes:
- ReadWriteOnce
storageClass: "retain-local-path"
storageClass: ""
# -- volume claim size
size: "500Mi"