Compare commits

..

17 Commits

Author SHA1 Message Date
hank
24feffcc92 New translations en.po (German) 2026-03-14 16:37:21 -04:00
hank
9586b461d8 New translations en.po (Turkish) 2026-03-02 08:16:29 -05:00
hank
78936b1481 New translations en.po (Chinese Simplified) 2026-03-01 12:14:20 -05:00
hank
5b6af761f1 New translations en.po (German) 2026-02-27 10:20:45 -05:00
hank
29b914a43b New translations en.po (Bulgarian) 2026-02-25 06:49:42 -05:00
hank
4a86357d64 New translations en.po (Bulgarian) 2026-02-25 03:59:03 -05:00
hank
b65f011222 New translations en.po (Dutch) 2026-02-24 06:37:18 -05:00
hank
f836609552 New translations en.po (Serbian (Cyrillic)) 2026-02-23 10:11:15 -05:00
hank
b2a3c52005 New translations en.po (Russian) 2026-02-21 04:46:18 -05:00
hank
6e2277ead1 New translations en.po (Chinese Traditional, Hong Kong) 2026-02-19 21:25:17 -05:00
hank
cffc3d8569 New translations en.po (Chinese Simplified) 2026-02-19 21:25:16 -05:00
henrygd
aa8b3711d7 update translations 2026-02-19 19:22:54 -05:00
henrygd
1fb0b25988 testing: improve flaky hub cleanup in agent_connect_test.go 2026-02-19 18:35:31 -05:00
henrygd
04600d83cc refactor: small go 1.26 updates and go fix changes 2026-02-19 18:04:33 -05:00
henrygd
5d8906c9b2 amd gpu: small refactor + trim "series" from device name 2026-02-19 17:39:13 -05:00
henrygd
daac287b9d ui: fix race issue with meter threshold colors
also increase the default container width
2026-02-19 17:37:57 -05:00
henrygd
d526ea61a9 ui: freeze header of smart device details table 2026-02-19 17:35:12 -05:00
63 changed files with 116 additions and 125 deletions

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,9 +1,9 @@
package agent
import (
"context"
"errors"
"log/slog"
"os"
"os/signal"
"syscall"
"time"
@@ -91,8 +91,8 @@ func (c *ConnectionManager) Start(serverOptions ServerOptions) error {
c.eventChan = make(chan ConnectionEvent, 1)
// signal handling for shutdown
sigChan := make(chan os.Signal, 1)
signal.Notify(sigChan, syscall.SIGINT, syscall.SIGTERM)
sigCtx, stopSignals := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
defer stopSignals()
c.startWsTicker()
c.connect()
@@ -109,8 +109,8 @@ func (c *ConnectionManager) Start(serverOptions ServerOptions) error {
_ = c.startWebSocketConnection()
case <-healthTicker:
_ = health.Update()
case <-sigChan:
slog.Info("Shutting down")
case <-sigCtx.Done():
slog.Info("Shutting down", "cause", context.Cause(sigCtx))
_ = c.agent.StopServer()
c.closeWebSocket()
return health.CleanUp()

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -89,10 +89,7 @@ func getPerCoreCpuUsage(cacheTimeMs uint16) (system.Uint8Slice, error) {
lastTimes := lastPerCoreCpuTimes[cacheTimeMs]
// Limit to the number of cores available in both samples
length := len(perCoreTimes)
if len(lastTimes) < length {
length = len(lastTimes)
}
length := min(len(lastTimes), len(perCoreTimes))
usage := make([]uint8, length)
for i := 0; i < length; i++ {

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -127,7 +127,7 @@ func (a *Agent) initializeDiskInfo() {
// Add EXTRA_FILESYSTEMS env var values to fsStats
if extraFilesystems, exists := GetEnv("EXTRA_FILESYSTEMS"); exists {
for _, fsEntry := range strings.Split(extraFilesystems, ",") {
for fsEntry := range strings.SplitSeq(extraFilesystems, ",") {
// Parse custom name from format: device__customname
fs, customName := parseFilesystemEntry(fsEntry)

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -103,10 +103,8 @@ func (gm *GPUManager) updateAmdGpuData(cardPath string) bool {
// Read all sysfs values first (no lock needed - these can be slow)
usage, usageErr := readSysfsFloat(filepath.Join(devicePath, "gpu_busy_percent"))
vramUsed, memUsedErr := readSysfsFloat(filepath.Join(devicePath, "mem_info_vram_used"))
vramTotal, _ := readSysfsFloat(filepath.Join(devicePath, "mem_info_vram_total"))
memUsed := vramUsed
memTotal := vramTotal
memUsed, memUsedErr := readSysfsFloat(filepath.Join(devicePath, "mem_info_vram_used"))
memTotal, _ := readSysfsFloat(filepath.Join(devicePath, "mem_info_vram_total"))
// if gtt is present, add it to the memory used and total (https://github.com/henrygd/beszel/issues/1569#issuecomment-3837640484)
if gttUsed, err := readSysfsFloat(filepath.Join(devicePath, "mem_info_gtt_used")); err == nil && gttUsed > 0 {
if gttTotal, err := readSysfsFloat(filepath.Join(devicePath, "mem_info_gtt_total")); err == nil {
@@ -243,7 +241,10 @@ func getCachedAmdgpuName(deviceID, revisionID string) (name string, found bool,
// normalizeAmdgpuName trims standard suffixes from AMDGPU product names.
func normalizeAmdgpuName(name string) string {
return strings.TrimSuffix(strings.TrimSpace(name), " Graphics")
for _, suffix := range []string{" Graphics", " Series"} {
name = strings.TrimSuffix(name, suffix)
}
return name
}
// cacheAmdgpuName stores a resolved AMDGPU name in the lookup cache.

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package health

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -476,7 +476,7 @@ func (sm *SmartManager) CollectSmart(deviceInfo *DeviceInfo) error {
output, err := cmd.CombinedOutput()
// Check if device is in standby (exit status 2)
if exitErr, ok := err.(*exec.ExitError); ok && exitErr.ExitCode() == 2 {
if exitErr, ok := errors.AsType[*exec.ExitError](err); ok && exitErr.ExitCode() == 2 {
if hasExistingData {
// Device is in standby and we have cached data, keep using cache
return nil

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package agent

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package alerts_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package alerts_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package alerts_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package alerts_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package alerts

View File

@@ -34,7 +34,7 @@ func ColorPrint(color, text string) {
fmt.Println(color + text + colorReset)
}
func ColorPrintf(color, format string, args ...interface{}) {
func ColorPrintf(color, format string, args ...any) {
fmt.Printf(color+format+colorReset+"\n", args...)
}

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package hub
@@ -10,6 +9,7 @@ import (
"net/http/httptest"
"os"
"path/filepath"
"runtime"
"strings"
"testing"
"time"
@@ -35,6 +35,26 @@ func createTestHub(t testing.TB) (*Hub, *pbtests.TestApp, error) {
return NewHub(testApp), testApp, nil
}
// cleanupTestHub stops background system goroutines before tearing down the app.
func cleanupTestHub(hub *Hub, testApp *pbtests.TestApp) {
if hub != nil {
sm := hub.GetSystemManager()
sm.RemoveAllSystems()
// Give updater goroutines a brief window to observe cancellation before DB teardown.
for range 20 {
if sm.GetSystemCount() == 0 {
break
}
runtime.Gosched()
time.Sleep(5 * time.Millisecond)
}
time.Sleep(20 * time.Millisecond)
}
if testApp != nil {
testApp.Cleanup()
}
}
// Helper function to create a test record
func createTestRecord(app core.App, collection string, data map[string]any) (*core.Record, error) {
col, err := app.FindCachedCollectionByNameOrId(collection)
@@ -64,7 +84,7 @@ func TestValidateAgentHeaders(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
testCases := []struct {
name string
@@ -145,7 +165,7 @@ func TestGetAllFingerprintRecordsByToken(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// create test user
userRecord, err := createTestUser(testApp)
@@ -235,7 +255,7 @@ func TestSetFingerprint(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// Create test user
userRecord, err := createTestUser(testApp)
@@ -315,7 +335,7 @@ func TestCreateSystemFromAgentData(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// Create test user
userRecord, err := createTestUser(testApp)
@@ -425,7 +445,7 @@ func TestUniversalTokenFlow(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer testApp.Cleanup()
defer cleanupTestHub(nil, testApp)
// Create test user
userRecord, err := createTestUser(testApp)
@@ -493,7 +513,7 @@ func TestAgentConnect(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// Create test user
userRecord, err := createTestUser(testApp)
@@ -652,7 +672,7 @@ func TestHandleAgentConnect(t *testing.T) {
if err != nil {
t.Fatal(err)
}
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// Create test user
userRecord, err := createTestUser(testApp)
@@ -737,7 +757,7 @@ func TestAgentWebSocketIntegration(t *testing.T) {
// Create hub and test app
hub, testApp, err := createTestHub(t)
require.NoError(t, err)
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// Get the hub's SSH key
hubSigner, err := hub.GetSSHKey("")
@@ -942,6 +962,8 @@ func TestAgentWebSocketIntegration(t *testing.T) {
}
}
time.Sleep(20 * time.Millisecond)
// Verify fingerprint state by re-reading the specific record
updatedFingerprintRecord, err := testApp.FindRecordById("fingerprints", fingerprintRecord.Id)
require.NoError(t, err)
@@ -976,7 +998,7 @@ func TestMultipleSystemsWithSameUniversalToken(t *testing.T) {
// Create hub and test app
hub, testApp, err := createTestHub(t)
require.NoError(t, err)
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// Get the hub's SSH key
hubSigner, err := hub.GetSSHKey("")
@@ -1144,6 +1166,8 @@ func TestMultipleSystemsWithSameUniversalToken(t *testing.T) {
assert.Equal(t, systemCount, systemsAfterCount, "Total system count should remain the same")
}
time.Sleep(20 * time.Millisecond)
// Verify that a fingerprint record exists for this fingerprint
fingerprints, err := testApp.FindRecordsByFilter("fingerprints", "token = {:token} && fingerprint = {:fingerprint}", "", -1, 0, map[string]any{
"token": universalToken,
@@ -1176,7 +1200,7 @@ func TestPermanentUniversalTokenFromDB(t *testing.T) {
// Create hub and test app
hub, testApp, err := createTestHub(t)
require.NoError(t, err)
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// Get the hub's SSH key
hubSigner, err := hub.GetSSHKey("")
@@ -1273,7 +1297,7 @@ verify:
func TestFindOrCreateSystemForToken(t *testing.T) {
hub, testApp, err := createTestHub(t)
require.NoError(t, err)
defer testApp.Cleanup()
defer cleanupTestHub(hub, testApp)
// Create test user
userRecord, err := createTestUser(testApp)

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package config_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package expirymap

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package heartbeat_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package hub_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package hub

View File

@@ -1,5 +1,4 @@
//go:build !testing
// +build !testing
package systems

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package systems_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package systems

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package ws

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package ws

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package ws

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package records_test

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
package records

View File

@@ -656,14 +656,14 @@ function DiskSheet({
</Tooltip>
</SheetDescription>
</SheetHeader>
<div className="flex-1 overflow-auto p-4 flex flex-col gap-4">
<div className="flex-1 overflow-hidden p-4 flex flex-col gap-4">
{isLoading ? (
<div className="flex justify-center py-8">
<LoaderCircleIcon className="animate-spin size-10 opacity-60" />
</div>
) : (
<>
<Alert className="pb-3">
<Alert className="pb-3 shrink-0">
{status === "PASSED" ? <CheckCircle2Icon className="size-4" /> : <XCircleIcon className="size-4" />}
<AlertTitle>
<Trans>S.M.A.R.T. Self-Test</Trans>: {status}
@@ -675,9 +675,9 @@ function DiskSheet({
)}
</Alert>
{smartAttributes.length > 0 ? (
<div className="rounded-md border overflow-auto">
<div className="rounded-md border min-h-0 flex flex-col">
<Table>
<TableHeader>
<TableHeader className="sticky top-0 z-10">
{table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}>
{headerGroup.headers.map((header) => (

View File

@@ -33,7 +33,6 @@ import {
decimalString,
formatBytes,
formatTemperature,
getMeterState,
parseSemVer,
secondsToUptimeString,
} from "@/lib/utils"
@@ -81,6 +80,10 @@ const STATUS_COLORS = {
[SystemStatus.Pending]: "bg-yellow-500",
} as const
function getMeterStateByThresholds(value: number, warn = 65, crit = 90): MeterState {
return value >= crit ? MeterState.Crit : value >= warn ? MeterState.Warn : MeterState.Good
}
/**
* @param viewMode - "table" or "grid"
* @returns - Column definitions for the systems table
@@ -209,6 +212,7 @@ export function SystemsTableColumns(viewMode: "table" | "grid"): ColumnDef<Syste
header: sortableHeader,
cell(info: CellContext<SystemRecord, unknown>) {
const { info: sysInfo, status } = info.row.original
const { colorWarn = 65, colorCrit = 90 } = useStore($userSettings, { keys: ["colorWarn", "colorCrit"] })
// agent version
const { minor, patch } = parseSemVer(sysInfo.v)
let loadAverages = sysInfo.la
@@ -224,7 +228,7 @@ export function SystemsTableColumns(viewMode: "table" | "grid"): ColumnDef<Syste
}
const normalizedLoad = max / (sysInfo.t ?? 1)
const threshold = getMeterState(normalizedLoad * 100)
const threshold = getMeterStateByThresholds(normalizedLoad * 100, colorWarn, colorCrit)
return (
<div className="flex items-center gap-[.35em] w-full tabular-nums tracking-tight">
@@ -463,8 +467,9 @@ function sortableHeader(context: HeaderContext<SystemRecord, unknown>) {
}
function TableCellWithMeter(info: CellContext<SystemRecord, unknown>) {
const { colorWarn = 65, colorCrit = 90 } = useStore($userSettings, { keys: ["colorWarn", "colorCrit"] })
const val = Number(info.getValue()) || 0
const threshold = getMeterState(val)
const threshold = getMeterStateByThresholds(val, colorWarn, colorCrit)
const meterClass = cn(
"h-full",
(info.row.original.status !== SystemStatus.Up && STATUS_COLORS.paused) ||
@@ -483,6 +488,7 @@ function TableCellWithMeter(info: CellContext<SystemRecord, unknown>) {
}
function DiskCellWithMultiple(info: CellContext<SystemRecord, unknown>) {
const { colorWarn = 65, colorCrit = 90 } = useStore($userSettings, { keys: ["colorWarn", "colorCrit"] })
const { info: sysInfo, status, id } = info.row.original
const extraFs = Object.entries(sysInfo.efs ?? {})
@@ -496,7 +502,7 @@ function DiskCellWithMultiple(info: CellContext<SystemRecord, unknown>) {
extraFs.sort((a, b) => b[1] - a[1])
function getIndicatorColor(pct: number) {
const threshold = getMeterState(pct)
const threshold = getMeterStateByThresholds(pct, colorWarn, colorCrit)
return (
(status !== SystemStatus.Up && STATUS_COLORS.paused) ||
(threshold === MeterState.Good && STATUS_COLORS.up) ||
@@ -514,7 +520,9 @@ function DiskCellWithMultiple(info: CellContext<SystemRecord, unknown>) {
const extraDiskIndicators =
status !== SystemStatus.Up
? []
: [...new Set(extraFs.map(([, pct]) => getMeterState(pct)))].sort().map((state) => stateColors[state])
: [...new Set(extraFs.map(([, pct]) => getMeterStateByThresholds(pct, colorWarn, colorCrit)))]
.sort()
.map((state) => stateColors[state])
return (
<Tooltip>

View File

@@ -6,7 +6,7 @@ import { useEffect, useState } from "react"
import { twMerge } from "tailwind-merge"
import { toast } from "@/components/ui/use-toast"
import type { ChartTimeData, FingerprintRecord, SemVer, SystemRecord } from "@/types"
import { HourFormat, MeterState, Unit } from "./enums"
import { HourFormat, Unit } from "./enums"
import { $copyContent, $userSettings } from "./stores"
export function cn(...inputs: ClassValue[]) {
@@ -210,7 +210,6 @@ export function useBrowserStorage<T>(key: string, defaultValue: T, storageInterf
const [value, setValue] = useState(() => {
return getStorageValue(key, defaultValue, storageInterface)
})
// biome-ignore lint/correctness/useExhaustiveDependencies: storageInterface won't change
useEffect(() => {
storageInterface?.setItem(key, JSON.stringify(value))
}, [key, value])
@@ -394,12 +393,6 @@ export function compareSemVer(a: SemVer, b: SemVer) {
return a.patch - b.patch
}
/** Get meter state from 0-100 value. Used for color coding meters. */
export function getMeterState(value: number): MeterState {
const { colorWarn = 65, colorCrit = 90 } = $userSettings.get()
return value >= colorCrit ? MeterState.Crit : value >= colorWarn ? MeterState.Warn : MeterState.Good
}
// biome-ignore lint/suspicious/noExplicitAny: any is used to allow any function to be passed in
export function debounce<T extends (...args: any[]) => any>(func: T, wait: number): (...args: Parameters<T>) => void {
let timeout: ReturnType<typeof setTimeout>

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: bg\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-01-31 21:16\n"
"PO-Revision-Date: 2026-02-25 11:49\n"
"Last-Translator: \n"
"Language-Team: Bulgarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -357,7 +357,7 @@ msgstr "Провери log-овете за повече информация."
#: src/components/routes/settings/heartbeat.tsx
msgid "Check your monitoring service"
msgstr "Проверете вашата услуга за мониторинг"
msgstr "Проверете мониторинг услугата си"
#: src/components/routes/settings/notifications.tsx
msgid "Check your notification service"
@@ -937,7 +937,6 @@ msgstr "Средно натоварване"
msgid "Load state"
msgstr "Състояние на зареждане"
#: src/components/routes/settings/heartbeat.tsx
#: src/components/systemd-table/systemd-table.tsx
msgid "Loading..."
msgstr "Зареждане..."
@@ -1378,7 +1377,7 @@ msgstr "Избери {foo}"
#: src/components/routes/settings/heartbeat.tsx
msgid "Send a single heartbeat ping to verify your endpoint is working."
msgstr "Изпратете единичен heartbeat пинг, за да проверите дали вашата крайна точка работи."
msgstr "Изпратете единичен heartbeat пинг, за да се уверите, че крайната Ви точка работи."
#: src/components/routes/settings/heartbeat.tsx
msgid "Send periodic outbound pings to an external monitoring service so you can monitor Beszel without exposing it to the internet."
@@ -1410,7 +1409,7 @@ msgstr "Задайте процентни прагове за цветовете
#: src/components/routes/settings/heartbeat.tsx
msgid "Set the following environment variables on your Beszel hub to enable heartbeat monitoring:"
msgstr "Задайте следните променливи на средата на вашия Beszel hub, за да активирате мониторинга на heartbeat:"
msgstr "Задайте следните променливи на средата на вашия Beszel hub, за да активирате heartbeat мониторинг:"
#: src/components/command-palette.tsx
#: src/components/command-palette.tsx
@@ -1800,7 +1799,7 @@ msgstr "Webhook / Пуш нотификации"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "When enabled, this token allows agents to self-register without prior system creation."
msgstr "Когато е активиран, този символ позволява на агентите да се регистрират сами без предварително създаване на система."
msgstr "Когато е активиран, този токен позволява на агентите да се регистрират сами без предварително създаване на система."
#: src/components/routes/settings/heartbeat.tsx
msgid "When using POST, each heartbeat includes a JSON payload with system status summary, list of down systems, and triggered alerts."
@@ -1835,3 +1834,4 @@ msgstr "Да"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Настройките за потребителя ти са обновени."

View File

@@ -1729,7 +1729,7 @@ msgstr "Odeslání"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Doba provozu"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-01-31 21:16\n"
"PO-Revision-Date: 2026-03-14 20:37\n"
"Last-Translator: \n"
"Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -236,7 +236,7 @@ msgstr "Bandbreite"
#. Battery label in systems table header
#: src/components/systems-table/systems-table-columns.tsx
msgid "Bat"
msgstr "Bat"
msgstr "Batt"
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
@@ -937,7 +937,6 @@ msgstr "Systemlast"
msgid "Load state"
msgstr "Ladezustand"
#: src/components/routes/settings/heartbeat.tsx
#: src/components/systemd-table/systemd-table.tsx
msgid "Loading..."
msgstr "Lädt..."
@@ -1178,7 +1177,7 @@ msgstr "Prozentsatz der Zeit in jedem Zustand"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Permanent"
msgstr "Permanent"
msgstr "Dauerhaft"
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Persistence"
@@ -1835,3 +1834,4 @@ msgstr "Ja"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Deine Benutzereinstellungen wurden aktualisiert."

View File

@@ -1729,7 +1729,7 @@ msgstr "Cargar"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Tiempo de actividad"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -1729,7 +1729,7 @@ msgstr "Téléverser"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Temps de fonctionnement"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -1729,7 +1729,7 @@ msgstr "Otpremi"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Vrijeme rada"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -1729,7 +1729,7 @@ msgstr "Carica"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Tempo di attività"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -1729,7 +1729,7 @@ msgstr "업로드"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "가동 시간"
msgstr "가동시간"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: nl\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-02-19 19:40\n"
"PO-Revision-Date: 2026-02-24 11:37\n"
"Last-Translator: \n"
"Language-Team: Dutch\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -836,7 +836,7 @@ msgstr "Gezondheid"
#: src/components/routes/settings/layout.tsx
msgid "Heartbeat"
msgstr "Heartbeat"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx
msgid "Heartbeat Monitoring"
@@ -884,7 +884,7 @@ msgstr "Inactief"
#: src/components/routes/settings/heartbeat.tsx
msgid "Interval"
msgstr "Interval"
msgstr ""
#: src/components/login/auth-form.tsx
msgid "Invalid email address."
@@ -937,7 +937,6 @@ msgstr "Gem. Belasting"
msgid "Load state"
msgstr "Laadstatus"
#: src/components/routes/settings/heartbeat.tsx
#: src/components/systemd-table/systemd-table.tsx
msgid "Loading..."
msgstr "Laden..."
@@ -1835,3 +1834,4 @@ msgstr "Ja"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Je gebruikersinstellingen zijn bijgewerkt."

View File

@@ -1729,7 +1729,7 @@ msgstr "Wysyłanie"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Czas pracy"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -1729,7 +1729,7 @@ msgstr "Carregar"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Tempo de Atividade"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ru\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-01-31 21:16\n"
"PO-Revision-Date: 2026-02-21 09:46\n"
"Last-Translator: \n"
"Language-Team: Russian\n"
"Plural-Forms: nplurals=4; plural=((n%10==1 && n%100!=11) ? 0 : ((n%10 >= 2 && n%10 <=4 && (n%100 < 12 || n%100 > 14)) ? 1 : ((n%10 == 0 || (n%10 >= 5 && n%10 <=9)) || (n%100 >= 11 && n%100 <= 14)) ? 2 : 3));\n"
@@ -937,7 +937,6 @@ msgstr "Ср. загрузка"
msgid "Load state"
msgstr "Состояние загрузки"
#: src/components/routes/settings/heartbeat.tsx
#: src/components/systemd-table/systemd-table.tsx
msgid "Loading..."
msgstr "Загрузка..."
@@ -1835,3 +1834,4 @@ msgstr "Да"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Ваши настройки пользователя были обновлены."

View File

@@ -1729,7 +1729,7 @@ msgstr "Naloži"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Čas delovanja"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: sr\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-02-03 15:27\n"
"PO-Revision-Date: 2026-02-23 15:11\n"
"Last-Translator: \n"
"Language-Team: Serbian (Cyrillic)\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
@@ -836,7 +836,7 @@ msgstr "Здравље"
#: src/components/routes/settings/layout.tsx
msgid "Heartbeat"
msgstr "Heartbeat"
msgstr "Оркуцај"
#: src/components/routes/settings/heartbeat.tsx
msgid "Heartbeat Monitoring"
@@ -884,7 +884,7 @@ msgstr "Неактивно"
#: src/components/routes/settings/heartbeat.tsx
msgid "Interval"
msgstr "Interval"
msgstr "Интервал"
#: src/components/login/auth-form.tsx
msgid "Invalid email address."
@@ -937,7 +937,6 @@ msgstr "Просечно опт."
msgid "Load state"
msgstr "Стање учитавања"
#: src/components/routes/settings/heartbeat.tsx
#: src/components/systemd-table/systemd-table.tsx
msgid "Loading..."
msgstr "Учитавање..."
@@ -1835,3 +1834,4 @@ msgstr "Да"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Ваша корисничка подешавања су ажурирана."

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: tr\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-01-31 21:16\n"
"PO-Revision-Date: 2026-03-02 13:16\n"
"Last-Translator: \n"
"Language-Team: Turkish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -143,7 +143,7 @@ msgstr "Sonra"
#: src/components/routes/settings/heartbeat.tsx
msgid "After setting the environment variables, restart your Beszel hub for changes to take effect."
msgstr "Ortam değişkenlerini ayarladıktan sonra, değişikliklerin etkili olması için Beszel hub'ınızı yeniden başlatın."
msgstr "Ortam değişkenlerini ayarladıktan sonra, değişikliklerin etkili olması için Beszel Hub'ınızı yeniden başlatın."
#: src/components/systems-table/systems-table-columns.tsx
msgid "Agent"
@@ -466,7 +466,7 @@ msgstr "YAML'ı kopyala"
#: src/components/systemd-table/systemd-table-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "CPU"
msgstr "CPU"
msgstr "İşlemci"
#: src/components/routes/system/cpu-sheet.tsx
msgid "CPU Cores"
@@ -565,7 +565,7 @@ msgstr "Boşalıyor"
#: src/components/systems-table/systems-table-columns.tsx
msgid "Disk"
msgstr "Disk"
msgstr "Depolama alanı"
#: src/components/routes/system.tsx
msgid "Disk I/O"
@@ -836,7 +836,7 @@ msgstr "Sağlık"
#: src/components/routes/settings/layout.tsx
msgid "Heartbeat"
msgstr "Heartbeat"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx
msgid "Heartbeat Monitoring"
@@ -937,7 +937,6 @@ msgstr "Yük Ort."
msgid "Load state"
msgstr "Yükleme durumu"
#: src/components/routes/settings/heartbeat.tsx
#: src/components/systemd-table/systemd-table.tsx
msgid "Loading..."
msgstr "Yükleniyor..."
@@ -1011,7 +1010,7 @@ msgstr "Docker konteynerlerinin bellek kullanımı"
#: src/components/routes/system/smart-table.tsx
msgid "Model"
msgstr "Model"
msgstr ""
#: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
@@ -1531,7 +1530,7 @@ msgstr "<0>URL</0>'yi Test Et"
#: src/components/routes/settings/heartbeat.tsx
msgid "Test heartbeat"
msgstr "Test heartbeat"
msgstr ""
#: src/components/routes/settings/notifications.tsx
msgid "Test notification sent"
@@ -1582,7 +1581,7 @@ msgstr "Temayı değiştir"
#: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token"
msgstr "Token"
msgstr "Erişim Anahtarı"
#: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
@@ -1835,3 +1834,4 @@ msgstr "Evet"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "Kullanıcı ayarlarınız güncellendi."

View File

@@ -1729,7 +1729,7 @@ msgstr "Відвантажити"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Час роботи"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -1729,7 +1729,7 @@ msgstr "Tải lên"
#: src/components/routes/system/info-bar.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Uptime"
msgstr "Thời gian hoạt động"
msgstr "Uptime"
#: src/components/routes/system.tsx
#: src/components/routes/system.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: zh\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-01-31 21:16\n"
"PO-Revision-Date: 2026-03-01 17:14\n"
"Last-Translator: \n"
"Language-Team: Chinese Simplified\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -836,7 +836,7 @@ msgstr "健康"
#: src/components/routes/settings/layout.tsx
msgid "Heartbeat"
msgstr "Heartbeat"
msgstr "心跳"
#: src/components/routes/settings/heartbeat.tsx
msgid "Heartbeat Monitoring"
@@ -937,7 +937,6 @@ msgstr "负载"
msgid "Load state"
msgstr "加载状态"
#: src/components/routes/settings/heartbeat.tsx
#: src/components/systemd-table/systemd-table.tsx
msgid "Loading..."
msgstr "加载中..."
@@ -1835,3 +1834,4 @@ msgstr "是"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "您的用户设置已更新。"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: zh\n"
"Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2026-01-31 21:16\n"
"PO-Revision-Date: 2026-02-20 02:25\n"
"Last-Translator: \n"
"Language-Team: Chinese Traditional, Hong Kong\n"
"Plural-Forms: nplurals=1; plural=0;\n"
@@ -836,7 +836,7 @@ msgstr "健康狀態"
#: src/components/routes/settings/layout.tsx
msgid "Heartbeat"
msgstr "Heartbeat"
msgstr ""
#: src/components/routes/settings/heartbeat.tsx
msgid "Heartbeat Monitoring"
@@ -1835,3 +1835,4 @@ msgstr "是"
#: src/components/routes/settings/layout.tsx
msgid "Your user settings have been updated."
msgstr "您的用戶設置已更新。"

View File

@@ -100,7 +100,7 @@ const Layout = () => {
<LoginPage />
</Suspense>
) : (
<div style={{ "--container": `${userSettings.layoutWidth ?? 1500}px` } as React.CSSProperties}>
<div style={{ "--container": `${userSettings.layoutWidth ?? 1580}px` } as React.CSSProperties}>
<div className="container">
<Navbar />
</div>

View File

@@ -1,5 +1,4 @@
//go:build testing
// +build testing
// Package tests provides helpers for testing the application.
package tests