mirror of
https://github.com/henrygd/beszel.git
synced 2025-11-17 02:26:10 +00:00
Compare commits
35 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a911670a2d | ||
|
|
b0cb0c2269 | ||
|
|
735d03577f | ||
|
|
a33f88d822 | ||
|
|
dfd1fc8fda | ||
|
|
1df08801a2 | ||
|
|
62f5f986bb | ||
|
|
a87b9af9d5 | ||
|
|
03900e54cc | ||
|
|
f4abbd1a5b | ||
|
|
77ed90cb4a | ||
|
|
2fe3b1adb1 | ||
|
|
f56093d0f0 | ||
|
|
77dba42f17 | ||
|
|
e233a0b0dc | ||
|
|
18e4c88875 | ||
|
|
904a6038cd | ||
|
|
ae55b86493 | ||
|
|
5360f762e4 | ||
|
|
0d464787f2 | ||
|
|
24f72ef596 | ||
|
|
2d8739052b | ||
|
|
1e32d13650 | ||
|
|
dbf3f94247 | ||
|
|
8a81c7bbac | ||
|
|
d24150c78b | ||
|
|
013da18789 | ||
|
|
5b663621e4 | ||
|
|
4056345216 | ||
|
|
d00c0488c3 | ||
|
|
d352ce00fa | ||
|
|
1623f5e751 | ||
|
|
612ad1238f | ||
|
|
1ad4409609 | ||
|
|
2a94e1d1ec |
@@ -152,7 +152,12 @@ func (a *Agent) gatherStats(cacheTimeMs uint16) *system.CombinedData {
|
||||
data.Stats.ExtraFs = make(map[string]*system.FsStats)
|
||||
for name, stats := range a.fsStats {
|
||||
if !stats.Root && stats.DiskTotal > 0 {
|
||||
data.Stats.ExtraFs[name] = stats
|
||||
// Use custom name if available, otherwise use device name
|
||||
key := name
|
||||
if stats.Name != "" {
|
||||
key = stats.Name
|
||||
}
|
||||
data.Stats.ExtraFs[key] = stats
|
||||
}
|
||||
}
|
||||
slog.Debug("Extra FS", "data", data.Stats.ExtraFs)
|
||||
|
||||
@@ -143,7 +143,9 @@ func (client *WebSocketClient) OnOpen(conn *gws.Conn) {
|
||||
// OnClose handles WebSocket connection closure.
|
||||
// It logs the closure reason and notifies the connection manager.
|
||||
func (client *WebSocketClient) OnClose(conn *gws.Conn, err error) {
|
||||
slog.Warn("Connection closed", "err", strings.TrimPrefix(err.Error(), "gws: "))
|
||||
if err != nil {
|
||||
slog.Warn("Connection closed", "err", strings.TrimPrefix(err.Error(), "gws: "))
|
||||
}
|
||||
client.agent.connectionManager.eventChan <- WebSocketDisconnect
|
||||
}
|
||||
|
||||
@@ -246,7 +248,13 @@ func (client *WebSocketClient) sendMessage(data any) error {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return client.Conn.WriteMessage(gws.OpcodeBinary, bytes)
|
||||
err = client.Conn.WriteMessage(gws.OpcodeBinary, bytes)
|
||||
if err != nil {
|
||||
// If writing fails (e.g., broken pipe due to network issues),
|
||||
// close the connection to trigger reconnection logic (#1263)
|
||||
client.Close()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// sendResponse sends a response with optional request ID for the new protocol
|
||||
@@ -263,6 +271,8 @@ func (client *WebSocketClient) sendResponse(data any, requestID *uint32) error {
|
||||
response.SystemData = v
|
||||
case *common.FingerprintResponse:
|
||||
response.Fingerprint = v
|
||||
case string:
|
||||
response.String = &v
|
||||
// case []byte:
|
||||
// response.RawBytes = v
|
||||
// case string:
|
||||
|
||||
@@ -37,6 +37,16 @@ func (t *DeltaTracker[K, V]) Set(id K, value V) {
|
||||
t.current[id] = value
|
||||
}
|
||||
|
||||
// Snapshot returns a copy of the current map.
|
||||
// func (t *DeltaTracker[K, V]) Snapshot() map[K]V {
|
||||
// t.RLock()
|
||||
// defer t.RUnlock()
|
||||
|
||||
// copyMap := make(map[K]V, len(t.current))
|
||||
// maps.Copy(copyMap, t.current)
|
||||
// return copyMap
|
||||
// }
|
||||
|
||||
// Deltas returns a map of all calculated deltas for the current interval.
|
||||
func (t *DeltaTracker[K, V]) Deltas() map[K]V {
|
||||
t.RLock()
|
||||
@@ -53,6 +63,15 @@ func (t *DeltaTracker[K, V]) Deltas() map[K]V {
|
||||
return deltas
|
||||
}
|
||||
|
||||
// Previous returns the previously recorded value for the given key, if it exists.
|
||||
func (t *DeltaTracker[K, V]) Previous(id K) (V, bool) {
|
||||
t.RLock()
|
||||
defer t.RUnlock()
|
||||
|
||||
value, ok := t.previous[id]
|
||||
return value, ok
|
||||
}
|
||||
|
||||
// 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 {
|
||||
|
||||
@@ -13,6 +13,19 @@ import (
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
)
|
||||
|
||||
// parseFilesystemEntry parses a filesystem entry in the format "device__customname"
|
||||
// Returns the device/filesystem part and the custom name part
|
||||
func parseFilesystemEntry(entry string) (device, customName string) {
|
||||
entry = strings.TrimSpace(entry)
|
||||
if parts := strings.SplitN(entry, "__", 2); len(parts) == 2 {
|
||||
device = strings.TrimSpace(parts[0])
|
||||
customName = strings.TrimSpace(parts[1])
|
||||
} else {
|
||||
device = entry
|
||||
}
|
||||
return device, customName
|
||||
}
|
||||
|
||||
// Sets up the filesystems to monitor for disk usage and I/O.
|
||||
func (a *Agent) initializeDiskInfo() {
|
||||
filesystem, _ := GetEnv("FILESYSTEM")
|
||||
@@ -37,7 +50,7 @@ func (a *Agent) initializeDiskInfo() {
|
||||
slog.Debug("Disk I/O", "diskstats", diskIoCounters)
|
||||
|
||||
// Helper function to add a filesystem to fsStats if it doesn't exist
|
||||
addFsStat := func(device, mountpoint string, root bool) {
|
||||
addFsStat := func(device, mountpoint string, root bool, customName ...string) {
|
||||
var key string
|
||||
if runtime.GOOS == "windows" {
|
||||
key = device
|
||||
@@ -66,7 +79,11 @@ func (a *Agent) initializeDiskInfo() {
|
||||
}
|
||||
}
|
||||
}
|
||||
a.fsStats[key] = &system.FsStats{Root: root, Mountpoint: mountpoint}
|
||||
fsStats := &system.FsStats{Root: root, Mountpoint: mountpoint}
|
||||
if len(customName) > 0 && customName[0] != "" {
|
||||
fsStats.Name = customName[0]
|
||||
}
|
||||
a.fsStats[key] = fsStats
|
||||
}
|
||||
}
|
||||
|
||||
@@ -86,11 +103,14 @@ func (a *Agent) initializeDiskInfo() {
|
||||
|
||||
// Add EXTRA_FILESYSTEMS env var values to fsStats
|
||||
if extraFilesystems, exists := GetEnv("EXTRA_FILESYSTEMS"); exists {
|
||||
for _, fs := range strings.Split(extraFilesystems, ",") {
|
||||
for _, fsEntry := range strings.Split(extraFilesystems, ",") {
|
||||
// Parse custom name from format: device__customname
|
||||
fs, customName := parseFilesystemEntry(fsEntry)
|
||||
|
||||
found := false
|
||||
for _, p := range partitions {
|
||||
if strings.HasSuffix(p.Device, fs) || p.Mountpoint == fs {
|
||||
addFsStat(p.Device, p.Mountpoint, false)
|
||||
addFsStat(p.Device, p.Mountpoint, false, customName)
|
||||
found = true
|
||||
break
|
||||
}
|
||||
@@ -98,7 +118,7 @@ func (a *Agent) initializeDiskInfo() {
|
||||
// if not in partitions, test if we can get disk usage
|
||||
if !found {
|
||||
if _, err := disk.Usage(fs); err == nil {
|
||||
addFsStat(filepath.Base(fs), fs, false)
|
||||
addFsStat(filepath.Base(fs), fs, false, customName)
|
||||
} else {
|
||||
slog.Error("Invalid filesystem", "name", fs, "err", err)
|
||||
}
|
||||
@@ -120,7 +140,8 @@ func (a *Agent) initializeDiskInfo() {
|
||||
|
||||
// Check if device is in /extra-filesystems
|
||||
if strings.HasPrefix(p.Mountpoint, efPath) {
|
||||
addFsStat(p.Device, p.Mountpoint, false)
|
||||
device, customName := parseFilesystemEntry(p.Mountpoint)
|
||||
addFsStat(device, p.Mountpoint, false, customName)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -135,7 +156,8 @@ func (a *Agent) initializeDiskInfo() {
|
||||
mountpoint := filepath.Join(efPath, folder.Name())
|
||||
slog.Debug("/extra-filesystems", "mountpoint", mountpoint)
|
||||
if !existingMountpoints[mountpoint] {
|
||||
addFsStat(folder.Name(), mountpoint, false)
|
||||
device, customName := parseFilesystemEntry(folder.Name())
|
||||
addFsStat(device, mountpoint, false, customName)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
235
agent/disk_test.go
Normal file
235
agent/disk_test.go
Normal file
@@ -0,0 +1,235 @@
|
||||
//go:build testing
|
||||
// +build testing
|
||||
|
||||
package agent
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"github.com/henrygd/beszel/internal/entities/system"
|
||||
"github.com/shirou/gopsutil/v4/disk"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestParseFilesystemEntry(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expectedFs string
|
||||
expectedName string
|
||||
}{
|
||||
{
|
||||
name: "simple device name",
|
||||
input: "sda1",
|
||||
expectedFs: "sda1",
|
||||
expectedName: "",
|
||||
},
|
||||
{
|
||||
name: "device with custom name",
|
||||
input: "sda1__my-storage",
|
||||
expectedFs: "sda1",
|
||||
expectedName: "my-storage",
|
||||
},
|
||||
{
|
||||
name: "full device path with custom name",
|
||||
input: "/dev/sdb1__backup-drive",
|
||||
expectedFs: "/dev/sdb1",
|
||||
expectedName: "backup-drive",
|
||||
},
|
||||
{
|
||||
name: "NVMe device with custom name",
|
||||
input: "nvme0n1p2__fast-ssd",
|
||||
expectedFs: "nvme0n1p2",
|
||||
expectedName: "fast-ssd",
|
||||
},
|
||||
{
|
||||
name: "whitespace trimmed",
|
||||
input: " sda2__trimmed-name ",
|
||||
expectedFs: "sda2",
|
||||
expectedName: "trimmed-name",
|
||||
},
|
||||
{
|
||||
name: "empty custom name",
|
||||
input: "sda3__",
|
||||
expectedFs: "sda3",
|
||||
expectedName: "",
|
||||
},
|
||||
{
|
||||
name: "empty device name",
|
||||
input: "__just-custom",
|
||||
expectedFs: "",
|
||||
expectedName: "just-custom",
|
||||
},
|
||||
{
|
||||
name: "multiple underscores in custom name",
|
||||
input: "sda1__my_custom_drive",
|
||||
expectedFs: "sda1",
|
||||
expectedName: "my_custom_drive",
|
||||
},
|
||||
{
|
||||
name: "custom name with spaces",
|
||||
input: "sda1__My Storage Drive",
|
||||
expectedFs: "sda1",
|
||||
expectedName: "My Storage Drive",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
fsEntry := strings.TrimSpace(tt.input)
|
||||
var fs, customName string
|
||||
if parts := strings.SplitN(fsEntry, "__", 2); len(parts) == 2 {
|
||||
fs = strings.TrimSpace(parts[0])
|
||||
customName = strings.TrimSpace(parts[1])
|
||||
} else {
|
||||
fs = fsEntry
|
||||
}
|
||||
|
||||
assert.Equal(t, tt.expectedFs, fs)
|
||||
assert.Equal(t, tt.expectedName, customName)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestInitializeDiskInfoWithCustomNames(t *testing.T) {
|
||||
// Set up environment variables
|
||||
oldEnv := os.Getenv("EXTRA_FILESYSTEMS")
|
||||
defer func() {
|
||||
if oldEnv != "" {
|
||||
os.Setenv("EXTRA_FILESYSTEMS", oldEnv)
|
||||
} else {
|
||||
os.Unsetenv("EXTRA_FILESYSTEMS")
|
||||
}
|
||||
}()
|
||||
|
||||
// Test with custom names
|
||||
os.Setenv("EXTRA_FILESYSTEMS", "sda1__my-storage,/dev/sdb1__backup-drive,nvme0n1p2")
|
||||
|
||||
// Mock disk partitions (we'll just test the parsing logic)
|
||||
// Since the actual disk operations are system-dependent, we'll focus on the parsing
|
||||
testCases := []struct {
|
||||
envValue string
|
||||
expectedFs []string
|
||||
expectedNames map[string]string
|
||||
}{
|
||||
{
|
||||
envValue: "sda1__my-storage,sdb1__backup-drive",
|
||||
expectedFs: []string{"sda1", "sdb1"},
|
||||
expectedNames: map[string]string{
|
||||
"sda1": "my-storage",
|
||||
"sdb1": "backup-drive",
|
||||
},
|
||||
},
|
||||
{
|
||||
envValue: "sda1,nvme0n1p2__fast-ssd",
|
||||
expectedFs: []string{"sda1", "nvme0n1p2"},
|
||||
expectedNames: map[string]string{
|
||||
"nvme0n1p2": "fast-ssd",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run("env_"+tc.envValue, func(t *testing.T) {
|
||||
os.Setenv("EXTRA_FILESYSTEMS", tc.envValue)
|
||||
|
||||
// Create mock partitions that would match our test cases
|
||||
partitions := []disk.PartitionStat{}
|
||||
for _, fs := range tc.expectedFs {
|
||||
if strings.HasPrefix(fs, "/dev/") {
|
||||
partitions = append(partitions, disk.PartitionStat{
|
||||
Device: fs,
|
||||
Mountpoint: fs,
|
||||
})
|
||||
} else {
|
||||
partitions = append(partitions, disk.PartitionStat{
|
||||
Device: "/dev/" + fs,
|
||||
Mountpoint: "/" + fs,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// Test the parsing logic by calling the relevant part
|
||||
// We'll create a simplified version to test just the parsing
|
||||
extraFilesystems := tc.envValue
|
||||
for _, fsEntry := range strings.Split(extraFilesystems, ",") {
|
||||
// Parse the entry
|
||||
fsEntry = strings.TrimSpace(fsEntry)
|
||||
var fs, customName string
|
||||
if parts := strings.SplitN(fsEntry, "__", 2); len(parts) == 2 {
|
||||
fs = strings.TrimSpace(parts[0])
|
||||
customName = strings.TrimSpace(parts[1])
|
||||
} else {
|
||||
fs = fsEntry
|
||||
}
|
||||
|
||||
// Verify the device is in our expected list
|
||||
assert.Contains(t, tc.expectedFs, fs, "parsed device should be in expected list")
|
||||
|
||||
// Check if custom name should exist
|
||||
if expectedName, exists := tc.expectedNames[fs]; exists {
|
||||
assert.Equal(t, expectedName, customName, "custom name should match expected")
|
||||
} else {
|
||||
assert.Empty(t, customName, "custom name should be empty when not expected")
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestFsStatsWithCustomNames(t *testing.T) {
|
||||
// Test that FsStats properly stores custom names
|
||||
fsStats := &system.FsStats{
|
||||
Mountpoint: "/mnt/storage",
|
||||
Name: "my-custom-storage",
|
||||
DiskTotal: 100.0,
|
||||
DiskUsed: 50.0,
|
||||
}
|
||||
|
||||
assert.Equal(t, "my-custom-storage", fsStats.Name)
|
||||
assert.Equal(t, "/mnt/storage", fsStats.Mountpoint)
|
||||
assert.Equal(t, 100.0, fsStats.DiskTotal)
|
||||
assert.Equal(t, 50.0, fsStats.DiskUsed)
|
||||
}
|
||||
|
||||
func TestExtraFsKeyGeneration(t *testing.T) {
|
||||
// Test the logic for generating ExtraFs keys with custom names
|
||||
testCases := []struct {
|
||||
name string
|
||||
deviceName string
|
||||
customName string
|
||||
expectedKey string
|
||||
}{
|
||||
{
|
||||
name: "with custom name",
|
||||
deviceName: "sda1",
|
||||
customName: "my-storage",
|
||||
expectedKey: "my-storage",
|
||||
},
|
||||
{
|
||||
name: "without custom name",
|
||||
deviceName: "sda1",
|
||||
customName: "",
|
||||
expectedKey: "sda1",
|
||||
},
|
||||
{
|
||||
name: "empty custom name falls back to device",
|
||||
deviceName: "nvme0n1p2",
|
||||
customName: "",
|
||||
expectedKey: "nvme0n1p2",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
// Simulate the key generation logic from agent.go
|
||||
key := tc.deviceName
|
||||
if tc.customName != "" {
|
||||
key = tc.customName
|
||||
}
|
||||
assert.Equal(t, tc.expectedKey, key)
|
||||
})
|
||||
}
|
||||
}
|
||||
207
agent/docker.go
207
agent/docker.go
@@ -3,8 +3,11 @@ package agent
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log/slog"
|
||||
"net"
|
||||
"net/http"
|
||||
@@ -25,6 +28,10 @@ const (
|
||||
dockerTimeoutMs = 2100
|
||||
// Maximum realistic network speed (5 GB/s) to detect bad deltas
|
||||
maxNetworkSpeedBps uint64 = 5e9
|
||||
// Maximum conceivable memory usage of a container (100TB) to detect bad memory stats
|
||||
maxMemoryUsage uint64 = 100 * 1024 * 1024 * 1024 * 1024
|
||||
// Number of log lines to request when fetching container logs
|
||||
dockerLogsTail = 200
|
||||
)
|
||||
|
||||
type dockerManager struct {
|
||||
@@ -198,17 +205,17 @@ func calculateMemoryUsage(apiStats *container.ApiStats, isWindows bool) (uint64,
|
||||
return apiStats.MemoryStats.PrivateWorkingSet, nil
|
||||
}
|
||||
|
||||
// Check if container has valid data, otherwise may be in restart loop (#103)
|
||||
if apiStats.MemoryStats.Usage == 0 {
|
||||
return 0, fmt.Errorf("no memory stats available")
|
||||
}
|
||||
|
||||
memCache := apiStats.MemoryStats.Stats.InactiveFile
|
||||
if memCache == 0 {
|
||||
memCache = apiStats.MemoryStats.Stats.Cache
|
||||
}
|
||||
|
||||
return apiStats.MemoryStats.Usage - memCache, nil
|
||||
usedDelta := apiStats.MemoryStats.Usage - memCache
|
||||
if usedDelta <= 0 || usedDelta > maxMemoryUsage {
|
||||
return 0, fmt.Errorf("bad memory stats")
|
||||
}
|
||||
|
||||
return usedDelta, nil
|
||||
}
|
||||
|
||||
// getNetworkTracker returns the DeltaTracker for a specific cache time, creating it if needed
|
||||
@@ -299,11 +306,46 @@ func updateContainerStatsValues(stats *container.Stats, cpuPct float64, usedMemo
|
||||
stats.PrevReadTime = readTime
|
||||
}
|
||||
|
||||
func parseDockerStatus(status string) (string, container.DockerHealth) {
|
||||
trimmed := strings.TrimSpace(status)
|
||||
if trimmed == "" {
|
||||
return "", container.DockerHealthNone
|
||||
}
|
||||
|
||||
// Remove "About " from status
|
||||
trimmed = strings.Replace(trimmed, "About ", "", 1)
|
||||
|
||||
openIdx := strings.LastIndex(trimmed, "(")
|
||||
if openIdx == -1 || !strings.HasSuffix(trimmed, ")") {
|
||||
return trimmed, container.DockerHealthNone
|
||||
}
|
||||
|
||||
statusText := strings.TrimSpace(trimmed[:openIdx])
|
||||
if statusText == "" {
|
||||
statusText = trimmed
|
||||
}
|
||||
|
||||
healthText := strings.ToLower(strings.TrimSpace(strings.TrimSuffix(trimmed[openIdx+1:], ")")))
|
||||
// Some Docker statuses include a "health:" prefix inside the parentheses.
|
||||
// Strip it so it maps correctly to the known health states.
|
||||
if colonIdx := strings.IndexRune(healthText, ':'); colonIdx != -1 {
|
||||
prefix := strings.TrimSpace(healthText[:colonIdx])
|
||||
if prefix == "health" || prefix == "health status" {
|
||||
healthText = strings.TrimSpace(healthText[colonIdx+1:])
|
||||
}
|
||||
}
|
||||
if health, ok := container.DockerHealthStrings[healthText]; ok {
|
||||
return statusText, health
|
||||
}
|
||||
|
||||
return trimmed, container.DockerHealthNone
|
||||
}
|
||||
|
||||
// Updates stats for individual container with cache-time-aware delta tracking
|
||||
func (dm *dockerManager) updateContainerStats(ctr *container.ApiInfo, cacheTimeMs uint16) error {
|
||||
name := ctr.Names[0][1:]
|
||||
|
||||
resp, err := dm.client.Get("http://localhost/containers/" + ctr.IdShort + "/stats?stream=0&one-shot=1")
|
||||
resp, err := dm.client.Get(fmt.Sprintf("http://localhost/containers/%s/stats?stream=0&one-shot=1", ctr.IdShort))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -314,10 +356,16 @@ func (dm *dockerManager) updateContainerStats(ctr *container.ApiInfo, cacheTimeM
|
||||
// add empty values if they doesn't exist in map
|
||||
stats, initialized := dm.containerStatsMap[ctr.IdShort]
|
||||
if !initialized {
|
||||
stats = &container.Stats{Name: name}
|
||||
stats = &container.Stats{Name: name, Id: ctr.IdShort, Image: ctr.Image}
|
||||
dm.containerStatsMap[ctr.IdShort] = stats
|
||||
}
|
||||
|
||||
stats.Id = ctr.IdShort
|
||||
|
||||
statusText, health := parseDockerStatus(ctr.Status)
|
||||
stats.Status = statusText
|
||||
stats.Health = health
|
||||
|
||||
// reset current stats
|
||||
stats.Cpu = 0
|
||||
stats.Mem = 0
|
||||
@@ -474,28 +522,49 @@ func newDockerManager(a *Agent) *dockerManager {
|
||||
return manager
|
||||
}
|
||||
|
||||
// Check docker version
|
||||
// (versions before 25.0.0 have a bug with one-shot which requires all requests to be made in one batch)
|
||||
// this can take up to 5 seconds with retry, so run in goroutine
|
||||
go manager.checkDockerVersion()
|
||||
|
||||
// give version check a chance to complete before returning
|
||||
time.Sleep(50 * time.Millisecond)
|
||||
|
||||
return manager
|
||||
}
|
||||
|
||||
// checkDockerVersion checks Docker version and sets goodDockerVersion if at least 25.0.0.
|
||||
// Versions before 25.0.0 have a bug with one-shot which requires all requests to be made in one batch.
|
||||
func (dm *dockerManager) checkDockerVersion() {
|
||||
var err error
|
||||
var resp *http.Response
|
||||
var versionInfo struct {
|
||||
Version string `json:"Version"`
|
||||
}
|
||||
resp, err := manager.client.Get("http://localhost/version")
|
||||
const versionMaxTries = 2
|
||||
for i := 1; i <= versionMaxTries; i++ {
|
||||
resp, err = dm.client.Get("http://localhost/version")
|
||||
if err == nil {
|
||||
break
|
||||
}
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
if i < versionMaxTries {
|
||||
slog.Debug("Failed to get Docker version; retrying", "attempt", i, "error", err)
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return manager
|
||||
return
|
||||
}
|
||||
|
||||
if err := manager.decode(resp, &versionInfo); err != nil {
|
||||
return manager
|
||||
if err := dm.decode(resp, &versionInfo); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// if version > 24, one-shot works correctly and we can limit concurrent operations
|
||||
if dockerVersion, err := semver.Parse(versionInfo.Version); err == nil && dockerVersion.Major > 24 {
|
||||
manager.goodDockerVersion = true
|
||||
dm.goodDockerVersion = true
|
||||
} else {
|
||||
slog.Info(fmt.Sprintf("Docker %s is outdated. Upgrade if possible. See https://github.com/henrygd/beszel/issues/58", versionInfo.Version))
|
||||
}
|
||||
|
||||
return manager
|
||||
}
|
||||
|
||||
// Decodes Docker API JSON response using a reusable buffer and decoder. Not thread safe.
|
||||
@@ -525,3 +594,103 @@ func getDockerHost() string {
|
||||
}
|
||||
return scheme + socks[0]
|
||||
}
|
||||
|
||||
// getContainerInfo fetches the inspection data for a container
|
||||
func (dm *dockerManager) getContainerInfo(ctx context.Context, containerID string) (string, error) {
|
||||
endpoint := fmt.Sprintf("http://localhost/containers/%s/json", containerID)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resp, err := dm.client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
|
||||
return "", fmt.Errorf("container info request failed: %s: %s", resp.Status, strings.TrimSpace(string(body)))
|
||||
}
|
||||
|
||||
data, err := io.ReadAll(resp.Body)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
// getLogs fetches the logs for a container
|
||||
func (dm *dockerManager) getLogs(ctx context.Context, containerID string) (string, error) {
|
||||
endpoint := fmt.Sprintf("http://localhost/containers/%s/logs?stdout=1&stderr=1&tail=%d", containerID, dockerLogsTail)
|
||||
req, err := http.NewRequestWithContext(ctx, http.MethodGet, endpoint, nil)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
resp, err := dm.client.Do(req)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
defer resp.Body.Close()
|
||||
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
body, _ := io.ReadAll(io.LimitReader(resp.Body, 1024))
|
||||
return "", fmt.Errorf("logs request failed: %s: %s", resp.Status, strings.TrimSpace(string(body)))
|
||||
}
|
||||
|
||||
var builder strings.Builder
|
||||
if err := decodeDockerLogStream(resp.Body, &builder); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return builder.String(), nil
|
||||
}
|
||||
|
||||
func decodeDockerLogStream(reader io.Reader, builder *strings.Builder) error {
|
||||
const headerSize = 8
|
||||
var header [headerSize]byte
|
||||
buf := make([]byte, 0, dockerLogsTail*200)
|
||||
|
||||
for {
|
||||
if _, err := io.ReadFull(reader, header[:]); err != nil {
|
||||
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
frameLen := binary.BigEndian.Uint32(header[4:])
|
||||
if frameLen == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
buf = allocateBuffer(buf, int(frameLen))
|
||||
if _, err := io.ReadFull(reader, buf[:frameLen]); err != nil {
|
||||
if errors.Is(err, io.EOF) || errors.Is(err, io.ErrUnexpectedEOF) {
|
||||
if len(buf) > 0 {
|
||||
builder.Write(buf[:min(int(frameLen), len(buf))])
|
||||
}
|
||||
return nil
|
||||
}
|
||||
return err
|
||||
}
|
||||
builder.Write(buf[:frameLen])
|
||||
}
|
||||
}
|
||||
|
||||
func allocateBuffer(current []byte, needed int) []byte {
|
||||
if cap(current) >= needed {
|
||||
return current[:needed]
|
||||
}
|
||||
return make([]byte, needed)
|
||||
}
|
||||
|
||||
func min(a, b int) int {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -858,6 +858,54 @@ func TestDeltaTrackerCacheTimeIsolation(t *testing.T) {
|
||||
assert.Equal(t, uint64(200000), recvTracker2.Delta(ctr.IdShort))
|
||||
}
|
||||
|
||||
func TestParseDockerStatus(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
input string
|
||||
expectedStatus string
|
||||
expectedHealth container.DockerHealth
|
||||
}{
|
||||
{
|
||||
name: "status with About an removed",
|
||||
input: "Up About an hour (healthy)",
|
||||
expectedStatus: "Up an hour",
|
||||
expectedHealth: container.DockerHealthHealthy,
|
||||
},
|
||||
{
|
||||
name: "status without About an unchanged",
|
||||
input: "Up 2 hours (healthy)",
|
||||
expectedStatus: "Up 2 hours",
|
||||
expectedHealth: container.DockerHealthHealthy,
|
||||
},
|
||||
{
|
||||
name: "status with About and no parentheses",
|
||||
input: "Up About an hour",
|
||||
expectedStatus: "Up an hour",
|
||||
expectedHealth: container.DockerHealthNone,
|
||||
},
|
||||
{
|
||||
name: "status without parentheses",
|
||||
input: "Created",
|
||||
expectedStatus: "Created",
|
||||
expectedHealth: container.DockerHealthNone,
|
||||
},
|
||||
{
|
||||
name: "empty status",
|
||||
input: "",
|
||||
expectedStatus: "",
|
||||
expectedHealth: container.DockerHealthNone,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
status, health := parseDockerStatus(tt.input)
|
||||
assert.Equal(t, tt.expectedStatus, status)
|
||||
assert.Equal(t, tt.expectedHealth, health)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestConstantsAndUtilityFunctions(t *testing.T) {
|
||||
// Test constants are properly defined
|
||||
assert.Equal(t, uint16(60000), defaultCacheTimeMs)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package agent
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
@@ -43,6 +44,8 @@ func NewHandlerRegistry() *HandlerRegistry {
|
||||
|
||||
registry.Register(common.GetData, &GetDataHandler{})
|
||||
registry.Register(common.CheckFingerprint, &CheckFingerprintHandler{})
|
||||
registry.Register(common.GetContainerLogs, &GetContainerLogsHandler{})
|
||||
registry.Register(common.GetContainerInfo, &GetContainerInfoHandler{})
|
||||
|
||||
return registry
|
||||
}
|
||||
@@ -99,3 +102,53 @@ type CheckFingerprintHandler struct{}
|
||||
func (h *CheckFingerprintHandler) Handle(hctx *HandlerContext) error {
|
||||
return hctx.Client.handleAuthChallenge(hctx.Request, hctx.RequestID)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GetContainerLogsHandler handles container log requests
|
||||
type GetContainerLogsHandler struct{}
|
||||
|
||||
func (h *GetContainerLogsHandler) Handle(hctx *HandlerContext) error {
|
||||
if hctx.Agent.dockerManager == nil {
|
||||
return hctx.SendResponse("", hctx.RequestID)
|
||||
}
|
||||
|
||||
var req common.ContainerLogsRequest
|
||||
if err := cbor.Unmarshal(hctx.Request.Data, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
logContent, err := hctx.Agent.dockerManager.getLogs(ctx, req.ContainerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return hctx.SendResponse(logContent, hctx.RequestID)
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// GetContainerInfoHandler handles container info requests
|
||||
type GetContainerInfoHandler struct{}
|
||||
|
||||
func (h *GetContainerInfoHandler) Handle(hctx *HandlerContext) error {
|
||||
if hctx.Agent.dockerManager == nil {
|
||||
return hctx.SendResponse("", hctx.RequestID)
|
||||
}
|
||||
|
||||
var req common.ContainerInfoRequest
|
||||
if err := cbor.Unmarshal(hctx.Request.Data, &req); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ctx := context.Background()
|
||||
info, err := hctx.Agent.dockerManager.getContainerInfo(ctx, req.ContainerID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return hctx.SendResponse(info, hctx.RequestID)
|
||||
}
|
||||
|
||||
@@ -172,8 +172,24 @@ func (a *Agent) sumAndTrackPerNicDeltas(cacheTimeMs uint16, msElapsed uint64, ne
|
||||
tracker.Set(upKey, v.BytesSent)
|
||||
tracker.Set(downKey, v.BytesRecv)
|
||||
if msElapsed > 0 {
|
||||
upDelta = tracker.Delta(upKey) * 1000 / msElapsed
|
||||
downDelta = tracker.Delta(downKey) * 1000 / msElapsed
|
||||
if prevVal, ok := tracker.Previous(upKey); ok {
|
||||
var deltaBytes uint64
|
||||
if v.BytesSent >= prevVal {
|
||||
deltaBytes = v.BytesSent - prevVal
|
||||
} else {
|
||||
deltaBytes = v.BytesSent
|
||||
}
|
||||
upDelta = deltaBytes * 1000 / msElapsed
|
||||
}
|
||||
if prevVal, ok := tracker.Previous(downKey); ok {
|
||||
var deltaBytes uint64
|
||||
if v.BytesRecv >= prevVal {
|
||||
deltaBytes = v.BytesRecv - prevVal
|
||||
} else {
|
||||
deltaBytes = v.BytesRecv
|
||||
}
|
||||
downDelta = deltaBytes * 1000 / msElapsed
|
||||
}
|
||||
}
|
||||
systemStats.NetworkInterfaces[v.Name] = [4]uint64{upDelta, downDelta, v.BytesSent, v.BytesRecv}
|
||||
}
|
||||
@@ -212,6 +228,10 @@ func (a *Agent) applyNetworkTotals(
|
||||
a.initializeNetIoStats()
|
||||
delete(a.netIoStats, cacheTimeMs)
|
||||
delete(a.netInterfaceDeltaTrackers, cacheTimeMs)
|
||||
systemStats.NetworkSent = 0
|
||||
systemStats.NetworkRecv = 0
|
||||
systemStats.Bandwidth[0], systemStats.Bandwidth[1] = 0, 0
|
||||
return
|
||||
}
|
||||
|
||||
systemStats.NetworkSent = networkSentPs
|
||||
|
||||
@@ -338,6 +338,43 @@ func TestSumAndTrackPerNicDeltas(t *testing.T) {
|
||||
assert.Equal(t, uint64(7000), ni[1])
|
||||
}
|
||||
|
||||
func TestSumAndTrackPerNicDeltasHandlesCounterReset(t *testing.T) {
|
||||
a := &Agent{
|
||||
netInterfaces: map[string]struct{}{"eth0": {}},
|
||||
netInterfaceDeltaTrackers: make(map[uint16]*deltatracker.DeltaTracker[string, uint64]),
|
||||
}
|
||||
|
||||
cache := uint16(77)
|
||||
|
||||
// First interval establishes baseline values
|
||||
initial := []psutilNet.IOCountersStat{{Name: "eth0", BytesSent: 4_000, BytesRecv: 6_000}}
|
||||
statsInitial := &system.Stats{}
|
||||
a.ensureNetworkInterfacesMap(statsInitial)
|
||||
_, _ = a.sumAndTrackPerNicDeltas(cache, 0, initial, statsInitial)
|
||||
|
||||
// Second interval increments counters normally so previous snapshot gets populated
|
||||
increment := []psutilNet.IOCountersStat{{Name: "eth0", BytesSent: 9_000, BytesRecv: 11_000}}
|
||||
statsIncrement := &system.Stats{}
|
||||
a.ensureNetworkInterfacesMap(statsIncrement)
|
||||
_, _ = a.sumAndTrackPerNicDeltas(cache, 1_000, increment, statsIncrement)
|
||||
|
||||
niIncrement, ok := statsIncrement.NetworkInterfaces["eth0"]
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, uint64(5_000), niIncrement[0])
|
||||
assert.Equal(t, uint64(5_000), niIncrement[1])
|
||||
|
||||
// Third interval simulates counter reset (values drop below previous totals)
|
||||
reset := []psutilNet.IOCountersStat{{Name: "eth0", BytesSent: 1_200, BytesRecv: 1_500}}
|
||||
statsReset := &system.Stats{}
|
||||
a.ensureNetworkInterfacesMap(statsReset)
|
||||
_, _ = a.sumAndTrackPerNicDeltas(cache, 1_000, reset, statsReset)
|
||||
|
||||
niReset, ok := statsReset.NetworkInterfaces["eth0"]
|
||||
require.True(t, ok)
|
||||
assert.Equal(t, uint64(1_200), niReset[0], "upload delta should match new counter value after reset")
|
||||
assert.Equal(t, uint64(1_500), niReset[1], "download delta should match new counter value after reset")
|
||||
}
|
||||
|
||||
func TestApplyNetworkTotals(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
@@ -441,10 +478,13 @@ func TestApplyNetworkTotals(t *testing.T) {
|
||||
)
|
||||
|
||||
if tt.expectReset {
|
||||
// Should have reset network tracking state - delta trackers should be cleared
|
||||
// Note: initializeNetIoStats resets the maps, then applyNetworkTotals sets nis back
|
||||
assert.Contains(t, a.netIoStats, cacheTimeMs, "cache entry should exist after reset")
|
||||
// Should have reset network tracking state - maps cleared and stats zeroed
|
||||
assert.NotContains(t, a.netIoStats, cacheTimeMs, "cache entry should be cleared after reset")
|
||||
assert.NotContains(t, a.netInterfaceDeltaTrackers, cacheTimeMs, "tracker should be cleared on reset")
|
||||
assert.Zero(t, systemStats.NetworkSent)
|
||||
assert.Zero(t, systemStats.NetworkRecv)
|
||||
assert.Zero(t, systemStats.Bandwidth[0])
|
||||
assert.Zero(t, systemStats.Bandwidth[1])
|
||||
} else {
|
||||
// Should have applied stats
|
||||
assert.Equal(t, tt.expectedNetworkSent, systemStats.NetworkSent)
|
||||
|
||||
@@ -168,6 +168,8 @@ func (a *Agent) handleSSHRequest(w io.Writer, req *common.HubRequest[cbor.RawMes
|
||||
switch v := data.(type) {
|
||||
case *system.CombinedData:
|
||||
response.SystemData = v
|
||||
case string:
|
||||
response.String = &v
|
||||
default:
|
||||
response.Error = fmt.Sprintf("unsupported response type: %T", data)
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ import "github.com/blang/semver"
|
||||
|
||||
const (
|
||||
// Version is the current version of the application.
|
||||
Version = "0.13.1"
|
||||
Version = "0.14.1"
|
||||
// AppName is the name of the application.
|
||||
AppName = "beszel"
|
||||
)
|
||||
|
||||
@@ -11,6 +11,10 @@ const (
|
||||
GetData WebSocketAction = iota
|
||||
// Check the fingerprint of the agent
|
||||
CheckFingerprint
|
||||
// Request container logs from agent
|
||||
GetContainerLogs
|
||||
// Request container info from agent
|
||||
GetContainerInfo
|
||||
// Add new actions here...
|
||||
)
|
||||
|
||||
@@ -27,6 +31,8 @@ type AgentResponse struct {
|
||||
SystemData *system.CombinedData `cbor:"1,keyasint,omitempty,omitzero"`
|
||||
Fingerprint *FingerprintResponse `cbor:"2,keyasint,omitempty,omitzero"`
|
||||
Error string `cbor:"3,keyasint,omitempty,omitzero"`
|
||||
String *string `cbor:"4,keyasint,omitempty,omitzero"`
|
||||
// Logs *LogsPayload `cbor:"4,keyasint,omitempty,omitzero"`
|
||||
// RawBytes []byte `cbor:"4,keyasint,omitempty,omitzero"`
|
||||
}
|
||||
|
||||
@@ -47,3 +53,11 @@ type DataRequestOptions struct {
|
||||
CacheTimeMs uint16 `cbor:"0,keyasint"`
|
||||
// ResourceType uint8 `cbor:"1,keyasint,omitempty,omitzero"`
|
||||
}
|
||||
|
||||
type ContainerLogsRequest struct {
|
||||
ContainerID string `cbor:"0,keyasint"`
|
||||
}
|
||||
|
||||
type ContainerInfoRequest struct {
|
||||
ContainerID string `cbor:"0,keyasint"`
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ type ApiInfo struct {
|
||||
IdShort string
|
||||
Names []string
|
||||
Status string
|
||||
// Image string
|
||||
State string
|
||||
Image string
|
||||
// ImageID string
|
||||
// Command string
|
||||
// Created int64
|
||||
@@ -16,7 +17,6 @@ type ApiInfo struct {
|
||||
// SizeRw int64 `json:",omitempty"`
|
||||
// SizeRootFs int64 `json:",omitempty"`
|
||||
// Labels map[string]string
|
||||
// State string
|
||||
// HostConfig struct {
|
||||
// NetworkMode string `json:",omitempty"`
|
||||
// Annotations map[string]string `json:",omitempty"`
|
||||
@@ -103,6 +103,22 @@ type prevNetStats struct {
|
||||
Recv uint64
|
||||
}
|
||||
|
||||
type DockerHealth = uint8
|
||||
|
||||
const (
|
||||
DockerHealthNone DockerHealth = iota
|
||||
DockerHealthStarting
|
||||
DockerHealthHealthy
|
||||
DockerHealthUnhealthy
|
||||
)
|
||||
|
||||
var DockerHealthStrings = map[string]DockerHealth{
|
||||
"none": DockerHealthNone,
|
||||
"starting": DockerHealthStarting,
|
||||
"healthy": DockerHealthHealthy,
|
||||
"unhealthy": DockerHealthUnhealthy,
|
||||
}
|
||||
|
||||
// Docker container stats
|
||||
type Stats struct {
|
||||
Name string `json:"n" cbor:"0,keyasint"`
|
||||
@@ -110,6 +126,11 @@ type Stats struct {
|
||||
Mem float64 `json:"m" cbor:"2,keyasint"`
|
||||
NetworkSent float64 `json:"ns" cbor:"3,keyasint"`
|
||||
NetworkRecv float64 `json:"nr" cbor:"4,keyasint"`
|
||||
|
||||
Health DockerHealth `json:"-" cbor:"5,keyasint"`
|
||||
Status string `json:"-" cbor:"6,keyasint"`
|
||||
Id string `json:"-" cbor:"7,keyasint"`
|
||||
Image string `json:"-" cbor:"8,keyasint"`
|
||||
// PrevCpu [2]uint64 `json:"-"`
|
||||
CpuSystem uint64 `json:"-"`
|
||||
CpuContainer uint64 `json:"-"`
|
||||
|
||||
@@ -62,6 +62,7 @@ type FsStats struct {
|
||||
Time time.Time `json:"-"`
|
||||
Root bool `json:"-"`
|
||||
Mountpoint string `json:"-"`
|
||||
Name string `json:"-"`
|
||||
DiskTotal float64 `json:"d" cbor:"0,keyasint"`
|
||||
DiskUsed float64 `json:"du" cbor:"1,keyasint"`
|
||||
TotalRead uint64 `json:"-"`
|
||||
|
||||
@@ -120,7 +120,19 @@ func (h *Hub) initialize(e *core.ServeEvent) error {
|
||||
return err
|
||||
}
|
||||
// set auth settings
|
||||
usersCollection, err := e.App.FindCollectionByNameOrId("users")
|
||||
if err := setCollectionAuthSettings(e.App); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// setCollectionAuthSettings sets up default authentication settings for the app
|
||||
func setCollectionAuthSettings(app core.App) error {
|
||||
usersCollection, err := app.FindCollectionByNameOrId("users")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
superusersCollection, err := app.FindCollectionByNameOrId(core.CollectionNameSuperusers)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -128,10 +140,6 @@ func (h *Hub) initialize(e *core.ServeEvent) error {
|
||||
disablePasswordAuth, _ := GetEnv("DISABLE_PASSWORD_AUTH")
|
||||
usersCollection.PasswordAuth.Enabled = disablePasswordAuth != "true"
|
||||
usersCollection.PasswordAuth.IdentityFields = []string{"email"}
|
||||
// disable oauth if no providers are configured (todo: remove this in post 0.9.0 release)
|
||||
if usersCollection.OAuth2.Enabled {
|
||||
usersCollection.OAuth2.Enabled = len(usersCollection.OAuth2.Providers) > 0
|
||||
}
|
||||
// allow oauth user creation if USER_CREATION is set
|
||||
if userCreation, _ := GetEnv("USER_CREATION"); userCreation == "true" {
|
||||
cr := "@request.context = 'oauth2'"
|
||||
@@ -139,11 +147,22 @@ func (h *Hub) initialize(e *core.ServeEvent) error {
|
||||
} else {
|
||||
usersCollection.CreateRule = nil
|
||||
}
|
||||
if err := e.App.Save(usersCollection); err != nil {
|
||||
// enable mfaOtp mfa if MFA_OTP env var is set
|
||||
mfaOtp, _ := GetEnv("MFA_OTP")
|
||||
usersCollection.OTP.Length = 6
|
||||
superusersCollection.OTP.Length = 6
|
||||
usersCollection.OTP.Enabled = mfaOtp == "true"
|
||||
usersCollection.MFA.Enabled = mfaOtp == "true"
|
||||
superusersCollection.OTP.Enabled = mfaOtp == "true" || mfaOtp == "superusers"
|
||||
superusersCollection.MFA.Enabled = mfaOtp == "true" || mfaOtp == "superusers"
|
||||
if err := app.Save(superusersCollection); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := app.Save(usersCollection); err != nil {
|
||||
return err
|
||||
}
|
||||
// allow all users to access systems if SHARE_ALL_SYSTEMS is set
|
||||
systemsCollection, err := e.App.FindCachedCollectionByNameOrId("systems")
|
||||
systemsCollection, err := app.FindCollectionByNameOrId("systems")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -158,10 +177,7 @@ func (h *Hub) initialize(e *core.ServeEvent) error {
|
||||
systemsCollection.ViewRule = &systemsReadRule
|
||||
systemsCollection.UpdateRule = &updateDeleteRule
|
||||
systemsCollection.DeleteRule = &updateDeleteRule
|
||||
if err := e.App.Save(systemsCollection); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
return app.Save(systemsCollection)
|
||||
}
|
||||
|
||||
// registerCronJobs sets up scheduled tasks
|
||||
@@ -236,7 +252,10 @@ func (h *Hub) registerApiRoutes(se *core.ServeEvent) error {
|
||||
// update / delete user alerts
|
||||
apiAuth.POST("/user-alerts", alerts.UpsertUserAlerts)
|
||||
apiAuth.DELETE("/user-alerts", alerts.DeleteUserAlerts)
|
||||
|
||||
// get container logs
|
||||
apiAuth.GET("/containers/logs", h.getContainerLogs)
|
||||
// get container info
|
||||
apiAuth.GET("/containers/info", h.getContainerInfo)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -267,6 +286,41 @@ func (h *Hub) getUniversalToken(e *core.RequestEvent) error {
|
||||
return e.JSON(http.StatusOK, response)
|
||||
}
|
||||
|
||||
// containerRequestHandler handles both container logs and info requests
|
||||
func (h *Hub) containerRequestHandler(e *core.RequestEvent, fetchFunc func(*systems.System, string) (string, error), responseKey string) error {
|
||||
systemID := e.Request.URL.Query().Get("system")
|
||||
containerID := e.Request.URL.Query().Get("container")
|
||||
|
||||
if systemID == "" || containerID == "" {
|
||||
return e.JSON(http.StatusBadRequest, map[string]string{"error": "system and container parameters are required"})
|
||||
}
|
||||
|
||||
system, err := h.sm.GetSystem(systemID)
|
||||
if err != nil {
|
||||
return e.JSON(http.StatusNotFound, map[string]string{"error": "system not found"})
|
||||
}
|
||||
|
||||
data, err := fetchFunc(system, containerID)
|
||||
if err != nil {
|
||||
return e.JSON(http.StatusInternalServerError, map[string]string{"error": err.Error()})
|
||||
}
|
||||
|
||||
return e.JSON(http.StatusOK, map[string]string{responseKey: data})
|
||||
}
|
||||
|
||||
// getContainerLogs handles GET /api/beszel/containers/logs requests
|
||||
func (h *Hub) getContainerLogs(e *core.RequestEvent) error {
|
||||
return h.containerRequestHandler(e, func(system *systems.System, containerID string) (string, error) {
|
||||
return system.FetchContainerLogsFromAgent(containerID)
|
||||
}, "logs")
|
||||
}
|
||||
|
||||
func (h *Hub) getContainerInfo(e *core.RequestEvent) error {
|
||||
return h.containerRequestHandler(e, func(system *systems.System, containerID string) (string, error) {
|
||||
return system.FetchContainerInfoFromAgent(containerID)
|
||||
}, "info")
|
||||
}
|
||||
|
||||
// generates key pair if it doesn't exist and returns signer
|
||||
func (h *Hub) GetSSHKey(dataDir string) (ssh.Signer, error) {
|
||||
if h.signer != nil {
|
||||
|
||||
@@ -449,6 +449,47 @@ func TestApiRoutesAuthentication(t *testing.T) {
|
||||
})
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "GET /containers/logs - no auth should fail",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/beszel/containers/logs?system=test-system&container=test-container",
|
||||
ExpectedStatus: 401,
|
||||
ExpectedContent: []string{"requires valid"},
|
||||
TestAppFactory: testAppFactory,
|
||||
},
|
||||
{
|
||||
Name: "GET /containers/logs - with auth but missing system param should fail",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/beszel/containers/logs?container=test-container",
|
||||
Headers: map[string]string{
|
||||
"Authorization": userToken,
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{"system and container parameters are required"},
|
||||
TestAppFactory: testAppFactory,
|
||||
},
|
||||
{
|
||||
Name: "GET /containers/logs - with auth but missing container param should fail",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/beszel/containers/logs?system=test-system",
|
||||
Headers: map[string]string{
|
||||
"Authorization": userToken,
|
||||
},
|
||||
ExpectedStatus: 400,
|
||||
ExpectedContent: []string{"system and container parameters are required"},
|
||||
TestAppFactory: testAppFactory,
|
||||
},
|
||||
{
|
||||
Name: "GET /containers/logs - with auth but invalid system should fail",
|
||||
Method: http.MethodGet,
|
||||
URL: "/api/beszel/containers/logs?system=invalid-system&container=test-container",
|
||||
Headers: map[string]string{
|
||||
"Authorization": userToken,
|
||||
},
|
||||
ExpectedStatus: 404,
|
||||
ExpectedContent: []string{"system not found"},
|
||||
TestAppFactory: testAppFactory,
|
||||
},
|
||||
|
||||
// Auth Optional Routes - Should work without authentication
|
||||
{
|
||||
|
||||
@@ -13,12 +13,14 @@ import (
|
||||
"github.com/henrygd/beszel/internal/common"
|
||||
"github.com/henrygd/beszel/internal/hub/ws"
|
||||
|
||||
"github.com/henrygd/beszel/internal/entities/container"
|
||||
"github.com/henrygd/beszel/internal/entities/system"
|
||||
|
||||
"github.com/henrygd/beszel"
|
||||
|
||||
"github.com/blang/semver"
|
||||
"github.com/fxamacker/cbor/v2"
|
||||
"github.com/pocketbase/dbx"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
"golang.org/x/crypto/ssh"
|
||||
)
|
||||
@@ -135,41 +137,81 @@ func (sys *System) createRecords(data *system.CombinedData) (*core.Record, error
|
||||
return nil, err
|
||||
}
|
||||
hub := sys.manager.hub
|
||||
// add system_stats and container_stats records
|
||||
systemStatsCollection, err := hub.FindCachedCollectionByNameOrId("system_stats")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
systemStatsRecord := core.NewRecord(systemStatsCollection)
|
||||
systemStatsRecord.Set("system", systemRecord.Id)
|
||||
systemStatsRecord.Set("stats", data.Stats)
|
||||
systemStatsRecord.Set("type", "1m")
|
||||
if err := hub.SaveNoValidate(systemStatsRecord); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// add new container_stats record
|
||||
if len(data.Containers) > 0 {
|
||||
containerStatsCollection, err := hub.FindCachedCollectionByNameOrId("container_stats")
|
||||
err = hub.RunInTransaction(func(txApp core.App) error {
|
||||
// add system_stats and container_stats records
|
||||
systemStatsCollection, err := txApp.FindCachedCollectionByNameOrId("system_stats")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return err
|
||||
}
|
||||
containerStatsRecord := core.NewRecord(containerStatsCollection)
|
||||
containerStatsRecord.Set("system", systemRecord.Id)
|
||||
containerStatsRecord.Set("stats", data.Containers)
|
||||
containerStatsRecord.Set("type", "1m")
|
||||
if err := hub.SaveNoValidate(containerStatsRecord); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
// update system record (do this last because it triggers alerts and we need above records to be inserted first)
|
||||
systemRecord.Set("status", up)
|
||||
|
||||
systemRecord.Set("info", data.Info)
|
||||
if err := hub.SaveNoValidate(systemRecord); err != nil {
|
||||
return nil, err
|
||||
systemStatsRecord := core.NewRecord(systemStatsCollection)
|
||||
systemStatsRecord.Set("system", systemRecord.Id)
|
||||
systemStatsRecord.Set("stats", data.Stats)
|
||||
systemStatsRecord.Set("type", "1m")
|
||||
if err := txApp.SaveNoValidate(systemStatsRecord); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(data.Containers) > 0 {
|
||||
// add / update containers records
|
||||
if data.Containers[0].Id != "" {
|
||||
if err := createContainerRecords(txApp, data.Containers, sys.Id); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// add new container_stats record
|
||||
containerStatsCollection, err := txApp.FindCachedCollectionByNameOrId("container_stats")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
containerStatsRecord := core.NewRecord(containerStatsCollection)
|
||||
containerStatsRecord.Set("system", systemRecord.Id)
|
||||
containerStatsRecord.Set("stats", data.Containers)
|
||||
containerStatsRecord.Set("type", "1m")
|
||||
if err := txApp.SaveNoValidate(containerStatsRecord); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
// update system record (do this last because it triggers alerts and we need above records to be inserted first)
|
||||
systemRecord.Set("status", up)
|
||||
|
||||
systemRecord.Set("info", data.Info)
|
||||
if err := txApp.SaveNoValidate(systemRecord); err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
|
||||
return systemRecord, err
|
||||
}
|
||||
|
||||
// createContainerRecords creates container records
|
||||
func createContainerRecords(app core.App, data []*container.Stats, systemId string) error {
|
||||
if len(data) == 0 {
|
||||
return nil
|
||||
}
|
||||
return systemRecord, nil
|
||||
params := dbx.Params{
|
||||
"system": systemId,
|
||||
"updated": time.Now().UTC().UnixMilli(),
|
||||
}
|
||||
valueStrings := make([]string, 0, len(data))
|
||||
for i, container := range data {
|
||||
suffix := fmt.Sprintf("%d", i)
|
||||
valueStrings = append(valueStrings, fmt.Sprintf("({:id%[1]s}, {:system}, {:name%[1]s}, {:image%[1]s}, {:status%[1]s}, {:health%[1]s}, {:cpu%[1]s}, {:memory%[1]s}, {:net%[1]s}, {:updated})", suffix))
|
||||
params["id"+suffix] = container.Id
|
||||
params["name"+suffix] = container.Name
|
||||
params["image"+suffix] = container.Image
|
||||
params["status"+suffix] = container.Status
|
||||
params["health"+suffix] = container.Health
|
||||
params["cpu"+suffix] = container.Cpu
|
||||
params["memory"+suffix] = container.Mem
|
||||
params["net"+suffix] = container.NetworkSent + container.NetworkRecv
|
||||
}
|
||||
queryString := fmt.Sprintf(
|
||||
"INSERT INTO containers (id, system, name, image, status, health, cpu, memory, net, updated) VALUES %s ON CONFLICT(id) DO UPDATE SET system = excluded.system, name = excluded.name, image = excluded.image, status = excluded.status, health = excluded.health, cpu = excluded.cpu, memory = excluded.memory, net = excluded.net, updated = excluded.updated",
|
||||
strings.Join(valueStrings, ","),
|
||||
)
|
||||
_, err := app.DB().NewQuery(queryString).Bind(params).Execute()
|
||||
return err
|
||||
}
|
||||
|
||||
// getRecord retrieves the system record from the database.
|
||||
@@ -242,37 +284,74 @@ func (sys *System) fetchDataViaWebSocket(options common.DataRequestOptions) (*sy
|
||||
return sys.data, nil
|
||||
}
|
||||
|
||||
// fetchStringFromAgentViaSSH is a generic function to fetch strings via SSH
|
||||
func (sys *System) fetchStringFromAgentViaSSH(action common.WebSocketAction, requestData any, errorMsg string) (string, error) {
|
||||
var result string
|
||||
err := sys.runSSHOperation(4*time.Second, 1, func(session *ssh.Session) (bool, error) {
|
||||
stdout, err := session.StdoutPipe()
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
stdin, stdinErr := session.StdinPipe()
|
||||
if stdinErr != nil {
|
||||
return false, stdinErr
|
||||
}
|
||||
if err := session.Shell(); err != nil {
|
||||
return false, err
|
||||
}
|
||||
req := common.HubRequest[any]{Action: action, Data: requestData}
|
||||
_ = cbor.NewEncoder(stdin).Encode(req)
|
||||
_ = stdin.Close()
|
||||
var resp common.AgentResponse
|
||||
err = cbor.NewDecoder(stdout).Decode(&resp)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
if resp.String == nil {
|
||||
return false, errors.New(errorMsg)
|
||||
}
|
||||
result = *resp.String
|
||||
return false, nil
|
||||
})
|
||||
return result, err
|
||||
}
|
||||
|
||||
// FetchContainerInfoFromAgent fetches container info from the agent
|
||||
func (sys *System) FetchContainerInfoFromAgent(containerID string) (string, error) {
|
||||
// fetch via websocket
|
||||
if sys.WsConn != nil && sys.WsConn.IsConnected() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
return sys.WsConn.RequestContainerInfo(ctx, containerID)
|
||||
}
|
||||
// fetch via SSH
|
||||
return sys.fetchStringFromAgentViaSSH(common.GetContainerInfo, common.ContainerInfoRequest{ContainerID: containerID}, "no info in response")
|
||||
}
|
||||
|
||||
// FetchContainerLogsFromAgent fetches container logs from the agent
|
||||
func (sys *System) FetchContainerLogsFromAgent(containerID string) (string, error) {
|
||||
// fetch via websocket
|
||||
if sys.WsConn != nil && sys.WsConn.IsConnected() {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
||||
defer cancel()
|
||||
return sys.WsConn.RequestContainerLogs(ctx, containerID)
|
||||
}
|
||||
// fetch via SSH
|
||||
return sys.fetchStringFromAgentViaSSH(common.GetContainerLogs, common.ContainerLogsRequest{ContainerID: containerID}, "no logs in response")
|
||||
}
|
||||
|
||||
// fetchDataViaSSH handles fetching data using SSH.
|
||||
// This function encapsulates the original SSH logic.
|
||||
// It updates sys.data directly upon successful fetch.
|
||||
func (sys *System) fetchDataViaSSH(options common.DataRequestOptions) (*system.CombinedData, error) {
|
||||
maxRetries := 1
|
||||
for attempt := 0; attempt <= maxRetries; attempt++ {
|
||||
if sys.client == nil || sys.Status == down {
|
||||
if err := sys.createSSHClient(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
session, err := sys.createSessionWithTimeout(4 * time.Second)
|
||||
if err != nil {
|
||||
if attempt >= maxRetries {
|
||||
return nil, err
|
||||
}
|
||||
sys.manager.hub.Logger().Warn("Session closed. Retrying...", "host", sys.Host, "port", sys.Port, "err", err)
|
||||
sys.closeSSHConnection()
|
||||
// Reset format detection on connection failure - agent might have been upgraded
|
||||
continue
|
||||
}
|
||||
defer session.Close()
|
||||
|
||||
err := sys.runSSHOperation(4*time.Second, 1, func(session *ssh.Session) (bool, error) {
|
||||
stdout, err := session.StdoutPipe()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return false, err
|
||||
}
|
||||
stdin, stdinErr := session.StdinPipe()
|
||||
if err := session.Shell(); err != nil {
|
||||
return nil, err
|
||||
return false, err
|
||||
}
|
||||
|
||||
*sys.data = system.CombinedData{}
|
||||
@@ -280,45 +359,82 @@ func (sys *System) fetchDataViaSSH(options common.DataRequestOptions) (*system.C
|
||||
if sys.agentVersion.GTE(beszel.MinVersionAgentResponse) && stdinErr == nil {
|
||||
req := common.HubRequest[any]{Action: common.GetData, Data: options}
|
||||
_ = cbor.NewEncoder(stdin).Encode(req)
|
||||
// Close write side to signal end of request
|
||||
_ = stdin.Close()
|
||||
|
||||
var resp common.AgentResponse
|
||||
if decErr := cbor.NewDecoder(stdout).Decode(&resp); decErr == nil && resp.SystemData != nil {
|
||||
*sys.data = *resp.SystemData
|
||||
// wait for the session to complete
|
||||
if err := session.Wait(); err != nil {
|
||||
return nil, err
|
||||
return false, err
|
||||
}
|
||||
return sys.data, nil
|
||||
return false, nil
|
||||
}
|
||||
// If decoding failed, fall back below
|
||||
}
|
||||
|
||||
var decodeErr error
|
||||
if sys.agentVersion.GTE(beszel.MinVersionCbor) {
|
||||
err = cbor.NewDecoder(stdout).Decode(sys.data)
|
||||
decodeErr = cbor.NewDecoder(stdout).Decode(sys.data)
|
||||
} else {
|
||||
err = json.NewDecoder(stdout).Decode(sys.data)
|
||||
decodeErr = json.NewDecoder(stdout).Decode(sys.data)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
sys.closeSSHConnection()
|
||||
if attempt < maxRetries {
|
||||
continue
|
||||
}
|
||||
return nil, err
|
||||
if decodeErr != nil {
|
||||
return true, decodeErr
|
||||
}
|
||||
|
||||
// wait for the session to complete
|
||||
if err := session.Wait(); err != nil {
|
||||
return nil, err
|
||||
return false, err
|
||||
}
|
||||
|
||||
return sys.data, nil
|
||||
return false, nil
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// this should never be reached due to the return in the loop
|
||||
return nil, fmt.Errorf("failed to fetch data")
|
||||
return sys.data, nil
|
||||
}
|
||||
|
||||
// runSSHOperation establishes an SSH session and executes the provided operation.
|
||||
// The operation can request a retry by returning true as the first return value.
|
||||
func (sys *System) runSSHOperation(timeout time.Duration, retries int, operation func(*ssh.Session) (bool, error)) error {
|
||||
for attempt := 0; attempt <= retries; attempt++ {
|
||||
if sys.client == nil || sys.Status == down {
|
||||
if err := sys.createSSHClient(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
session, err := sys.createSessionWithTimeout(timeout)
|
||||
if err != nil {
|
||||
if attempt >= retries {
|
||||
return err
|
||||
}
|
||||
sys.manager.hub.Logger().Warn("Session closed. Retrying...", "host", sys.Host, "port", sys.Port, "err", err)
|
||||
sys.closeSSHConnection()
|
||||
continue
|
||||
}
|
||||
|
||||
retry, opErr := func() (bool, error) {
|
||||
defer session.Close()
|
||||
return operation(session)
|
||||
}()
|
||||
|
||||
if opErr == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
if retry {
|
||||
sys.closeSSHConnection()
|
||||
if attempt < retries {
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
return opErr
|
||||
}
|
||||
|
||||
return fmt.Errorf("ssh operation failed")
|
||||
}
|
||||
|
||||
// createSSHClient creates a new SSH client for the system
|
||||
|
||||
@@ -63,6 +63,15 @@ func NewSystemManager(hub hubLike) *SystemManager {
|
||||
}
|
||||
}
|
||||
|
||||
// GetSystem returns a system by ID from the store
|
||||
func (sm *SystemManager) GetSystem(systemID string) (*System, error) {
|
||||
sys, ok := sm.systems.GetOk(systemID)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("system not found")
|
||||
}
|
||||
return sys, nil
|
||||
}
|
||||
|
||||
// Initialize sets up the system manager by binding event hooks and starting existing systems.
|
||||
// It configures SSH client settings and begins monitoring all non-paused systems from the database.
|
||||
// Systems are started with staggered delays to prevent overwhelming the hub during startup.
|
||||
|
||||
@@ -154,19 +154,20 @@ func (sm *SystemManager) startRealtimeWorker() {
|
||||
// fetchRealtimeDataAndNotify fetches realtime data for all active subscriptions and notifies the clients.
|
||||
func (sm *SystemManager) fetchRealtimeDataAndNotify() {
|
||||
for systemId, info := range activeSubscriptions {
|
||||
system, ok := sm.systems.GetOk(systemId)
|
||||
if ok {
|
||||
go func() {
|
||||
data, err := system.fetchDataFromAgent(common.DataRequestOptions{CacheTimeMs: 1000})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
bytes, err := json.Marshal(data)
|
||||
if err == nil {
|
||||
notify(sm.hub, info.subscription, bytes)
|
||||
}
|
||||
}()
|
||||
system, err := sm.GetSystem(systemId)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
go func() {
|
||||
data, err := system.fetchDataFromAgent(common.DataRequestOptions{CacheTimeMs: 1000})
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
bytes, err := json.Marshal(data)
|
||||
if err == nil {
|
||||
notify(sm.hub, info.subscription, bytes)
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,11 +18,11 @@ type ResponseHandler interface {
|
||||
}
|
||||
|
||||
// BaseHandler provides a default implementation that can be embedded to make HandleLegacy optional
|
||||
// type BaseHandler struct{}
|
||||
type BaseHandler struct{}
|
||||
|
||||
// func (h *BaseHandler) HandleLegacy(rawData []byte) error {
|
||||
// return errors.New("legacy format not supported")
|
||||
// }
|
||||
func (h *BaseHandler) HandleLegacy(rawData []byte) error {
|
||||
return errors.New("legacy format not supported")
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
@@ -63,6 +63,58 @@ func (ws *WsConn) RequestSystemData(ctx context.Context, data *system.CombinedDa
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// stringResponseHandler is a generic handler for string responses from agents
|
||||
type stringResponseHandler struct {
|
||||
BaseHandler
|
||||
value string
|
||||
errorMsg string
|
||||
}
|
||||
|
||||
func (h *stringResponseHandler) Handle(agentResponse common.AgentResponse) error {
|
||||
if agentResponse.String == nil {
|
||||
return errors.New(h.errorMsg)
|
||||
}
|
||||
h.value = *agentResponse.String
|
||||
return nil
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// requestContainerStringViaWS is a generic function to request container-related strings via WebSocket
|
||||
func (ws *WsConn) requestContainerStringViaWS(ctx context.Context, action common.WebSocketAction, requestData any, errorMsg string) (string, error) {
|
||||
if !ws.IsConnected() {
|
||||
return "", gws.ErrConnClosed
|
||||
}
|
||||
|
||||
req, err := ws.requestManager.SendRequest(ctx, action, requestData)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
handler := &stringResponseHandler{errorMsg: errorMsg}
|
||||
if err := ws.handleAgentRequest(req, handler); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return handler.value, nil
|
||||
}
|
||||
|
||||
// RequestContainerLogs requests logs for a specific container via WebSocket.
|
||||
func (ws *WsConn) RequestContainerLogs(ctx context.Context, containerID string) (string, error) {
|
||||
return ws.requestContainerStringViaWS(ctx, common.GetContainerLogs, common.ContainerLogsRequest{ContainerID: containerID}, "no logs in response")
|
||||
}
|
||||
|
||||
// RequestContainerInfo requests information about a specific container via WebSocket.
|
||||
func (ws *WsConn) RequestContainerInfo(ctx context.Context, containerID string) (string, error) {
|
||||
return ws.requestContainerStringViaWS(ctx, common.GetContainerInfo, common.ContainerInfoRequest{ContainerID: containerID}, "no info in response")
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// fingerprintHandler implements ResponseHandler for fingerprint requests
|
||||
type fingerprintHandler struct {
|
||||
result *common.FingerprintResponse
|
||||
|
||||
@@ -181,6 +181,17 @@ func TestCommonActions(t *testing.T) {
|
||||
// Test that the actions we use exist and have expected values
|
||||
assert.Equal(t, common.WebSocketAction(0), common.GetData, "GetData should be action 0")
|
||||
assert.Equal(t, common.WebSocketAction(1), common.CheckFingerprint, "CheckFingerprint should be action 1")
|
||||
assert.Equal(t, common.WebSocketAction(2), common.GetContainerLogs, "GetLogs should be action 2")
|
||||
}
|
||||
|
||||
func TestLogsHandler(t *testing.T) {
|
||||
h := &stringResponseHandler{errorMsg: "no logs in response"}
|
||||
|
||||
logValue := "test logs"
|
||||
resp := common.AgentResponse{String: &logValue}
|
||||
err := h.Handle(resp)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, logValue, h.value)
|
||||
}
|
||||
|
||||
// TestHandler tests that we can create a Handler
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
package migrations
|
||||
|
||||
import (
|
||||
"github.com/google/uuid"
|
||||
"github.com/pocketbase/pocketbase/core"
|
||||
m "github.com/pocketbase/pocketbase/migrations"
|
||||
)
|
||||
@@ -860,6 +859,152 @@ func init() {
|
||||
"system": false,
|
||||
"authRule": "verified=true",
|
||||
"manageRule": null
|
||||
},
|
||||
{
|
||||
"id": "pbc_1864144027",
|
||||
"listRule": "@request.auth.id != \"\" && system.users.id ?= @request.auth.id",
|
||||
"viewRule": null,
|
||||
"createRule": null,
|
||||
"updateRule": null,
|
||||
"deleteRule": null,
|
||||
"name": "containers",
|
||||
"type": "base",
|
||||
"fields": [
|
||||
{
|
||||
"autogeneratePattern": "[a-f0-9]{6}",
|
||||
"hidden": false,
|
||||
"id": "text3208210256",
|
||||
"max": 12,
|
||||
"min": 6,
|
||||
"name": "id",
|
||||
"pattern": "^[a-f0-9]+$",
|
||||
"presentable": false,
|
||||
"primaryKey": true,
|
||||
"required": true,
|
||||
"system": true,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"cascadeDelete": false,
|
||||
"collectionId": "2hz5ncl8tizk5nx",
|
||||
"hidden": false,
|
||||
"id": "relation3377271179",
|
||||
"maxSelect": 1,
|
||||
"minSelect": 0,
|
||||
"name": "system",
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "relation"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text1579384326",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "name",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text2063623452",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "status",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "number3470402323",
|
||||
"max": null,
|
||||
"min": null,
|
||||
"name": "health",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "number3128971310",
|
||||
"max": 100,
|
||||
"min": 0,
|
||||
"name": "cpu",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "number3933025333",
|
||||
"max": null,
|
||||
"min": 0,
|
||||
"name": "memory",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "number4075427327",
|
||||
"max": null,
|
||||
"min": null,
|
||||
"name": "net",
|
||||
"onlyInt": false,
|
||||
"presentable": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"hidden": false,
|
||||
"id": "number3332085495",
|
||||
"max": null,
|
||||
"min": null,
|
||||
"name": "updated",
|
||||
"onlyInt": true,
|
||||
"presentable": false,
|
||||
"required": true,
|
||||
"system": false,
|
||||
"type": "number"
|
||||
},
|
||||
{
|
||||
"autogeneratePattern": "",
|
||||
"hidden": false,
|
||||
"id": "text3309110367",
|
||||
"max": 0,
|
||||
"min": 0,
|
||||
"name": "image",
|
||||
"pattern": "",
|
||||
"presentable": false,
|
||||
"primaryKey": false,
|
||||
"required": false,
|
||||
"system": false,
|
||||
"type": "text"
|
||||
}
|
||||
],
|
||||
"indexes": [
|
||||
"CREATE INDEX ` + "`" + `idx_JxWirjdhyO` + "`" + ` ON ` + "`" + `containers` + "`" + ` (` + "`" + `updated` + "`" + `)",
|
||||
"CREATE INDEX ` + "`" + `idx_r3Ja0rs102` + "`" + ` ON ` + "`" + `containers` + "`" + ` (` + "`" + `system` + "`" + `)"
|
||||
],
|
||||
"system": false
|
||||
}
|
||||
]`
|
||||
|
||||
@@ -868,31 +1013,6 @@ func init() {
|
||||
return err
|
||||
}
|
||||
|
||||
// Get all systems that don't have fingerprint records
|
||||
var systemIds []string
|
||||
err = app.DB().NewQuery(`
|
||||
SELECT s.id FROM systems s
|
||||
LEFT JOIN fingerprints f ON s.id = f.system
|
||||
WHERE f.system IS NULL
|
||||
`).Column(&systemIds)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
// Create fingerprint records with unique UUID tokens for each system
|
||||
for _, systemId := range systemIds {
|
||||
token := uuid.New().String()
|
||||
_, err = app.DB().NewQuery(`
|
||||
INSERT INTO fingerprints (system, token)
|
||||
VALUES ({:system}, {:token})
|
||||
`).Bind(map[string]any{
|
||||
"system": systemId,
|
||||
"token": token,
|
||||
}).Execute()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}, func(app core.App) error {
|
||||
return nil
|
||||
@@ -437,6 +437,10 @@ func (rm *RecordManager) DeleteOldRecords() {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = deleteOldContainerRecords(txApp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
err = deleteOldAlertsHistory(txApp, 200, 250)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -506,6 +510,20 @@ func deleteOldSystemStats(app core.App) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deletes container records that haven't been updated in the last 10 minutes
|
||||
func deleteOldContainerRecords(app core.App) error {
|
||||
now := time.Now().UTC()
|
||||
tenMinutesAgo := now.Add(-10 * time.Minute)
|
||||
|
||||
// Delete container records where updated < tenMinutesAgo
|
||||
_, err := app.DB().NewQuery("DELETE FROM containers WHERE updated < {:updated}").Bind(dbx.Params{"updated": tenMinutesAgo.UnixMilli()}).Execute()
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete old container records: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
/* Round float to two decimals */
|
||||
func twoDecimals(value float64) float64 {
|
||||
return math.Round(value*100) / 100
|
||||
|
||||
Binary file not shown.
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<link rel="manifest" href="./static/manifest.json" />
|
||||
<link rel="icon" type="image/svg+xml" href="./static/favicon.svg" />
|
||||
<link rel="icon" type="image/svg+xml" href="./static/icon.svg" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1.0, user-scalable=no, viewport-fit=cover" />
|
||||
<meta name="robots" content="noindex, nofollow" />
|
||||
<title>Beszel</title>
|
||||
|
||||
761
internal/site/package-lock.json
generated
761
internal/site/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "beszel",
|
||||
"private": true,
|
||||
"version": "0.13.1",
|
||||
"version": "0.14.1",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
"dev": "vite --host",
|
||||
@@ -49,11 +49,12 @@
|
||||
"react": "^19.1.1",
|
||||
"react-dom": "^19.1.1",
|
||||
"recharts": "^2.15.4",
|
||||
"shiki": "^3.13.0",
|
||||
"tailwind-merge": "^3.3.1",
|
||||
"valibot": "^0.42.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@biomejs/biome": "2.2.3",
|
||||
"@biomejs/biome": "2.2.4",
|
||||
"@lingui/cli": "^5.4.1",
|
||||
"@lingui/swc-plugin": "^5.6.1",
|
||||
"@lingui/vite-plugin": "^5.4.1",
|
||||
@@ -76,4 +77,4 @@
|
||||
"optionalDependencies": {
|
||||
"@esbuild/linux-arm64": "^0.21.5"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70" fill="#22c55e"><path d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 906 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70" fill="#dc2626"><path d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 906 B |
@@ -1 +0,0 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70" fill="#888"><path d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/></svg>
|
||||
|
Before Width: | Height: | Size: 903 B |
9
internal/site/public/static/icon.svg
Normal file
9
internal/site/public/static/icon.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70">
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="20%" x2="100%" y2="120%">
|
||||
<stop offset="0%" style="stop-color:#747bff"/>
|
||||
<stop offset="100%" style="stop-color:#24eb5c"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path fill="url(#gradient)" d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
85
internal/site/src/components/active-alerts.tsx
Normal file
85
internal/site/src/components/active-alerts.tsx
Normal file
@@ -0,0 +1,85 @@
|
||||
import { alertInfo } from "@/lib/alerts"
|
||||
import { $alerts, $allSystemsById } from "@/lib/stores"
|
||||
import type { AlertRecord } from "@/types"
|
||||
import { Plural, Trans } from "@lingui/react/macro"
|
||||
import { useStore } from "@nanostores/react"
|
||||
import { getPagePath } from "@nanostores/router"
|
||||
import { useMemo } from "react"
|
||||
import { $router, Link } from "./router"
|
||||
import { Alert, AlertTitle, AlertDescription } from "./ui/alert"
|
||||
import { Card, CardHeader, CardTitle, CardContent } from "./ui/card"
|
||||
|
||||
export const ActiveAlerts = () => {
|
||||
const alerts = useStore($alerts)
|
||||
const systems = useStore($allSystemsById)
|
||||
|
||||
const { activeAlerts, alertsKey } = useMemo(() => {
|
||||
const activeAlerts: AlertRecord[] = []
|
||||
// key to prevent re-rendering if alerts change but active alerts didn't
|
||||
const alertsKey: string[] = []
|
||||
|
||||
for (const systemId of Object.keys(alerts)) {
|
||||
for (const alert of alerts[systemId].values()) {
|
||||
if (alert.triggered && alert.name in alertInfo) {
|
||||
activeAlerts.push(alert)
|
||||
alertsKey.push(`${alert.system}${alert.value}${alert.min}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { activeAlerts, alertsKey }
|
||||
}, [alerts])
|
||||
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: alertsKey is inclusive
|
||||
return useMemo(() => {
|
||||
if (activeAlerts.length === 0) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<Card>
|
||||
<CardHeader className="pb-4 px-2 sm:px-6 max-sm:pt-5 max-sm:pb-1">
|
||||
<div className="px-2 sm:px-1">
|
||||
<CardTitle>
|
||||
<Trans>Active Alerts</Trans>
|
||||
</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="max-sm:p-2">
|
||||
{activeAlerts.length > 0 && (
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-3">
|
||||
{activeAlerts.map((alert) => {
|
||||
const info = alertInfo[alert.name as keyof typeof alertInfo]
|
||||
return (
|
||||
<Alert
|
||||
key={alert.id}
|
||||
className="hover:-translate-y-px duration-200 bg-transparent border-foreground/10 hover:shadow-md shadow-black/5"
|
||||
>
|
||||
<info.icon className="h-4 w-4" />
|
||||
<AlertTitle>
|
||||
{systems[alert.system]?.name} {info.name().toLowerCase().replace("cpu", "CPU")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{alert.name === "Status" ? (
|
||||
<Trans>Connection is down</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
Exceeds {alert.value}
|
||||
{info.unit} in last <Plural value={alert.min} one="# minute" other="# minutes" />
|
||||
</Trans>
|
||||
)}
|
||||
</AlertDescription>
|
||||
<Link
|
||||
href={getPagePath($router, "system", { id: systems[alert.system]?.id })}
|
||||
className="absolute inset-0 w-full h-full"
|
||||
aria-label="View system"
|
||||
></Link>
|
||||
</Alert>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}, [alertsKey.join("")])
|
||||
}
|
||||
@@ -94,8 +94,11 @@ export default memo(function ContainerChart({
|
||||
if (!filter) {
|
||||
return new Set<string>()
|
||||
}
|
||||
const filterLower = filter.toLowerCase()
|
||||
return new Set(Object.keys(chartConfig).filter((key) => !key.toLowerCase().includes(filterLower)))
|
||||
const filterTerms = filter.toLowerCase().split(" ").filter(term => term.length > 0)
|
||||
return new Set(Object.keys(chartConfig).filter((key) => {
|
||||
const keyLower = key.toLowerCase()
|
||||
return !filterTerms.some(term => keyLower.includes(term))
|
||||
}))
|
||||
}, [chartConfig, filter])
|
||||
|
||||
// console.log('rendered at', new Date())
|
||||
|
||||
@@ -4,7 +4,7 @@ import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
|
||||
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
|
||||
import { Unit } from "@/lib/enums"
|
||||
import { chartMargin, cn, decimalString, formatBytes, formatShortDate, toFixedFloat } from "@/lib/utils"
|
||||
import type { ChartData } from "@/types"
|
||||
import type { ChartData, SystemStatsRecord } from "@/types"
|
||||
import { useYAxisWidth } from "./hooks"
|
||||
|
||||
export default memo(function DiskChart({
|
||||
@@ -12,7 +12,7 @@ export default memo(function DiskChart({
|
||||
diskSize,
|
||||
chartData,
|
||||
}: {
|
||||
dataKey: string
|
||||
dataKey: string | ((data: SystemStatsRecord) => number | undefined)
|
||||
diskSize: number
|
||||
chartData: ChartData
|
||||
}) {
|
||||
|
||||
@@ -91,7 +91,8 @@ export default memo(function TemperatureChart({ chartData }: { chartData: ChartD
|
||||
}
|
||||
/>
|
||||
{colors.map((key) => {
|
||||
const filtered = filter && !key.toLowerCase().includes(filter.toLowerCase())
|
||||
const filterTerms = filter ? filter.toLowerCase().split(" ").filter(term => term.length > 0) : []
|
||||
const filtered = filterTerms.length > 0 && !filterTerms.some(term => key.toLowerCase().includes(term))
|
||||
const strokeOpacity = filtered ? 0.1 : 1
|
||||
return (
|
||||
<Line
|
||||
|
||||
@@ -5,6 +5,7 @@ import { DialogDescription } from "@radix-ui/react-dialog"
|
||||
import {
|
||||
AlertOctagonIcon,
|
||||
BookIcon,
|
||||
ContainerIcon,
|
||||
DatabaseBackupIcon,
|
||||
FingerprintIcon,
|
||||
LayoutDashboard,
|
||||
@@ -80,7 +81,7 @@ export default memo(function CommandPalette({ open, setOpen }: { open: boolean;
|
||||
)}
|
||||
<CommandGroup heading={t`Pages / Settings`}>
|
||||
<CommandItem
|
||||
keywords={["home"]}
|
||||
keywords={["home", t`All Systems`]}
|
||||
onSelect={() => {
|
||||
navigate(basePath)
|
||||
setOpen(false)
|
||||
@@ -94,6 +95,20 @@ export default memo(function CommandPalette({ open, setOpen }: { open: boolean;
|
||||
<Trans>Page</Trans>
|
||||
</CommandShortcut>
|
||||
</CommandItem>
|
||||
<CommandItem
|
||||
onSelect={() => {
|
||||
navigate(getPagePath($router, "containers"))
|
||||
setOpen(false)
|
||||
}}
|
||||
>
|
||||
<ContainerIcon className="me-2 size-4" />
|
||||
<span>
|
||||
<Trans>All Containers</Trans>
|
||||
</span>
|
||||
<CommandShortcut>
|
||||
<Trans>Page</Trans>
|
||||
</CommandShortcut>
|
||||
</CommandItem>
|
||||
<CommandItem
|
||||
onSelect={() => {
|
||||
navigate(getPagePath($router, "settings", { name: "general" }))
|
||||
|
||||
@@ -0,0 +1,176 @@
|
||||
import type { Column, ColumnDef } from "@tanstack/react-table"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { cn, decimalString, formatBytes, hourWithSeconds } from "@/lib/utils"
|
||||
import type { ContainerRecord } from "@/types"
|
||||
import { ContainerHealth, ContainerHealthLabels } from "@/lib/enums"
|
||||
import {
|
||||
ArrowUpDownIcon,
|
||||
ClockIcon,
|
||||
ContainerIcon,
|
||||
CpuIcon,
|
||||
LayersIcon,
|
||||
MemoryStickIcon,
|
||||
ServerIcon,
|
||||
ShieldCheckIcon,
|
||||
} from "lucide-react"
|
||||
import { EthernetIcon, HourglassIcon } from "../ui/icons"
|
||||
import { Badge } from "../ui/badge"
|
||||
import { t } from "@lingui/core/macro"
|
||||
import { $allSystemsById } from "@/lib/stores"
|
||||
import { useStore } from "@nanostores/react"
|
||||
|
||||
// Unit names and their corresponding number of seconds for converting docker status strings
|
||||
const unitSeconds = [["s", 1], ["mi", 60], ["h", 3600], ["d", 86400], ["w", 604800], ["mo", 2592000]] as const
|
||||
// Convert docker status string to number of seconds ("Up X minutes", "Up X hours", etc.)
|
||||
function getStatusValue(status: string): number {
|
||||
const [_, num, unit] = status.split(" ")
|
||||
const numValue = Number(num)
|
||||
for (const [unitName, value] of unitSeconds) {
|
||||
if (unit.startsWith(unitName)) {
|
||||
return numValue * value
|
||||
}
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
export const containerChartCols: ColumnDef<ContainerRecord>[] = [
|
||||
{
|
||||
id: "name",
|
||||
sortingFn: (a, b) => a.original.name.localeCompare(b.original.name),
|
||||
accessorFn: (record) => record.name,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Name`} Icon={ContainerIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
return <span className="ms-1.5 xl:w-45 block truncate">{getValue() as string}</span>
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "system",
|
||||
accessorFn: (record) => record.system,
|
||||
sortingFn: (a, b) => {
|
||||
const allSystems = $allSystemsById.get()
|
||||
const systemNameA = allSystems[a.original.system]?.name ?? ""
|
||||
const systemNameB = allSystems[b.original.system]?.name ?? ""
|
||||
return systemNameA.localeCompare(systemNameB)
|
||||
},
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`System`} Icon={ServerIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
const allSystems = useStore($allSystemsById)
|
||||
return <span className="ms-1.5 xl:w-32 block truncate">{allSystems[getValue() as string]?.name ?? ""}</span>
|
||||
},
|
||||
},
|
||||
// {
|
||||
// id: "id",
|
||||
// accessorFn: (record) => record.id,
|
||||
// sortingFn: (a, b) => a.original.id.localeCompare(b.original.id),
|
||||
// header: ({ column }) => <HeaderButton column={column} name="ID" Icon={HashIcon} />,
|
||||
// cell: ({ getValue }) => {
|
||||
// return <span className="ms-1.5 me-3 font-mono">{getValue() as string}</span>
|
||||
// },
|
||||
// },
|
||||
{
|
||||
id: "cpu",
|
||||
accessorFn: (record) => record.cpu,
|
||||
invertSorting: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`CPU`} Icon={CpuIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
const val = getValue() as number
|
||||
return <span className="ms-1.5 tabular-nums">{`${decimalString(val, val >= 10 ? 1 : 2)}%`}</span>
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "memory",
|
||||
accessorFn: (record) => record.memory,
|
||||
invertSorting: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Memory`} Icon={MemoryStickIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
const val = getValue() as number
|
||||
const formatted = formatBytes(val, false, undefined, true)
|
||||
return (
|
||||
<span className="ms-1.5 tabular-nums">{`${decimalString(formatted.value, formatted.value >= 10 ? 1 : 2)} ${formatted.unit}`}</span>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "net",
|
||||
accessorFn: (record) => record.net,
|
||||
invertSorting: true,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Net`} Icon={EthernetIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
const val = getValue() as number
|
||||
const formatted = formatBytes(val, true, undefined, true)
|
||||
return (
|
||||
<span className="ms-1.5 tabular-nums">{`${decimalString(formatted.value, formatted.value >= 10 ? 1 : 2)} ${formatted.unit}`}</span>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "health",
|
||||
invertSorting: true,
|
||||
accessorFn: (record) => record.health,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Health`} Icon={ShieldCheckIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
const healthValue = getValue() as number
|
||||
const healthStatus = ContainerHealthLabels[healthValue] || "Unknown"
|
||||
return (
|
||||
<Badge variant="outline" className="dark:border-white/12">
|
||||
<span className={cn("size-2 me-1.5 rounded-full", {
|
||||
"bg-green-500": healthValue === ContainerHealth.Healthy,
|
||||
"bg-red-500": healthValue === ContainerHealth.Unhealthy,
|
||||
"bg-yellow-500": healthValue === ContainerHealth.Starting,
|
||||
"bg-zinc-500": healthValue === ContainerHealth.None,
|
||||
})}>
|
||||
</span>
|
||||
{healthStatus}
|
||||
</Badge>
|
||||
)
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "image",
|
||||
sortingFn: (a, b) => a.original.image.localeCompare(b.original.image),
|
||||
accessorFn: (record) => record.image,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t({ message: "Image", context: "Docker image" })} Icon={LayersIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
return <span className="ms-1.5 xl:w-36 block truncate">{getValue() as string}</span>
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "status",
|
||||
accessorFn: (record) => record.status,
|
||||
invertSorting: true,
|
||||
sortingFn: (a, b) => getStatusValue(a.original.status) - getStatusValue(b.original.status),
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Status`} Icon={HourglassIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
return <span className="ms-1.5 w-25 block truncate">{getValue() as string}</span>
|
||||
},
|
||||
},
|
||||
{
|
||||
id: "updated",
|
||||
invertSorting: true,
|
||||
accessorFn: (record) => record.updated,
|
||||
header: ({ column }) => <HeaderButton column={column} name={t`Updated`} Icon={ClockIcon} />,
|
||||
cell: ({ getValue }) => {
|
||||
const timestamp = getValue() as number
|
||||
return (
|
||||
<span className="ms-1.5 tabular-nums">
|
||||
{hourWithSeconds(new Date(timestamp).toISOString())}
|
||||
</span>
|
||||
)
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
function HeaderButton({ column, name, Icon }: { column: Column<ContainerRecord>; name: string; Icon: React.ElementType }) {
|
||||
const isSorted = column.getIsSorted()
|
||||
return (
|
||||
<Button
|
||||
className={cn("h-9 px-3 flex items-center gap-2 duration-50", isSorted && "bg-accent/70 light:bg-accent text-accent-foreground/90")}
|
||||
variant="ghost"
|
||||
onClick={() => column.toggleSorting(column.getIsSorted() === "asc")}
|
||||
>
|
||||
{Icon && <Icon className="size-4" />}
|
||||
{name}
|
||||
<ArrowUpDownIcon className="size-4" />
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
@@ -0,0 +1,495 @@
|
||||
import { t } from "@lingui/core/macro"
|
||||
import { Trans } from "@lingui/react/macro"
|
||||
import {
|
||||
type ColumnFiltersState,
|
||||
flexRender,
|
||||
getCoreRowModel,
|
||||
getFilteredRowModel,
|
||||
getSortedRowModel,
|
||||
type Row,
|
||||
type SortingState,
|
||||
type Table as TableType,
|
||||
useReactTable,
|
||||
type VisibilityState,
|
||||
} from "@tanstack/react-table"
|
||||
import { useVirtualizer, type VirtualItem } from "@tanstack/react-virtual"
|
||||
import { memo, RefObject, useEffect, useRef, useState } from "react"
|
||||
import { Input } from "@/components/ui/input"
|
||||
import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
|
||||
import { pb } from "@/lib/api"
|
||||
import type { ContainerRecord } from "@/types"
|
||||
import { containerChartCols } from "@/components/containers-table/containers-table-columns"
|
||||
import { Card, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { type ContainerHealth, ContainerHealthLabels } from "@/lib/enums"
|
||||
import { cn, useBrowserStorage } from "@/lib/utils"
|
||||
import { Sheet, SheetTitle, SheetHeader, SheetContent, SheetDescription } from "../ui/sheet"
|
||||
import { Dialog, DialogContent, DialogTitle } from "../ui/dialog"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { $allSystemsById } from "@/lib/stores"
|
||||
import { MaximizeIcon, RefreshCwIcon } from "lucide-react"
|
||||
import { Separator } from "../ui/separator"
|
||||
import { $router, Link } from "../router"
|
||||
import { listenKeys } from "nanostores"
|
||||
import { getPagePath } from "@nanostores/router"
|
||||
|
||||
const syntaxTheme = "github-dark-dimmed"
|
||||
|
||||
export default function ContainersTable({ systemId }: { systemId?: string }) {
|
||||
const [data, setData] = useState<ContainerRecord[]>([])
|
||||
const [sorting, setSorting] = useBrowserStorage<SortingState>(
|
||||
`sort-c-${systemId ? 1 : 0}`,
|
||||
[{ id: systemId ? "name" : "system", desc: false }],
|
||||
sessionStorage
|
||||
)
|
||||
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
|
||||
const [columnVisibility, setColumnVisibility] = useState<VisibilityState>({})
|
||||
const [rowSelection, setRowSelection] = useState({})
|
||||
const [globalFilter, setGlobalFilter] = useState("")
|
||||
|
||||
useEffect(() => {
|
||||
const pbOptions = {
|
||||
fields: "id,name,image,cpu,memory,net,health,status,system,updated",
|
||||
}
|
||||
|
||||
const fetchData = (lastXMs: number) => {
|
||||
const updated = Date.now() - lastXMs
|
||||
let filter: string
|
||||
if (systemId) {
|
||||
filter = pb.filter("system={:system} && updated > {:updated}", { system: systemId, updated })
|
||||
} else {
|
||||
filter = pb.filter("updated > {:updated}", { updated })
|
||||
}
|
||||
pb.collection<ContainerRecord>("containers")
|
||||
.getList(0, 2000, {
|
||||
...pbOptions,
|
||||
filter,
|
||||
})
|
||||
.then(({ items }) => setData((curItems) => {
|
||||
const containerIds = new Set(items.map(item => item.id))
|
||||
const now = Date.now()
|
||||
for (const item of curItems) {
|
||||
if (!containerIds.has(item.id) && now - item.updated < 70_000) {
|
||||
items.push(item)
|
||||
}
|
||||
}
|
||||
return items
|
||||
}))
|
||||
}
|
||||
|
||||
// initial load
|
||||
fetchData(70_000)
|
||||
|
||||
// if no systemId, poll every 10 seconds
|
||||
if (!systemId) {
|
||||
// poll every 10 seconds
|
||||
const intervalId = setInterval(() => fetchData(10_500), 10_000)
|
||||
// clear interval on unmount
|
||||
return () => clearInterval(intervalId)
|
||||
}
|
||||
|
||||
// if systemId, fetch containers after the system is updated
|
||||
return listenKeys($allSystemsById, [systemId], (_newSystems) => {
|
||||
setTimeout(() => fetchData(1000), 100)
|
||||
})
|
||||
}, [])
|
||||
|
||||
const table = useReactTable({
|
||||
data,
|
||||
columns: containerChartCols.filter(col => systemId ? col.id !== "system" : true),
|
||||
getCoreRowModel: getCoreRowModel(),
|
||||
getSortedRowModel: getSortedRowModel(),
|
||||
getFilteredRowModel: getFilteredRowModel(),
|
||||
onSortingChange: setSorting,
|
||||
onColumnFiltersChange: setColumnFilters,
|
||||
onColumnVisibilityChange: setColumnVisibility,
|
||||
onRowSelectionChange: setRowSelection,
|
||||
defaultColumn: {
|
||||
sortUndefined: "last",
|
||||
size: 100,
|
||||
minSize: 0,
|
||||
},
|
||||
state: {
|
||||
sorting,
|
||||
columnFilters,
|
||||
columnVisibility,
|
||||
rowSelection,
|
||||
globalFilter,
|
||||
},
|
||||
onGlobalFilterChange: setGlobalFilter,
|
||||
globalFilterFn: (row, _columnId, filterValue) => {
|
||||
const container = row.original
|
||||
const systemName = $allSystemsById.get()[container.system]?.name ?? ""
|
||||
const id = container.id ?? ""
|
||||
const name = container.name ?? ""
|
||||
const status = container.status ?? ""
|
||||
const healthLabel = ContainerHealthLabels[container.health as ContainerHealth] ?? ""
|
||||
const image = container.image ?? ""
|
||||
const searchString = `${systemName} ${id} ${name} ${healthLabel} ${status} ${image}`.toLowerCase()
|
||||
|
||||
return (filterValue as string)
|
||||
.toLowerCase()
|
||||
.split(" ")
|
||||
.every((term) => searchString.includes(term))
|
||||
},
|
||||
})
|
||||
|
||||
const rows = table.getRowModel().rows
|
||||
const visibleColumns = table.getVisibleLeafColumns()
|
||||
|
||||
return (
|
||||
<Card className="p-6 @container w-full">
|
||||
<CardHeader className="p-0 mb-4">
|
||||
<div className="grid md:flex gap-5 w-full items-end">
|
||||
<div className="px-2 sm:px-1">
|
||||
<CardTitle className="mb-2">
|
||||
<Trans>All Containers</Trans>
|
||||
</CardTitle>
|
||||
<CardDescription className="flex">
|
||||
<Trans>Click on a container to view more information.</Trans>
|
||||
</CardDescription>
|
||||
</div>
|
||||
<Input
|
||||
placeholder={t`Filter...`}
|
||||
value={globalFilter}
|
||||
onChange={(e) => setGlobalFilter(e.target.value)}
|
||||
className="ms-auto px-4 w-full max-w-full md:w-64"
|
||||
/>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<div className="rounded-md">
|
||||
<AllContainersTable table={table} rows={rows} colLength={visibleColumns.length} />
|
||||
</div>
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
const AllContainersTable = memo(
|
||||
function AllContainersTable({ table, rows, colLength }: { table: TableType<ContainerRecord>; rows: Row<ContainerRecord>[]; colLength: number }) {
|
||||
// The virtualizer will need a reference to the scrollable container element
|
||||
const scrollRef = useRef<HTMLDivElement>(null)
|
||||
const activeContainer = useRef<ContainerRecord | null>(null)
|
||||
const [sheetOpen, setSheetOpen] = useState(false)
|
||||
const openSheet = (container: ContainerRecord) => {
|
||||
activeContainer.current = container
|
||||
setSheetOpen(true)
|
||||
}
|
||||
|
||||
const virtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({
|
||||
count: rows.length,
|
||||
estimateSize: () => 54,
|
||||
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))
|
||||
|
||||
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() + 48}px`, paddingTop, paddingBottom }}>
|
||||
<table className="text-sm w-full h-full text-nowrap">
|
||||
<ContainersTableHead table={table} />
|
||||
<TableBody>
|
||||
{rows.length ? (
|
||||
virtualRows.map((virtualRow) => {
|
||||
const row = rows[virtualRow.index]
|
||||
return (
|
||||
<ContainerTableRow
|
||||
key={row.id}
|
||||
row={row}
|
||||
virtualRow={virtualRow}
|
||||
openSheet={openSheet}
|
||||
/>
|
||||
)
|
||||
})
|
||||
) : (
|
||||
<TableRow>
|
||||
<TableCell colSpan={colLength} className="h-37 text-center pointer-events-none">
|
||||
<Trans>No results.</Trans>
|
||||
</TableCell>
|
||||
</TableRow>
|
||||
)}
|
||||
</TableBody>
|
||||
</table>
|
||||
</div>
|
||||
<ContainerSheet sheetOpen={sheetOpen} setSheetOpen={setSheetOpen} activeContainer={activeContainer} />
|
||||
</div>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
async function getLogsHtml(container: ContainerRecord): Promise<string> {
|
||||
try {
|
||||
const [{ highlighter }, logsHtml] = await Promise.all([import('@/lib/shiki'), pb.send<{ logs: string }>("/api/beszel/containers/logs", {
|
||||
system: container.system,
|
||||
container: container.id,
|
||||
})])
|
||||
return highlighter.codeToHtml(logsHtml.logs, { lang: "log", theme: syntaxTheme })
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
async function getInfoHtml(container: ContainerRecord): Promise<string> {
|
||||
try {
|
||||
let [{ highlighter }, { info }] = await Promise.all([import('@/lib/shiki'), pb.send<{ info: string }>("/api/beszel/containers/info", {
|
||||
system: container.system,
|
||||
container: container.id,
|
||||
})])
|
||||
try {
|
||||
info = JSON.stringify(JSON.parse(info), null, 2)
|
||||
} catch (_) { }
|
||||
return highlighter.codeToHtml(info, { lang: "json", theme: syntaxTheme })
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
function ContainerSheet({ sheetOpen, setSheetOpen, activeContainer }: { sheetOpen: boolean, setSheetOpen: (open: boolean) => void, activeContainer: RefObject<ContainerRecord | null> }) {
|
||||
const container = activeContainer.current
|
||||
if (!container) return null
|
||||
|
||||
const [logsDisplay, setLogsDisplay] = useState<string>("")
|
||||
const [infoDisplay, setInfoDisplay] = useState<string>("")
|
||||
const [logsFullscreenOpen, setLogsFullscreenOpen] = useState<boolean>(false)
|
||||
const [infoFullscreenOpen, setInfoFullscreenOpen] = useState<boolean>(false)
|
||||
const [isRefreshingLogs, setIsRefreshingLogs] = useState<boolean>(false)
|
||||
const logsContainerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
function scrollLogsToBottom() {
|
||||
if (logsContainerRef.current) {
|
||||
logsContainerRef.current.scrollTo({ top: logsContainerRef.current.scrollHeight })
|
||||
}
|
||||
}
|
||||
|
||||
const refreshLogs = async () => {
|
||||
setIsRefreshingLogs(true)
|
||||
const startTime = Date.now()
|
||||
|
||||
try {
|
||||
const logsHtml = await getLogsHtml(container)
|
||||
setLogsDisplay(logsHtml)
|
||||
setTimeout(scrollLogsToBottom, 20)
|
||||
} catch (error) {
|
||||
console.error(error)
|
||||
} finally {
|
||||
// Ensure minimum spin duration of 800ms
|
||||
const elapsed = Date.now() - startTime
|
||||
const remaining = Math.max(0, 500 - elapsed)
|
||||
setTimeout(() => {
|
||||
setIsRefreshingLogs(false)
|
||||
}, remaining)
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() => {
|
||||
setLogsDisplay("")
|
||||
setInfoDisplay("");
|
||||
if (!container) return
|
||||
(async () => {
|
||||
const [logsHtml, infoHtml] = await Promise.all([getLogsHtml(container), getInfoHtml(container)])
|
||||
setLogsDisplay(logsHtml)
|
||||
setInfoDisplay(infoHtml)
|
||||
setTimeout(scrollLogsToBottom, 20)
|
||||
})()
|
||||
}, [container])
|
||||
|
||||
return (
|
||||
<>
|
||||
<LogsFullscreenDialog
|
||||
open={logsFullscreenOpen}
|
||||
onOpenChange={setLogsFullscreenOpen}
|
||||
logsDisplay={logsDisplay}
|
||||
containerName={container.name}
|
||||
onRefresh={refreshLogs}
|
||||
isRefreshing={isRefreshingLogs}
|
||||
/>
|
||||
<InfoFullscreenDialog
|
||||
open={infoFullscreenOpen}
|
||||
onOpenChange={setInfoFullscreenOpen}
|
||||
infoDisplay={infoDisplay}
|
||||
containerName={container.name}
|
||||
/>
|
||||
<Sheet open={sheetOpen} onOpenChange={setSheetOpen}>
|
||||
<SheetContent className="w-full sm:max-w-220 p-2">
|
||||
<SheetHeader>
|
||||
<SheetTitle>{container.name}</SheetTitle>
|
||||
<SheetDescription className="flex flex-wrap items-center gap-x-2 gap-y-1">
|
||||
<Link className="hover:underline" href={getPagePath($router, "system", { id: container.system })}>{$allSystemsById.get()[container.system]?.name ?? ""}</Link>
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
{container.status}
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
{container.image}
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
{container.id}
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
{ContainerHealthLabels[container.health as ContainerHealth]}
|
||||
</SheetDescription>
|
||||
</SheetHeader>
|
||||
<div className="px-3 pb-3 -mt-4 flex flex-col gap-3 h-full items-start">
|
||||
<div className="flex items-center w-full">
|
||||
<h3>{t`Logs`}</h3>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={refreshLogs}
|
||||
className="h-8 w-8 p-0 ms-auto"
|
||||
disabled={isRefreshingLogs}
|
||||
>
|
||||
<RefreshCwIcon
|
||||
className={`size-4 transition-transform duration-300 ${isRefreshingLogs ? 'animate-spin' : ''}`}
|
||||
/>
|
||||
</Button>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setLogsFullscreenOpen(true)}
|
||||
className="h-8 w-8 p-0"
|
||||
>
|
||||
<MaximizeIcon className="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<div ref={logsContainerRef} className={cn("max-h-[calc(50dvh-10rem)] w-full overflow-auto p-3 rounded-md bg-gh-dark text-sm", !logsDisplay && ["animate-pulse", "h-full"])}>
|
||||
<div dangerouslySetInnerHTML={{ __html: logsDisplay }} />
|
||||
</div>
|
||||
<div className="flex items-center w-full">
|
||||
<h3>{t`Detail`}</h3>
|
||||
<Button
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setInfoFullscreenOpen(true)}
|
||||
className="h-8 w-8 p-0 ms-auto"
|
||||
>
|
||||
<MaximizeIcon className="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
<div className={cn("grow h-[calc(50dvh-4rem)] w-full overflow-auto p-3 rounded-md bg-gh-dark text-sm", !infoDisplay && "animate-pulse")}>
|
||||
<div dangerouslySetInnerHTML={{ __html: infoDisplay }} />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</SheetContent>
|
||||
</Sheet>
|
||||
</>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
function ContainersTableHead({ table }: { table: TableType<ContainerRecord> }) {
|
||||
return (
|
||||
<TableHeader className="sticky top-0 z-50 w-full border-b-2">
|
||||
{table.getHeaderGroups().map((headerGroup) => (
|
||||
<tr key={headerGroup.id}>
|
||||
{headerGroup.headers.map((header) => {
|
||||
return (
|
||||
<TableHead className="px-2" key={header.id}>
|
||||
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
|
||||
</TableHead>
|
||||
)
|
||||
})}
|
||||
</tr>
|
||||
))}
|
||||
</TableHeader>
|
||||
)
|
||||
}
|
||||
|
||||
const ContainerTableRow = memo(
|
||||
function ContainerTableRow({
|
||||
row,
|
||||
virtualRow,
|
||||
openSheet,
|
||||
}: {
|
||||
row: Row<ContainerRecord>
|
||||
virtualRow: VirtualItem
|
||||
openSheet: (container: ContainerRecord) => void
|
||||
}) {
|
||||
return (
|
||||
<TableRow
|
||||
data-state={row.getIsSelected() && "selected"}
|
||||
className="cursor-pointer transition-opacity"
|
||||
onClick={() => openSheet(row.original)}
|
||||
>
|
||||
{row.getVisibleCells().map((cell) => (
|
||||
<TableCell
|
||||
key={cell.id}
|
||||
className="py-0"
|
||||
style={{
|
||||
height: virtualRow.size,
|
||||
}}
|
||||
>
|
||||
{flexRender(cell.column.columnDef.cell, cell.getContext())}
|
||||
</TableCell>
|
||||
))}
|
||||
</TableRow>
|
||||
)
|
||||
}
|
||||
)
|
||||
|
||||
function LogsFullscreenDialog({ open, onOpenChange, logsDisplay, containerName, onRefresh, isRefreshing }: { open: boolean, onOpenChange: (open: boolean) => void, logsDisplay: string, containerName: string, onRefresh: () => void | Promise<void>, isRefreshing: boolean }) {
|
||||
const outerContainerRef = useRef<HTMLDivElement>(null)
|
||||
|
||||
useEffect(() => {
|
||||
if (open && logsDisplay) {
|
||||
// Scroll the outer container to bottom
|
||||
const scrollToBottom = () => {
|
||||
if (outerContainerRef.current) {
|
||||
outerContainerRef.current.scrollTop = outerContainerRef.current.scrollHeight
|
||||
}
|
||||
}
|
||||
setTimeout(scrollToBottom, 50)
|
||||
}
|
||||
}, [open, logsDisplay])
|
||||
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="w-[calc(100vw-20px)] h-[calc(100dvh-20px)] max-w-none p-0 bg-gh-dark border-0 text-white">
|
||||
<DialogTitle className="sr-only">{containerName} logs</DialogTitle>
|
||||
<div ref={outerContainerRef} className="h-full overflow-auto">
|
||||
<div className="h-full w-full px-3 leading-relaxed rounded-md bg-gh-dark text-sm">
|
||||
<div className="py-3" dangerouslySetInnerHTML={{ __html: logsDisplay }} />
|
||||
</div>
|
||||
</div>
|
||||
<button
|
||||
onClick={() => {
|
||||
void onRefresh()
|
||||
}}
|
||||
className="absolute top-3 right-11 opacity-60 hover:opacity-100 p-1"
|
||||
disabled={isRefreshing}
|
||||
title={t`Refresh`}
|
||||
aria-label={t`Refresh`}
|
||||
>
|
||||
<RefreshCwIcon
|
||||
className={`size-4 transition-transform duration-300 ${isRefreshing ? 'animate-spin' : ''}`}
|
||||
/>
|
||||
</button>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
|
||||
function InfoFullscreenDialog({ open, onOpenChange, infoDisplay, containerName }: { open: boolean, onOpenChange: (open: boolean) => void, infoDisplay: string, containerName: string }) {
|
||||
return (
|
||||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||||
<DialogContent className="w-[calc(100vw-20px)] h-[calc(100dvh-20px)] max-w-none p-0 bg-gh-dark border-0 text-white">
|
||||
<DialogTitle className="sr-only">{containerName} info</DialogTitle>
|
||||
<div className="flex-1 overflow-auto">
|
||||
<div className="h-full w-full overflow-auto p-3 rounded-md bg-gh-dark text-sm leading-relaxed">
|
||||
<div dangerouslySetInnerHTML={{ __html: infoDisplay }} />
|
||||
</div>
|
||||
</div>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
)
|
||||
}
|
||||
26
internal/site/src/components/footer-repo-link.tsx
Normal file
26
internal/site/src/components/footer-repo-link.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { GithubIcon } from "lucide-react"
|
||||
import { Separator } from "./ui/separator"
|
||||
|
||||
export function FooterRepoLink() {
|
||||
return (
|
||||
<div className="flex gap-1.5 justify-end items-center pe-3 sm:pe-6 mt-3.5 mb-4 text-xs opacity-80">
|
||||
<a
|
||||
href="https://github.com/henrygd/beszel"
|
||||
target="_blank"
|
||||
className="flex items-center gap-0.5 text-muted-foreground hover:text-foreground duration-75"
|
||||
rel="noopener"
|
||||
>
|
||||
<GithubIcon className="h-3 w-3" /> GitHub
|
||||
</a>
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
<a
|
||||
href="https://github.com/henrygd/beszel/releases"
|
||||
target="_blank"
|
||||
className="text-muted-foreground hover:text-foreground duration-75"
|
||||
rel="noopener"
|
||||
>
|
||||
Beszel {globalThis.BESZEL.HUB_VERSION}
|
||||
</a>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -12,7 +12,7 @@ export function LangToggle() {
|
||||
return (
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button variant={"ghost"} size="icon" className="hidden 450:flex">
|
||||
<Button variant={"ghost"} size="icon" className="hidden sm:flex">
|
||||
<LanguagesIcon className="absolute h-[1.2rem] w-[1.2rem] light:opacity-85" />
|
||||
<span className="sr-only">Language</span>
|
||||
</Button>
|
||||
|
||||
@@ -1,16 +1,27 @@
|
||||
import { useId } from "react"
|
||||
|
||||
const d = "M146.4 73.1h-30.5V59.8h30.5a3.2 3.2 0 0 0 2.3-1 3.2 3.2 0 0 0 1-2.3q0-.8-.3-1.3a1.5 1.5 0 0 0-.7-.6 4.7 4.7 0 0 0-1-.3l-1.3-.1h-13.9q-3.4 0-6.5-1.3-3-1.3-5.2-3.6a16.9 16.9 0 0 1-3.6-5.3 16.3 16.3 0 0 1-1.3-6.5 16.4 16.4 0 0 1 1.3-6.4q1.3-3.1 3.6-5.4 2.2-2.2 5.2-3.5a16.3 16.3 0 0 1 6.5-1.3h27v13.3h-27a3.2 3.2 0 0 0-2.3 1 3.2 3.2 0 0 0-1 2.3 3.3 3.3 0 0 0 1 2.4 3.3 3.3 0 0 0 1.2.8 3.2 3.2 0 0 0 1.1.2h13.9a18.1 18.1 0 0 1 6 1 17.3 17.3 0 0 1 .4.2q3 1.1 5.3 3.2a15.1 15.1 0 0 1 3.6 4.9 14.7 14.7 0 0 1 1.3 5.4 17.2 17.2 0 0 1 0 .9 16 16 0 0 1-1 5.8 15.4 15.4 0 0 1-.3.7 17.3 17.3 0 0 1-3.6 5.2 16.4 16.4 0 0 1-5.3 3.6 16.2 16.2 0 0 1-6.4 1.3Zm64.5-13.3v13.3h-43.6l22-39h-22V21h43.6l-22 39h22ZM35 73.1H0v-70h35q4.4 0 8.2 1.6a21.4 21.4 0 0 1 6.6 4.6q2.9 2.8 4.5 6.6 1.7 3.8 1.7 8.2a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5 1.4 1.6 2.4 3.5a18.3 18.3 0 0 1 1.5 4A17.4 17.4 0 0 1 56 51a15.3 15.3 0 0 1 0 1.1q0 4.3-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.5-3.8 1.7-8.2 1.7Zm76-43L86 60.4l1.5.3a16.7 16.7 0 0 0 1.6 0q2 0 3.8-.4 1.8-.6 3.4-1.6 1.6-1 2.8-2.4a12.8 12.8 0 0 0 2-3.2l9.8 9.8q-1.9 2.6-4.3 4.7a27 27 0 0 1-5.2 3.6 26.1 26.1 0 0 1-6 2.2 26.8 26.8 0 0 1-6.3.8 26.4 26.4 0 0 1-10.4-2 26.2 26.2 0 0 1-8.5-5.8 26.7 26.7 0 0 1-5.5-8.3 30.4 30.4 0 0 1-.2-.4q-2.1-5-2.1-11.1a31.9 31.9 0 0 1 .7-7 27 27 0 0 1 1.4-4.3 27 27 0 0 1 3.8-6.6 24.5 24.5 0 0 1 2-2.2 26 26 0 0 1 8.4-5.6 27 27 0 0 1 10.4-2 26.3 26.3 0 0 1 6.4.8 26.9 26.9 0 0 1 6 2.2q2.7 1.5 5.2 3.6 2.4 2.1 4.3 4.8Zm152.3 0-25 30.2 1.5.3a16.7 16.7 0 0 0 1.6 0q2 0 3.8-.4 1.8-.6 3.4-1.6 1.5-1 2.8-2.4a12.8 12.8 0 0 0 2-3.2l9.8 9.8q-1.9 2.6-4.3 4.7a27 27 0 0 1-5.2 3.6 26.1 26.1 0 0 1-6 2.2 26.8 26.8 0 0 1-6.3.8 26.4 26.4 0 0 1-10.4-2 26.2 26.2 0 0 1-8.5-5.8A26.7 26.7 0 0 1 217 58a30.4 30.4 0 0 1-.2-.4q-2.1-5-2.1-11.1a31.9 31.9 0 0 1 .7-7 27 27 0 0 1 1.4-4.3 27 27 0 0 1 3.8-6.6 24.5 24.5 0 0 1 2-2.2 26 26 0 0 1 8.4-5.6 27 27 0 0 1 10.4-2 26.3 26.3 0 0 1 6.4.8 26.9 26.9 0 0 1 6 2.2q2.7 1.5 5.2 3.6 2.4 2.1 4.3 4.8ZM283.4 0v73.1H270V0h13.4ZM14 17v14.1h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 30 40 29a6.9 6.9 0 0 0 1.5-2.3q.5-1.3.5-2.7a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.5q-.6-1.2-1.5-2.2a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.5 7.9 7.9 0 0 0-.2 0H14Zm0 28.1v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.2Q39 58 40 57.1a7 7 0 0 0 1.5-2.3 6.9 6.9 0 0 0 .5-2.5 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 48 40 47a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm63.3 8.3 15.5-20.6a8 8 0 0 0-1.4-.4 7 7 0 0 0-.4 0 17.2 17.2 0 0 0-1.6-.1 19.2 19.2 0 0 0-.3 0 13.3 13.3 0 0 0-5.1 1q-2.5 1-4.2 2.8a13.1 13.1 0 0 0-2.5 3.6 15.5 15.5 0 0 0-.3.9 14.7 14.7 0 0 0-1 3.5 18.7 18.7 0 0 0 0 2.4 17.6 17.6 0 0 0 0 .7v.8a29.4 29.4 0 0 0 0 .1 19.2 19.2 0 0 0 .2 2 20.2 20.2 0 0 0 .4 1.6 18.6 18.6 0 0 0 0 .2 7.5 7.5 0 0 0 .4.9 6 6 0 0 0 .3.6Zm152.3 0L245 32.8a8 8 0 0 0-1.4-.4 7 7 0 0 0-.4 0 17.2 17.2 0 0 0-1.6-.1 19.2 19.2 0 0 0-.3 0 13.3 13.3 0 0 0-5.1 1q-2.5 1-4.2 2.8a13.1 13.1 0 0 0-2.5 3.6 15.5 15.5 0 0 0-.4.9 14.7 14.7 0 0 0-.8 3.5 18.7 18.7 0 0 0-.2 2.4 17.6 17.6 0 0 0 0 .7v.8a29.4 29.4 0 0 0 .1.1 19.2 19.2 0 0 0 .2 2 20.2 20.2 0 0 0 .4 1.6 18.6 18.6 0 0 0 0 .2 7.5 7.5 0 0 0 .4.9 6 6 0 0 0 .3.6Z"
|
||||
|
||||
export function Logo({ className }: { className?: string }) {
|
||||
const id = useId()
|
||||
|
||||
return (
|
||||
// Righteous
|
||||
// Righteous font from Google Fonts
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 285 75" className={className}>
|
||||
{/* <defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="20%" x2="100%" y2="120%">
|
||||
<stop offset="0%" style={{ stopColor: "#747bff" }} />
|
||||
<stop offset="100%" style={{ stopColor: "#24eb5c" }} />
|
||||
<defs>
|
||||
<linearGradient id={id} x1="0%" y1="20%" x2="100%" y2="120%">
|
||||
<stop offset="10%" style={{ stopColor: "#747bff" }} />
|
||||
<stop offset="90%" style={{ stopColor: "#24eb5c" }} />
|
||||
</linearGradient>
|
||||
</defs> */}
|
||||
</defs>
|
||||
<path
|
||||
// fill="url(#gradient)"
|
||||
d="M146.4 73.1h-30.5V59.8h30.5a3.2 3.2 0 0 0 2.3-1 3.2 3.2 0 0 0 1-2.3q0-.8-.3-1.3a1.5 1.5 0 0 0-.7-.6 4.7 4.7 0 0 0-1-.3l-1.3-.1h-13.9q-3.4 0-6.5-1.3-3-1.3-5.2-3.6a16.9 16.9 0 0 1-3.6-5.3 16.3 16.3 0 0 1-1.3-6.5 16.4 16.4 0 0 1 1.3-6.4q1.3-3.1 3.6-5.4 2.2-2.2 5.2-3.5a16.3 16.3 0 0 1 6.5-1.3h27v13.3h-27a3.2 3.2 0 0 0-2.3 1 3.2 3.2 0 0 0-1 2.3 3.3 3.3 0 0 0 1 2.4 3.3 3.3 0 0 0 1.2.8 3.2 3.2 0 0 0 1.1.2h13.9a18.1 18.1 0 0 1 6 1 17.3 17.3 0 0 1 .4.2q3 1.1 5.3 3.2a15.1 15.1 0 0 1 3.6 4.9 14.7 14.7 0 0 1 1.3 5.4 17.2 17.2 0 0 1 0 .9 16 16 0 0 1-1 5.8 15.4 15.4 0 0 1-.3.7 17.3 17.3 0 0 1-3.6 5.2 16.4 16.4 0 0 1-5.3 3.6 16.2 16.2 0 0 1-6.4 1.3Zm64.5-13.3v13.3h-43.6l22-39h-22V21h43.6l-22 39h22ZM35 73.1H0v-70h35q4.4 0 8.2 1.6a21.4 21.4 0 0 1 6.6 4.6q2.9 2.8 4.5 6.6 1.7 3.8 1.7 8.2a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5 1.4 1.6 2.4 3.5a18.3 18.3 0 0 1 1.5 4A17.4 17.4 0 0 1 56 51a15.3 15.3 0 0 1 0 1.1q0 4.3-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.5-3.8 1.7-8.2 1.7Zm76-43L86 60.4l1.5.3a16.7 16.7 0 0 0 1.6 0q2 0 3.8-.4 1.8-.6 3.4-1.6 1.6-1 2.8-2.4a12.8 12.8 0 0 0 2-3.2l9.8 9.8q-1.9 2.6-4.3 4.7a27 27 0 0 1-5.2 3.6 26.1 26.1 0 0 1-6 2.2 26.8 26.8 0 0 1-6.3.8 26.4 26.4 0 0 1-10.4-2 26.2 26.2 0 0 1-8.5-5.8 26.7 26.7 0 0 1-5.5-8.3 30.4 30.4 0 0 1-.2-.4q-2.1-5-2.1-11.1a31.9 31.9 0 0 1 .7-7 27 27 0 0 1 1.4-4.3 27 27 0 0 1 3.8-6.6 24.5 24.5 0 0 1 2-2.2 26 26 0 0 1 8.4-5.6 27 27 0 0 1 10.4-2 26.3 26.3 0 0 1 6.4.8 26.9 26.9 0 0 1 6 2.2q2.7 1.5 5.2 3.6 2.4 2.1 4.3 4.8Zm152.3 0-25 30.2 1.5.3a16.7 16.7 0 0 0 1.6 0q2 0 3.8-.4 1.8-.6 3.4-1.6 1.5-1 2.8-2.4a12.8 12.8 0 0 0 2-3.2l9.8 9.8q-1.9 2.6-4.3 4.7a27 27 0 0 1-5.2 3.6 26.1 26.1 0 0 1-6 2.2 26.8 26.8 0 0 1-6.3.8 26.4 26.4 0 0 1-10.4-2 26.2 26.2 0 0 1-8.5-5.8A26.7 26.7 0 0 1 217 58a30.4 30.4 0 0 1-.2-.4q-2.1-5-2.1-11.1a31.9 31.9 0 0 1 .7-7 27 27 0 0 1 1.4-4.3 27 27 0 0 1 3.8-6.6 24.5 24.5 0 0 1 2-2.2 26 26 0 0 1 8.4-5.6 27 27 0 0 1 10.4-2 26.3 26.3 0 0 1 6.4.8 26.9 26.9 0 0 1 6 2.2q2.7 1.5 5.2 3.6 2.4 2.1 4.3 4.8ZM283.4 0v73.1H270V0h13.4ZM14 17v14.1h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 30 40 29a6.9 6.9 0 0 0 1.5-2.3q.5-1.3.5-2.7a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.5q-.6-1.2-1.5-2.2a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.5 7.9 7.9 0 0 0-.2 0H14Zm0 28.1v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.2Q39 58 40 57.1a7 7 0 0 0 1.5-2.3 6.9 6.9 0 0 0 .5-2.5 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 48 40 47a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm63.3 8.3 15.5-20.6a8 8 0 0 0-1.4-.4 7 7 0 0 0-.4 0 17.2 17.2 0 0 0-1.6-.1 19.2 19.2 0 0 0-.3 0 13.3 13.3 0 0 0-5.1 1q-2.5 1-4.2 2.8a13.1 13.1 0 0 0-2.5 3.6 15.5 15.5 0 0 0-.3.9 14.7 14.7 0 0 0-1 3.5 18.7 18.7 0 0 0 0 2.4 17.6 17.6 0 0 0 0 .7v.8a29.4 29.4 0 0 0 0 .1 19.2 19.2 0 0 0 .2 2 20.2 20.2 0 0 0 .4 1.6 18.6 18.6 0 0 0 0 .2 7.5 7.5 0 0 0 .4.9 6 6 0 0 0 .3.6Zm152.3 0L245 32.8a8 8 0 0 0-1.4-.4 7 7 0 0 0-.4 0 17.2 17.2 0 0 0-1.6-.1 19.2 19.2 0 0 0-.3 0 13.3 13.3 0 0 0-5.1 1q-2.5 1-4.2 2.8a13.1 13.1 0 0 0-2.5 3.6 15.5 15.5 0 0 0-.4.9 14.7 14.7 0 0 0-.8 3.5 18.7 18.7 0 0 0-.2 2.4 17.6 17.6 0 0 0 0 .7v.8a29.4 29.4 0 0 0 .1.1 19.2 19.2 0 0 0 .2 2 20.2 20.2 0 0 0 .4 1.6 18.6 18.6 0 0 0 0 .2 7.5 7.5 0 0 0 .4.9 6 6 0 0 0 .3.6Z"
|
||||
className="duration-250 group-hover:opacity-0 group-hover:ease-in ease-out"
|
||||
d={d}
|
||||
/>
|
||||
<path
|
||||
className="opacity-0 duration-250 group-hover:opacity-100 ease-in-out"
|
||||
fill={`url(#${id})`}
|
||||
d={d}
|
||||
/>
|
||||
</svg>
|
||||
)
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Trans } from "@lingui/react/macro"
|
||||
import { getPagePath } from "@nanostores/router"
|
||||
import {
|
||||
ContainerIcon,
|
||||
DatabaseBackupIcon,
|
||||
LogOutIcon,
|
||||
LogsIcon,
|
||||
@@ -39,7 +40,7 @@ export default function Navbar() {
|
||||
<Link
|
||||
href={basePath}
|
||||
aria-label="Home"
|
||||
className="p-2 ps-0 me-3"
|
||||
className="p-2 ps-0 me-3 group"
|
||||
onMouseEnter={runOnce(() => import("@/components/routes/home"))}
|
||||
>
|
||||
<Logo className="h-[1.1rem] md:h-5 fill-foreground" />
|
||||
@@ -47,18 +48,25 @@ export default function Navbar() {
|
||||
<SearchButton />
|
||||
|
||||
<div className="flex items-center ms-auto" onMouseEnter={() => import("@/components/routes/settings/general")}>
|
||||
<Link
|
||||
href={getPagePath($router, "containers")}
|
||||
className={cn(buttonVariants({ variant: "ghost", size: "icon" }))}
|
||||
aria-label="Containers"
|
||||
>
|
||||
<ContainerIcon className="h-[1.2rem] w-[1.2rem]" strokeWidth={1.5} />
|
||||
</Link>
|
||||
<LangToggle />
|
||||
<ModeToggle />
|
||||
<Link
|
||||
href={getPagePath($router, "settings", { name: "general" })}
|
||||
aria-label="Settings"
|
||||
className={cn("", buttonVariants({ variant: "ghost", size: "icon" }))}
|
||||
className={cn(buttonVariants({ variant: "ghost", size: "icon" }))}
|
||||
>
|
||||
<SettingsIcon className="h-[1.2rem] w-[1.2rem]" />
|
||||
</Link>
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<button aria-label="User Actions" className={cn("", buttonVariants({ variant: "ghost", size: "icon" }))}>
|
||||
<button aria-label="User Actions" className={cn(buttonVariants({ variant: "ghost", size: "icon" }))}>
|
||||
<UserIcon className="h-[1.2rem] w-[1.2rem]" />
|
||||
</button>
|
||||
</DropdownMenuTrigger>
|
||||
@@ -112,7 +120,7 @@ export default function Navbar() {
|
||||
</DropdownMenuItem>
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<AddSystemButton className="ms-2" />
|
||||
<AddSystemButton className="ms-2 hidden 450:flex" />
|
||||
</div>
|
||||
</div>
|
||||
)
|
||||
|
||||
@@ -2,6 +2,7 @@ import { createRouter } from "@nanostores/router"
|
||||
|
||||
const routes = {
|
||||
home: "/",
|
||||
containers: "/containers",
|
||||
system: `/system/:id`,
|
||||
settings: `/settings/:name?`,
|
||||
forgot_password: `/forgot-password`,
|
||||
|
||||
26
internal/site/src/components/routes/containers.tsx
Normal file
26
internal/site/src/components/routes/containers.tsx
Normal file
@@ -0,0 +1,26 @@
|
||||
import { useLingui } from "@lingui/react/macro"
|
||||
import { memo, useEffect, useMemo } from "react"
|
||||
import ContainersTable from "@/components/containers-table/containers-table"
|
||||
import { ActiveAlerts } from "@/components/active-alerts"
|
||||
import { FooterRepoLink } from "@/components/footer-repo-link"
|
||||
|
||||
export default memo(() => {
|
||||
const { t } = useLingui()
|
||||
|
||||
useEffect(() => {
|
||||
document.title = `${t`All Containers`} / Beszel`
|
||||
}, [t])
|
||||
|
||||
return useMemo(
|
||||
() => (
|
||||
<>
|
||||
<div className="grid gap-4">
|
||||
<ActiveAlerts />
|
||||
<ContainersTable />
|
||||
</div>
|
||||
<FooterRepoLink />
|
||||
</>
|
||||
),
|
||||
[]
|
||||
)
|
||||
})
|
||||
@@ -1,128 +1,28 @@
|
||||
import { Plural, Trans, useLingui } from "@lingui/react/macro"
|
||||
import { useStore } from "@nanostores/react"
|
||||
import { getPagePath } from "@nanostores/router"
|
||||
import { GithubIcon } from "lucide-react"
|
||||
import { useLingui } from "@lingui/react/macro"
|
||||
import { memo, Suspense, useEffect, useMemo } from "react"
|
||||
import { $router, Link } from "@/components/router"
|
||||
import SystemsTable from "@/components/systems-table/systems-table"
|
||||
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card"
|
||||
import { Separator } from "@/components/ui/separator"
|
||||
import { alertInfo } from "@/lib/alerts"
|
||||
import { $alerts, $allSystemsById } from "@/lib/stores"
|
||||
import type { AlertRecord } from "@/types"
|
||||
import { ActiveAlerts } from "@/components/active-alerts"
|
||||
import { FooterRepoLink } from "@/components/footer-repo-link"
|
||||
|
||||
export default memo(() => {
|
||||
const { t } = useLingui()
|
||||
|
||||
useEffect(() => {
|
||||
document.title = `${t`Dashboard`} / Beszel`
|
||||
document.title = `${t`All Systems`} / Beszel`
|
||||
}, [t])
|
||||
|
||||
return useMemo(
|
||||
() => (
|
||||
<>
|
||||
<ActiveAlerts />
|
||||
<Suspense>
|
||||
<SystemsTable />
|
||||
</Suspense>
|
||||
|
||||
<div className="flex gap-1.5 justify-end items-center pe-3 sm:pe-6 mt-3.5 mb-4 text-xs opacity-80">
|
||||
<a
|
||||
href="https://github.com/henrygd/beszel"
|
||||
target="_blank"
|
||||
className="flex items-center gap-0.5 text-muted-foreground hover:text-foreground duration-75"
|
||||
rel="noopener"
|
||||
>
|
||||
<GithubIcon className="h-3 w-3" /> GitHub
|
||||
</a>
|
||||
<Separator orientation="vertical" className="h-2.5 bg-muted-foreground opacity-70" />
|
||||
<a
|
||||
href="https://github.com/henrygd/beszel/releases"
|
||||
target="_blank"
|
||||
className="text-muted-foreground hover:text-foreground duration-75"
|
||||
rel="noopener"
|
||||
>
|
||||
Beszel {globalThis.BESZEL.HUB_VERSION}
|
||||
</a>
|
||||
<div className="flex flex-col gap-4">
|
||||
<ActiveAlerts />
|
||||
<Suspense>
|
||||
<SystemsTable />
|
||||
</Suspense>
|
||||
</div>
|
||||
<FooterRepoLink />
|
||||
</>
|
||||
),
|
||||
[]
|
||||
)
|
||||
})
|
||||
|
||||
const ActiveAlerts = () => {
|
||||
const alerts = useStore($alerts)
|
||||
const systems = useStore($allSystemsById)
|
||||
|
||||
const { activeAlerts, alertsKey } = useMemo(() => {
|
||||
const activeAlerts: AlertRecord[] = []
|
||||
// key to prevent re-rendering if alerts change but active alerts didn't
|
||||
const alertsKey: string[] = []
|
||||
|
||||
for (const systemId of Object.keys(alerts)) {
|
||||
for (const alert of alerts[systemId].values()) {
|
||||
if (alert.triggered && alert.name in alertInfo) {
|
||||
activeAlerts.push(alert)
|
||||
alertsKey.push(`${alert.system}${alert.value}${alert.min}`)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return { activeAlerts, alertsKey }
|
||||
}, [alerts])
|
||||
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: alertsKey is inclusive
|
||||
return useMemo(() => {
|
||||
if (activeAlerts.length === 0) {
|
||||
return null
|
||||
}
|
||||
return (
|
||||
<Card className="mb-4">
|
||||
<CardHeader className="pb-4 px-2 sm:px-6 max-sm:pt-5 max-sm:pb-1">
|
||||
<div className="px-2 sm:px-1">
|
||||
<CardTitle>
|
||||
<Trans>Active Alerts</Trans>
|
||||
</CardTitle>
|
||||
</div>
|
||||
</CardHeader>
|
||||
<CardContent className="max-sm:p-2">
|
||||
{activeAlerts.length > 0 && (
|
||||
<div className="grid sm:grid-cols-2 lg:grid-cols-3 2xl:grid-cols-4 gap-3">
|
||||
{activeAlerts.map((alert) => {
|
||||
const info = alertInfo[alert.name as keyof typeof alertInfo]
|
||||
return (
|
||||
<Alert
|
||||
key={alert.id}
|
||||
className="hover:-translate-y-px duration-200 bg-transparent border-foreground/10 hover:shadow-md shadow-black/5"
|
||||
>
|
||||
<info.icon className="h-4 w-4" />
|
||||
<AlertTitle>
|
||||
{systems[alert.system]?.name} {info.name().toLowerCase().replace("cpu", "CPU")}
|
||||
</AlertTitle>
|
||||
<AlertDescription>
|
||||
{alert.name === "Status" ? (
|
||||
<Trans>Connection is down</Trans>
|
||||
) : (
|
||||
<Trans>
|
||||
Exceeds {alert.value}
|
||||
{info.unit} in last <Plural value={alert.min} one="# minute" other="# minutes" />
|
||||
</Trans>
|
||||
)}
|
||||
</AlertDescription>
|
||||
<Link
|
||||
href={getPagePath($router, "system", { id: systems[alert.system]?.id })}
|
||||
className="absolute inset-0 w-full h-full"
|
||||
aria-label="View system"
|
||||
></Link>
|
||||
</Alert>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
</CardContent>
|
||||
</Card>
|
||||
)
|
||||
}, [alertsKey.join("")])
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ import {
|
||||
XIcon,
|
||||
} from "lucide-react"
|
||||
import { subscribeKeys } from "nanostores"
|
||||
import React, { type JSX, memo, useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import React, { type JSX, lazy, memo, useCallback, useEffect, useMemo, useRef, useState } from "react"
|
||||
import AreaChartDefault, { type DataPoint } from "@/components/charts/area-chart"
|
||||
import ContainerChart from "@/components/charts/container-chart"
|
||||
import DiskChart from "@/components/charts/disk-chart"
|
||||
@@ -41,6 +41,7 @@ import { useIntersectionObserver } from "@/lib/use-intersection-observer"
|
||||
import {
|
||||
chartTimeData,
|
||||
cn,
|
||||
compareSemVer,
|
||||
debounce,
|
||||
decimalString,
|
||||
formatBytes,
|
||||
@@ -73,6 +74,8 @@ import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/
|
||||
import NetworkSheet from "./system/network-sheet"
|
||||
import LineChartDefault from "../charts/line-chart"
|
||||
|
||||
|
||||
|
||||
type ChartTimeData = {
|
||||
time: number
|
||||
data: {
|
||||
@@ -168,7 +171,7 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
const [system, setSystem] = useState({} as SystemRecord)
|
||||
const [systemStats, setSystemStats] = useState([] as SystemStatsRecord[])
|
||||
const [containerData, setContainerData] = useState([] as ChartData["containerData"])
|
||||
const netCardRef = useRef<HTMLDivElement>(null)
|
||||
const temperatureChartRef = useRef<HTMLDivElement>(null)
|
||||
const persistChartTime = useRef(false)
|
||||
const [bottomSpacing, setBottomSpacing] = useState(0)
|
||||
const [chartLoading, setChartLoading] = useState(true)
|
||||
@@ -214,7 +217,7 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
// subscribe to realtime metrics if chart time is 1m
|
||||
// biome-ignore lint/correctness/useExhaustiveDependencies: not necessary
|
||||
useEffect(() => {
|
||||
let unsub = () => {}
|
||||
let unsub = () => { }
|
||||
if (!system.id || chartTime !== "1m") {
|
||||
return
|
||||
}
|
||||
@@ -395,19 +398,20 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
}[]
|
||||
}, [system, t])
|
||||
|
||||
/** Space for tooltip if more than 12 containers */
|
||||
/** Space for tooltip if more than 10 sensors and no containers table */
|
||||
useEffect(() => {
|
||||
if (!netCardRef.current || !containerData.length) {
|
||||
const sensors = Object.keys(systemStats.at(-1)?.stats.t ?? {})
|
||||
if (!temperatureChartRef.current || sensors.length < 10 || containerData.length > 0) {
|
||||
setBottomSpacing(0)
|
||||
return
|
||||
}
|
||||
const tooltipHeight = (Object.keys(containerData[0]).length - 11) * 17.8 - 40
|
||||
const tooltipHeight = (sensors.length - 10) * 17.8 - 40
|
||||
const wrapperEl = chartWrapRef.current as HTMLDivElement
|
||||
const wrapperRect = wrapperEl.getBoundingClientRect()
|
||||
const chartRect = netCardRef.current.getBoundingClientRect()
|
||||
const chartRect = temperatureChartRef.current.getBoundingClientRect()
|
||||
const distanceToBottom = wrapperRect.bottom - chartRect.bottom
|
||||
setBottomSpacing(tooltipHeight - distanceToBottom)
|
||||
}, [containerData])
|
||||
}, [])
|
||||
|
||||
// keyboard navigation between systems
|
||||
useEffect(() => {
|
||||
@@ -741,26 +745,20 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
</ChartCard>
|
||||
|
||||
{containerFilterBar && containerData.length > 0 && (
|
||||
<div
|
||||
ref={netCardRef}
|
||||
className={cn({
|
||||
"col-span-full": !grid,
|
||||
})}
|
||||
<ChartCard
|
||||
empty={dataEmpty}
|
||||
grid={grid}
|
||||
title={dockerOrPodman(t`Docker Network I/O`, system)}
|
||||
description={dockerOrPodman(t`Network traffic of docker containers`, system)}
|
||||
cornerEl={containerFilterBar}
|
||||
>
|
||||
<ChartCard
|
||||
empty={dataEmpty}
|
||||
title={dockerOrPodman(t`Docker Network I/O`, system)}
|
||||
description={dockerOrPodman(t`Network traffic of docker containers`, system)}
|
||||
cornerEl={containerFilterBar}
|
||||
>
|
||||
<ContainerChart
|
||||
chartData={chartData}
|
||||
chartType={ChartType.Network}
|
||||
dataKey="n"
|
||||
chartConfig={containerChartConfigs.network}
|
||||
/>
|
||||
</ChartCard>
|
||||
</div>
|
||||
<ContainerChart
|
||||
chartData={chartData}
|
||||
chartType={ChartType.Network}
|
||||
dataKey="n"
|
||||
chartConfig={containerChartConfigs.network}
|
||||
/>
|
||||
</ChartCard>
|
||||
)}
|
||||
|
||||
{/* Swap chart */}
|
||||
@@ -790,16 +788,21 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
|
||||
{/* Temperature chart */}
|
||||
{systemStats.at(-1)?.stats.t && (
|
||||
<ChartCard
|
||||
empty={dataEmpty}
|
||||
grid={grid}
|
||||
title={t`Temperature`}
|
||||
description={t`Temperatures of system sensors`}
|
||||
cornerEl={<FilterBar store={$temperatureFilter} />}
|
||||
legend={Object.keys(systemStats.at(-1)?.stats.t ?? {}).length < 12}
|
||||
<div
|
||||
ref={temperatureChartRef}
|
||||
className={cn("odd:last-of-type:col-span-full", { "col-span-full": !grid })}
|
||||
>
|
||||
<TemperatureChart chartData={chartData} />
|
||||
</ChartCard>
|
||||
<ChartCard
|
||||
empty={dataEmpty}
|
||||
grid={grid}
|
||||
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>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Battery chart */}
|
||||
@@ -932,7 +935,7 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
>
|
||||
<DiskChart
|
||||
chartData={chartData}
|
||||
dataKey={`stats.efs.${extraFsName}.du`}
|
||||
dataKey={({ stats }: SystemStatsRecord) => stats?.efs?.[extraFsName]?.du}
|
||||
diskSize={systemStats.at(-1)?.stats.efs?.[extraFsName].d ?? NaN}
|
||||
/>
|
||||
</ChartCard>
|
||||
@@ -987,6 +990,9 @@ export default memo(function SystemDetail({ id }: { id: string }) {
|
||||
})}
|
||||
</div>
|
||||
)}
|
||||
{containerData.length > 0 && compareSemVer(chartData.agentVersion, parseSemVer("0.14.0")) >= 0 && (
|
||||
<LazyContainersTable systemId={id} />
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* add space for tooltip if more than 12 containers */}
|
||||
@@ -1116,3 +1122,14 @@ export function ChartCard({
|
||||
</Card>
|
||||
)
|
||||
}
|
||||
|
||||
const ContainersTable = lazy(() => import("../containers-table/containers-table"))
|
||||
|
||||
function LazyContainersTable({ systemId }: { systemId: string }) {
|
||||
const { isIntersecting, ref } = useIntersectionObserver()
|
||||
return (
|
||||
<div ref={ref}>
|
||||
{isIntersecting && <ContainersTable systemId={systemId} />}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
@@ -91,16 +91,16 @@ const ChartTooltip = RechartsPrimitive.Tooltip
|
||||
const ChartTooltipContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.ComponentProps<typeof RechartsPrimitive.Tooltip> &
|
||||
React.ComponentProps<"div"> & {
|
||||
hideLabel?: boolean
|
||||
indicator?: "line" | "dot" | "dashed"
|
||||
nameKey?: string
|
||||
labelKey?: string
|
||||
unit?: string
|
||||
filter?: string
|
||||
contentFormatter?: (item: any, key: string) => React.ReactNode | string
|
||||
truncate?: boolean
|
||||
}
|
||||
React.ComponentProps<"div"> & {
|
||||
hideLabel?: boolean
|
||||
indicator?: "line" | "dot" | "dashed"
|
||||
nameKey?: string
|
||||
labelKey?: string
|
||||
unit?: string
|
||||
filter?: string
|
||||
contentFormatter?: (item: any, key: string) => React.ReactNode | string
|
||||
truncate?: boolean
|
||||
}
|
||||
>(
|
||||
(
|
||||
{
|
||||
@@ -129,7 +129,11 @@ const ChartTooltipContent = React.forwardRef<
|
||||
|
||||
React.useMemo(() => {
|
||||
if (filter) {
|
||||
payload = payload?.filter((item) => (item.name as string)?.toLowerCase().includes(filter.toLowerCase()))
|
||||
const filterTerms = filter.toLowerCase().split(" ").filter(term => term.length > 0)
|
||||
payload = payload?.filter((item) => {
|
||||
const itemName = (item.name as string)?.toLowerCase()
|
||||
return filterTerms.some(term => itemName?.includes(term))
|
||||
})
|
||||
}
|
||||
if (itemSorter) {
|
||||
// @ts-expect-error
|
||||
@@ -250,10 +254,10 @@ const ChartLegend = RechartsPrimitive.Legend
|
||||
const ChartLegendContent = React.forwardRef<
|
||||
HTMLDivElement,
|
||||
React.ComponentProps<"div"> &
|
||||
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
|
||||
hideIcon?: boolean
|
||||
nameKey?: string
|
||||
}
|
||||
Pick<RechartsPrimitive.LegendProps, "payload" | "verticalAlign"> & {
|
||||
hideIcon?: boolean
|
||||
nameKey?: string
|
||||
}
|
||||
>(({ className, payload, verticalAlign = "bottom" }, ref) => {
|
||||
// const { config } = useChart()
|
||||
|
||||
|
||||
@@ -82,6 +82,8 @@
|
||||
--color-green-900: hsl(140 54% 12%);
|
||||
--color-green-950: hsl(140 57% 6%);
|
||||
|
||||
--color-gh-dark: #22272e;
|
||||
|
||||
--color-background: var(--background);
|
||||
--color-foreground: var(--foreground);
|
||||
--color-card: var(--card);
|
||||
@@ -110,12 +112,14 @@
|
||||
}
|
||||
|
||||
@layer utilities {
|
||||
|
||||
/* Fonts */
|
||||
@supports (font-variation-settings: normal) {
|
||||
:root {
|
||||
font-family: Inter, InterVariable, sans-serif;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: InterVariable;
|
||||
font-style: normal;
|
||||
@@ -130,9 +134,11 @@
|
||||
@apply border-border outline-ring/50;
|
||||
overflow-anchor: none;
|
||||
}
|
||||
|
||||
body {
|
||||
@apply bg-background text-foreground;
|
||||
}
|
||||
|
||||
button {
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -149,16 +155,17 @@
|
||||
@utility ns-dialog {
|
||||
/* New system dialog width */
|
||||
min-width: 30.3rem;
|
||||
|
||||
:where(:lang(zh), :lang(zh-CN), :lang(ko)) & {
|
||||
min-width: 27.9rem;
|
||||
}
|
||||
}
|
||||
|
||||
.recharts-tooltip-wrapper {
|
||||
z-index: 1;
|
||||
z-index: 51;
|
||||
@apply tabular-nums;
|
||||
}
|
||||
|
||||
.recharts-yAxis {
|
||||
@apply tabular-nums;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ import PocketBase from "pocketbase"
|
||||
import { basePath } from "@/components/router"
|
||||
import { toast } from "@/components/ui/use-toast"
|
||||
import type { ChartTimes, UserSettings } from "@/types"
|
||||
import { $alerts, $allSystemsByName, $userSettings } from "./stores"
|
||||
import { $alerts, $allSystemsById, $allSystemsByName, $userSettings } from "./stores"
|
||||
import { chartTimeData } from "./utils"
|
||||
|
||||
/** PocketBase JS Client */
|
||||
@@ -28,6 +28,7 @@ export const verifyAuth = () => {
|
||||
/** Logs the user out by clearing the auth store and unsubscribing from realtime updates. */
|
||||
export function logOut() {
|
||||
$allSystemsByName.set({})
|
||||
$allSystemsById.set({})
|
||||
$alerts.set({})
|
||||
$userSettings.set({} as UserSettings)
|
||||
sessionStorage.setItem("lo", "t") // prevent auto login on logout
|
||||
|
||||
@@ -54,6 +54,16 @@ export enum HourFormat {
|
||||
"24h" = "24h",
|
||||
}
|
||||
|
||||
/** Container health status */
|
||||
export enum ContainerHealth {
|
||||
None,
|
||||
Starting,
|
||||
Healthy,
|
||||
Unhealthy,
|
||||
}
|
||||
|
||||
export const ContainerHealthLabels = ["None", "Starting", "Healthy", "Unhealthy"] as const
|
||||
|
||||
/** Connection type */
|
||||
export enum ConnectionType {
|
||||
SSH = 1,
|
||||
|
||||
28
internal/site/src/lib/shiki.ts
Normal file
28
internal/site/src/lib/shiki.ts
Normal file
@@ -0,0 +1,28 @@
|
||||
// https://shiki.style/guide/bundles#fine-grained-bundle
|
||||
|
||||
// directly import the theme and language modules, only the ones you imported will be bundled.
|
||||
import githubDarkDimmed from '@shikijs/themes/github-dark-dimmed'
|
||||
|
||||
// `shiki/core` entry does not include any themes or languages or the wasm binary.
|
||||
import { createHighlighterCore } from 'shiki/core'
|
||||
import { createOnigurumaEngine } from 'shiki/engine/oniguruma'
|
||||
|
||||
export const highlighter = await createHighlighterCore({
|
||||
themes: [
|
||||
// instead of strings, you need to pass the imported module
|
||||
githubDarkDimmed,
|
||||
// or a dynamic import if you want to do chunk splitting
|
||||
// import('@shikijs/themes/material-theme-ocean')
|
||||
],
|
||||
langs: [
|
||||
import('@shikijs/langs/log'),
|
||||
import('@shikijs/langs/json'),
|
||||
// shiki will try to interop the module with the default export
|
||||
// () => import('@shikijs/langs/css'),
|
||||
],
|
||||
// `shiki/wasm` contains the wasm binary inlined as base64 string.
|
||||
engine: createOnigurumaEngine(import('shiki/wasm'))
|
||||
})
|
||||
|
||||
// optionally, load themes and languages after creation
|
||||
// await highlighter.loadTheme(import('@shikijs/themes/vitesse-light'))
|
||||
@@ -9,7 +9,7 @@ import {
|
||||
$pausedSystems,
|
||||
$upSystems,
|
||||
} from "@/lib/stores"
|
||||
import { FAVICON_DEFAULT, FAVICON_GREEN, FAVICON_RED, updateFavicon } from "@/lib/utils"
|
||||
import { updateFavicon } from "@/lib/utils"
|
||||
import type { SystemRecord } from "@/types"
|
||||
import { SystemStatus } from "./enums"
|
||||
|
||||
@@ -74,9 +74,7 @@ export function init() {
|
||||
|
||||
/** Update the longest system name length and favicon based on system status */
|
||||
function onSystemsChanged(_: Record<string, SystemRecord>, changedSystem: SystemRecord | undefined) {
|
||||
const upSystemsStore = $upSystems.get()
|
||||
const downSystemsStore = $downSystems.get()
|
||||
const upSystems = Object.values(upSystemsStore)
|
||||
const downSystems = Object.values(downSystemsStore)
|
||||
|
||||
// Update longest system name length
|
||||
@@ -86,14 +84,7 @@ function onSystemsChanged(_: Record<string, SystemRecord>, changedSystem: System
|
||||
$longestSystemNameLen.set(nameLen)
|
||||
}
|
||||
|
||||
// Update favicon based on system status
|
||||
if (downSystems.length > 0) {
|
||||
updateFavicon(FAVICON_RED)
|
||||
} else if (upSystems.length > 0) {
|
||||
updateFavicon(FAVICON_GREEN)
|
||||
} else {
|
||||
updateFavicon(FAVICON_DEFAULT)
|
||||
}
|
||||
updateFavicon(downSystems.length)
|
||||
}
|
||||
|
||||
/** Fetch systems from collection */
|
||||
|
||||
@@ -4,16 +4,11 @@ import { listenKeys } from "nanostores"
|
||||
import { timeDay, timeHour, timeMinute } from "d3-time"
|
||||
import { useEffect, useState } from "react"
|
||||
import { twMerge } from "tailwind-merge"
|
||||
import { prependBasePath } from "@/components/router"
|
||||
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"
|
||||
|
||||
export const FAVICON_DEFAULT = "favicon.svg"
|
||||
export const FAVICON_GREEN = "favicon-green.svg"
|
||||
export const FAVICON_RED = "favicon-red.svg"
|
||||
|
||||
export function cn(...inputs: ClassValue[]) {
|
||||
return twMerge(clsx(inputs))
|
||||
}
|
||||
@@ -100,14 +95,41 @@ export const formatDay = (timestamp: string) => {
|
||||
return dayFormatter.format(new Date(timestamp))
|
||||
}
|
||||
|
||||
export const updateFavicon = (newIcon: string) => {
|
||||
;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = prependBasePath(`/static/${newIcon}`)
|
||||
}
|
||||
export const updateFavicon = (() => {
|
||||
let prevDownCount = 0
|
||||
return (downCount = 0) => {
|
||||
if (downCount === prevDownCount) {
|
||||
return
|
||||
}
|
||||
prevDownCount = downCount
|
||||
const svg = `
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 56 70">
|
||||
<defs>
|
||||
<linearGradient id="gradient" x1="0%" y1="20%" x2="100%" y2="120%">
|
||||
<stop offset="0%" style="stop-color:#747bff"/>
|
||||
<stop offset="100%" style="stop-color:#24eb5c"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<path fill="url(#gradient)" d="M35 70H0V0h35q4.4 0 8.2 1.7a21.4 21.4 0 0 1 6.6 4.5q2.9 2.8 4.5 6.6Q56 16.7 56 21a15.4 15.4 0 0 1-.3 3.2 17.6 17.6 0 0 1-.2.8 19.4 19.4 0 0 1-1.5 4 17 17 0 0 1-2.4 3.4 13.5 13.5 0 0 1-2.6 2.3 12.5 12.5 0 0 1-.4.3q1.7 1 3 2.5Q53 39.1 54 41a18.3 18.3 0 0 1 1.5 4 17.4 17.4 0 0 1 .5 3 15.3 15.3 0 0 1 0 1q0 4.4-1.7 8.2a21.4 21.4 0 0 1-4.5 6.6q-2.8 2.9-6.6 4.6Q39.4 70 35 70ZM14 14v14h21a7 7 0 0 0 2.3-.3 6.6 6.6 0 0 0 .4-.2Q39 27 40 26a6.9 6.9 0 0 0 1.5-2.2q.5-1.3.5-2.8a7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 17 40 16a7 7 0 0 0-2.3-1.4 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Zm0 28v14h21a7 7 0 0 0 2.3-.4 6.6 6.6 0 0 0 .4-.1Q39 54.9 40 54a7 7 0 0 0 1.5-2.2 6.9 6.9 0 0 0 .5-2.6 7.9 7.9 0 0 0 0-.2 7 7 0 0 0-.4-2.3 6.6 6.6 0 0 0-.1-.4Q40.9 45 40 44a7 7 0 0 0-2.3-1.5 6.9 6.9 0 0 0-2.5-.6 7.9 7.9 0 0 0-.2 0H14Z"/>
|
||||
${
|
||||
downCount > 0 &&
|
||||
`
|
||||
<circle cx="40" cy="50" r="22" fill="#f00"/>
|
||||
<text x="40" y="60" font-size="34" text-anchor="middle" fill="#fff" font-family="Arial" font-weight="bold">${downCount}</text>
|
||||
`
|
||||
}
|
||||
</svg>
|
||||
`
|
||||
const blob = new Blob([svg], { type: "image/svg+xml" })
|
||||
const url = URL.createObjectURL(blob)
|
||||
;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = url
|
||||
}
|
||||
})()
|
||||
|
||||
export const chartTimeData: ChartTimeData = {
|
||||
"1m": {
|
||||
type: "1m",
|
||||
expectedInterval: 1000,
|
||||
expectedInterval: 2000, // allow a bit of latency for one second updates (#1247)
|
||||
label: () => t`1 minute`,
|
||||
format: (timestamp: string) => hourWithSeconds(timestamp),
|
||||
ticks: 3,
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "إجراءات"
|
||||
msgid "Active"
|
||||
msgstr "نشط"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "التنبيهات النشطة"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "سجل التنبيهات"
|
||||
msgid "Alerts"
|
||||
msgstr "التنبيهات"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "جميع الحاويات"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "تحقق من السجلات لمزيد من التفاصيل."
|
||||
msgid "Check your notification service"
|
||||
msgstr "تحقق من خدمة الإشعارات الخاصة بك"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "انقر على حاوية لعرض مزيد من المعلومات."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "انقر على نظام لعرض مزيد من المعلومات."
|
||||
@@ -289,7 +301,7 @@ msgstr "هيئ التنبيهات الواردة"
|
||||
msgid "Confirm password"
|
||||
msgstr "تأكيد كلمة المرور"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "الاتصال مقطوع"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "انسخ محتوى <0>docker-compose.yml</0> للوكيل أدناه،
|
||||
msgid "Copy YAML"
|
||||
msgstr "نسخ YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "المعالج"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "الحالة الحالية"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "لوحة التحكم"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "حذف"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "حذف البصمة"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "التفاصيل"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "خطأ"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "يتجاوز {0}{1} في آخر {2, plural, one {# دقيقة} other {# دقائق}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "فشل في إرسال إشعار الاختبار"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "فشل في تحديث التنبيه"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "استهلاك طاقة وحدة معالجة الرسوميات"
|
||||
msgid "Grid"
|
||||
msgstr "شبكة"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "الصحة"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "خاملة"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "إذا فقدت كلمة المرور لحساب المسؤول الخاص بك، يمكنك إعادة تعيينها باستخدام الأمر التالي."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "صورة"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "عنوان البريد الإشباكي غير صالح."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "فشل محاولة تسجيل الدخول"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "السجلات"
|
||||
@@ -689,6 +716,7 @@ msgstr "تعليمات الإعداد اليدوي"
|
||||
msgid "Max 1 min"
|
||||
msgstr "الحد الأقصى دقيقة"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "الذاكرة"
|
||||
@@ -704,9 +732,11 @@ msgstr "استخدام الذاكرة لحاويات دوكر"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "الاسم"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "الشبكة"
|
||||
@@ -731,6 +761,7 @@ msgstr "وحدة الشبكة"
|
||||
msgid "No results found."
|
||||
msgstr "لم يتم العثور على نتائج."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "لا توجد نتائج."
|
||||
@@ -772,6 +803,7 @@ msgstr "أو المتابعة باستخدام"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "الكتابة فوق التنبيهات الحالية"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "صفحة"
|
||||
@@ -876,6 +908,11 @@ msgstr "قراءة"
|
||||
msgid "Received"
|
||||
msgstr "تم الاستلام"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "تحديث"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "طلب كلمة مرور لمرة واحدة"
|
||||
@@ -967,6 +1004,7 @@ msgstr "الترتيب حسب"
|
||||
msgid "State"
|
||||
msgstr "الحالة"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "استخدام التبديل"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "قيد التشغيل"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "قيد التشغيل ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "تم التحديث"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "رفع"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Действия"
|
||||
msgid "Active"
|
||||
msgstr "Активен"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Активни тревоги"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "История на нотификациите"
|
||||
msgid "Alerts"
|
||||
msgstr "Тревоги"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Всички контейнери"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Провери log-овете за повече информация."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Провери услугата си за удостоверяване"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Кликнете върху контейнер, за да видите повече информация."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Кликнете върху система, за да видите повече информация."
|
||||
@@ -289,7 +301,7 @@ msgstr "Настрой как получаваш нотификации за т
|
||||
msgid "Confirm password"
|
||||
msgstr "Потвърди парола"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Връзката е прекъсната"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Копирайте съдържанието на<0>docker-compose.yml</0
|
||||
msgid "Copy YAML"
|
||||
msgstr "Копирай YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "Процесор"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Текущо състояние"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Табло"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Изтрий"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Изтрий пръстов отпечатък"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Подробности"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Грешка"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Надвишава {0}{1} в последните {2, plural, one {# минута} other {# минути}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Неуспешно изпрати тестова нотификация"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Неуспешно обнови тревога"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Консумация на ток от графична карта"
|
||||
msgid "Grid"
|
||||
msgstr "Мрежово"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Здраве"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Неактивна"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Ако си загубил паролата до администраторския акаунт, можеш да я нулираш със следващата команда."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Образ"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Невалиден имейл адрес."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Неуспешен опит за вход"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Логове"
|
||||
@@ -689,6 +716,7 @@ msgstr "Инструкции за ръчна настройка"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Максимум 1 минута"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Памет"
|
||||
@@ -704,9 +732,11 @@ msgstr "Използването на памет от docker контейнер
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Име"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Мрежа"
|
||||
@@ -731,6 +761,7 @@ msgstr "Единица за измерване на скорост"
|
||||
msgid "No results found."
|
||||
msgstr "Няма намерени резултати."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Няма резултати."
|
||||
@@ -772,6 +803,7 @@ msgstr "Или продължи с"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Презапиши съществуващи тревоги"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Страница"
|
||||
@@ -876,6 +908,11 @@ msgstr "Прочети"
|
||||
msgid "Received"
|
||||
msgstr "Получени"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Опресни"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Заявка за еднократна парола"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Сортиране по"
|
||||
msgid "State"
|
||||
msgstr "Състояние"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Използване на swap"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Нагоре"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Нагоре ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Актуализирано"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Качване"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Akce"
|
||||
msgid "Active"
|
||||
msgstr "Aktivní"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktivní výstrahy"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Historie upozornění"
|
||||
msgid "Alerts"
|
||||
msgstr "Výstrahy"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Všechny kontejnery"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Pro více informací zkontrolujte logy."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Zkontrolujte službu upozornění"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Klikněte na kontejner pro zobrazení dalších informací."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Klikněte na systém pro zobrazení více informací."
|
||||
@@ -289,7 +301,7 @@ msgstr "Konfigurace způsobu přijímání upozornění."
|
||||
msgid "Confirm password"
|
||||
msgstr "Potvrdit heslo"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Připojení je nedostupné"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Zkopírujte obsah <0>docker-compose.yml</0> pro agenta níže nebo autom
|
||||
msgid "Copy YAML"
|
||||
msgstr "Kopírovat YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "Procesor"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Aktuální stav"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Přehled"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Odstranit"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Smazat identifikátor"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detail"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Chyba"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Překračuje {0}{1} za {2, plural, one {poslední # minutu} few {poslední # minuty} other {posledních # minut}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Nepodařilo se odeslat testovací oznámení"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Nepodařilo se aktualizovat upozornění"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Spotřeba energie GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Mřížka"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Zdraví"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Neaktivní"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Pokud jste ztratili heslo k vašemu účtu správce, můžete jej obnovit pomocí následujícího příkazu."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Obraz"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Neplatná e-mailová adresa."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Pokus o přihlášení selhal"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logy"
|
||||
@@ -689,6 +716,7 @@ msgstr "Pokyny k manuálnímu nastavení"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Max. 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Paměť"
|
||||
@@ -704,9 +732,11 @@ msgstr "Využití paměti docker kontejnerů"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Název"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Síť"
|
||||
@@ -731,6 +761,7 @@ msgstr "Síťová jednotka"
|
||||
msgid "No results found."
|
||||
msgstr "Nenalezeny žádné výskyty."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Žádné výsledky."
|
||||
@@ -772,6 +803,7 @@ msgstr "Nebo pokračujte s"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Přepsat existující upozornění"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Stránka"
|
||||
@@ -876,6 +908,11 @@ msgstr "Číst"
|
||||
msgid "Received"
|
||||
msgstr "Přijato"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Aktualizovat"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Požádat o jednorázové heslo"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Seřadit podle"
|
||||
msgid "State"
|
||||
msgstr "Stav"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap využití"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Funkční"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Funkční ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Aktualizováno"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Odeslání"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Handlinger"
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktive Alarmer"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr ""
|
||||
msgid "Alerts"
|
||||
msgstr "Alarmer"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alle containere"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Tjek logfiler for flere detaljer."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Tjek din notifikationstjeneste"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Klik på en container for at se mere information."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr ""
|
||||
@@ -289,7 +301,7 @@ msgstr "Konfigurer hvordan du modtager advarselsmeddelelser."
|
||||
msgid "Confirm password"
|
||||
msgstr "Bekræft adgangskode"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr ""
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr ""
|
||||
msgid "Copy YAML"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Nuværende tilstand"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Oversigtspanel"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Slet"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detalje"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Fejl"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Overskrider {0}{1} i sidste {2, plural, one {# minut} other {# minutter}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Afsendelse af testnotifikation mislykkedes"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Kunne ikke opdatere alarm"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Gpu Strøm Træk"
|
||||
msgid "Grid"
|
||||
msgstr "Gitter"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Sundhed"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Inaktiv"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Hvis du har mistet adgangskoden til din administratorkonto, kan du nulstille den ved hjælp af følgende kommando."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ugyldig email adresse."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Loginforsøg mislykkedes"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
@@ -689,6 +716,7 @@ msgstr "Manuel opsætningsvejledning"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Maks. 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Hukommelse"
|
||||
@@ -704,9 +732,11 @@ msgstr "Hukommelsesforbrug af dockercontainere"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Navn"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Net"
|
||||
@@ -731,6 +761,7 @@ msgstr ""
|
||||
msgid "No results found."
|
||||
msgstr "Ingen resultater fundet."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
@@ -772,6 +803,7 @@ msgstr "Eller fortsæt med"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Overskriv eksisterende alarmer"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Side"
|
||||
@@ -876,6 +908,11 @@ msgstr "Læs"
|
||||
msgid "Received"
|
||||
msgstr "Modtaget"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Opdater"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Anmod om engangsadgangskode"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Sorter efter"
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap forbrug"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Oppe"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Opdateret"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Upload"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Aktionen"
|
||||
msgid "Active"
|
||||
msgstr "Aktiv"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktive Warnungen"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Alarm-Verlauf"
|
||||
msgid "Alerts"
|
||||
msgstr "Warnungen"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alle Container"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Überprüfe die Protokolle für weitere Details."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Überprüfe deinen Benachrichtigungsdienst"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Klicken Sie auf einen Container, um weitere Informationen zu sehen."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Klicke auf ein System, um weitere Informationen zu sehen."
|
||||
@@ -289,7 +301,7 @@ msgstr "Konfiguriere, wie du Warnbenachrichtigungen erhältst."
|
||||
msgid "Confirm password"
|
||||
msgstr "Passwort bestätigen"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Verbindung unterbrochen"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Kopieren Sie den<0>docker-compose.yml</0> Inhalt für den Agent unten od
|
||||
msgid "Copy YAML"
|
||||
msgstr "YAML kopieren"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Aktueller Zustand"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashboard"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Löschen"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Fingerabdruck löschen"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detail"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Fehler"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Überschreitet {0}{1} in den letzten {2, plural, one {# Minute} other {# Minuten}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Testbenachrichtigung konnte nicht gesendet werden"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Warnung konnte nicht aktualisiert werden"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU-Leistungsaufnahme"
|
||||
msgid "Grid"
|
||||
msgstr "Raster"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Gesundheit"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Untätig"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Wenn du das Passwort für dein Administratorkonto verloren hast, kannst du es mit dem folgenden Befehl zurücksetzen."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ungültige E-Mail-Adresse."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Anmeldeversuch fehlgeschlagen"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Protokolle"
|
||||
@@ -689,6 +716,7 @@ msgstr "Anleitung zur manuellen Einrichtung"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Max 1 Min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Arbeitsspeicher"
|
||||
@@ -704,9 +732,11 @@ msgstr "Arbeitsspeichernutzung der Docker-Container"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Netz"
|
||||
@@ -731,6 +761,7 @@ msgstr "Netzwerkeinheit"
|
||||
msgid "No results found."
|
||||
msgstr "Keine Ergebnisse gefunden."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Keine Ergebnisse."
|
||||
@@ -772,6 +803,7 @@ msgstr "Oder fortfahren mit"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Bestehende Warnungen überschreiben"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Seite"
|
||||
@@ -876,6 +908,11 @@ msgstr "Lesen"
|
||||
msgid "Received"
|
||||
msgstr "Empfangen"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Aktualisieren"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Einmalpasswort anfordern"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Sortieren nach"
|
||||
msgid "State"
|
||||
msgstr "Status"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap-Nutzung"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "aktiv"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "aktiv ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Aktualisiert"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Hochladen"
|
||||
|
||||
@@ -84,7 +84,7 @@ msgstr "Actions"
|
||||
msgid "Active"
|
||||
msgstr "Active"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Active Alerts"
|
||||
|
||||
@@ -128,7 +128,15 @@ msgstr "Alert History"
|
||||
msgid "Alerts"
|
||||
msgstr "Alerts"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "All Containers"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -262,6 +270,10 @@ msgstr "Check logs for more details."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Check your notification service"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Click on a container to view more information."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Click on a system to view more information."
|
||||
@@ -284,7 +296,7 @@ msgstr "Configure how you receive alert notifications."
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirm password"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Connection is down"
|
||||
|
||||
@@ -343,6 +355,7 @@ msgstr "Copy the<0>docker-compose.yml</0> content for the agent below, or regist
|
||||
msgid "Copy YAML"
|
||||
msgstr "Copy YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -380,7 +393,6 @@ msgid "Current state"
|
||||
msgstr "Current state"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashboard"
|
||||
|
||||
@@ -397,6 +409,10 @@ msgstr "Delete"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Delete fingerprint"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detail"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -503,7 +519,7 @@ msgstr "Error"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
|
||||
@@ -544,6 +560,7 @@ msgstr "Failed to send test notification"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Failed to update alert"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -591,6 +608,10 @@ msgstr "GPU Power Draw"
|
||||
msgid "Grid"
|
||||
msgstr "Grid"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Health"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -610,6 +631,11 @@ msgstr "Idle"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Invalid email address."
|
||||
@@ -662,6 +688,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Login attempt failed"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
@@ -684,6 +711,7 @@ msgstr "Manual setup instructions"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Max 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Memory"
|
||||
@@ -699,9 +727,11 @@ msgstr "Memory usage of docker containers"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Name"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Net"
|
||||
@@ -726,6 +756,7 @@ msgstr "Network unit"
|
||||
msgid "No results found."
|
||||
msgstr "No results found."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "No results."
|
||||
@@ -767,6 +798,7 @@ msgstr "Or continue with"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Overwrite existing alerts"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Page"
|
||||
@@ -871,6 +903,11 @@ msgstr "Read"
|
||||
msgid "Received"
|
||||
msgstr "Received"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Refresh"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Request a one-time password"
|
||||
@@ -962,6 +999,7 @@ msgstr "Sort By"
|
||||
msgid "State"
|
||||
msgstr "State"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -976,6 +1014,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap Usage"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1149,6 +1188,10 @@ msgstr "Up"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Up ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Updated"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Upload"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Acciones"
|
||||
msgid "Active"
|
||||
msgstr "Activo"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Alertas Activas"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Historial de Alertas"
|
||||
msgid "Alerts"
|
||||
msgstr "Alertas"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Todos los contenedores"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Revise los registros para más detalles."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Verifique su servicio de notificaciones"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Haga clic en un contenedor para ver más información."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Haga clic en un sistema para ver más información."
|
||||
@@ -289,7 +301,7 @@ msgstr "Configure cómo recibe las notificaciones de alertas."
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirmar contraseña"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "La conexión está caída"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Copia el contenido del<0>docker-compose.yml</0> para el agente a continu
|
||||
msgid "Copy YAML"
|
||||
msgstr "Copiar YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Estado actual"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Tablero"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Eliminar"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Eliminar huella digital"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detalle"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Error"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Excede {0}{1} en el último {2, plural, one {# minuto} other {# minutos}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Error al enviar la notificación de prueba"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Error al actualizar la alerta"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Consumo de energía de la GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Cuadrícula"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Estado"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Inactiva"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Si ha perdido la contraseña de su cuenta de administrador, puede restablecerla usando el siguiente comando."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Imagen"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Dirección de correo electrónico no válida."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Intento de inicio de sesión fallido"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Registros"
|
||||
@@ -689,6 +716,7 @@ msgstr "Instrucciones manuales de configuración"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Máx 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Memoria"
|
||||
@@ -704,9 +732,11 @@ msgstr "Uso de memoria de los contenedores de Docker"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Nombre"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Red"
|
||||
@@ -731,6 +761,7 @@ msgstr "Unidad de red"
|
||||
msgid "No results found."
|
||||
msgstr "No se encontraron resultados."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Sin resultados."
|
||||
@@ -772,6 +803,7 @@ msgstr "O continuar con"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Sobrescribir alertas existentes"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Página"
|
||||
@@ -876,6 +908,11 @@ msgstr "Lectura"
|
||||
msgid "Received"
|
||||
msgstr "Recibido"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Actualizar"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Solicitar contraseña de un solo uso"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Ordenar por"
|
||||
msgid "State"
|
||||
msgstr "Estado"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Uso de Swap"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Activo"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Activo ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Actualizado"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Cargar"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "عملیات"
|
||||
msgid "Active"
|
||||
msgstr "فعال"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr " هشدارهای فعال"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "تاریخچه هشدارها"
|
||||
msgid "Alerts"
|
||||
msgstr "هشدارها"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "همه کانتینرها"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "برای جزئیات بیشتر، لاگها را بررسی کنی
|
||||
msgid "Check your notification service"
|
||||
msgstr "سرویس اطلاعرسانی خود را بررسی کنید"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "برای مشاهده اطلاعات بیشتر روی کانتینر کلیک کنید."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "برای مشاهده اطلاعات بیشتر روی یک سیستم کلیک کنید."
|
||||
@@ -289,7 +301,7 @@ msgstr "نحوه دریافت هشدارهای اطلاعرسانی را پی
|
||||
msgid "Confirm password"
|
||||
msgstr "تأیید رمز عبور"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "اتصال قطع است"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "محتوای <0>docker-compose.yml</0> عامل زیر را کپی کن
|
||||
msgid "Copy YAML"
|
||||
msgstr "کپی YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "پردازنده"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "وضعیت فعلی"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "داشبورد"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "حذف"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "حذف اثر انگشت"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "جزئیات"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "خطا"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "در {2, plural, one {# دقیقه} other {# دقیقه}} گذشته از {0}{1} بیشتر است"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "ارسال اعلان آزمایشی ناموفق بود"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "بهروزرسانی هشدار ناموفق بود"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "مصرف برق پردازنده گرافیکی"
|
||||
msgid "Grid"
|
||||
msgstr "جدول"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "سلامتی"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "بیکار"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "اگر رمز عبور حساب مدیر خود را گم کردهاید، میتوانید آن را با استفاده از دستور زیر بازنشانی کنید."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "تصویر"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "آدرس ایمیل نامعتبر است."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "تلاش برای ورود ناموفق بود"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "لاگها"
|
||||
@@ -689,6 +716,7 @@ msgstr "دستورالعملهای راهاندازی دستی"
|
||||
msgid "Max 1 min"
|
||||
msgstr "حداکثر ۱ دقیقه"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "حافظه"
|
||||
@@ -704,9 +732,11 @@ msgstr "میزان استفاده از حافظه کانتینرهای داکر"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "نام"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "شبکه"
|
||||
@@ -731,6 +761,7 @@ msgstr "واحد شبکه"
|
||||
msgid "No results found."
|
||||
msgstr "هیچ نتیجهای یافت نشد."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "نتیجهای یافت نشد."
|
||||
@@ -772,6 +803,7 @@ msgstr "یا ادامه با"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "بازنویسی هشدارهای موجود"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "صفحه"
|
||||
@@ -876,6 +908,11 @@ msgstr "خواندن"
|
||||
msgid "Received"
|
||||
msgstr "دریافت شد"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "تازهسازی"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "درخواست رمز عبور یکبار مصرف"
|
||||
@@ -967,6 +1004,7 @@ msgstr "مرتبسازی بر اساس"
|
||||
msgid "State"
|
||||
msgstr "وضعیت"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "میزان استفاده از Swap"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "فعال"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "فعال ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "بهروزرسانی شد"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "آپلود"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: fr\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-08-28 23:21\n"
|
||||
"PO-Revision-Date: 2025-10-20 16:38\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: French\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n > 1);\n"
|
||||
@@ -31,13 +31,13 @@ msgstr "{0, plural, one {# heure} other {# heures}}"
|
||||
#. 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 ""
|
||||
msgstr "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
|
||||
|
||||
#. 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 ""
|
||||
msgstr "{0} sur {1} ligne(s) sélectionnée(s)."
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 hour"
|
||||
@@ -46,7 +46,7 @@ msgstr "1 heure"
|
||||
#. Load average
|
||||
#: src/components/charts/load-average-chart.tsx
|
||||
msgid "1 min"
|
||||
msgstr ""
|
||||
msgstr "1 min"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 minute"
|
||||
@@ -63,7 +63,7 @@ msgstr "12 heures"
|
||||
#. 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 +76,7 @@ msgstr "30 jours"
|
||||
#. 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
|
||||
@@ -87,9 +87,9 @@ msgstr "Actions"
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
msgstr "Active"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Alertes actives"
|
||||
|
||||
@@ -126,14 +126,22 @@ msgstr "Agent"
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Alert History"
|
||||
msgstr ""
|
||||
msgstr "Historique des alertes"
|
||||
|
||||
#: src/components/alerts/alert-button.tsx
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Alerts"
|
||||
msgstr "Alertes"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Tous les conteneurs"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -145,7 +153,7 @@ msgstr "Êtes-vous sûr de vouloir supprimer {name} ?"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Are you sure?"
|
||||
msgstr ""
|
||||
msgstr "Êtes-vous sûr ?"
|
||||
|
||||
#: src/components/copy-to-clipboard.tsx
|
||||
msgid "Automatic copy requires a secure context."
|
||||
@@ -210,12 +218,12 @@ msgstr "Binaire"
|
||||
#: 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,11 +240,11 @@ msgstr "Attention - perte de données potentielle"
|
||||
|
||||
#: 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."
|
||||
msgstr ""
|
||||
msgstr "Ajuster les unités d'affichage pour les métriques."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Change general application options."
|
||||
@@ -267,9 +275,13 @@ msgstr "Vérifiez les journaux pour plus de détails."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Vérifiez votre service de notification"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Cliquez sur un conteneur pour voir plus d'informations."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr ""
|
||||
msgstr "Cliquez sur un système pour voir plus d'informations."
|
||||
|
||||
#: src/components/ui/input-copy.tsx
|
||||
msgid "Click to copy"
|
||||
@@ -289,9 +301,9 @@ msgstr "Configurez comment vous recevez les notifications d'alerte."
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirmer le mot de passe"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr ""
|
||||
msgstr "Connexion interrompue"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
@@ -348,6 +360,7 @@ msgstr "Copiez le contenu du<0>docker-compose.yml</0> pour l'agent ci-dessous, o
|
||||
msgid "Copy YAML"
|
||||
msgstr "Copier YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -365,7 +378,7 @@ msgstr "Créer un compte"
|
||||
#. Context: date created
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Created"
|
||||
msgstr ""
|
||||
msgstr "Date de création"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Critical (%)"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "État actuel"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Tableau de bord"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Supprimer"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Supprimer l'empreinte"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Détail"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -417,7 +433,7 @@ msgstr "Entrée/Sortie disque"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Disk unit"
|
||||
msgstr ""
|
||||
msgstr "Unité disque"
|
||||
|
||||
#: src/components/charts/disk-chart.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -455,7 +471,7 @@ msgstr "Injoignable"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Down ({downSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Injoignable ({downSystemsLength})"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Download"
|
||||
@@ -463,7 +479,7 @@ msgstr "Télécharger"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Duration"
|
||||
msgstr ""
|
||||
msgstr "Durée"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
@@ -508,7 +524,7 @@ msgstr "Erreur"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Dépasse {0}{1} dans {2, plural, one {la dernière # minute} other {les dernières # minutes}}"
|
||||
|
||||
@@ -518,7 +534,7 @@ msgstr "Les systèmes existants non définis dans <0>config.yml</0> seront suppr
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Export"
|
||||
msgstr ""
|
||||
msgstr "Exporter"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Export configuration"
|
||||
@@ -530,7 +546,7 @@ msgstr "Exportez la configuration actuelle de vos systèmes."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Fahrenheit (°F)"
|
||||
msgstr ""
|
||||
msgstr "Fahrenheit (°F)"
|
||||
|
||||
#: src/lib/api.ts
|
||||
msgid "Failed to authenticate"
|
||||
@@ -549,6 +565,7 @@ msgstr "Échec de l'envoi de la notification de test"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Échec de la mise à jour de l'alerte"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -557,7 +574,7 @@ msgstr "Filtrer..."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Fingerprint"
|
||||
msgstr ""
|
||||
msgstr "Empreinte"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
|
||||
@@ -596,6 +613,10 @@ msgstr "Consommation du GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Grille"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Santé"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Inactive"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Si vous avez perdu le mot de passe de votre compte administrateur, vous pouvez le réinitialiser en utilisant la commande suivante."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Adresse email invalide."
|
||||
@@ -634,24 +660,24 @@ msgstr "Disposition"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Load Average"
|
||||
msgstr ""
|
||||
msgstr "Charge moyenne"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 15m"
|
||||
msgstr ""
|
||||
msgstr "Charge moyenne 15m"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 1m"
|
||||
msgstr ""
|
||||
msgstr "Charge moyenne 1m"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 5m"
|
||||
msgstr ""
|
||||
msgstr "Charge moyenne 5m"
|
||||
|
||||
#. Short label for load average
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Load Avg"
|
||||
msgstr ""
|
||||
msgstr "Charge moy."
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Log Out"
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Échec de la tentative de connexion"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Journaux"
|
||||
@@ -689,6 +716,7 @@ msgstr "Guide pour une installation manuelle"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Max 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Mémoire"
|
||||
@@ -704,9 +732,11 @@ msgstr "Utilisation de la mémoire des conteneurs Docker"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Nom"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Net"
|
||||
@@ -725,15 +755,16 @@ msgstr "Trafic réseau des interfaces publiques"
|
||||
#. Context: Bytes or bits
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Network unit"
|
||||
msgstr ""
|
||||
msgstr "Unité réseau"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "No results found."
|
||||
msgstr "Aucun résultat trouvé."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
msgstr "Aucun résultat."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -772,6 +803,7 @@ msgstr "Ou continuer avec"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Écraser les alertes existantes"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Page"
|
||||
@@ -780,7 +812,7 @@ msgstr "Page"
|
||||
#. placeholder {1}: table.getPageCount()
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Page {0} of {1}"
|
||||
msgstr ""
|
||||
msgstr "Page {0} sur {1}"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Pages / Settings"
|
||||
@@ -813,7 +845,7 @@ msgstr "En pause"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Paused ({pausedSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Mis en pause ({pausedSystemsLength})"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
|
||||
@@ -876,6 +908,11 @@ msgstr "Lecture"
|
||||
msgid "Received"
|
||||
msgstr "Reçu"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Actualiser"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Demander un mot de passe à usage unique"
|
||||
@@ -892,7 +929,7 @@ msgstr "Réinitialiser le mot de passe"
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Resolved"
|
||||
msgstr ""
|
||||
msgstr "Résolue"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Resume"
|
||||
@@ -904,7 +941,7 @@ msgstr "Faire tourner le token"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Rows per page"
|
||||
msgstr ""
|
||||
msgstr "Lignes par page"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Save address using enter key or comma. Leave blank to disable email notifications."
|
||||
@@ -965,8 +1002,9 @@ msgstr "Trier par"
|
||||
#. Context: alert state (active or resolved)
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
msgstr "État"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Utilisation du swap"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -989,7 +1028,7 @@ msgstr "Système"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "System load averages over time"
|
||||
msgstr ""
|
||||
msgstr "Charges moyennes du système dans le temps"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Systems"
|
||||
@@ -1039,7 +1078,7 @@ msgstr "Cette action ne peut pas être annulée. Cela supprimera définitivement
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "This will permanently delete all selected records from the database."
|
||||
msgstr ""
|
||||
msgstr "Ceci supprimera définitivement tous les enregistrements sélectionnés de la base de données."
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Throughput of {extraFsName}"
|
||||
@@ -1069,7 +1108,7 @@ msgstr "Changer le thème"
|
||||
#: 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
|
||||
@@ -1099,11 +1138,11 @@ msgstr ""
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 15 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Se déclenche lorsque la charge moyenne sur 15 minute dépasse un seuil"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 5 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Se déclenche lorsque la charge moyenne sur 5 minute dépasse un seuil"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when any sensor exceeds a threshold"
|
||||
@@ -1132,7 +1171,7 @@ msgstr "Déclenchement lorsque l'utilisation de tout disque dépasse un seuil"
|
||||
#. Temperature / network units
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Unit preferences"
|
||||
msgstr ""
|
||||
msgstr "Préférences des unités"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
@@ -1152,7 +1191,11 @@ msgstr "Joignable"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Joignable ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Mis à jour"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
@@ -1185,7 +1228,7 @@ msgstr "Utilisateurs"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
msgstr "Valeur"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "View"
|
||||
@@ -1197,7 +1240,7 @@ msgstr "Voir plus"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "View your 200 most recent alerts."
|
||||
msgstr ""
|
||||
msgstr "Voir vos 200 dernières alertes."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Visible Fields"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: hr\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-09-23 12:43\n"
|
||||
"PO-Revision-Date: 2025-10-18 23:59\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"
|
||||
@@ -31,13 +31,13 @@ msgstr "{0, plural, one {# sat} other {# sati}}"
|
||||
#. 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 ""
|
||||
msgstr "{0, plural, one {# minuta} few {# minuta} many {# minuta} other {# minute}}"
|
||||
|
||||
#. 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 ""
|
||||
msgstr "{0} od {1} redaka izabrano."
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 hour"
|
||||
@@ -76,7 +76,7 @@ msgstr "30 dana"
|
||||
#. Load average
|
||||
#: src/components/charts/load-average-chart.tsx
|
||||
msgid "5 min"
|
||||
msgstr ""
|
||||
msgstr "5 minuta"
|
||||
|
||||
#. Table column
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
@@ -89,7 +89,7 @@ msgstr "Akcije"
|
||||
msgid "Active"
|
||||
msgstr "Aktivan"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktivna upozorenja"
|
||||
|
||||
@@ -126,14 +126,22 @@ msgstr "Agent"
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Alert History"
|
||||
msgstr ""
|
||||
msgstr "Povijest Upozorenja"
|
||||
|
||||
#: src/components/alerts/alert-button.tsx
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Alerts"
|
||||
msgstr "Upozorenja"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Svi spremnici"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -166,7 +174,7 @@ msgstr "Prosjek premašuje <0>{value}{0}</0>"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average power consumption of GPUs"
|
||||
msgstr ""
|
||||
msgstr "Prosječna potrošnja energije grafičkog procesora"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average system-wide CPU utilization"
|
||||
@@ -175,7 +183,7 @@ msgstr "Prosječna iskorištenost procesora na cijelom sustavu"
|
||||
#. placeholder {0}: gpu.n
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average utilization of {0}"
|
||||
msgstr ""
|
||||
msgstr "Prosječna iskorištenost {0}"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Average utilization of GPU engines"
|
||||
@@ -210,12 +218,12 @@ msgstr "Binarni"
|
||||
#: src/components/routes/settings/general.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Bits (Kbps, Mbps, Gbps)"
|
||||
msgstr ""
|
||||
msgstr "Bitovi (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 "Bajtovi (KB/s, MB/s, GB/s)"
|
||||
|
||||
#: src/components/charts/mem-chart.tsx
|
||||
msgid "Cache / Buffers"
|
||||
@@ -232,11 +240,11 @@ msgstr "Oprez - mogući gubitak podataka"
|
||||
|
||||
#: 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."
|
||||
msgstr ""
|
||||
msgstr "Promijenite mjerene jedinice korištene za prikazivanje podataka."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Change general application options."
|
||||
@@ -267,9 +275,13 @@ msgstr "Provjerite logove za više detalja."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Provjerite Vaš servis notifikacija"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Kliknite na spremnik za prikaz više informacija."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr ""
|
||||
msgstr "Odaberite sustav za prikaz više informacija."
|
||||
|
||||
#: src/components/ui/input-copy.tsx
|
||||
msgid "Click to copy"
|
||||
@@ -289,9 +301,9 @@ msgstr "Konfigurirajte način primanja obavijesti upozorenja."
|
||||
msgid "Confirm password"
|
||||
msgstr "Potvrdite lozinku"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr ""
|
||||
msgstr "Veza je pala"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
@@ -338,16 +350,17 @@ msgstr "Kopiraj 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 ""
|
||||
msgstr "Kopirajte instalacijsku komandu za opisanog agenta ili automatski registrirajte agenta uz pomoć <0>sveopćeg tokena</0>."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>."
|
||||
msgstr ""
|
||||
msgstr "Kopirajte sadržaj <0>docker-compose.yml</0> datoteke za opisanog agenta ili automatski registrirajte agenta uz pomoć <1>sveopćeg tokena</1>."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Copy YAML"
|
||||
msgstr ""
|
||||
msgstr "Kopiraj YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "Procesor"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Trenutno stanje"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Nadzorna ploča"
|
||||
|
||||
@@ -400,7 +412,11 @@ msgstr "Izbriši"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Delete fingerprint"
|
||||
msgstr ""
|
||||
msgstr "Izbriši otisak"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detalj"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -417,7 +433,7 @@ msgstr "Disk I/O"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Disk unit"
|
||||
msgstr ""
|
||||
msgstr "Mjerna jedinica za disk"
|
||||
|
||||
#: src/components/charts/disk-chart.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -451,11 +467,11 @@ msgstr "Dokumentacija"
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Down"
|
||||
msgstr ""
|
||||
msgstr "Sustav je pao"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Down ({downSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Sustav je pao ({downSystemsLength})"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Download"
|
||||
@@ -508,7 +524,7 @@ msgstr "Greška"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Premašuje {0}{1} u posljednjih {2, plural, one {# minuta} other {# minute}}"
|
||||
|
||||
@@ -530,7 +546,7 @@ msgstr "Izvoz trenutne sistemske konfiguracije."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Fahrenheit (°F)"
|
||||
msgstr ""
|
||||
msgstr "Farenhajt (°F)"
|
||||
|
||||
#: src/lib/api.ts
|
||||
msgid "Failed to authenticate"
|
||||
@@ -549,6 +565,7 @@ msgstr "Neuspješno slanje testne notifikacije"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Ažuriranje upozorenja nije uspjelo"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -590,12 +607,16 @@ msgstr "GPU motori"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "GPU Power Draw"
|
||||
msgstr ""
|
||||
msgstr "Energetska potrošnja grafičkog procesora"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Grid"
|
||||
msgstr "Mreža"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Zdravlje"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Neaktivna"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Ako ste izgubili lozinku za svoj administratorski račun, možete ju resetirati pomoću sljedeće naredbe."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Slika"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Nevažeća adresa e-pošte."
|
||||
@@ -622,7 +648,7 @@ msgstr "Nevažeća adresa e-pošte."
|
||||
#. Linux kernel
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Kernel"
|
||||
msgstr "Kernel"
|
||||
msgstr "Jezgra"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Language"
|
||||
@@ -634,19 +660,19 @@ msgstr "Izgled"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Load Average"
|
||||
msgstr ""
|
||||
msgstr "Prosječno Opterećenje"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 15m"
|
||||
msgstr ""
|
||||
msgstr "Prosječno Opterećenje 15m"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 1m"
|
||||
msgstr ""
|
||||
msgstr "Prosječno Opterećenje 1m"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 5m"
|
||||
msgstr ""
|
||||
msgstr "Prosječno Opterećenje 5m"
|
||||
|
||||
#. Short label for load average
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Pokušaj prijave nije uspio"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logovi"
|
||||
@@ -682,13 +709,14 @@ msgstr "Upravljajte postavkama prikaza i obavijesti."
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Manual setup instructions"
|
||||
msgstr ""
|
||||
msgstr "Upute za ručno postavljanje"
|
||||
|
||||
#. Chart select field. Please try to keep this short.
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Max 1 min"
|
||||
msgstr "Maksimalno 1 minuta"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Memorija"
|
||||
@@ -704,9 +732,11 @@ msgstr "Upotreba memorije Docker spremnika"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Ime"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Mreža"
|
||||
@@ -725,12 +755,13 @@ msgstr "Mrežni promet javnih sučelja"
|
||||
#. Context: Bytes or bits
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Network unit"
|
||||
msgstr ""
|
||||
msgstr "Mjerna jedinica za mrežu"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "No results found."
|
||||
msgstr "Nema rezultata."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Nema rezultata."
|
||||
@@ -772,6 +803,7 @@ msgstr "Ili nastavi sa"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Prebrišite postojeća upozorenja"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Stranica"
|
||||
@@ -876,6 +908,11 @@ msgstr "Pročitaj"
|
||||
msgid "Received"
|
||||
msgstr "Primljeno"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Osvježi"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Zatraži jednokratnu lozinku"
|
||||
@@ -892,7 +929,7 @@ msgstr "Resetiraj Lozinku"
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Resolved"
|
||||
msgstr ""
|
||||
msgstr "Razrješeno"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Resume"
|
||||
@@ -900,11 +937,11 @@ msgstr "Nastavi"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Rotate token"
|
||||
msgstr ""
|
||||
msgstr "Promijeni token"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Rows per page"
|
||||
msgstr ""
|
||||
msgstr "Redovi po stranici"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Save address using enter key or comma. Leave blank to disable email notifications."
|
||||
@@ -917,7 +954,7 @@ msgstr "Spremi Postavke"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Save system"
|
||||
msgstr ""
|
||||
msgstr "Spremi sustav"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Search"
|
||||
@@ -965,8 +1002,9 @@ msgstr "Sortiraj po"
|
||||
#. Context: alert state (active or resolved)
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
msgstr "Stanje"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap Iskorištenost"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -989,7 +1028,7 @@ msgstr "Sistem"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "System load averages over time"
|
||||
msgstr ""
|
||||
msgstr "Prosječno opterećenje sustava kroz vrijeme"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Systems"
|
||||
@@ -1006,7 +1045,7 @@ msgstr "Tablica"
|
||||
#. 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
|
||||
@@ -1015,7 +1054,7 @@ msgstr "Temperatura"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Temperature unit"
|
||||
msgstr ""
|
||||
msgstr "Mjerna jedinica za temperaturu"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Temperatures of system sensors"
|
||||
@@ -1039,7 +1078,7 @@ msgstr "Ova radnja se ne može poništiti. Ovo će trajno izbrisati sve trenutne
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "This will permanently delete all selected records from the database."
|
||||
msgstr ""
|
||||
msgstr "Ovom radnjom će se trajno izbrisati svi odabrani zapisi iz baze podataka."
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Throughput of {extraFsName}"
|
||||
@@ -1069,21 +1108,21 @@ msgstr "Uključi/isključi temu"
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Token"
|
||||
msgstr ""
|
||||
msgstr "Token"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens & Fingerprints"
|
||||
msgstr ""
|
||||
msgstr "Tokeni & Otisci"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens allow agents to connect and register. Fingerprints are stable identifiers unique to each system, set on first connection."
|
||||
msgstr ""
|
||||
msgstr "Tokeni dopuštaju agentima prijavu i registraciju. Otisci su stabilni identifikatori jedinstveni svakom sustavu, koji se postavljaju prilikom prvog spajanja."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
|
||||
msgstr ""
|
||||
msgstr "Tokeni se uz otiske koriste za autentifikaciju WebSocket veza prema središnjoj kontroli."
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Total data received for each interface"
|
||||
@@ -1095,15 +1134,15 @@ msgstr "Ukupni podaci poslani za svako sučelje"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 1 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Pokreće se kada prosječna opterećenost sustava unutar 1 minute prijeđe prag"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 15 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Pokreće se kada prosječna opterećenost sustava unutar 15 minuta prijeđe prag"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 5 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Pokreće se kada prosječna opterećenost sustava unutar 5 minuta prijeđe prag"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when any sensor exceeds a threshold"
|
||||
@@ -1132,12 +1171,12 @@ msgstr "Pokreće se kada iskorištenost bilo kojeg diska premaši prag"
|
||||
#. Temperature / network units
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Unit preferences"
|
||||
msgstr ""
|
||||
msgstr "Opcije mjernih jedinica"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Universal token"
|
||||
msgstr ""
|
||||
msgstr "Sveopći token"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -1148,11 +1187,15 @@ msgstr "Nepoznata"
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Up"
|
||||
msgstr ""
|
||||
msgstr "Sustav je podignut"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Sustav je podignut ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Ažurirano"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
@@ -1197,7 +1240,7 @@ msgstr "Prikaži više"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "View your 200 most recent alerts."
|
||||
msgstr ""
|
||||
msgstr "Pogledajte posljednjih 200 upozorenja."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Visible Fields"
|
||||
@@ -1225,7 +1268,7 @@ msgstr "Webhook / Push obavijest"
|
||||
|
||||
#: 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 ""
|
||||
msgstr "Kada je podešen, ovaj token dopušta agentima da se prijave bez prvobitnog stvaranja sustava. Ističe nakon jednog sata ili ponovnog pokretanja središnje kontrole."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
|
||||
@@ -8,15 +8,15 @@ msgstr ""
|
||||
"Language: hu\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-08-28 23:21\n"
|
||||
"PO-Revision-Date: 2025-10-14 23:40\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/beszel/site/src/locales/en/en.po\n"
|
||||
"X-Crowdin-File-ID: 16\n"
|
||||
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
|
||||
"X-Crowdin-File-ID: 32\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 ""
|
||||
msgstr "{0, plural, one {# perc} few {# perc} many {# perc} other {# perc}}"
|
||||
|
||||
#. 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 ""
|
||||
msgstr "{0} a(z) {1} sorból kiválasztva."
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 hour"
|
||||
@@ -46,7 +46,7 @@ msgstr "1 óra"
|
||||
#. Load average
|
||||
#: src/components/charts/load-average-chart.tsx
|
||||
msgid "1 min"
|
||||
msgstr ""
|
||||
msgstr "1 perc"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 minute"
|
||||
@@ -63,7 +63,7 @@ msgstr "12 óra"
|
||||
#. Load average
|
||||
#: src/components/charts/load-average-chart.tsx
|
||||
msgid "15 min"
|
||||
msgstr ""
|
||||
msgstr "15 perc"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "24 hours"
|
||||
@@ -76,7 +76,7 @@ msgstr "30 nap"
|
||||
#. Load average
|
||||
#: src/components/charts/load-average-chart.tsx
|
||||
msgid "5 min"
|
||||
msgstr ""
|
||||
msgstr "5 perc"
|
||||
|
||||
#. Table column
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
@@ -87,9 +87,9 @@ msgstr "Műveletek"
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
msgstr "Aktív"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktív riasztások"
|
||||
|
||||
@@ -116,7 +116,7 @@ msgstr "Állítsa be a diagram megjelenítését."
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Admin"
|
||||
msgstr "Admin"
|
||||
msgstr "Adminisztráció"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Agent"
|
||||
@@ -126,14 +126,22 @@ msgstr "Ügynök"
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Alert History"
|
||||
msgstr ""
|
||||
msgstr "Riasztási előzmények"
|
||||
|
||||
#: src/components/alerts/alert-button.tsx
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Alerts"
|
||||
msgstr "Riasztások"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Összes konténer"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -145,7 +153,7 @@ msgstr "Biztosan törölni szeretnéd {name}-t?"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Are you sure?"
|
||||
msgstr ""
|
||||
msgstr "Biztos vagy benne?"
|
||||
|
||||
#: src/components/copy-to-clipboard.tsx
|
||||
msgid "Automatic copy requires a secure context."
|
||||
@@ -210,12 +218,12 @@ msgstr "Bináris"
|
||||
#: src/components/routes/settings/general.tsx
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Bits (Kbps, Mbps, Gbps)"
|
||||
msgstr ""
|
||||
msgstr "Bitek (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 "Byte-ok (KB/s, MB/s, GB/s)"
|
||||
|
||||
#: src/components/charts/mem-chart.tsx
|
||||
msgid "Cache / Buffers"
|
||||
@@ -232,11 +240,11 @@ msgstr "Figyelem - potenciális adatvesztés"
|
||||
|
||||
#: 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."
|
||||
msgstr ""
|
||||
msgstr "A mértékegységek megjelenítésének megváltoztatása."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Change general application options."
|
||||
@@ -267,9 +275,13 @@ msgstr "Ellenőrizd a naplót a további részletekért."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Ellenőrizd az értesítési szolgáltatásodat"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Kattintson egy konténerre a további információk megtekintéséhez."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr ""
|
||||
msgstr "További információkért kattints egy rendszerre."
|
||||
|
||||
#: src/components/ui/input-copy.tsx
|
||||
msgid "Click to copy"
|
||||
@@ -289,9 +301,9 @@ msgstr "Konfiguráld, hogyan kapod az értesítéseket."
|
||||
msgid "Confirm password"
|
||||
msgstr "Jelszó megerősítése"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr ""
|
||||
msgstr "Kapcsolat megszakadt"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
@@ -317,7 +329,7 @@ msgstr "Docker run másolása"
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Environment variables"
|
||||
msgid "Copy env"
|
||||
msgstr ""
|
||||
msgstr "Környezet másolása"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Copy host"
|
||||
@@ -346,8 +358,9 @@ msgstr ""
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Copy YAML"
|
||||
msgstr ""
|
||||
msgstr "YAML másolása"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -365,7 +378,7 @@ msgstr "Fiók létrehozása"
|
||||
#. Context: date created
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Created"
|
||||
msgstr ""
|
||||
msgstr "Létrehozva"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Critical (%)"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Jelenlegi állapot"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Áttekintés"
|
||||
|
||||
@@ -400,7 +412,11 @@ msgstr "Törlés"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Delete fingerprint"
|
||||
msgstr ""
|
||||
msgstr "Ujjlenyomat törlése"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Részlet"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -417,7 +433,7 @@ msgstr "Lemez I/O"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Disk unit"
|
||||
msgstr ""
|
||||
msgstr "Lemez mértékegysége"
|
||||
|
||||
#: src/components/charts/disk-chart.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -451,11 +467,11 @@ msgstr "Dokumentáció"
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Down"
|
||||
msgstr ""
|
||||
msgstr "Offline"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Down ({downSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Offline ({downSystemsLength})"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Download"
|
||||
@@ -463,12 +479,12 @@ msgstr "Letöltés"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Duration"
|
||||
msgstr ""
|
||||
msgstr "Időtartam"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Edit"
|
||||
msgstr ""
|
||||
msgstr "Szerkesztés"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
@@ -508,7 +524,7 @@ msgstr "Hiba"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Túllépi a {0}{1} értéket az elmúlt {2, plural, one {# percben} other {# percben}}"
|
||||
|
||||
@@ -518,7 +534,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 ""
|
||||
msgstr "Exportálás"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Export configuration"
|
||||
@@ -530,7 +546,7 @@ msgstr "Exportálja a jelenlegi rendszerkonfigurációt."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Fahrenheit (°F)"
|
||||
msgstr ""
|
||||
msgstr "Fahrenheit (°F)"
|
||||
|
||||
#: src/lib/api.ts
|
||||
msgid "Failed to authenticate"
|
||||
@@ -549,6 +565,7 @@ msgstr "Teszt értesítés elküldése sikertelen"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Nem sikerült frissíteni a riasztást"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -557,7 +574,7 @@ msgstr "Szűrő..."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Fingerprint"
|
||||
msgstr ""
|
||||
msgstr "Ujjlenyomat"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU áramfelvétele"
|
||||
msgid "Grid"
|
||||
msgstr "Rács"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Egészség"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Tétlen"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Ha elvesztette az admin fiók jelszavát, a következő paranccsal állíthatja vissza."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Kép"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Érvénytelen e-mail cím."
|
||||
@@ -634,24 +660,24 @@ msgstr "Elrendezés"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Load Average"
|
||||
msgstr ""
|
||||
msgstr "Terhelési átlag"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 15m"
|
||||
msgstr ""
|
||||
msgstr "Terhelési átlag 15p"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 1m"
|
||||
msgstr ""
|
||||
msgstr "Terhelési átlag 1p"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 5m"
|
||||
msgstr ""
|
||||
msgstr "Terhelési átlag 5p"
|
||||
|
||||
#. Short label for load average
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Load Avg"
|
||||
msgstr ""
|
||||
msgstr "Terhelési átlag"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Log Out"
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Bejelentkezés sikertelen"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Naplók"
|
||||
@@ -682,13 +709,14 @@ 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 ""
|
||||
msgstr "Manuális beállítási lépések"
|
||||
|
||||
#. Chart select field. Please try to keep this short.
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Max 1 min"
|
||||
msgstr "Maximum 1 perc"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "RAM"
|
||||
@@ -704,9 +732,11 @@ msgstr "Docker konténerek memória használata"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Név"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Hálózat"
|
||||
@@ -725,15 +755,16 @@ msgstr "Nyilvános interfészek hálózati forgalma"
|
||||
#. Context: Bytes or bits
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Network unit"
|
||||
msgstr ""
|
||||
msgstr "Sávszélesség mértékegysége"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "No results found."
|
||||
msgstr "Nincs találat."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
msgstr "Nincs találat."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -772,6 +803,7 @@ msgstr "Vagy folytasd ezzel"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Felülírja a meglévő riasztásokat"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Oldal"
|
||||
@@ -780,7 +812,7 @@ msgstr "Oldal"
|
||||
#. placeholder {1}: table.getPageCount()
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Page {0} of {1}"
|
||||
msgstr ""
|
||||
msgstr "{0}/{1} oldal"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Pages / Settings"
|
||||
@@ -797,7 +829,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 ""
|
||||
msgstr "A jelszó legfeljebb 72 byte lehet."
|
||||
|
||||
#: src/components/login/forgot-pass-form.tsx
|
||||
msgid "Password reset request received"
|
||||
@@ -813,7 +845,7 @@ msgstr "Szüneteltetve"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Paused ({pausedSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Szüneteltetve ({pausedSystemsLength})"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
|
||||
@@ -876,6 +908,11 @@ msgstr "Olvasás"
|
||||
msgid "Received"
|
||||
msgstr "Fogadott"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Frissítés"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Egyszeri jelszó kérése"
|
||||
@@ -892,7 +929,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 ""
|
||||
msgstr "Megoldva"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Resume"
|
||||
@@ -900,11 +937,11 @@ msgstr "Folytatás"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Rotate token"
|
||||
msgstr ""
|
||||
msgstr "Tokenváltás"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Rows per page"
|
||||
msgstr ""
|
||||
msgstr "Sorok száma oldalanként"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Save address using enter key or comma. Leave blank to disable email notifications."
|
||||
@@ -917,7 +954,7 @@ msgstr "Beállítások mentése"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Save system"
|
||||
msgstr ""
|
||||
msgstr "Rendszer mentése"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Search"
|
||||
@@ -965,8 +1002,9 @@ msgstr "Rendezés"
|
||||
#. Context: alert state (active or resolved)
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
msgstr "Állapot"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap használat"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -989,7 +1028,7 @@ msgstr "Rendszer"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "System load averages over time"
|
||||
msgstr ""
|
||||
msgstr "Rendszer terhelési átlaga"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Systems"
|
||||
@@ -1006,7 +1045,7 @@ msgstr "Tábla"
|
||||
#. Temperature label in systems table
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Temp"
|
||||
msgstr ""
|
||||
msgstr "Hőmérséklet"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1015,7 +1054,7 @@ msgstr "Hőmérséklet"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Temperature unit"
|
||||
msgstr ""
|
||||
msgstr "Hőmérséklet mértékegysége"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Temperatures of system sensors"
|
||||
@@ -1039,7 +1078,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 ""
|
||||
msgstr "Ez véglegesen törli az összes kijelölt bejegyzést az adatbázisból."
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Throughput of {extraFsName}"
|
||||
@@ -1069,13 +1108,13 @@ msgstr "Téma váltása"
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Token"
|
||||
msgstr ""
|
||||
msgstr "Token"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens & Fingerprints"
|
||||
msgstr ""
|
||||
msgstr "Tokenek & Ujjlenyomatok"
|
||||
|
||||
#: 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 +1134,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 ""
|
||||
msgstr "Riaszt, ha az 1 perces terhelési átlag túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 15 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Riaszt, ha a 15 perces terhelési átlag túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 5 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Riaszt, ha az 5 perces terhelési átlag túllép egy küszöbértéket"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when any sensor exceeds a threshold"
|
||||
@@ -1132,12 +1171,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 ""
|
||||
msgstr "Mértékegység beállítások"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Universal token"
|
||||
msgstr ""
|
||||
msgstr "Univerzális token"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -1148,11 +1187,15 @@ msgstr "Ismeretlen"
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Up"
|
||||
msgstr ""
|
||||
msgstr "Online"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Online ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Frissítve"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
@@ -1185,7 +1228,7 @@ msgstr "Felhasználók"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
msgstr "Érték"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "View"
|
||||
@@ -1197,7 +1240,7 @@ msgstr "Továbbiak megjelenítése"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "View your 200 most recent alerts."
|
||||
msgstr ""
|
||||
msgstr "Legfrissebb 200 riasztásod áttekintése."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Visible Fields"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Aðgerðir"
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Virkar tilkynningar"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr ""
|
||||
msgid "Alerts"
|
||||
msgstr "Tilkynningar"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Allar gámar"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Skoðaðu logga til að sjá meiri upplýsingar."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Athugaðu tilkynningaþjónustuna þína"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Smelltu á gám til að sjá frekari upplýsingar."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr ""
|
||||
@@ -289,7 +301,7 @@ msgstr "Stilltu hvernig þú vilt fá tilkynningar."
|
||||
msgid "Confirm password"
|
||||
msgstr "Staðfestu lykilorð"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr ""
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr ""
|
||||
msgid "Copy YAML"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "Örgjörvi"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Núverandi ástand"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Yfirlitssíða"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Eyða"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Nánar"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Villa"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Fór yfir {0}{1} á síðustu {2, plural, one {# mínútu} other {# mínútum}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Villa í sendingu prufu skilaboða"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Mistókst að uppfæra tilkynningu"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Skjákorts rafmagnsnotkun"
|
||||
msgid "Grid"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Heilsa"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Aðgerðalaus"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Mynd"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ógilt netfang."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Innskránings tilraun misheppnaðist"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Loggar"
|
||||
@@ -689,6 +716,7 @@ msgstr ""
|
||||
msgid "Max 1 min"
|
||||
msgstr "Mest 1 mínúta"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Minni"
|
||||
@@ -704,9 +732,11 @@ msgstr "Minnisnotkun docker kerfa"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Nafn"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Net"
|
||||
@@ -731,6 +761,7 @@ msgstr ""
|
||||
msgid "No results found."
|
||||
msgstr "Engar niðurstöður fundust."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
@@ -772,6 +803,7 @@ msgstr "Eða halda áfram með"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Yfirskrifa núverandi tilkynningu"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Síða"
|
||||
@@ -876,6 +908,11 @@ msgstr "Lesa"
|
||||
msgid "Received"
|
||||
msgstr "Móttekið"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Endurhlaða"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr ""
|
||||
@@ -967,6 +1004,7 @@ msgstr "Raða eftir"
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Skipti minni"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr ""
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Uppfært"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr ""
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Azioni"
|
||||
msgid "Active"
|
||||
msgstr "Attivo"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Avvisi Attivi"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Cronologia Avvisi"
|
||||
msgid "Alerts"
|
||||
msgstr "Avvisi"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Tutti i contenitori"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Controlla i log per maggiori dettagli."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Controlla il tuo servizio di notifica"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Fare clic su un contenitore per visualizzare ulteriori informazioni."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Clicca su un sistema per visualizzare più informazioni."
|
||||
@@ -289,7 +301,7 @@ msgstr "Configura come ricevere le notifiche di avviso."
|
||||
msgid "Confirm password"
|
||||
msgstr "Conferma password"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "La connessione è interrotta"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Copia il contenuto<0>docker-compose.yml</0> per l'agente qui sotto, o re
|
||||
msgid "Copy YAML"
|
||||
msgstr "Copia YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Stato attuale"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Cruscotto"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Elimina"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Elimina impronta digitale"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Dettagli"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Errore"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Supera {0}{1} negli ultimi {2, plural, one {# minuto} other {# minuti}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Invio della notifica di test fallito"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Aggiornamento dell'avviso fallito"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Consumo della GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Griglia"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Stato"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Inattiva"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Se hai perso la password del tuo account amministratore, puoi reimpostarla utilizzando il seguente comando."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Immagine"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Indirizzo email non valido."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Tentativo di accesso fallito"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Log"
|
||||
@@ -689,6 +716,7 @@ msgstr "Istruzioni di configurazione manuale"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Max 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Memoria"
|
||||
@@ -704,9 +732,11 @@ msgstr "Utilizzo della memoria dei container Docker"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Rete"
|
||||
@@ -731,6 +761,7 @@ msgstr "Unità rete"
|
||||
msgid "No results found."
|
||||
msgstr "Nessun risultato trovato."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Nessun risultato."
|
||||
@@ -772,6 +803,7 @@ msgstr "Oppure continua con"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Sovrascrivi avvisi esistenti"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Pagina"
|
||||
@@ -876,6 +908,11 @@ msgstr "Lettura"
|
||||
msgid "Received"
|
||||
msgstr "Ricevuto"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Aggiorna"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Richiedi una password monouso"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Ordina per"
|
||||
msgid "State"
|
||||
msgstr "Stato"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Utilizzo Swap"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Attivo"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Attivo ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Aggiornato"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Carica"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "アクション"
|
||||
msgid "Active"
|
||||
msgstr "アクティブ"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "アクティブなアラート"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "アラート履歴"
|
||||
msgid "Alerts"
|
||||
msgstr "アラート"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "すべてのコンテナ"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "詳細についてはログを確認してください。"
|
||||
msgid "Check your notification service"
|
||||
msgstr "通知サービスを確認してください"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "詳細情報を表示するにはコンテナをクリックしてください。"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "システムをクリックして詳細を表示します。"
|
||||
@@ -289,7 +301,7 @@ msgstr "アラート通知の受信方法を設定します。"
|
||||
msgid "Confirm password"
|
||||
msgstr "パスワードを確認"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "接続が切断されました"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "下記のエージェントの<0>docker-compose.yml</0>内容をコピ
|
||||
msgid "Copy YAML"
|
||||
msgstr "YAMLをコピー"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "現在の状態"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "ダッシュボード"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "削除"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "フィンガープリントを削除"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "詳細"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "エラー"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "過去{2, plural, one {# 分} other {# 分}}で{0}{1}を超えています"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "テスト通知の送信に失敗しました"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "アラートの更新に失敗しました"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPUの消費電力"
|
||||
msgid "Grid"
|
||||
msgstr "グリッド"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "ヘルス"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "アイドル"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "管理者アカウントのパスワードを忘れた場合は、次のコマンドを使用してリセットできます。"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "イメージ"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "無効なメールアドレスです。"
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "ログイン試行に失敗しました"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "ログ"
|
||||
@@ -689,6 +716,7 @@ msgstr "手動セットアップの手順"
|
||||
msgid "Max 1 min"
|
||||
msgstr "最大1分"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "メモリ"
|
||||
@@ -704,9 +732,11 @@ msgstr "Dockerコンテナのメモリ使用率"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "名前"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "帯域"
|
||||
@@ -731,6 +761,7 @@ msgstr "ネットワーク単位"
|
||||
msgid "No results found."
|
||||
msgstr "結果が見つかりませんでした。"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "結果がありません。"
|
||||
@@ -772,6 +803,7 @@ msgstr "または、以下の方法でログイン"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "既存のアラートを上書き"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "ページ"
|
||||
@@ -876,6 +908,11 @@ msgstr "読み取り"
|
||||
msgid "Received"
|
||||
msgstr "受信"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "更新"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "ワンタイムパスワードをリクエスト"
|
||||
@@ -967,6 +1004,7 @@ msgstr "並び替え基準"
|
||||
msgid "State"
|
||||
msgstr "状態"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "スワップ使用量"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "正常"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "正常 ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "更新済み"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "アップロード"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "작업"
|
||||
msgid "Active"
|
||||
msgstr "활성"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "활성화된 알림들"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "알림 기록"
|
||||
msgid "Alerts"
|
||||
msgstr "알림"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "모든 컨테이너"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "자세한 내용은 로그를 확인하세요."
|
||||
msgid "Check your notification service"
|
||||
msgstr "알림 서비스를 확인하세요."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "더 많은 정보를 보려면 컨테이너를 클릭하세요."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "더 많은 정보를 보려면 시스템을 클릭하세요."
|
||||
@@ -289,7 +301,7 @@ msgstr "알림을 수신할 방법을 설정하세요."
|
||||
msgid "Confirm password"
|
||||
msgstr "비밀번호 확인"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "연결이 끊겼습니다"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "아래 에이전트의 <0>docker-compose.yml</0> 내용을 복사하거
|
||||
msgid "Copy YAML"
|
||||
msgstr "YAML 복사"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "현재 상태"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "대시보드"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "삭제"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "지문 삭제"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "세부사항"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "오류"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "마지막 {2, plural, one {# 분} other {# 분}} 동안 {0}{1} 초과"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "테스트 알림 전송 실패"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "알림 수정 실패"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU 전원 사용량"
|
||||
msgid "Grid"
|
||||
msgstr "그리드"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "상태"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "대기"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "관리자 계정의 비밀번호를 잃어버린 경우, 다음 명령어를 사용하여 재설정할 수 있습니다."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "이미지"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "잘못된 이메일 주소입니다."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "로그인 실패"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "로그"
|
||||
@@ -689,6 +716,7 @@ msgstr "수동 설정 방법"
|
||||
msgid "Max 1 min"
|
||||
msgstr "1분간 최댓값"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "메모리"
|
||||
@@ -704,9 +732,11 @@ msgstr "Docker 컨테이너의 메모리 사용량"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "이름"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "네트워크"
|
||||
@@ -731,6 +761,7 @@ msgstr "네트워크 단위"
|
||||
msgid "No results found."
|
||||
msgstr "결과가 없습니다."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "결과 없음."
|
||||
@@ -772,6 +803,7 @@ msgstr "또는 아래 항목으로 진행하기"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "기존 알림 덮어쓰기"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "페이지"
|
||||
@@ -876,6 +908,11 @@ msgstr "읽기"
|
||||
msgid "Received"
|
||||
msgstr "수신됨"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "새로고침"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "OTP 요청"
|
||||
@@ -967,6 +1004,7 @@ msgstr "정렬 기준"
|
||||
msgid "State"
|
||||
msgstr "상태"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "스왑 사용량"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "온라인"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "온라인 ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "업데이트됨"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "업로드"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Acties"
|
||||
msgid "Active"
|
||||
msgstr "Actief"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Actieve waarschuwingen"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Melding geschiedenis"
|
||||
msgid "Alerts"
|
||||
msgstr "Waarschuwingen"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alle containers"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Controleer de logs voor meer details."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Controleer je meldingsservice"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Klik op een container om meer informatie te zien."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Klik op een systeem om meer informatie te bekijken."
|
||||
@@ -289,7 +301,7 @@ msgstr "Configureer hoe je waarschuwingsmeldingen ontvangt."
|
||||
msgid "Confirm password"
|
||||
msgstr "Bevestig wachtwoord"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Verbinding is niet actief"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Kopieer de<0>docker-compose.yml</0> inhoud voor de agent hieronder, of r
|
||||
msgid "Copy YAML"
|
||||
msgstr "YAML kopiëren"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Huidige status"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashboard"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Verwijderen"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Vingerafdruk verwijderen"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detail"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Fout"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Overschrijdt {0}{1} in de laatste {2, plural, one {# minuut} other {# minuten}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Versturen test notificatie mislukt"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Bijwerken waarschuwing mislukt"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU stroomverbruik"
|
||||
msgid "Grid"
|
||||
msgstr "Raster"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Gezondheid"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Inactief"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Als je het wachtwoord voor je beheerdersaccount bent kwijtgeraakt, kan je het opnieuw instellen met behulp van de volgende opdracht."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ongeldig e-mailadres."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Aanmelding mislukt"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
@@ -689,6 +716,7 @@ msgstr "Handmatige installatie-instructies"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Max 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Geheugen"
|
||||
@@ -704,9 +732,11 @@ msgstr "Geheugengebruik van docker containers"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Naam"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Net"
|
||||
@@ -731,6 +761,7 @@ msgstr "Netwerk eenheid"
|
||||
msgid "No results found."
|
||||
msgstr "Geen resultaten gevonden."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Geen resultaten."
|
||||
@@ -772,6 +803,7 @@ msgstr "Of ga verder met"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Overschrijf bestaande waarschuwingen"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Pagina"
|
||||
@@ -876,6 +908,11 @@ msgstr "Lezen"
|
||||
msgid "Received"
|
||||
msgstr "Ontvangen"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Vernieuwen"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Eenmalig wachtwoord aanvragen"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Sorteren op"
|
||||
msgid "State"
|
||||
msgstr "Status"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap gebruik"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Online"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Online ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Bijgewerkt"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Uploaden"
|
||||
|
||||
@@ -8,15 +8,15 @@ msgstr ""
|
||||
"Language: no\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-08-28 23:21\n"
|
||||
"PO-Revision-Date: 2025-10-13 17:31\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/beszel/site/src/locales/en/en.po\n"
|
||||
"X-Crowdin-File-ID: 16\n"
|
||||
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
|
||||
"X-Crowdin-File-ID: 32\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 ""
|
||||
msgstr "{0, plural, one {# minutt} other {# minutter}}"
|
||||
|
||||
#. 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 ""
|
||||
msgstr "{0} av {1} rad(er) valgt."
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 hour"
|
||||
@@ -46,7 +46,7 @@ msgstr "1 time"
|
||||
#. Load average
|
||||
#: src/components/charts/load-average-chart.tsx
|
||||
msgid "1 min"
|
||||
msgstr ""
|
||||
msgstr "1 min"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 minute"
|
||||
@@ -63,7 +63,7 @@ msgstr "12 timer"
|
||||
#. 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 +76,7 @@ msgstr "30 dager"
|
||||
#. 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
|
||||
@@ -87,9 +87,9 @@ msgstr "Handlinger"
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
msgstr "Aktiv"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktive Alarmer"
|
||||
|
||||
@@ -126,14 +126,22 @@ msgstr "Agent"
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
msgid "Alert History"
|
||||
msgstr ""
|
||||
msgstr "Varselhistorikk"
|
||||
|
||||
#: src/components/alerts/alert-button.tsx
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "Alerts"
|
||||
msgstr "Alarmer"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alle containere"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -145,7 +153,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 ""
|
||||
msgstr "Er du sikker?"
|
||||
|
||||
#: src/components/copy-to-clipboard.tsx
|
||||
msgid "Automatic copy requires a secure context."
|
||||
@@ -210,12 +218,12 @@ 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
|
||||
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,11 +240,11 @@ msgstr "Advarsel - potensielt tap av data"
|
||||
|
||||
#: 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."
|
||||
msgstr ""
|
||||
msgstr "Endre måleenheter for målinger."
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Change general application options."
|
||||
@@ -267,9 +275,13 @@ msgstr "Sjekk loggene for flere detaljer."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Sjekk din meldingstjeneste"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Klikk på en container for å se mer informasjon."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr ""
|
||||
msgstr "Klikk på et system for å se mer informasjon."
|
||||
|
||||
#: src/components/ui/input-copy.tsx
|
||||
msgid "Click to copy"
|
||||
@@ -289,9 +301,9 @@ msgstr "Konfigurer hvordan du vil motta alarmvarsler."
|
||||
msgid "Confirm password"
|
||||
msgstr "Bekreft passord"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr ""
|
||||
msgstr "Tilkoblingen er nede"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
@@ -317,7 +329,7 @@ msgstr "Kopier docker run"
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Environment variables"
|
||||
msgid "Copy env"
|
||||
msgstr ""
|
||||
msgstr "Kopier env"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Copy host"
|
||||
@@ -338,16 +350,17 @@ 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 ""
|
||||
msgstr "Kopier installasjonskommandoen for agenten nedenfor, eller registrer agenter automatisk med en <0>universal token</0>."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
msgid "Copy the<0>docker-compose.yml</0> content for the agent below, or register agents automatically with a <1>universal token</1>."
|
||||
msgstr ""
|
||||
msgstr "Kopier <0>docker-compose.yml</0> for agenten nedenfor, eller registrer agenter automatisk med en <0>universal token</0>."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Copy YAML"
|
||||
msgstr ""
|
||||
msgstr "Kopier YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -365,7 +378,7 @@ msgstr "Opprett konto"
|
||||
#. Context: date created
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Created"
|
||||
msgstr ""
|
||||
msgstr "Opprettet"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Critical (%)"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Nåværende tilstand"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashbord"
|
||||
|
||||
@@ -400,7 +412,11 @@ msgstr "Slett"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Delete fingerprint"
|
||||
msgstr ""
|
||||
msgstr "Slett fingeravtrykk"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detalj"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -417,7 +433,7 @@ msgstr "Disk I/O"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Disk unit"
|
||||
msgstr ""
|
||||
msgstr "Diskenhet"
|
||||
|
||||
#: src/components/charts/disk-chart.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -455,7 +471,7 @@ msgstr "Nede"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Down ({downSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Nede ({downSystemsLength})"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Download"
|
||||
@@ -463,7 +479,7 @@ msgstr "Last ned"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Duration"
|
||||
msgstr ""
|
||||
msgstr "Varighet"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
@@ -508,7 +524,7 @@ msgstr "Feil"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Overstiger {0}{1} {2, plural, one {det siste minuttet} other {de siste # minuttene}}"
|
||||
|
||||
@@ -518,7 +534,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 ""
|
||||
msgstr "Eksporter"
|
||||
|
||||
#: src/components/routes/settings/config-yaml.tsx
|
||||
msgid "Export configuration"
|
||||
@@ -530,7 +546,7 @@ msgstr "Eksporter din nåværende systemkonfigurasjon"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Fahrenheit (°F)"
|
||||
msgstr ""
|
||||
msgstr "Fahrenheit (°F)"
|
||||
|
||||
#: src/lib/api.ts
|
||||
msgid "Failed to authenticate"
|
||||
@@ -549,6 +565,7 @@ msgstr "Kunne ikke sende test-varsling"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Kunne ikke oppdatere alarm"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -557,7 +574,7 @@ msgstr "Filter..."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Fingerprint"
|
||||
msgstr ""
|
||||
msgstr "Fingeravtrykk"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
|
||||
@@ -576,7 +593,7 @@ msgstr "FreeBSD kommando"
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Full"
|
||||
msgstr "Full"
|
||||
msgstr "Fullt"
|
||||
|
||||
#. Context: General settings
|
||||
#: src/components/routes/settings/general.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU Effektforbruk"
|
||||
msgid "Grid"
|
||||
msgstr "Rutenett"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Helse"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Inaktiv"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Dersom du har mistet passordet til admin-kontoen kan du nullstille det med følgende kommando."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ugyldig e-postadresse."
|
||||
@@ -630,28 +656,28 @@ msgstr "Språk"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Layout"
|
||||
msgstr "Layout"
|
||||
msgstr "Oppsett"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Load Average"
|
||||
msgstr ""
|
||||
msgstr "Snittbelastning Last"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 15m"
|
||||
msgstr ""
|
||||
msgstr "Snittbelastning 15m"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 1m"
|
||||
msgstr ""
|
||||
msgstr "Snittbelastning 1m"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Load Average 5m"
|
||||
msgstr ""
|
||||
msgstr "Snittbelastning 5m"
|
||||
|
||||
#. Short label for load average
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Load Avg"
|
||||
msgstr ""
|
||||
msgstr "Snittbelastning"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Log Out"
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Innlogging mislyktes"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logger"
|
||||
@@ -689,6 +716,7 @@ msgstr "Instruks for Manuell Installasjon"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Maks 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Minne"
|
||||
@@ -704,9 +732,11 @@ msgstr "Minnebruk av docker-konteinere"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Navn"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Nett"
|
||||
@@ -725,15 +755,16 @@ msgstr "Nettverkstrafikk av eksterne nettverksgrensesnitt"
|
||||
#. Context: Bytes or bits
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Network unit"
|
||||
msgstr ""
|
||||
msgstr "Nettverksenhet"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "No results found."
|
||||
msgstr "Ingen resultater funnet."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
msgstr "Ingen resultater."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -772,6 +803,7 @@ msgstr "Eller fortsett med"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Overskriv eksisterende alarmer"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Side"
|
||||
@@ -780,7 +812,7 @@ msgstr "Side"
|
||||
#. placeholder {1}: table.getPageCount()
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Page {0} of {1}"
|
||||
msgstr ""
|
||||
msgstr "Side {0} av {1}"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Pages / Settings"
|
||||
@@ -813,7 +845,7 @@ msgstr "Satt på Pause"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Paused ({pausedSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Pauset ({pausedSystemsLength})"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
|
||||
@@ -876,6 +908,11 @@ msgstr "Lesing"
|
||||
msgid "Received"
|
||||
msgstr "Mottatt"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Oppdater"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Be om engangspassord"
|
||||
@@ -892,7 +929,7 @@ msgstr "Nullstill Passord"
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Resolved"
|
||||
msgstr ""
|
||||
msgstr "Løst"
|
||||
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Resume"
|
||||
@@ -900,11 +937,11 @@ msgstr "Gjenoppta"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Rotate token"
|
||||
msgstr ""
|
||||
msgstr "Forny token"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "Rows per page"
|
||||
msgstr ""
|
||||
msgstr "Rader per side"
|
||||
|
||||
#: src/components/routes/settings/notifications.tsx
|
||||
msgid "Save address using enter key or comma. Leave blank to disable email notifications."
|
||||
@@ -965,8 +1002,9 @@ msgstr "Sorter Etter"
|
||||
#. Context: alert state (active or resolved)
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
msgstr "Tilstand"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap-bruk"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -989,7 +1028,7 @@ msgstr "System"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "System load averages over time"
|
||||
msgstr ""
|
||||
msgstr "Systembelastning gjennomsnitt over tid"
|
||||
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Systems"
|
||||
@@ -1015,7 +1054,7 @@ msgstr "Temperatur"
|
||||
|
||||
#: src/components/routes/settings/general.tsx
|
||||
msgid "Temperature unit"
|
||||
msgstr ""
|
||||
msgstr "Temperaturenhet"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Temperatures of system sensors"
|
||||
@@ -1039,7 +1078,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 ""
|
||||
msgstr "Dette vil permanent slette alle valgte oppføringer fra databasen."
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
msgid "Throughput of {extraFsName}"
|
||||
@@ -1069,21 +1108,21 @@ msgstr "Tema av/på"
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Token"
|
||||
msgstr ""
|
||||
msgstr "Token"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/layout.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens & Fingerprints"
|
||||
msgstr ""
|
||||
msgstr "Tokens & Fingeravtrykk"
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens allow agents to connect and register. Fingerprints are stable identifiers unique to each system, set on first connection."
|
||||
msgstr ""
|
||||
msgstr "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."
|
||||
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
|
||||
msgstr ""
|
||||
msgstr "Tokens og fingeravtrykk blir brukt for å autentisere WebSocket-tilkoblinger til huben."
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Total data received for each interface"
|
||||
@@ -1095,15 +1134,15 @@ msgstr "Totalt sendt data for hvert grensesnitt"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 1 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Slår inn når gjennomsnittsbelastningen over 1 minutt overstiger en grenseverdi"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 15 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Slår inn når gjennomsnittsbelastningen over 15 minutter overstiger en grenseverdi"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when 5 minute load average exceeds a threshold"
|
||||
msgstr ""
|
||||
msgstr "Slår inn når gjennomsnittsbelastningen over 5 minutter overstiger en grenseverdi"
|
||||
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Triggers when any sensor exceeds a threshold"
|
||||
@@ -1132,12 +1171,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 ""
|
||||
msgstr "Enhetspreferanser"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgid "Universal token"
|
||||
msgstr ""
|
||||
msgstr "Universal token"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
@@ -1152,7 +1191,11 @@ msgstr "Oppe"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr ""
|
||||
msgstr "Oppe ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Oppdatert"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
@@ -1185,7 +1228,7 @@ msgstr "Brukere"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
msgid "Value"
|
||||
msgstr ""
|
||||
msgstr "Verdi"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "View"
|
||||
@@ -1197,7 +1240,7 @@ msgstr "Se mer"
|
||||
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "View your 200 most recent alerts."
|
||||
msgstr ""
|
||||
msgstr "Vis de 200 siste varslene."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Visible Fields"
|
||||
@@ -1225,7 +1268,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 ""
|
||||
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."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Akcje"
|
||||
msgid "Active"
|
||||
msgstr "Aktywny"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktywne alerty"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Historia alertów"
|
||||
msgid "Alerts"
|
||||
msgstr "Alerty"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Wszystkie kontenery"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Sprawdź logi, aby uzyskać więcej informacji."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Sprawdź swój serwis powiadomień"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Kliknij na kontener, aby wyświetlić więcej informacji."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Kliknij na system, aby zobaczyć więcej informacji."
|
||||
@@ -289,7 +301,7 @@ msgstr "Skonfiguruj sposób otrzymywania powiadomień."
|
||||
msgid "Confirm password"
|
||||
msgstr "Potwierdź hasło"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Brak połączenia"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Skopiuj poniżej zawartość pliku <0>docker-compose.yml</0> dla agenta
|
||||
msgid "Copy YAML"
|
||||
msgstr "Kopiuj YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "Procesor"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Aktualny stan"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Panel kontrolny"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Usuń"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Usuń odcisk palca"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Szczegół"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Błąd"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Przekracza {0}{1} w ciągu ostatnich {2, plural, one {# minuty} other {# minut}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Nie udało się wysłać testowego powiadomienia"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Nie udało się zaktualizować powiadomienia"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Moc GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Siatka"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Zdrowie"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Bezczynna"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Jeśli utraciłeś hasło do swojego konta administratora, możesz je zresetować, używając następującego polecenia."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Obraz"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Nieprawidłowy adres e-mail."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Próba logowania nie powiodła się"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logi"
|
||||
@@ -689,6 +716,7 @@ msgstr "Instrukcja ręcznej konfiguracji"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Maks. 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Pamięć"
|
||||
@@ -704,9 +732,11 @@ msgstr "Użycie pamięci przez kontenery Docker."
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Nazwa"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Sieć"
|
||||
@@ -731,6 +761,7 @@ msgstr "Jednostka sieciowa"
|
||||
msgid "No results found."
|
||||
msgstr "Brak wyników."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Brak wyników."
|
||||
@@ -772,6 +803,7 @@ msgstr "Lub kontynuuj z"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Nadpisz istniejące alerty"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Strona"
|
||||
@@ -876,6 +908,11 @@ msgstr "Odczyt"
|
||||
msgid "Received"
|
||||
msgstr "Otrzymane"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Odśwież"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Zażądaj jednorazowego hasła"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Sortuj według"
|
||||
msgid "State"
|
||||
msgstr "Stan"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Użycie pamięci wymiany"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Działa"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Działa ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Zaktualizowano"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Wysyłanie"
|
||||
|
||||
@@ -8,7 +8,7 @@ msgstr ""
|
||||
"Language: pt\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-08-28 23:21\n"
|
||||
"PO-Revision-Date: 2025-10-09 12:03\n"
|
||||
"Last-Translator: \n"
|
||||
"Language-Team: Portuguese\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
@@ -89,7 +89,7 @@ msgstr "Ações"
|
||||
msgid "Active"
|
||||
msgstr "Ativo"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Alertas Ativos"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Histórico de alertas"
|
||||
msgid "Alerts"
|
||||
msgstr "Alertas"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Todos os contentores"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -184,7 +192,7 @@ msgstr "Utilização média dos motores GPU"
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Backups"
|
||||
msgstr "Backups"
|
||||
msgstr "Cópias de segurança"
|
||||
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -267,6 +275,10 @@ msgstr "Verifique os logs para mais detalhes."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Verifique seu serviço de notificação"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Clique num contentor para ver mais informações."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Clique em um sistema para ver mais informações."
|
||||
@@ -289,7 +301,7 @@ msgstr "Configure como você recebe notificações de alerta."
|
||||
msgid "Confirm password"
|
||||
msgstr "Confirmar senha"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "A conexão está inativa"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Copie o conteúdo do <0>docker-compose.yml</0> do agente abaixo, ou regi
|
||||
msgid "Copy YAML"
|
||||
msgstr "Copiar YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Estado atual"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Painel"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Excluir"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Excluir impressão digital"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detalhe"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Erro"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Excede {0}{1} no último {2, plural, one {# minuto} other {# minutos}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Falha ao enviar notificação de teste"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Falha ao atualizar alerta"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Consumo de Energia da GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Grade"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Saúde"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Inativa"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Se você perdeu a senha da sua conta de administrador, pode redefini-la usando o seguinte comando."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Imagem"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Endereço de email inválido."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Tentativa de login falhou"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Logs"
|
||||
@@ -689,6 +716,7 @@ msgstr "Instruções de configuração manual"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Máx 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Memória"
|
||||
@@ -704,9 +732,11 @@ msgstr "Uso de memória dos contêineres Docker"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Nome"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Rede"
|
||||
@@ -731,6 +761,7 @@ msgstr "Unidade de rede"
|
||||
msgid "No results found."
|
||||
msgstr "Nenhum resultado encontrado."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Sem resultados."
|
||||
@@ -772,6 +803,7 @@ msgstr "Ou continue com"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Sobrescrever alertas existentes"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Página"
|
||||
@@ -876,6 +908,11 @@ msgstr "Ler"
|
||||
msgid "Received"
|
||||
msgstr "Recebido"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Atualizar"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Solicitar senha de uso único"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Ordenar Por"
|
||||
msgid "State"
|
||||
msgstr "Estado"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Uso de Swap"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "“Ligado”"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Ativo ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Atualizado"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Carregar"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Действия"
|
||||
msgid "Active"
|
||||
msgstr "Активно"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Активные оповещения"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "История оповещений"
|
||||
msgid "Alerts"
|
||||
msgstr "Оповещения"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Все контейнеры"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Проверьте журналы для получения более
|
||||
msgid "Check your notification service"
|
||||
msgstr "Проверьте ваш сервис уведомлений"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Нажмите на контейнер, чтобы просмотреть дополнительную информацию."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Нажмите на систему для просмотра дополнительной информации."
|
||||
@@ -289,7 +301,7 @@ msgstr "Настройте, как вы получаете уведомлени
|
||||
msgid "Confirm password"
|
||||
msgstr "Подтвердите пароль"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Нет соединения"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Скопируйте содержимое <0>docker-compose.yml</0> дл
|
||||
msgid "Copy YAML"
|
||||
msgstr "Скопировать YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "ЦП"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Текущее состояние"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Панель управления"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Удалить"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Удалить отпечаток"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Подробности"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Ошибка"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Превышает {0}{1} за последние {2, plural, one {# минуту} other {# минут}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Не удалось отправить тестовое уведомле
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Не удалось обновить оповещение"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Потребляемая мощность GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Сетка"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Здоровье"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Неактивная"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Если вы потеряли пароль от своей учетной записи администратора, вы можете сбросить его, используя следующую команду."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Образ"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Неверный адрес электронной почты."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Попытка входа не удалась"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Журналы"
|
||||
@@ -689,6 +716,7 @@ msgstr "Инструкции по ручной настройке"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Макс 1 мин"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Память"
|
||||
@@ -704,9 +732,11 @@ msgstr "Использование памяти контейнерами Docker"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Имя"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Сеть"
|
||||
@@ -731,6 +761,7 @@ msgstr "Единицы измерения скорости сети"
|
||||
msgid "No results found."
|
||||
msgstr "Результаты не найдены."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Нет результатов."
|
||||
@@ -772,6 +803,7 @@ msgstr "Или продолжить с"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Перезаписать существующие оповещения"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Страница"
|
||||
@@ -876,6 +908,11 @@ msgstr "Чтение"
|
||||
msgid "Received"
|
||||
msgstr "Получено"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Обновить"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Запросить одноразовый пароль"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Сортировать по"
|
||||
msgid "State"
|
||||
msgstr "Состояние"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Использование подкачки"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "В сети"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "В сети ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Обновлено"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Загрузить"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Dejanja"
|
||||
msgid "Active"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktivna opozorila"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr ""
|
||||
msgid "Alerts"
|
||||
msgstr "Opozorila"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Vsi kontejnerji"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Za več podrobnosti preverite dnevnike."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Preverite storitev obveščanja"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Kliknite na kontejner za več informacij."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr ""
|
||||
@@ -289,7 +301,7 @@ msgstr "Nastavi način prejemanja opozorilnih obvestil."
|
||||
msgid "Confirm password"
|
||||
msgstr "Potrdite geslo"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr ""
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr ""
|
||||
msgid "Copy YAML"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Trenutno stanje"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Nadzorna plošča"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Izbriši"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Podrobnost"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Napaka"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Preseženo {0}{1} v zadnjih {2, plural, one {# minuti} other {# minutah}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Pošiljanje testnega obvestila ni uspelo"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Opozorila ni bilo mogoče posodobiti"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU poraba moči"
|
||||
msgid "Grid"
|
||||
msgstr "Mreža"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Zdravje"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Neaktivna"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Če ste izgubili geslo za svoj skrbniški račun, ga lahko ponastavite z naslednjim ukazom."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Slika"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Napačen e-poštni naslov."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Poskus prijave ni uspel"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Dnevniki"
|
||||
@@ -689,6 +716,7 @@ msgstr ""
|
||||
msgid "Max 1 min"
|
||||
msgstr "Največ 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Pomnilnik"
|
||||
@@ -704,9 +732,11 @@ msgstr "Poraba pomnilnika docker kontejnerjev"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Naziv"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Mreža"
|
||||
@@ -731,6 +761,7 @@ msgstr ""
|
||||
msgid "No results found."
|
||||
msgstr "Ni rezultatov."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
@@ -772,6 +803,7 @@ msgstr "Ali nadaljuj z"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Prepiši obstoječe alarme"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Stran"
|
||||
@@ -876,6 +908,11 @@ msgstr "Preberano"
|
||||
msgid "Received"
|
||||
msgstr "Prejeto"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Osveži"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Zahtevaj enkratno geslo"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Razvrsti po"
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap uporaba"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr ""
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Posodobljeno"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Naloži"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Åtgärder"
|
||||
msgid "Active"
|
||||
msgstr "Aktiv"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktiva larm"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr ""
|
||||
msgid "Alerts"
|
||||
msgstr "Larm"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Alla behållare"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Kontrollera loggarna för mer information."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Kontrollera din aviseringstjänst"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Klicka på en behållare för att visa mer information."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr ""
|
||||
@@ -289,7 +301,7 @@ msgstr "Konfigurera hur du tar emot larmaviseringar."
|
||||
msgid "Confirm password"
|
||||
msgstr "Bekräfta lösenord"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Ej ansluten"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr ""
|
||||
msgid "Copy YAML"
|
||||
msgstr "Kopiera YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Aktuellt tillstånd"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Dashboard"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Ta bort"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Detalj"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Fel"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Överskrider {0}{1} under de senaste {2, plural, one {# minuten} other {# minuterna}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Kunde inte skicka testavisering"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Kunde inte uppdatera larm"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU-strömförbrukning"
|
||||
msgid "Grid"
|
||||
msgstr "Rutnät"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Hälsa"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Vilande"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Om du har glömt lösenordet till ditt administratörskonto kan du återställa det med följande kommando."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Image"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Ogiltig e-postadress."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Inloggningsförsök misslyckades"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Loggar"
|
||||
@@ -689,6 +716,7 @@ msgstr ""
|
||||
msgid "Max 1 min"
|
||||
msgstr "Max 1 min"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Minne"
|
||||
@@ -704,9 +732,11 @@ msgstr "Minnesanvändning för dockercontainrar"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Namn"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Nät"
|
||||
@@ -731,6 +761,7 @@ msgstr ""
|
||||
msgid "No results found."
|
||||
msgstr "Inga resultat hittades."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr ""
|
||||
@@ -772,6 +803,7 @@ msgstr "Eller fortsätt med"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Skriv över befintliga larm"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Sida"
|
||||
@@ -876,6 +908,11 @@ msgstr "Läs"
|
||||
msgid "Received"
|
||||
msgstr "Mottaget"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Uppdatera"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Begär engångslösenord"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Sortera efter"
|
||||
msgid "State"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Swap-användning"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr ""
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr ""
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Uppdaterad"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Ladda upp"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Eylemler"
|
||||
msgid "Active"
|
||||
msgstr "Aktif"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Aktif Uyarılar"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Uyarı Geçmişi"
|
||||
msgid "Alerts"
|
||||
msgstr "Uyarılar"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Tüm Konteynerler"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Daha fazla ayrıntı için günlükleri kontrol edin."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Bildirim hizmetinizi kontrol edin"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Daha fazla bilgi görüntülemek için bir konteynere tıklayın."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Daha fazla bilgi görmek için bir sisteme tıklayın."
|
||||
@@ -289,7 +301,7 @@ msgstr "Uyarı bildirimlerini nasıl alacağınızı yapılandırın."
|
||||
msgid "Confirm password"
|
||||
msgstr "Şifreyi onayla"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Bağlantı kesildi"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Aşağıdaki agent için <0>docker-compose.yml</0> içeriğini kopyalay
|
||||
msgid "Copy YAML"
|
||||
msgstr "YAML'ı kopyala"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Mevcut durum"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Gösterge Paneli"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Sil"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Parmak izini sil"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Ayrıntı"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Hata"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Son {2, plural, one {# dakika} other {# dakika}} içinde {0}{1} aşıyor"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Test bildirimi gönderilemedi"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Uyarı güncellenemedi"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU Güç Çekimi"
|
||||
msgid "Grid"
|
||||
msgstr "Izgara"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Sağlık"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Boşta"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Yönetici hesabınızın şifresini kaybettiyseniz, aşağıdaki komutu kullanarak sıfırlayabilirsiniz."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "İmaj"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Geçersiz e-posta adresi."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Giriş denemesi başarısız"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Günlükler"
|
||||
@@ -689,6 +716,7 @@ msgstr "Manuel kurulum talimatları"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Maks 1 dk"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Bellek"
|
||||
@@ -704,9 +732,11 @@ msgstr "Docker konteynerlerinin bellek kullanımı"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Ad"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Ağ"
|
||||
@@ -731,6 +761,7 @@ msgstr "Ağ birimi"
|
||||
msgid "No results found."
|
||||
msgstr "Sonuç bulunamadı."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Sonuç yok."
|
||||
@@ -772,6 +803,7 @@ msgstr "Veya devam et"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Mevcut uyarıların üzerine yaz"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Sayfa"
|
||||
@@ -876,6 +908,11 @@ msgstr "Oku"
|
||||
msgid "Received"
|
||||
msgstr "Alındı"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Yenile"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Tek kullanımlık şifre iste"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Sıralama Ölçütü"
|
||||
msgid "State"
|
||||
msgstr "Durum"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Takas Kullanımı"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Açık"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Açık ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Güncellendi"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Yükle"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Дії"
|
||||
msgid "Active"
|
||||
msgstr "Активне"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Активні сповіщення"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Історія сповіщень"
|
||||
msgid "Alerts"
|
||||
msgstr "Сповіщення"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Всі контейнери"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Перевірте журнали для отримання додатк
|
||||
msgid "Check your notification service"
|
||||
msgstr "Перевірте свій сервіс сповіщень"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Натисніть на контейнер, щоб переглянути більше інформації."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Натисніть на систему, щоб переглянути більше інформації."
|
||||
@@ -289,7 +301,7 @@ msgstr "Налаштуйте, як ви отримуєте сповіщення
|
||||
msgid "Confirm password"
|
||||
msgstr "Підтвердьте пароль"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "З'єднання розірвано"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Скопіюйте вміст <0>docker-compose.yml</0> для аген
|
||||
msgid "Copy YAML"
|
||||
msgstr "Копіювати YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "ЦП"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Поточний стан"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Панель управління"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Видалити"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Видалити відбиток"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Деталі"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Помилка"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Перевищує {0}{1} протягом {2, plural, one {останньої # хвилини} other {останніх # хвилин}}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Не вдалося надіслати тестове сповіщенн
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Не вдалося оновити сповіщення"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Енергоспоживання GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Сітка"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Здоров'я"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Неактивна"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Якщо ви втратили пароль до свого адміністративного облікового запису, ви можете скинути його за допомогою наступної команди."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Образ"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Неправильна адреса електронної пошти."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Спроба входу не вдалася"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Журнали"
|
||||
@@ -689,6 +716,7 @@ msgstr "Інструкції з ручного налаштування"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Макс 1 хв"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Пам'ять"
|
||||
@@ -704,9 +732,11 @@ msgstr "Використання пам'яті контейнерами Docker"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Ім'я"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Мережа"
|
||||
@@ -731,6 +761,7 @@ msgstr "Одиниця виміру мережі"
|
||||
msgid "No results found."
|
||||
msgstr "Результатів не знайдено."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Немає результатів."
|
||||
@@ -772,6 +803,7 @@ msgstr "Або продовжити з"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Перезаписати існуючі сповіщення"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Сторінка"
|
||||
@@ -876,6 +908,11 @@ msgstr "Читання"
|
||||
msgid "Received"
|
||||
msgstr "Отримано"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Оновити"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Запит одноразового пароля"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Сортувати за"
|
||||
msgid "State"
|
||||
msgstr "Стан"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Використання підкачки"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Працює"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Працює ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Оновлено"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Відвантажити"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "Hành động"
|
||||
msgid "Active"
|
||||
msgstr "Hoạt động"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "Cảnh báo hoạt động"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "Lịch sử Cảnh báo"
|
||||
msgid "Alerts"
|
||||
msgstr "Cảnh báo"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "Tất cả container"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "Kiểm tra nhật ký để biết thêm chi tiết."
|
||||
msgid "Check your notification service"
|
||||
msgstr "Kiểm tra dịch vụ thông báo của bạn"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "Nhấp vào container để xem thêm thông tin."
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "Nhấp vào hệ thống để xem thêm thông tin."
|
||||
@@ -289,7 +301,7 @@ msgstr "Cấu hình cách bạn nhận thông báo cảnh báo."
|
||||
msgid "Confirm password"
|
||||
msgstr "Xác nhận mật khẩu"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "Mất kết nối"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "Sao chép nội dung <0>docker-compose.yml</0> cho tác nhân bên dư
|
||||
msgid "Copy YAML"
|
||||
msgstr "Sao chép YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "Trạng thái hiện tại"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "Bảng điều khiển"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "Xóa"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "Xóa vân tay"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "Chi tiết"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "Lỗi"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "Vượt quá {0}{1} trong {2, plural, one {# phút} other {# phút}} qua"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "Gửi thông báo thử nghiệm thất bại"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "Cập nhật cảnh báo thất bại"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "Mức tiêu thụ điện của GPU"
|
||||
msgid "Grid"
|
||||
msgstr "Lưới"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "Sức khỏe"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "Không hoạt động"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "Nếu bạn đã mất mật khẩu cho tài khoản quản trị viên của mình, bạn có thể đặt lại bằng cách sử dụng lệnh sau."
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "Hình ảnh"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "Địa chỉ email không hợp lệ."
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "Nỗ lực đăng nhập thất bại"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "Nhật ký"
|
||||
@@ -689,6 +716,7 @@ msgstr "Hướng dẫn cài đặt thủ công"
|
||||
msgid "Max 1 min"
|
||||
msgstr "Tối đa 1 phút"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "Bộ nhớ"
|
||||
@@ -704,9 +732,11 @@ msgstr "Sử dụng bộ nhớ của các container Docker"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "Tên"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "Mạng"
|
||||
@@ -731,6 +761,7 @@ msgstr "Đơn vị mạng"
|
||||
msgid "No results found."
|
||||
msgstr "Không tìm thấy kết quả."
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "Không có kết quả."
|
||||
@@ -772,6 +803,7 @@ msgstr "Hoặc tiếp tục với"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "Ghi đè các cảnh báo hiện có"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "Trang"
|
||||
@@ -876,6 +908,11 @@ msgstr "Đọc"
|
||||
msgid "Received"
|
||||
msgstr "Đã nhận"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "Làm mới"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "Yêu cầu mật khẩu một lần"
|
||||
@@ -967,6 +1004,7 @@ msgstr "Sắp xếp theo"
|
||||
msgid "State"
|
||||
msgstr "Trạng thái"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "Sử dụng Hoán đổi"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "Hoạt động"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "Hoạt động ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "Đã cập nhật"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "Tải lên"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "操作"
|
||||
msgid "Active"
|
||||
msgstr "活跃"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "启用的警报"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "警报历史"
|
||||
msgid "Alerts"
|
||||
msgstr "警报"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "所有容器"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "检查日志以获取更多详细信息。"
|
||||
msgid "Check your notification service"
|
||||
msgstr "检查您的通知服务"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "点击容器查看更多信息。"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "点击系统查看更多信息。"
|
||||
@@ -289,7 +301,7 @@ msgstr "配置您接收警报通知的方式。"
|
||||
msgid "Confirm password"
|
||||
msgstr "确认密码"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "连接已断开"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "复制下面的客户端<0>docker-compose.yml</0>内容,或使用<1>
|
||||
msgid "Copy YAML"
|
||||
msgstr "复制 YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "当前状态"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "仪表板"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "删除"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "删除指纹"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "详情"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "错误"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "在过去的{2, plural, one {# 分钟} other {# 分钟}}中超过{0}{1}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "发送测试通知失败"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "更新警报失败"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU 功耗"
|
||||
msgid "Grid"
|
||||
msgstr "网格"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "健康"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "闲置"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "如果您丢失了管理员账户的密码,可以使用以下命令重置。"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "镜像"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "无效的电子邮件地址。"
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "登录尝试失败"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "日志"
|
||||
@@ -689,6 +716,7 @@ msgstr "手动设置说明"
|
||||
msgid "Max 1 min"
|
||||
msgstr "1分钟内最大值"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "内存"
|
||||
@@ -704,9 +732,11 @@ msgstr "Docker 容器的内存使用率"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "名称"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "网络"
|
||||
@@ -731,6 +761,7 @@ msgstr "网络单位"
|
||||
msgid "No results found."
|
||||
msgstr "未找到结果。"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "无结果。"
|
||||
@@ -772,6 +803,7 @@ msgstr "或使用以下方式登录"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "覆盖现有警报"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "页面"
|
||||
@@ -876,6 +908,11 @@ msgstr "读取"
|
||||
msgid "Received"
|
||||
msgstr "接收"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "刷新"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "请求一次性密码"
|
||||
@@ -967,6 +1004,7 @@ msgstr "排序依据"
|
||||
msgid "State"
|
||||
msgstr "状态"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "SWAP 使用率"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "在线"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "在线 ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "已更新"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "上传"
|
||||
|
||||
@@ -89,7 +89,7 @@ msgstr "操作"
|
||||
msgid "Active"
|
||||
msgstr "啟用中"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "活動警報"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "警報歷史"
|
||||
msgid "Alerts"
|
||||
msgstr "警報"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "所有容器"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "檢查日誌以取得更多資訊。"
|
||||
msgid "Check your notification service"
|
||||
msgstr "檢查您的通知服務"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "點擊容器以查看更多資訊。"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "點擊系統以查看更多資訊。"
|
||||
@@ -289,7 +301,7 @@ msgstr "配置您接收警報通知的方式。"
|
||||
msgid "Confirm password"
|
||||
msgstr "確認密碼"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "連線中斷"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "複製下面的代理程式<0>docker-compose.yml</0>內容,或使用<1
|
||||
msgid "Copy YAML"
|
||||
msgstr "複製YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "目前狀態"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "控制面板"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "刪除"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "刪除指紋"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "詳細資訊"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "錯誤"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "在過去的{2, plural, one {# 分鐘} other {# 分鐘}}中超過{0}{1}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "發送測試通知失敗"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "更新警報失敗"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU 功耗"
|
||||
msgid "Grid"
|
||||
msgstr "網格"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "健康狀態"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "閒置"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "如果您遺失了管理員帳號密碼,可以使用以下指令重設。"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "鏡像"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "無效的電子郵件地址。"
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "登入嘗試失敗"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "日誌"
|
||||
@@ -689,6 +716,7 @@ msgstr "手動設定說明"
|
||||
msgid "Max 1 min"
|
||||
msgstr "一分鐘內最大值"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "記憶體"
|
||||
@@ -704,9 +732,11 @@ msgstr "Docker 容器的記憶體使用量"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "名稱"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "網絡"
|
||||
@@ -731,6 +761,7 @@ msgstr "網路單位"
|
||||
msgid "No results found."
|
||||
msgstr "未找到結果。"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "沒有結果。"
|
||||
@@ -772,6 +803,7 @@ msgstr "或繼續使用"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "覆蓋現有警報"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "頁面"
|
||||
@@ -876,6 +908,11 @@ msgstr "讀取"
|
||||
msgid "Received"
|
||||
msgstr "接收"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "重新整理"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "請求一次性密碼"
|
||||
@@ -967,6 +1004,7 @@ msgstr "排序依據"
|
||||
msgid "State"
|
||||
msgstr "狀態"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "交換使用"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "上線"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "上線 ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "已更新"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "上傳"
|
||||
|
||||
@@ -8,15 +8,15 @@ msgstr ""
|
||||
"Language: zh\n"
|
||||
"Project-Id-Version: beszel\n"
|
||||
"Report-Msgid-Bugs-To: \n"
|
||||
"PO-Revision-Date: 2025-08-28 23:21\n"
|
||||
"PO-Revision-Date: 2025-10-12 03:15\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/beszel/site/src/locales/en/en.po\n"
|
||||
"X-Crowdin-File-ID: 16\n"
|
||||
"X-Crowdin-File: /main/internal/site/src/locales/en/en.po\n"
|
||||
"X-Crowdin-File-ID: 32\n"
|
||||
|
||||
#. placeholder {0}: Math.trunc(system.info?.u / 86400)
|
||||
#: src/components/routes/system.tsx
|
||||
@@ -50,7 +50,7 @@ msgstr "1 分鐘"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 minute"
|
||||
msgstr "1 分钟"
|
||||
msgstr "1 分鐘"
|
||||
|
||||
#: src/lib/utils.ts
|
||||
msgid "1 week"
|
||||
@@ -89,7 +89,7 @@ msgstr "操作"
|
||||
msgid "Active"
|
||||
msgstr "啟用中"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Active Alerts"
|
||||
msgstr "活動警報"
|
||||
|
||||
@@ -133,7 +133,15 @@ msgstr "警報歷史"
|
||||
msgid "Alerts"
|
||||
msgstr "警報"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/containers.tsx
|
||||
msgid "All Containers"
|
||||
msgstr "所有容器"
|
||||
|
||||
#: src/components/alerts/alerts-sheet.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "All Systems"
|
||||
@@ -267,6 +275,10 @@ msgstr "檢查系統記錄以取得更多資訊。"
|
||||
msgid "Check your notification service"
|
||||
msgstr "檢查您的通知服務"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Click on a container to view more information."
|
||||
msgstr "點擊容器以查看更多資訊。"
|
||||
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
msgid "Click on a system to view more information."
|
||||
msgstr "點擊系統以查看更多資訊。"
|
||||
@@ -289,7 +301,7 @@ msgstr "設定您要如何接收警報通知"
|
||||
msgid "Confirm password"
|
||||
msgstr "確認密碼"
|
||||
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Connection is down"
|
||||
msgstr "連線中斷"
|
||||
|
||||
@@ -348,6 +360,7 @@ msgstr "複製下面的代理程式<0>docker-compose.yml</0>內容,或使用<1
|
||||
msgid "Copy YAML"
|
||||
msgstr "複製YAML"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "CPU"
|
||||
msgstr "CPU"
|
||||
@@ -385,7 +398,6 @@ msgid "Current state"
|
||||
msgstr "目前狀態"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/routes/home.tsx
|
||||
msgid "Dashboard"
|
||||
msgstr "控制面板"
|
||||
|
||||
@@ -402,6 +414,10 @@ msgstr "刪除"
|
||||
msgid "Delete fingerprint"
|
||||
msgstr "刪除指紋"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Detail"
|
||||
msgstr "詳細資訊"
|
||||
|
||||
#. Context: Battery state
|
||||
#: src/lib/i18n.ts
|
||||
msgid "Discharging"
|
||||
@@ -508,7 +524,7 @@ msgstr "錯誤"
|
||||
#. placeholder {0}: alert.value
|
||||
#. placeholder {1}: info.unit
|
||||
#. placeholder {2}: alert.min
|
||||
#: src/components/routes/home.tsx
|
||||
#: src/components/active-alerts.tsx
|
||||
msgid "Exceeds {0}{1} in last {2, plural, one {# minute} other {# minutes}}"
|
||||
msgstr "在過去的{2, plural, one {# 分鐘} other {# 分鐘}}中超過{0}{1}"
|
||||
|
||||
@@ -549,6 +565,7 @@ msgstr "發送測試通知失敗"
|
||||
msgid "Failed to update alert"
|
||||
msgstr "更新警報失敗"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
#: src/components/routes/system.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
@@ -596,6 +613,10 @@ msgstr "GPU 功耗"
|
||||
msgid "Grid"
|
||||
msgstr "網格"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Health"
|
||||
msgstr "健康狀態"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
msgctxt "Button to copy install command"
|
||||
@@ -615,6 +636,11 @@ msgstr "閒置"
|
||||
msgid "If you've lost the password to your admin account, you may reset it using the following command."
|
||||
msgstr "如果您遺失管理員帳號密碼,可以使用以下指令重設。"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgctxt "Docker image"
|
||||
msgid "Image"
|
||||
msgstr "鏡像"
|
||||
|
||||
#: src/components/login/auth-form.tsx
|
||||
msgid "Invalid email address."
|
||||
msgstr "無效的電子郵件地址。"
|
||||
@@ -667,6 +693,7 @@ msgid "Login attempt failed"
|
||||
msgstr "登入失敗"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/navbar.tsx
|
||||
msgid "Logs"
|
||||
msgstr "系統記錄"
|
||||
@@ -689,6 +716,7 @@ msgstr "手動設定說明"
|
||||
msgid "Max 1 min"
|
||||
msgstr "最多1分鐘"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Memory"
|
||||
msgstr "記憶體"
|
||||
@@ -704,9 +732,11 @@ msgstr "Docker 容器的記憶體使用量"
|
||||
|
||||
#: src/components/add-system.tsx
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Name"
|
||||
msgstr "名稱"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
msgid "Net"
|
||||
msgstr "網路"
|
||||
@@ -731,6 +761,7 @@ msgstr "網路單位"
|
||||
msgid "No results found."
|
||||
msgstr "找不到結果。"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/routes/settings/alerts-history-data-table.tsx
|
||||
msgid "No results."
|
||||
msgstr "沒有結果。"
|
||||
@@ -772,6 +803,7 @@ msgstr "或繼續使用"
|
||||
msgid "Overwrite existing alerts"
|
||||
msgstr "覆蓋現有警報"
|
||||
|
||||
#: src/components/command-palette.tsx
|
||||
#: src/components/command-palette.tsx
|
||||
msgid "Page"
|
||||
msgstr "頁面"
|
||||
@@ -876,6 +908,11 @@ msgstr "讀取"
|
||||
msgid "Received"
|
||||
msgstr "接收"
|
||||
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
#: src/components/containers-table/containers-table.tsx
|
||||
msgid "Refresh"
|
||||
msgstr "重新整理"
|
||||
|
||||
#: src/components/login/login.tsx
|
||||
msgid "Request a one-time password"
|
||||
msgstr "請求一次性密碼"
|
||||
@@ -967,6 +1004,7 @@ msgstr "排序"
|
||||
msgid "State"
|
||||
msgstr "狀態"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/systems-table/systems-table.tsx
|
||||
#: src/lib/alerts.ts
|
||||
msgid "Status"
|
||||
@@ -981,6 +1019,7 @@ msgid "Swap Usage"
|
||||
msgstr "虛擬記憶體使用量"
|
||||
|
||||
#: src/components/alerts-history-columns.tsx
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
#: src/components/routes/settings/tokens-fingerprints.tsx
|
||||
#: src/components/systems-table/systems-table-columns.tsx
|
||||
#: src/lib/alerts.ts
|
||||
@@ -1154,6 +1193,10 @@ msgstr "上線"
|
||||
msgid "Up ({upSystemsLength})"
|
||||
msgstr "上線 ({upSystemsLength})"
|
||||
|
||||
#: src/components/containers-table/containers-table-columns.tsx
|
||||
msgid "Updated"
|
||||
msgstr "已更新"
|
||||
|
||||
#: src/components/routes/system/network-sheet.tsx
|
||||
msgid "Upload"
|
||||
msgstr "上傳"
|
||||
|
||||
@@ -19,6 +19,7 @@ import * as systemsManager from "@/lib/systemsManager.ts"
|
||||
|
||||
const LoginPage = lazy(() => import("@/components/login/login.tsx"))
|
||||
const Home = lazy(() => import("@/components/routes/home.tsx"))
|
||||
const Containers = lazy(() => import("@/components/routes/containers.tsx"))
|
||||
const SystemDetail = lazy(() => import("@/components/routes/system.tsx"))
|
||||
const CopyToClipboardDialog = lazy(() => import("@/components/copy-to-clipboard.tsx"))
|
||||
|
||||
@@ -48,7 +49,6 @@ const App = memo(() => {
|
||||
// subscribe to new alert updates
|
||||
.then(alertManager.subscribe)
|
||||
return () => {
|
||||
// updateFavicon("favicon.svg")
|
||||
alertManager.unsubscribe()
|
||||
systemsManager.unsubscribe()
|
||||
}
|
||||
@@ -60,6 +60,8 @@ const App = memo(() => {
|
||||
return <Home />
|
||||
} else if (page.route === "system") {
|
||||
return <SystemDetail id={page.params.id} />
|
||||
} else if (page.route === "containers") {
|
||||
return <Containers />
|
||||
} else if (page.route === "settings") {
|
||||
return <Settings />
|
||||
}
|
||||
|
||||
13
internal/site/src/types.d.ts
vendored
13
internal/site/src/types.d.ts
vendored
@@ -236,6 +236,19 @@ export interface AlertsHistoryRecord extends RecordModel {
|
||||
resolved?: string | null
|
||||
}
|
||||
|
||||
export interface ContainerRecord extends RecordModel {
|
||||
id: string
|
||||
system: string
|
||||
name: string
|
||||
image: string
|
||||
cpu: number
|
||||
memory: number
|
||||
net: number
|
||||
health: number
|
||||
status: string
|
||||
updated: number
|
||||
}
|
||||
|
||||
export type ChartTimes = "1m" | "1h" | "12h" | "24h" | "1w" | "30d"
|
||||
|
||||
export interface ChartTimeData {
|
||||
|
||||
@@ -1,3 +1,31 @@
|
||||
## 0.14.1
|
||||
|
||||
- Add `MFA_OTP` environment variable to enable email-based one-time password for users and/or superusers.
|
||||
|
||||
- Add image name to containers table. (#1302)
|
||||
|
||||
- Add spacing for long temperature chart tooltip. (#1299)
|
||||
|
||||
- Fix sorting by status in containers table. (#1294)
|
||||
|
||||
## 0.14.0
|
||||
|
||||
- Add `/containers` page for viewing current status of all running containers. (#928)
|
||||
|
||||
- Add ability to view container status, health, details, and basic logs. (#928)
|
||||
|
||||
- Probable fix for erroneous network stats when interface resets (#1267, #1246)
|
||||
|
||||
# 0.13.2
|
||||
|
||||
- Add ability to set custom name for extra filesystems. (#379)
|
||||
|
||||
- Improve WebSocket agent reconnection after network interruptions. (#1263)
|
||||
|
||||
- Allow more latency in one minute charts before visually disconnecting points. (#1247)
|
||||
|
||||
- Update favicon and add add down systems count in bubble.
|
||||
|
||||
## 0.13.1
|
||||
|
||||
- Fix one minute charts on systems without Docker. (#1237)
|
||||
|
||||
@@ -6,13 +6,14 @@ param (
|
||||
[string]$Url = "",
|
||||
[int]$Port = 45876,
|
||||
[string]$AgentPath = "",
|
||||
[string]$NSSMPath = ""
|
||||
[string]$NSSMPath = "",
|
||||
[switch]$ConfigureFirewall
|
||||
)
|
||||
|
||||
# Check if required parameters are provided
|
||||
if ([string]::IsNullOrWhiteSpace($Key)) {
|
||||
Write-Host "ERROR: SSH Key is required." -ForegroundColor Red
|
||||
Write-Host "Usage: .\install-agent.ps1 -Key 'your-ssh-key-here' [-Token 'your-token-here'] [-Url 'your-hub-url-here'] [-Port port-number]" -ForegroundColor Yellow
|
||||
Write-Host "Usage: .\install-agent.ps1 -Key 'your-ssh-key-here' [-Token 'your-token-here'] [-Url 'your-hub-url-here'] [-Port port-number] [-ConfigureFirewall]" -ForegroundColor Yellow
|
||||
Write-Host "Note: Token and Url are optional for backwards compatibility with older hub versions." -ForegroundColor Yellow
|
||||
exit 1
|
||||
}
|
||||
@@ -568,6 +569,10 @@ try {
|
||||
$argumentList += "-NSSMPath"
|
||||
$argumentList += "`"$NSSMPath`""
|
||||
}
|
||||
|
||||
if ($ConfigureFirewall) {
|
||||
$argumentList += "-ConfigureFirewall"
|
||||
}
|
||||
|
||||
# Relaunch the script with the -Elevated switch and pass parameters
|
||||
Start-Process powershell.exe -Verb RunAs -ArgumentList $argumentList
|
||||
@@ -579,8 +584,11 @@ try {
|
||||
# Install the service
|
||||
Install-NSSMService -AgentPath $AgentPath -Key $Key -Token $Token -HubUrl $Url -Port $Port -NSSMPath $NSSMPath
|
||||
|
||||
# Configure firewall
|
||||
Configure-Firewall -Port $Port
|
||||
if ($ConfigureFirewall) {
|
||||
Configure-Firewall -Port $Port
|
||||
} else {
|
||||
Write-Host "Skipping firewall configuration. Use -ConfigureFirewall to add an inbound rule for port $Port." -ForegroundColor Yellow
|
||||
}
|
||||
|
||||
# Start the service
|
||||
Start-BeszelAgentService -NSSMPath $NSSMPath
|
||||
|
||||
@@ -757,20 +757,12 @@ start_service() {
|
||||
procd_set_param user beszel
|
||||
procd_set_param pidfile /var/run/beszel-agent.pid
|
||||
procd_set_param env PORT="$PORT" KEY="$KEY" TOKEN="$TOKEN" HUB_URL="$HUB_URL"
|
||||
procd_set_param respawn
|
||||
procd_set_param stdout 1
|
||||
procd_set_param stderr 1
|
||||
procd_close_instance
|
||||
}
|
||||
|
||||
stop_service() {
|
||||
killall beszel-agent
|
||||
}
|
||||
|
||||
restart_service() {
|
||||
stop
|
||||
start
|
||||
}
|
||||
|
||||
# Extra command to trigger agent update
|
||||
EXTRA_COMMANDS="update restart"
|
||||
EXTRA_HELP=" update Update the Beszel agent
|
||||
|
||||
Reference in New Issue
Block a user