Compare commits

..

70 Commits

Author SHA1 Message Date
henrygd
5e37469ea9 0.12.7 release :) 2025-09-05 14:00:24 -04:00
henrygd
e027479bb1 make sure initial user is verfied when supplying user/pass 2025-09-05 14:00:21 -04:00
henrygd
1597e869c1 update translations 2025-09-05 13:53:17 -04:00
henrygd
862399d8ec update language files 2025-09-05 12:36:45 -04:00
henrygd
f6f85f8f9d Add USER_EMAIL and USER_PASSWORD env vars to set the email / pass of initial user (#1137) 2025-09-05 11:42:43 -04:00
Riedel, Max
e22d7ca801 fix: add nextSystemToken to deps of useEffect to generate a new token after system creation (#1142) 2025-09-05 11:00:32 -04:00
henrygd
c382c1d5f6 windows: make LHM opt-in with LHM=true (#1130) 2025-09-05 10:39:18 -04:00
henrygd
f7618ed6b0 update go version for vulcheck action 2025-09-04 19:17:44 -04:00
henrygd
d1295b7c50 alerts tests and small refactoring 2025-09-04 19:13:10 -04:00
henrygd
a162a54a58 bump go version and add keyword 2025-09-04 19:13:10 -04:00
henrygd
794db0ac6a make sure old names are removed in systemsbyname store 2025-09-04 19:13:10 -04:00
henrygd
e9fb9b856f install script: remove newlines from KEY (#1139) 2025-09-04 11:26:53 -04:00
Sven van Ginkel
66bca11d36 [Bug] Update install script to use crontab on Alpine (#1136)
* add cron

* update the install script
2025-09-03 23:10:38 -04:00
henrygd
86e87f0d47 refactor hub dev server
- moved html replacement functionality from vite to go
2025-09-01 22:16:57 -04:00
henrygd
fadfc5d81d refactor(hub): separate development and production server logic 2025-09-01 19:27:11 -04:00
henrygd
fc39ff1e4d add pflag to go deps 2025-09-01 19:24:26 -04:00
henrygd
82ccfc66e0 refactor: shared container charts config hook 2025-09-01 18:41:30 -04:00
henrygd
890bad1c39 refactor: improve runOnce with weakmap cache 2025-09-01 18:34:29 -04:00
henrygd
9c458885f1 refactor (hub): add systemsManager module
- Removed the `updateSystemList` function and replaced it with a more efficient system management approach using `systemsManager`.
- Updated the `App` component to initialize and subscribe to system updates through the new `systemsManager`.
- Refactored the `SystemsTable` and `SystemDetail` components to utilize the new state management for systems, improving performance and maintainability.
- Enhanced the `ActiveAlerts` component to fetch system names directly from the new state structure.
2025-09-01 17:29:33 -04:00
henrygd
d2aed0dc72 refactor: replace useLocalStorage with useBrowserStorage 2025-09-01 17:28:13 -04:00
Augustin ROLET
3dbcb5d7da Minor UI changes (#1110)
* ui: add devices count from #1078

* ux: save sortMode in localStorage from #1024

* fix: reload component when system switch to "up"

* ux: move running systems to desc field
2025-08-31 18:16:25 -04:00
Alexander Mnich
57a1a8b39e [Feature] improved support for mips and mipsle architectures (#1112)
* switch mipsle to softfloat

* feat: add support for mips
2025-08-30 15:50:15 -04:00
Alexander Mnich
ab81c04569 [Fix] fix GitHub workflow errors in forks (#1113)
* feat: do not run winget/homebrew/scoop release in fork

* fix: replaced deprecated goreleaser fields

https://goreleaser.com/deprecations/#archivesbuilds

* fix: push docker images only with access to the registry
2025-08-30 15:49:49 -04:00
henrygd
0c32be3bea 0.12.6 release :) 2025-08-29 17:24:45 -04:00
henrygd
81d43fbf6e refactor: small style improvements 2025-08-29 17:23:47 -04:00
henrygd
96f441de40 Virtualize All Systems table to improve performance with hundreds of systems (#1100)
- Also truncate long system names in tables and alerts sheet. (#1104)
2025-08-29 16:16:45 -04:00
henrygd
0e95caaee9 update command ui component 2025-08-29 15:04:26 -04:00
Sven van Ginkel
7697a12b42 fix alignment for metrics (#1109) 2025-08-29 14:00:17 -04:00
henrygd
94245a9ba4 fix update mirror and make opt-in with --china-mirrors (#1035) 2025-08-29 13:46:24 -04:00
henrygd
b084814aea auth form: fix border style and add theme toggle 2025-08-28 21:17:44 -04:00
Impact
cce74246ee Use older cuda image for increased compatibility (#1103) 2025-08-28 20:49:52 -04:00
henrygd
a3420b8c67 add max 1 min memory 2025-08-28 20:07:22 -04:00
henrygd
e1bb17ee9e update locale files 2025-08-28 18:23:40 -04:00
henrygd
52983f60b7 refactor: add api module and page preloading 2025-08-28 18:23:24 -04:00
henrygd
1f053fd85d update 2025-08-28 17:31:18 -04:00
Sven van Ginkel
a989d121d3 [Feature] Add Status Filtering to Systems Table (#927) 2025-08-28 17:30:44 -04:00
Sven van Ginkel
50d2406423 [Bug] Fix system table in Safari (#1092)
Co-authored-by: henrygd <hank@henrygd.me>
2025-08-28 12:07:27 -04:00
Sven van Ginkel
059d2d0a5b Add missing os.Chmod step to hub update command (#1093) 2025-08-27 13:00:03 -04:00
henrygd
621bef30b5 update changelog 2025-08-26 21:26:18 -04:00
henrygd
5f4d3dc730 0.12.5 release :) 2025-08-26 21:04:46 -04:00
henrygd
8fa9aece63 change long german translation 2025-08-26 20:50:35 -04:00
henrygd
2f1a022e2a refactor: use width for meters instead of scale 2025-08-26 20:49:31 -04:00
henrygd
4815cd29bc ghupdate: rename plugin struct 2025-08-26 18:41:42 -04:00
henrygd
e49bfaf5d7 downgrade gopsutil to fix freebsd bug (#1083) 2025-08-26 18:40:32 -04:00
henrygd
b13915b76f freebsd: fix battery-related bug (#1081) 2025-08-26 18:39:42 -04:00
henrygd
e2a57dc43b update tooltip component for tailwind 4 2025-08-26 16:16:38 -04:00
henrygd
7222224b40 add battery to supported metrics 2025-08-25 23:15:19 -04:00
henrygd
02ff475b84 improve language toggle selected style 2025-08-25 22:14:48 -04:00
henrygd
09cd8d0db9 add check for battery array length (#1076) 2025-08-25 21:34:34 -04:00
henrygd
36f1a0c53b update synctest.run to synctest.test 2025-08-25 21:25:19 -04:00
henrygd
0b0e94e045 remove pocketbase imports from ghupdate 2025-08-25 21:16:43 -04:00
henrygd
20ca6edf81 0.12.4 release :) 2025-08-25 20:23:38 -04:00
henrygd
1990f8c6df use mirror for asset download in update command (#1035) 2025-08-25 20:18:31 -04:00
henrygd
6e9dbf863f remove rhysd/go-github-selfupdate dependency 2025-08-25 20:05:02 -04:00
henrygd
fa921d77f1 update updater (#1009) 2025-08-25 20:04:23 -04:00
Sven van Ginkel
ff854d481d [Chore] Improve auto update mechanism (#1009) 2025-08-25 17:30:42 -04:00
henrygd
4ce491fe48 i18n: add default machine translations for new strings 2025-08-25 17:02:34 -04:00
henrygd
493bae7eb6 i18n: new battery strings 2025-08-25 16:46:15 -04:00
henrygd
ae5532aa36 new translations 2025-08-25 16:37:20 -04:00
NaNomicon
a1eae6413a New Vietnamese translations 2025-08-25 16:36:41 -04:00
henrygd
ee52bf1fbf New Polish translations by dymek37 2025-08-25 16:32:15 -04:00
Alex van Steenhoven
2ff0bd6b44 New Dutch translations 2025-08-25 16:30:57 -04:00
harupong
a385233b7d New Japanese translations 2025-08-25 16:28:02 -04:00
henrygd
f5648a415d New Italian translations by Tommaso Cavazza 2025-08-25 16:27:35 -04:00
Radoslav Mandev
556fb18953 New Bulgarian translations 2025-08-25 16:26:03 -04:00
henrygd
a482f78739 add changelog 2025-08-25 16:21:07 -04:00
henrygd
4a580ce972 tailwind 4 upgrade + update js deps 2025-08-25 16:12:15 -04:00
henrygd
e07558237f remove dropdown from theme mode toggle 2025-08-25 16:09:49 -04:00
henrygd
fb3c70a1bc update battery charge to include all batteries 2025-08-24 22:34:38 -04:00
henrygd
cba4d60895 improve chart legend alignment 2025-08-24 22:34:26 -04:00
122 changed files with 7726 additions and 3939 deletions

View File

@@ -93,7 +93,9 @@ jobs:
# https://github.com/docker/login-action # https://github.com/docker/login-action
- name: Login to Docker Hub - name: Login to Docker Hub
if: github.event_name != 'pull_request' env:
password_secret_exists: ${{ secrets[matrix.password_secret] != '' && 'true' || 'false' }}
if: github.event_name != 'pull_request' && env.password_secret_exists == 'true'
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
username: ${{ matrix.username || secrets[matrix.username_secret] }} username: ${{ matrix.username || secrets[matrix.username_secret] }}
@@ -108,6 +110,6 @@ jobs:
context: "${{ matrix.context }}" context: "${{ matrix.context }}"
file: ${{ matrix.dockerfile }} file: ${{ matrix.dockerfile }}
platforms: ${{ matrix.platforms || 'linux/amd64,linux/arm64,linux/arm/v7' }} platforms: ${{ matrix.platforms || 'linux/amd64,linux/arm64,linux/arm/v7' }}
push: ${{ github.ref_type == 'tag' }} push: ${{ github.ref_type == 'tag' && secrets[matrix.password_secret] != '' }}
tags: ${{ steps.metadata.outputs.tags }} tags: ${{ steps.metadata.outputs.tags }}
labels: ${{ steps.metadata.outputs.labels }} labels: ${{ steps.metadata.outputs.labels }}

View File

@@ -51,3 +51,4 @@ jobs:
env: env:
GITHUB_TOKEN: ${{ secrets.TOKEN || secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.TOKEN || secrets.GITHUB_TOKEN }}
WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }} WINGET_TOKEN: ${{ secrets.WINGET_TOKEN }}
IS_FORK: ${{ github.repository_owner != 'henrygd' }}

View File

@@ -15,7 +15,7 @@ permissions:
jobs: jobs:
vulncheck: vulncheck:
name: Analysis name: VulnCheck
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Check out code into the Go module directory - name: Check out code into the Go module directory
@@ -23,8 +23,8 @@ jobs:
- name: Set up Go - name: Set up Go
uses: actions/setup-go@v5 uses: actions/setup-go@v5
with: with:
go-version: 1.24.x go-version: 1.25.x
cached: false # cached: false
- name: Get official govulncheck - name: Get official govulncheck
run: go install golang.org/x/vuln/cmd/govulncheck@latest run: go install golang.org/x/vuln/cmd/govulncheck@latest
shell: bash shell: bash

View File

@@ -38,12 +38,25 @@ builds:
- mips64 - mips64
- riscv64 - riscv64
- mipsle - mipsle
- mips
- ppc64le - ppc64le
gomips:
- hardfloat
- softfloat
ignore: ignore:
- goos: freebsd - goos: freebsd
goarch: arm goarch: arm
- goos: openbsd - goos: openbsd
goarch: arm goarch: arm
- goos: linux
goarch: mips64
gomips: softfloat
- goos: linux
goarch: mipsle
gomips: hardfloat
- goos: linux
goarch: mips
gomips: hardfloat
- goos: windows - goos: windows
goarch: arm goarch: arm
- goos: darwin - goos: darwin
@@ -54,7 +67,7 @@ builds:
archives: archives:
- id: beszel-agent - id: beszel-agent
formats: [tar.gz] formats: [tar.gz]
builds: ids:
- beszel-agent - beszel-agent
name_template: >- name_template: >-
{{ .Binary }}_ {{ .Binary }}_
@@ -66,7 +79,7 @@ archives:
- id: beszel - id: beszel
formats: [tar.gz] formats: [tar.gz]
builds: ids:
- beszel - beszel
name_template: >- name_template: >-
{{ .Binary }}_ {{ .Binary }}_
@@ -85,7 +98,7 @@ nfpms:
API access. API access.
maintainer: henrygd <hank@henrygd.me> maintainer: henrygd <hank@henrygd.me>
section: net section: net
builds: ids:
- beszel-agent - beszel-agent
formats: formats:
- deb - deb
@@ -122,6 +135,7 @@ scoops:
homepage: "https://beszel.dev" homepage: "https://beszel.dev"
description: "Agent for Beszel, a lightweight server monitoring platform." description: "Agent for Beszel, a lightweight server monitoring platform."
license: MIT license: MIT
skip_upload: "{{ if .Env.IS_FORK }}true{{ else }}auto{{ end }}"
# # Needs choco installed, so doesn't build on linux / default gh workflow :( # # Needs choco installed, so doesn't build on linux / default gh workflow :(
# chocolateys: # chocolateys:
@@ -155,7 +169,7 @@ brews:
homepage: "https://beszel.dev" homepage: "https://beszel.dev"
description: "Agent for Beszel, a lightweight server monitoring platform." description: "Agent for Beszel, a lightweight server monitoring platform."
license: MIT license: MIT
skip_upload: auto skip_upload: "{{ if .Env.IS_FORK }}true{{ else }}auto{{ end }}"
extra_install: | extra_install: |
(bin/"beszel-agent-launcher").write <<~EOS (bin/"beszel-agent-launcher").write <<~EOS
#!/bin/bash #!/bin/bash
@@ -187,7 +201,7 @@ winget:
release_notes_url: "https://github.com/henrygd/beszel/releases/tag/v{{ .Version }}" release_notes_url: "https://github.com/henrygd/beszel/releases/tag/v{{ .Version }}"
publisher_support_url: "https://github.com/henrygd/beszel/issues" publisher_support_url: "https://github.com/henrygd/beszel/issues"
short_description: "Agent for Beszel, a lightweight server monitoring platform." short_description: "Agent for Beszel, a lightweight server monitoring platform."
skip_upload: auto skip_upload: "{{ if .Env.IS_FORK }}true{{ else }}auto{{ end }}"
description: | description: |
Beszel is a lightweight server monitoring platform that includes Docker Beszel is a lightweight server monitoring platform that includes Docker
statistics, historical data, and alert functions. It has a friendly web statistics, historical data, and alert functions. It has a friendly web

View File

@@ -7,7 +7,7 @@ SKIP_WEB ?= false
# Set executable extension based on target OS # Set executable extension based on target OS
EXE_EXT := $(if $(filter windows,$(OS)),.exe,) EXE_EXT := $(if $(filter windows,$(OS)),.exe,)
.PHONY: tidy build-agent build-hub build clean lint dev-server dev-agent dev-hub dev generate-locales .PHONY: tidy build-agent build-hub build-hub-dev build clean lint dev-server dev-agent dev-hub dev generate-locales
.DEFAULT_GOAL := build .DEFAULT_GOAL := build
clean: clean:
@@ -53,6 +53,10 @@ build-agent: tidy build-dotnet-conditional
build-hub: tidy $(if $(filter false,$(SKIP_WEB)),build-web-ui) build-hub: tidy $(if $(filter false,$(SKIP_WEB)),build-web-ui)
GOOS=$(OS) GOARCH=$(ARCH) go build -o ./build/beszel_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" beszel/cmd/hub GOOS=$(OS) GOARCH=$(ARCH) go build -o ./build/beszel_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" beszel/cmd/hub
build-hub-dev: tidy
mkdir -p ./site/dist && touch ./site/dist/index.html
GOOS=$(OS) GOARCH=$(ARCH) go build -tags development -o ./build/beszel-dev_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" beszel/cmd/hub
build: build-agent build-hub build: build-agent build-hub
generate-locales: generate-locales:
@@ -73,9 +77,9 @@ dev-hub: export ENV=dev
dev-hub: dev-hub:
mkdir -p ./site/dist && touch ./site/dist/index.html mkdir -p ./site/dist && touch ./site/dist/index.html
@if command -v entr >/dev/null 2>&1; then \ @if command -v entr >/dev/null 2>&1; then \
find ./cmd/hub/*.go ./internal/{alerts,hub,records,users}/*.go | entr -r -s "cd ./cmd/hub && go run . serve --http 0.0.0.0:8090"; \ find ./cmd/hub/*.go ./internal/{alerts,hub,records,users}/*.go | entr -r -s "cd ./cmd/hub && go run -tags development . serve --http 0.0.0.0:8090"; \
else \ else \
cd ./cmd/hub && go run . serve --http 0.0.0.0:8090; \ cd ./cmd/hub && go run -tags development . serve --http 0.0.0.0:8090; \
fi fi
dev-agent: dev-agent:

View File

@@ -4,12 +4,12 @@ import (
"beszel" "beszel"
"beszel/internal/agent" "beszel/internal/agent"
"beszel/internal/agent/health" "beszel/internal/agent/health"
"flag"
"fmt" "fmt"
"log" "log"
"os" "os"
"strings" "strings"
"github.com/spf13/pflag"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
) )
@@ -17,43 +17,24 @@ import (
type cmdOptions struct { type cmdOptions struct {
key string // key is the public key(s) for SSH authentication. key string // key is the public key(s) for SSH authentication.
listen string // listen is the address or port to listen on. listen string // listen is the address or port to listen on.
// TODO: add hubURL and token
// hubURL string // hubURL is the URL of the hub to use.
// token string // token is the token to use for authentication.
} }
// parse parses the command line flags and populates the config struct. // parse parses the command line flags and populates the config struct.
// It returns true if a subcommand was handled and the program should exit. // It returns true if a subcommand was handled and the program should exit.
func (opts *cmdOptions) parse() bool { func (opts *cmdOptions) parse() bool {
flag.StringVar(&opts.key, "key", "", "Public key(s) for SSH authentication")
flag.StringVar(&opts.listen, "listen", "", "Address or port to listen on")
flag.Usage = func() {
builder := strings.Builder{}
builder.WriteString("Usage: ")
builder.WriteString(os.Args[0])
builder.WriteString(" [command] [flags]\n")
builder.WriteString("\nCommands:\n")
builder.WriteString(" health Check if the agent is running\n")
builder.WriteString(" help Display this help message\n")
builder.WriteString(" update Update to the latest version\n")
builder.WriteString("\nFlags:\n")
fmt.Print(builder.String())
flag.PrintDefaults()
}
subcommand := "" subcommand := ""
if len(os.Args) > 1 { if len(os.Args) > 1 {
subcommand = os.Args[1] subcommand = os.Args[1]
} }
// Subcommands that don't require any pflag parsing
switch subcommand { switch subcommand {
case "-v", "version": case "-v", "version":
fmt.Println(beszel.AppName+"-agent", beszel.Version) fmt.Println(beszel.AppName+"-agent", beszel.Version)
return true return true
case "help":
flag.Usage()
return true
case "update":
agent.Update()
return true
case "health": case "health":
err := health.Check() err := health.Check()
if err != nil { if err != nil {
@@ -63,7 +44,57 @@ func (opts *cmdOptions) parse() bool {
return true return true
} }
flag.Parse() // pflag.CommandLine.ParseErrorsWhitelist.UnknownFlags = true
pflag.StringVarP(&opts.key, "key", "k", "", "Public key(s) for SSH authentication")
pflag.StringVarP(&opts.listen, "listen", "l", "", "Address or port to listen on")
// pflag.StringVarP(&opts.hubURL, "hub-url", "u", "", "URL of the hub to use")
// pflag.StringVarP(&opts.token, "token", "t", "", "Token to use for authentication")
chinaMirrors := pflag.BoolP("china-mirrors", "c", false, "Use mirror for update (gh.beszel.dev) instead of GitHub")
help := pflag.BoolP("help", "h", false, "Show this help message")
// Convert old single-dash long flags to double-dash for backward compatibility
flagsToConvert := []string{"key", "listen"}
for i, arg := range os.Args {
for _, flag := range flagsToConvert {
singleDash := "-" + flag
doubleDash := "--" + flag
if arg == singleDash {
os.Args[i] = doubleDash
break
} else if strings.HasPrefix(arg, singleDash+"=") {
os.Args[i] = doubleDash + arg[len(singleDash):]
break
}
}
}
pflag.Usage = func() {
builder := strings.Builder{}
builder.WriteString("Usage: ")
builder.WriteString(os.Args[0])
builder.WriteString(" [command] [flags]\n")
builder.WriteString("\nCommands:\n")
builder.WriteString(" health Check if the agent is running\n")
// builder.WriteString(" help Display this help message\n")
builder.WriteString(" update Update to the latest version\n")
builder.WriteString("\nFlags:\n")
fmt.Print(builder.String())
pflag.PrintDefaults()
}
// Parse all arguments with pflag
pflag.Parse()
// Must run after pflag.Parse()
switch {
case *help || subcommand == "help":
pflag.Usage()
return true
case subcommand == "update":
agent.Update(*chinaMirrors)
return true
}
return false return false
} }

View File

@@ -3,11 +3,11 @@ package main
import ( import (
"beszel/internal/agent" "beszel/internal/agent"
"crypto/ed25519" "crypto/ed25519"
"flag"
"os" "os"
"path/filepath" "path/filepath"
"testing" "testing"
"github.com/spf13/pflag"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require" "github.com/stretchr/testify/require"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
@@ -245,7 +245,7 @@ func TestParseFlags(t *testing.T) {
oldArgs := os.Args oldArgs := os.Args
defer func() { defer func() {
os.Args = oldArgs os.Args = oldArgs
flag.CommandLine = flag.NewFlagSet(os.Args[0], flag.ExitOnError) pflag.CommandLine = pflag.NewFlagSet(os.Args[0], pflag.ExitOnError)
}() }()
tests := []struct { tests := []struct {
@@ -269,6 +269,22 @@ func TestParseFlags(t *testing.T) {
listen: "", listen: "",
}, },
}, },
{
name: "key flag double dash",
args: []string{"cmd", "--key", "testkey"},
expected: cmdOptions{
key: "testkey",
listen: "",
},
},
{
name: "key flag short",
args: []string{"cmd", "-k", "testkey"},
expected: cmdOptions{
key: "testkey",
listen: "",
},
},
{ {
name: "addr flag only", name: "addr flag only",
args: []string{"cmd", "-listen", ":8080"}, args: []string{"cmd", "-listen", ":8080"},
@@ -277,6 +293,22 @@ func TestParseFlags(t *testing.T) {
listen: ":8080", listen: ":8080",
}, },
}, },
{
name: "addr flag double dash",
args: []string{"cmd", "--listen", ":8080"},
expected: cmdOptions{
key: "",
listen: ":8080",
},
},
{
name: "addr flag short",
args: []string{"cmd", "-l", ":8080"},
expected: cmdOptions{
key: "",
listen: ":8080",
},
},
{ {
name: "both flags", name: "both flags",
args: []string{"cmd", "-key", "testkey", "-listen", ":8080"}, args: []string{"cmd", "-key", "testkey", "-listen", ":8080"},
@@ -290,12 +322,12 @@ func TestParseFlags(t *testing.T) {
for _, tt := range tests { for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) { t.Run(tt.name, func(t *testing.T) {
// Reset flags for each test // Reset flags for each test
flag.CommandLine = flag.NewFlagSet(tt.args[0], flag.ExitOnError) pflag.CommandLine = pflag.NewFlagSet(tt.args[0], pflag.ExitOnError)
os.Args = tt.args os.Args = tt.args
var opts cmdOptions var opts cmdOptions
opts.parse() opts.parse()
flag.Parse() pflag.Parse()
assert.Equal(t, tt.expected, opts) assert.Equal(t, tt.expected, opts)
}) })

View File

@@ -45,11 +45,13 @@ func getBaseApp() *pocketbase.PocketBase {
baseApp.RootCmd.Use = beszel.AppName baseApp.RootCmd.Use = beszel.AppName
baseApp.RootCmd.Short = "" baseApp.RootCmd.Short = ""
// add update command // add update command
baseApp.RootCmd.AddCommand(&cobra.Command{ updateCmd := &cobra.Command{
Use: "update", Use: "update",
Short: "Update " + beszel.AppName + " to the latest version", Short: "Update " + beszel.AppName + " to the latest version",
Run: hub.Update, Run: hub.Update,
}) }
updateCmd.Flags().Bool("china-mirrors", false, "Use mirror (gh.beszel.dev) instead of GitHub")
baseApp.RootCmd.AddCommand(updateCmd)
// add health command // add health command
baseApp.RootCmd.AddCommand(newHealthCmd()) baseApp.RootCmd.AddCommand(newHealthCmd())

View File

@@ -15,7 +15,7 @@ RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-
# -------------------------- # --------------------------
# Final image: GPU-enabled agent with nvidia-smi # Final image: GPU-enabled agent with nvidia-smi
# -------------------------- # --------------------------
FROM nvidia/cuda:12.9.1-base-ubuntu22.04 FROM nvidia/cuda:12.2.2-base-ubuntu22.04
COPY --from=builder /agent /agent COPY --from=builder /agent /agent
ENTRYPOINT ["/agent"] ENTRYPOINT ["/agent"]

View File

@@ -1,6 +1,6 @@
module beszel module beszel
go 1.24.4 go 1.25.1
// lock shoutrrr to specific version to allow review before updating // lock shoutrrr to specific version to allow review before updating
replace github.com/nicholas-fedor/shoutrrr => github.com/nicholas-fedor/shoutrrr v0.8.8 replace github.com/nicholas-fedor/shoutrrr => github.com/nicholas-fedor/shoutrrr v0.8.8
@@ -15,10 +15,10 @@ require (
github.com/nicholas-fedor/shoutrrr v0.8.17 github.com/nicholas-fedor/shoutrrr v0.8.17
github.com/pocketbase/dbx v1.11.0 github.com/pocketbase/dbx v1.11.0
github.com/pocketbase/pocketbase v0.29.3 github.com/pocketbase/pocketbase v0.29.3
github.com/rhysd/go-github-selfupdate v1.2.3 github.com/shirou/gopsutil/v4 v4.25.6
github.com/shirou/gopsutil/v4 v4.25.7
github.com/spf13/cast v1.9.2 github.com/spf13/cast v1.9.2
github.com/spf13/cobra v1.9.1 github.com/spf13/cobra v1.9.1
github.com/spf13/pflag v1.0.7
github.com/stretchr/testify v1.11.0 github.com/stretchr/testify v1.11.0
golang.org/x/crypto v0.41.0 golang.org/x/crypto v0.41.0
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b
@@ -41,9 +41,6 @@ require (
github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect github.com/go-ozzo/ozzo-validation/v4 v4.3.0 // indirect
github.com/go-sql-driver/mysql v1.9.1 // indirect github.com/go-sql-driver/mysql v1.9.1 // indirect
github.com/golang-jwt/jwt/v5 v5.3.0 // indirect github.com/golang-jwt/jwt/v5 v5.3.0 // indirect
github.com/google/go-github/v30 v30.1.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/compress v1.18.0 // indirect
github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d // indirect github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d // indirect
@@ -53,11 +50,8 @@ require (
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/spf13/pflag v1.0.7 // indirect
github.com/tcnksm/go-gitconfig v0.1.2 // indirect
github.com/tklauser/go-sysconf v0.3.15 // indirect github.com/tklauser/go-sysconf v0.3.15 // indirect
github.com/tklauser/numcpus v0.10.0 // indirect github.com/tklauser/numcpus v0.10.0 // indirect
github.com/ulikunitz/xz v0.5.13 // indirect
github.com/x448/float16 v0.8.4 // indirect github.com/x448/float16 v0.8.4 // indirect
github.com/yusufpapurcu/wmi v1.2.4 // indirect github.com/yusufpapurcu/wmi v1.2.4 // indirect
golang.org/x/image v0.30.0 // indirect golang.org/x/image v0.30.0 // indirect
@@ -66,6 +60,7 @@ require (
golang.org/x/sync v0.16.0 // indirect golang.org/x/sync v0.16.0 // indirect
golang.org/x/sys v0.35.0 // indirect golang.org/x/sys v0.35.0 // indirect
golang.org/x/text v0.28.0 // indirect golang.org/x/text v0.28.0 // indirect
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect
howett.net/plist v1.0.1 // indirect howett.net/plist v1.0.1 // indirect
modernc.org/libc v1.66.3 // indirect modernc.org/libc v1.66.3 // indirect
modernc.org/mathutil v1.7.1 // indirect modernc.org/mathutil v1.7.1 // indirect

View File

@@ -27,7 +27,6 @@ github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU= github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8= github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM= github.com/fxamacker/cbor/v2 v2.9.0 h1:NpKPmjDBgUfBms6tr6JZkTHtfFGcMKsw3eGcmD/sapM=
github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ= github.com/fxamacker/cbor/v2 v2.9.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY= github.com/gabriel-vasile/mimetype v1.4.9 h1:5k+WDwEsD9eTLL8Tz3L0VnmVh9QxGjRmjBvAG7U/oYY=
@@ -50,24 +49,13 @@ github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1v
github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8=
github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo= github.com/golang-jwt/jwt/v5 v5.3.0 h1:pv4AsKCKKZuqlgs5sUmn4x8UlGa0kEVt/puTpKx9vvo=
github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE= github.com/golang-jwt/jwt/v5 v5.3.0/go.mod h1:fxCRLWMO43lRc8nhHWY6LGqRcf+1gQWArsqaEUEa5bE=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
github.com/google/go-github/v30 v30.1.0 h1:VLDx+UolQICEOKu2m4uAoMti1SxuEBAl7RSEG16L+Oo=
github.com/google/go-github/v30 v30.1.0/go.mod h1:n8jBpHl45a/rlBUtRJMOG4GhNADUQFEufcolZ95JfU8=
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6 h1:BHT72Gu3keYf3ZEu2J0b1vyeLSOYI8bm5wbJM/8yDe8=
github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA= github.com/google/pprof v0.0.0-20250403155104-27863c87afa6/go.mod h1:boTsfXsheKC2y+lKOCMpSfarhxDeIzfZG1jqGcPl3cA=
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf/go.mod h1:hyb9oH7vZsitZCiBt0ZvifOrB+qc8PS5IiilCIb87rg=
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
github.com/jarcoal/httpmock v1.4.0 h1:BvhqnH0JAYbNudL2GMJKgOHe2CtKlzJ/5rWKyp+hc2k= github.com/jarcoal/httpmock v1.4.0 h1:BvhqnH0JAYbNudL2GMJKgOHe2CtKlzJ/5rWKyp+hc2k=
@@ -75,11 +63,8 @@ github.com/jarcoal/httpmock v1.4.0/go.mod h1:ftW1xULwo+j0R0JJkJIIi7UKigZUXCLLany
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo= github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ= github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d h1:vFzYZc8yji+9DmNRhpEbs8VBK4CgV/DPfGzeVJSSp/8= github.com/lufia/plan9stats v0.0.0-20250821153705-5981dea3221d h1:vFzYZc8yji+9DmNRhpEbs8VBK4CgV/DPfGzeVJSSp/8=
@@ -94,11 +79,8 @@ github.com/ncruces/go-strftime v0.1.9 h1:bY0MQC28UADQmHmaF5dgpLmImcShSi2kHU9XLdh
github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls= github.com/ncruces/go-strftime v0.1.9/go.mod h1:Fwc5htZGVVkseilnfgOVb9mKy6w1naJmn9CehxcKcls=
github.com/nicholas-fedor/shoutrrr v0.8.8 h1:F/oyoatWK5cbHPPgkjRZrA0262TP7KWuUQz9KskRtR8= github.com/nicholas-fedor/shoutrrr v0.8.8 h1:F/oyoatWK5cbHPPgkjRZrA0262TP7KWuUQz9KskRtR8=
github.com/nicholas-fedor/shoutrrr v0.8.8/go.mod h1:T30Y+eoZFEjDk4HtOItcHQioZSOe3Z6a6aNfSz6jc5c= github.com/nicholas-fedor/shoutrrr v0.8.8/go.mod h1:T30Y+eoZFEjDk4HtOItcHQioZSOe3Z6a6aNfSz6jc5c=
github.com/onsi/ginkgo v1.6.0 h1:Ix8l273rp3QzYgXSR+c8d1fTG7UPgYkOSELPhiY/YGw=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus=
github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8=
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y=
github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
@@ -112,13 +94,11 @@ github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/rhysd/go-github-selfupdate v1.2.3 h1:iaa+J202f+Nc+A8zi75uccC8Wg3omaM7HDeimXA22Ag=
github.com/rhysd/go-github-selfupdate v1.2.3/go.mod h1:mp/N8zj6jFfBQy/XMYoWsmfzxazpPAODuqarmPDe2Rg=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/shirou/gopsutil/v4 v4.25.7 h1:bNb2JuqKuAu3tRlPv5piSmBZyMfecwQ+t/ILq+1JqVM= github.com/shirou/gopsutil/v4 v4.25.6 h1:kLysI2JsKorfaFPcYmcJqbzROzsBWEOAtw6A7dIfqXs=
github.com/shirou/gopsutil/v4 v4.25.7/go.mod h1:XV/egmwJtd3ZQjBpJVY5kndsiOO4IRqy9TQnmm6VP7U= github.com/shirou/gopsutil/v4 v4.25.6/go.mod h1:PfybzyydfZcN+JMMjkF6Zb8Mq1A/VcogFFg7hj50W9c=
github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE=
github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo=
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
@@ -130,15 +110,10 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8= github.com/stretchr/testify v1.11.0 h1:ib4sjIrwZKxE5u/Japgo/7SJV3PvgjGiRNAvTVGqQl8=
github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/stretchr/testify v1.11.0/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U=
github.com/tcnksm/go-gitconfig v0.1.2 h1:iiDhRitByXAEyjgBqsKi9QU4o2TNtv9kPP3RgPgXBPw=
github.com/tcnksm/go-gitconfig v0.1.2/go.mod h1:/8EhP4H7oJZdIPyT+/UIsG87kTzrzM4UsLGSItWYCpE=
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4= github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4= github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso= github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ= github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.13 h1:ar98gWrjf4H1ev05fYP/o29PDZw9DrI3niHtnEqyuXA=
github.com/ulikunitz/xz v0.5.13/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM= github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg= github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
@@ -146,7 +121,6 @@ github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQ
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4= golang.org/x/crypto v0.41.0 h1:WKYxWedPGCTVVl5+WHSSrOBT0O8lx32+zxmHxijgXp4=
golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc= golang.org/x/crypto v0.41.0/go.mod h1:pO5AFd7FA68rFak7rOAGVuygIISepHftHnr8dr6+sUc=
golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0= golang.org/x/exp v0.0.0-20250819193227-8b4c13bb791b h1:DXr+pvt3nC887026GRP39Ej11UATqWDmWuS99x26cD0=
@@ -156,72 +130,53 @@ golang.org/x/image v0.30.0 h1:jD5RhkmVAnjqaCUXfbGBrn3lpxbknfN9w2UhHHU+5B4=
golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c= golang.org/x/image v0.30.0/go.mod h1:SAEUTxCCMWSrJcCy/4HwavEsfZZJlYxeHLc6tTiAe/c=
golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ= golang.org/x/mod v0.27.0 h1:kb+q2PyFnEADO2IEF935ehFUXlWiNjJWtRNgBLSfbxQ=
golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc= golang.org/x/mod v0.27.0/go.mod h1:rWI627Fq0DEoudcK+MBkNkCe0EetEaDSwJJkCcjpazc=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE= golang.org/x/net v0.43.0 h1:lat02VYK2j4aLzMzecihNvTlJNQUq316m2Mr9rnM6YE=
golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg= golang.org/x/net v0.43.0/go.mod h1:vhO1fvI4dGsIjh73sWfUVjj3N7CA9WkKJNQm2svM6Jg=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20181106182150-f42d05182288/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI=
golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw= golang.org/x/sync v0.16.0 h1:ycBJEhp9p4vXvUZNszeOq0kGTPghopOL8q0fq3vstxw=
golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= golang.org/x/sync v0.16.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI= golang.org/x/sys v0.35.0 h1:vz1N37gP5bs89s7He8XuIYXpyY0+QlsKmzipCbUtyxI=
golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/sys v0.35.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4= golang.org/x/term v0.34.0 h1:O/2T7POpk0ZZ7MAzMeWFSg6S5IpWd/RXDlM9hgM3DR4=
golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw= golang.org/x/term v0.34.0/go.mod h1:5jC53AEywhIVebHgPVeg0mj8OD3VO9OzclacVrqpaAw=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng= golang.org/x/text v0.28.0 h1:rhazDwis8INMIwQ4tpjLDzUhx6RlXqZNPEM0huQojng=
golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU= golang.org/x/text v0.28.0/go.mod h1:U8nCwOR8jO/marOQ0QbDiOngZVEBB7MAiitBuMjXiNU=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg= golang.org/x/tools v0.36.0 h1:kWS0uv/zsvHEle1LbV5LE8QujrxB3wfQyxHfhOk0Qkg=
golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s= golang.org/x/tools v0.36.0/go.mod h1:WBDiHKJK8YgLHlcQPYQzNCkUxUypCaa5ZegCVutKm+s=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.3.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM= howett.net/plist v1.0.1 h1:37GdZ8tP09Q35o9ych3ehygcsL+HqKSwzctveSlarvM=
howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g= howett.net/plist v1.0.1/go.mod h1:lqaXoTrLY4hg8tnEzNru53gicrbv7rrk+2xJA/7hw9g=
modernc.org/cc/v4 v4.26.3 h1:yEN8dzrkRFnn4PUUKXLYIqVf2PJYAEjMTFjO3BDGc3I= modernc.org/cc/v4 v4.26.2 h1:991HMkLjJzYBIfha6ECZdjrIYz2/1ayr+FL8GN+CNzM=
modernc.org/cc/v4 v4.26.3/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0= modernc.org/cc/v4 v4.26.2/go.mod h1:uVtb5OGqUKpoLWhqwNQo/8LwvoiEBLvZXIQ/SmO6mL0=
modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU= modernc.org/ccgo/v4 v4.28.0 h1:rjznn6WWehKq7dG4JtLRKxb52Ecv8OUGah8+Z/SfpNU=
modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE= modernc.org/ccgo/v4 v4.28.0/go.mod h1:JygV3+9AV6SmPhDasu4JgquwU81XAKLd3OKTUDNOiKE=
modernc.org/fileutil v1.3.15 h1:rJAXTP6ilMW/1+kzDiqmBlHLWszheUFXIyGQIAvjJpY= modernc.org/fileutil v1.3.8 h1:qtzNm7ED75pd1C7WgAGcK4edm4fvhtBsEiI/0NQ54YM=
modernc.org/fileutil v1.3.15/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc= modernc.org/fileutil v1.3.8/go.mod h1:HxmghZSZVAz/LXcMNwZPA/DRrQZEVP9VX0V4LQGQFOc=
modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI= modernc.org/gc/v2 v2.6.5 h1:nyqdV8q46KvTpZlsw66kWqwXRHdjIlJOhG6kxiV/9xI=
modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito= modernc.org/gc/v2 v2.6.5/go.mod h1:YgIahr1ypgfe7chRuJi2gD7DBQiKSLMPgBQe9oIiito=
modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks= modernc.org/goabi0 v0.2.0 h1:HvEowk7LxcPd0eq6mVOAEMai46V+i7Jrj13t4AzuNks=
modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI= modernc.org/goabi0 v0.2.0/go.mod h1:CEFRnnJhKvWT1c1JTI3Avm+tgOWbkOu5oPA8eH8LnMI=
modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ= modernc.org/libc v1.66.3 h1:cfCbjTUcdsKyyZZfEUKfoHcP3S0Wkvz3jgSzByEWVCQ=
modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8= modernc.org/libc v1.66.3/go.mod h1:XD9zO8kt59cANKvHPXpx7yS2ELPheAey0vjIuZOhOU8=
modernc.org/libc v1.66.7 h1:rjhZ8OSCybKWxS1CJr0hikpEi6Vg+944Ouyrd+bQsoY=
modernc.org/libc v1.66.7/go.mod h1:ln6tbWX0NH+mzApEoDRvilBvAWFt1HX7AUA4VDdVDPM=
modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU= modernc.org/mathutil v1.7.1 h1:GCZVGXdaN8gTqB1Mf/usp1Y/hSqgI2vAGGP4jZMCxOU=
modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg= modernc.org/mathutil v1.7.1/go.mod h1:4p5IwJITfppl0G4sUEDtCr4DthTaT47/N3aT6MhfgJg=
modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI= modernc.org/memory v1.11.0 h1:o4QC8aMQzmcwCK3t3Ux/ZHmwFPzE6hf2Y5LbkRs+hbI=

View File

@@ -36,7 +36,6 @@ type Agent struct {
server *ssh.Server // SSH server server *ssh.Server // SSH server
dataDir string // Directory for persisting data dataDir string // Directory for persisting data
keys []gossh.PublicKey // SSH public keys keys []gossh.PublicKey // SSH public keys
hasBattery bool // true if agent has access to battery stats
} }
// NewAgent creates a new agent with the given data directory for persisting data. // NewAgent creates a new agent with the given data directory for persisting data.

View File

@@ -14,7 +14,7 @@ import (
) )
func TestSessionCache_GetSet(t *testing.T) { func TestSessionCache_GetSet(t *testing.T) {
synctest.Run(func() { synctest.Test(t, func(t *testing.T) {
cache := NewSessionCache(69 * time.Second) cache := NewSessionCache(69 * time.Second)
testData := &system.CombinedData{ testData := &system.CombinedData{

View File

@@ -1,24 +0,0 @@
package agent
import "github.com/distatus/battery"
// getBatteryStats returns the current battery percent and charge state
func getBatteryStats() (batteryPercent uint8, batteryState uint8, err error) {
batteries, err := battery.GetAll()
if err != nil {
return batteryPercent, batteryState, err
}
totalCapacity := float64(0)
totalCharge := float64(0)
for _, bat := range batteries {
if bat.Design != 0 {
totalCapacity += bat.Design
} else {
totalCapacity += bat.Full
}
totalCharge += bat.Current
}
batteryPercent = uint8(totalCharge / totalCapacity * 100)
batteryState = uint8(batteries[0].State.Raw)
return batteryPercent, batteryState, nil
}

View File

@@ -0,0 +1,53 @@
//go:build !freebsd
// Package battery provides functions to check if the system has a battery and to get the battery stats.
package battery
import (
"errors"
"log/slog"
"github.com/distatus/battery"
)
var systemHasBattery = false
var haveCheckedBattery = false
// HasReadableBattery checks if the system has a battery and returns true if it does.
func HasReadableBattery() bool {
if haveCheckedBattery {
return systemHasBattery
}
haveCheckedBattery = true
bat, err := battery.Get(0)
if err == nil && bat != nil {
systemHasBattery = true
} else {
slog.Debug("No battery found", "err", err)
}
return systemHasBattery
}
// GetBatteryStats returns the current battery percent and charge state
func GetBatteryStats() (batteryPercent uint8, batteryState uint8, err error) {
if !systemHasBattery {
return batteryPercent, batteryState, errors.ErrUnsupported
}
batteries, err := battery.GetAll()
if err != nil || len(batteries) == 0 {
return batteryPercent, batteryState, err
}
totalCapacity := float64(0)
totalCharge := float64(0)
for _, bat := range batteries {
if bat.Design != 0 {
totalCapacity += bat.Design
} else {
totalCapacity += bat.Full
}
totalCharge += bat.Current
}
batteryPercent = uint8(totalCharge / totalCapacity * 100)
batteryState = uint8(batteries[0].State.Raw)
return batteryPercent, batteryState, nil
}

View File

@@ -0,0 +1,13 @@
//go:build freebsd
package battery
import "errors"
func HasReadableBattery() bool {
return false
}
func GetBatteryStats() (uint8, uint8, error) {
return 0, 0, errors.ErrUnsupported
}

View File

@@ -39,7 +39,7 @@ func TestHealth(t *testing.T) {
// This test uses synctest to simulate time passing. // This test uses synctest to simulate time passing.
// NOTE: This test requires GOEXPERIMENT=synctest to run. // NOTE: This test requires GOEXPERIMENT=synctest to run.
t.Run("check with simulated time", func(t *testing.T) { t.Run("check with simulated time", func(t *testing.T) {
synctest.Run(func() { synctest.Test(t, func(t *testing.T) {
// Update the file to set the initial timestamp. // Update the file to set the initial timestamp.
require.NoError(t, Update(), "Update() failed inside synctest") require.NoError(t, Update(), "Update() failed inside synctest")

View File

@@ -46,9 +46,10 @@ var lhmFs embed.FS
var ( var (
beszelLhm *lhmProcess beszelLhm *lhmProcess
beszelLhmOnce sync.Once beszelLhmOnce sync.Once
useLHM = os.Getenv("LHM") == "true"
) )
var errNoSensors = errors.New("no sensors found (try running as admin)") var errNoSensors = errors.New("no sensors found (try running as admin with LHM=true)")
// newlhmProcess copies the embedded LHM executable to a temporary directory and starts it. // newlhmProcess copies the embedded LHM executable to a temporary directory and starts it.
func newlhmProcess() (*lhmProcess, error) { func newlhmProcess() (*lhmProcess, error) {
@@ -139,7 +140,7 @@ func (lhm *lhmProcess) cleanupProcess() {
} }
func (lhm *lhmProcess) getTemps(ctx context.Context) (temps []sensors.TemperatureStat, err error) { func (lhm *lhmProcess) getTemps(ctx context.Context) (temps []sensors.TemperatureStat, err error) {
if lhm.stoppedNoSensors { if !useLHM || lhm.stoppedNoSensors {
// Fall back to gopsutil if we can't get sensors from LHM // Fall back to gopsutil if we can't get sensors from LHM
return sensors.TemperaturesWithContext(ctx) return sensors.TemperaturesWithContext(ctx)
} }
@@ -222,6 +223,10 @@ func getSensorTemps(ctx context.Context) (temps []sensors.TemperatureStat, err e
} }
}() }()
if !useLHM {
return sensors.TemperaturesWithContext(ctx)
}
// Initialize process once // Initialize process once
beszelLhmOnce.Do(func() { beszelLhmOnce.Do(func() {
beszelLhm, err = newlhmProcess() beszelLhm, err = newlhmProcess()

View File

@@ -2,6 +2,7 @@ package agent
import ( import (
"beszel" "beszel"
"beszel/internal/agent/battery"
"beszel/internal/entities/system" "beszel/internal/entities/system"
"bufio" "bufio"
"fmt" "fmt"
@@ -64,13 +65,6 @@ func (a *Agent) initializeSystemInfo() {
} else { } else {
a.zfs = true a.zfs = true
} }
// battery
if _, _, err := getBatteryStats(); err != nil {
slog.Debug("No battery detected", "err", err)
} else {
a.hasBattery = true
}
} }
// Returns current info, stats about the host system // Returns current info, stats about the host system
@@ -78,8 +72,8 @@ func (a *Agent) getSystemStats() system.Stats {
systemStats := system.Stats{} systemStats := system.Stats{}
// battery // battery
if a.hasBattery { if battery.HasReadableBattery() {
systemStats.Battery[0], systemStats.Battery[1], _ = getBatteryStats() systemStats.Battery[0], systemStats.Battery[1], _ = battery.GetBatteryStats()
} }
// cpu percent // cpu percent

View File

@@ -1,56 +1,150 @@
package agent package agent
import ( import (
"beszel" "beszel/internal/ghupdate"
"fmt" "fmt"
"log"
"os" "os"
"os/exec"
"strings" "strings"
"github.com/blang/semver"
"github.com/rhysd/go-github-selfupdate/selfupdate"
) )
// Update updates beszel-agent to the latest version // restarter knows how to restart the beszel-agent service.
func Update() { type restarter interface {
var latest *selfupdate.Release Restart() error
var found bool }
var err error
currentVersion := semver.MustParse(beszel.Version) type systemdRestarter struct{ cmd string }
fmt.Println("beszel-agent", currentVersion)
fmt.Println("Checking for updates...") func (s *systemdRestarter) Restart() error {
updater, _ := selfupdate.NewUpdater(selfupdate.Config{ // Only restart if the service is active
Filters: []string{"beszel-agent"}, if err := exec.Command(s.cmd, "is-active", "beszel-agent.service").Run(); err != nil {
}) return nil
latest, found, err = updater.DetectLatest("henrygd/beszel") }
ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel-agent.service via systemd…")
if err != nil { return exec.Command(s.cmd, "restart", "beszel-agent.service").Run()
fmt.Println("Error checking for updates:", err) }
os.Exit(1)
} type openRCRestarter struct{ cmd string }
if !found { func (o *openRCRestarter) Restart() error {
fmt.Println("No updates found") if err := exec.Command(o.cmd, "status", "beszel-agent").Run(); err != nil {
os.Exit(0) return nil
} }
ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel-agent via OpenRC…")
fmt.Println("Latest version:", latest.Version) return exec.Command(o.cmd, "restart", "beszel-agent").Run()
}
if latest.Version.LTE(currentVersion) {
fmt.Println("You are up to date") type openWRTRestarter struct{ cmd string }
return
} func (w *openWRTRestarter) Restart() error {
if err := exec.Command(w.cmd, "running", "beszel-agent").Run(); err != nil {
var binaryPath string return nil
fmt.Printf("Updating from %s to %s...\n", currentVersion, latest.Version) }
binaryPath, err = os.Executable() ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel-agent via procd…")
if err != nil { return exec.Command(w.cmd, "restart", "beszel-agent").Run()
fmt.Println("Error getting binary path:", err) }
os.Exit(1)
} func detectRestarter() restarter {
err = selfupdate.UpdateTo(latest.AssetURL, binaryPath) if path, err := exec.LookPath("systemctl"); err == nil {
if err != nil { return &systemdRestarter{cmd: path}
fmt.Println("Please try rerunning with sudo. Error:", err) }
os.Exit(1) if path, err := exec.LookPath("rc-service"); err == nil {
} return &openRCRestarter{cmd: path}
fmt.Printf("Successfully updated to %s\n\n%s\n", latest.Version, strings.TrimSpace(latest.ReleaseNotes)) }
if path, err := exec.LookPath("service"); err == nil {
return &openWRTRestarter{cmd: path}
}
return nil
}
// Update checks GitHub for a newer release of beszel-agent, applies it,
// fixes SELinux context if needed, and restarts the service.
func Update(useMirror bool) error {
exePath, _ := os.Executable()
dataDir, err := getDataDir()
if err != nil {
dataDir = os.TempDir()
}
updated, err := ghupdate.Update(ghupdate.Config{
ArchiveExecutable: "beszel-agent",
DataDir: dataDir,
UseMirror: useMirror,
})
if err != nil {
log.Fatal(err)
}
if !updated {
return nil
}
// make sure the file is executable
if err := os.Chmod(exePath, 0755); err != nil {
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: failed to set executable permissions: %v", err)
}
// set ownership to beszel:beszel if possible
if chownPath, err := exec.LookPath("chown"); err == nil {
if err := exec.Command(chownPath, "beszel:beszel", exePath).Run(); err != nil {
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: failed to set file ownership: %v", err)
}
}
// 6) Fix SELinux context if necessary
if err := handleSELinuxContext(exePath); err != nil {
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: SELinux context handling: %v", err)
}
// 7) Restart service if running under a recognised init system
if r := detectRestarter(); r != nil {
if err := r.Restart(); err != nil {
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: failed to restart service: %v", err)
ghupdate.ColorPrint(ghupdate.ColorYellow, "Please restart the service manually.")
} else {
ghupdate.ColorPrint(ghupdate.ColorGreen, "Service restarted successfully")
}
} else {
ghupdate.ColorPrint(ghupdate.ColorYellow, "No supported init system detected; please restart manually if needed.")
}
return nil
}
// handleSELinuxContext restores or applies the correct SELinux label to the binary.
func handleSELinuxContext(path string) error {
out, err := exec.Command("getenforce").Output()
if err != nil {
// SELinux not enabled or getenforce not available
return nil
}
state := strings.TrimSpace(string(out))
if state == "Disabled" {
return nil
}
ghupdate.ColorPrint(ghupdate.ColorYellow, "SELinux is enabled; applying context…")
var errs []string
// Try persistent context via semanage+restorecon
if semanagePath, err := exec.LookPath("semanage"); err == nil {
if err := exec.Command(semanagePath, "fcontext", "-a", "-t", "bin_t", path).Run(); err != nil {
errs = append(errs, "semanage fcontext failed: "+err.Error())
} else if restoreconPath, err := exec.LookPath("restorecon"); err == nil {
if err := exec.Command(restoreconPath, "-v", path).Run(); err != nil {
errs = append(errs, "restorecon failed: "+err.Error())
}
}
}
// Fallback to temporary context via chcon
if chconPath, err := exec.LookPath("chcon"); err == nil {
if err := exec.Command(chconPath, "-t", "bin_t", path).Run(); err != nil {
errs = append(errs, "chcon failed: "+err.Error())
}
}
if len(errs) > 0 {
return fmt.Errorf("SELinux context errors: %s", strings.Join(errs, "; "))
}
return nil
} }

View File

@@ -87,7 +87,7 @@ var supportsTitle = map[string]struct{}{
func NewAlertManager(app hubLike) *AlertManager { func NewAlertManager(app hubLike) *AlertManager {
am := &AlertManager{ am := &AlertManager{
hub: app, hub: app,
alertQueue: make(chan alertTask), alertQueue: make(chan alertTask, 5),
stopChan: make(chan struct{}), stopChan: make(chan struct{}),
} }
am.bindEvents() am.bindEvents()

View File

@@ -42,21 +42,10 @@ func updateHistoryOnAlertUpdate(e *core.RecordEvent) error {
// resolveAlertHistoryRecord sets the resolved field to the current time // resolveAlertHistoryRecord sets the resolved field to the current time
func resolveAlertHistoryRecord(app core.App, alertRecordID string) error { func resolveAlertHistoryRecord(app core.App, alertRecordID string) error {
alertHistoryRecords, err := app.FindRecordsByFilter( alertHistoryRecord, err := app.FindFirstRecordByFilter("alerts_history", "alert_id={:alert_id} && resolved=null", dbx.Params{"alert_id": alertRecordID})
"alerts_history", if err != nil || alertHistoryRecord == nil {
"alert_id={:alert_id} && resolved=null",
"-created",
1,
0,
dbx.Params{"alert_id": alertRecordID},
)
if err != nil {
return err return err
} }
if len(alertHistoryRecords) == 0 {
return nil
}
alertHistoryRecord := alertHistoryRecords[0] // there should be only one record
alertHistoryRecord.Set("resolved", time.Now().UTC()) alertHistoryRecord.Set("resolved", time.Now().UTC())
err = app.Save(alertHistoryRecord) err = app.Save(alertHistoryRecord)
if err != nil { if err != nil {

View File

@@ -10,6 +10,8 @@ import (
"net/http" "net/http"
"strings" "strings"
"testing" "testing"
"testing/synctest"
"time"
beszelTests "beszel/internal/tests" beszelTests "beszel/internal/tests"
@@ -63,14 +65,14 @@ func TestUserAlertsApi(t *testing.T) {
} }
scenarios := []beszelTests.ApiScenario{ scenarios := []beszelTests.ApiScenario{
{ // {
Name: "GET not implemented - returns index", // Name: "GET not implemented - returns index",
Method: http.MethodGet, // Method: http.MethodGet,
URL: "/api/beszel/user-alerts", // URL: "/api/beszel/user-alerts",
ExpectedStatus: 200, // ExpectedStatus: 200,
ExpectedContent: []string{"<html ", "globalThis.BESZEL"}, // ExpectedContent: []string{"<html ", "globalThis.BESZEL"},
TestAppFactory: testAppFactory, // TestAppFactory: testAppFactory,
}, // },
{ {
Name: "POST no auth", Name: "POST no auth",
Method: http.MethodPost, Method: http.MethodPost,
@@ -366,3 +368,237 @@ func TestUserAlertsApi(t *testing.T) {
scenario.Test(t) scenario.Test(t)
} }
} }
func getHubWithUser(t *testing.T) (*beszelTests.TestHub, *core.Record) {
hub, err := beszelTests.NewTestHub(t.TempDir())
assert.NoError(t, err)
hub.StartHub()
// Manually initialize the system manager to bind event hooks
err = hub.GetSystemManager().Initialize()
assert.NoError(t, err)
// Create a test user
user, err := beszelTests.CreateUser(hub, "test@example.com", "password")
assert.NoError(t, err)
// Create user settings for the test user (required for alert notifications)
userSettingsData := map[string]any{
"user": user.Id,
"settings": `{"emails":[test@example.com],"webhooks":[]}`,
}
_, err = beszelTests.CreateRecord(hub, "user_settings", userSettingsData)
assert.NoError(t, err)
return hub, user
}
func TestStatusAlerts(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
hub, user := getHubWithUser(t)
defer hub.Cleanup()
systems, err := beszelTests.CreateSystems(hub, 4, user.Id, "paused")
assert.NoError(t, err)
var alerts []*core.Record
for i, system := range systems {
alert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
"name": "Status",
"system": system.Id,
"user": user.Id,
"min": i + 1,
})
assert.NoError(t, err)
alerts = append(alerts, alert)
}
time.Sleep(10 * time.Millisecond)
for _, alert := range alerts {
assert.False(t, alert.GetBool("triggered"), "Alert should not be triggered immediately")
}
if hub.TestMailer.TotalSend() != 0 {
assert.Zero(t, hub.TestMailer.TotalSend(), "Expected 0 messages, got %d", hub.TestMailer.TotalSend())
}
for _, system := range systems {
assert.EqualValues(t, "paused", system.GetString("status"), "System should be paused")
}
for _, system := range systems {
system.Set("status", "up")
err = hub.SaveNoValidate(system)
assert.NoError(t, err)
}
time.Sleep(time.Second)
assert.EqualValues(t, 0, hub.GetPendingAlertsCount(), "should have 0 alerts in the pendingAlerts map")
for _, system := range systems {
system.Set("status", "down")
err = hub.SaveNoValidate(system)
assert.NoError(t, err)
}
// after 30 seconds, should have 4 alerts in the pendingAlerts map, no triggered alerts
time.Sleep(time.Second * 30)
assert.EqualValues(t, 4, hub.GetPendingAlertsCount(), "should have 4 alerts in the pendingAlerts map")
triggeredCount, err := hub.CountRecords("alerts", dbx.HashExp{"triggered": true})
assert.NoError(t, err)
assert.EqualValues(t, 0, triggeredCount, "should have 0 alert triggered")
assert.EqualValues(t, 0, hub.TestMailer.TotalSend(), "should have 0 messages sent")
// after 1:30 seconds, should have 1 triggered alert and 3 pending alerts
time.Sleep(time.Second * 60)
assert.EqualValues(t, 3, hub.GetPendingAlertsCount(), "should have 3 alerts in the pendingAlerts map")
triggeredCount, err = hub.CountRecords("alerts", dbx.HashExp{"triggered": true})
assert.NoError(t, err)
assert.EqualValues(t, 1, triggeredCount, "should have 1 alert triggered")
assert.EqualValues(t, 1, hub.TestMailer.TotalSend(), "should have 1 messages sent")
// after 2:30 seconds, should have 2 triggered alerts and 2 pending alerts
time.Sleep(time.Second * 60)
assert.EqualValues(t, 2, hub.GetPendingAlertsCount(), "should have 2 alerts in the pendingAlerts map")
triggeredCount, err = hub.CountRecords("alerts", dbx.HashExp{"triggered": true})
assert.NoError(t, err)
assert.EqualValues(t, 2, triggeredCount, "should have 2 alert triggered")
assert.EqualValues(t, 2, hub.TestMailer.TotalSend(), "should have 2 messages sent")
// now we will bring the remaning systems back up
for _, system := range systems {
system.Set("status", "up")
err = hub.SaveNoValidate(system)
assert.NoError(t, err)
}
time.Sleep(time.Second)
// should have 0 alerts in the pendingAlerts map and 0 alerts triggered
assert.EqualValues(t, 0, hub.GetPendingAlertsCount(), "should have 0 alerts in the pendingAlerts map")
triggeredCount, err = hub.CountRecords("alerts", dbx.HashExp{"triggered": true})
assert.NoError(t, err)
assert.Zero(t, triggeredCount, "should have 0 alert triggered")
// 4 messages sent, 2 down alerts and 2 up alerts for first 2 systems
assert.EqualValues(t, 4, hub.TestMailer.TotalSend(), "should have 4 messages sent")
})
}
func TestAlertsHistory(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
hub, user := getHubWithUser(t)
defer hub.Cleanup()
// Create systems and alerts
systems, err := beszelTests.CreateSystems(hub, 1, user.Id, "up")
assert.NoError(t, err)
system := systems[0]
alert, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
"name": "Status",
"system": system.Id,
"user": user.Id,
"min": 1,
})
assert.NoError(t, err)
// Initially, no alert history records should exist
initialHistoryCount, err := hub.CountRecords("alerts_history", nil)
assert.NoError(t, err)
assert.Zero(t, initialHistoryCount, "Should have 0 alert history records initially")
// Set system to up initially
system.Set("status", "up")
err = hub.SaveNoValidate(system)
assert.NoError(t, err)
time.Sleep(10 * time.Millisecond)
// Set system to down to trigger alert
system.Set("status", "down")
err = hub.SaveNoValidate(system)
assert.NoError(t, err)
// Wait for alert to trigger (after the downtime delay)
// With 1 minute delay, we need to wait at least 1 minute + some buffer
time.Sleep(time.Second * 75)
// Check that alert is triggered
triggeredCount, err := hub.CountRecords("alerts", dbx.HashExp{"triggered": true, "id": alert.Id})
assert.NoError(t, err)
assert.EqualValues(t, 1, triggeredCount, "Alert should be triggered")
// Check that alert history record was created
historyCount, err := hub.CountRecords("alerts_history", dbx.HashExp{"alert_id": alert.Id})
assert.NoError(t, err)
assert.EqualValues(t, 1, historyCount, "Should have 1 alert history record for triggered alert")
// Get the alert history record and verify it's not resolved immediately
historyRecord, err := hub.FindFirstRecordByFilter("alerts_history", "alert_id={:alert_id}", dbx.Params{"alert_id": alert.Id})
assert.NoError(t, err)
assert.NotNil(t, historyRecord, "Alert history record should exist")
assert.Equal(t, alert.Id, historyRecord.GetString("alert_id"), "Alert history should reference correct alert")
assert.Equal(t, system.Id, historyRecord.GetString("system"), "Alert history should reference correct system")
assert.Equal(t, "Status", historyRecord.GetString("name"), "Alert history should have correct name")
// The alert history might be resolved immediately in some cases, so let's check the alert's triggered status
alertRecord, err := hub.FindFirstRecordByFilter("alerts", "id={:id}", dbx.Params{"id": alert.Id})
assert.NoError(t, err)
assert.True(t, alertRecord.GetBool("triggered"), "Alert should still be triggered when checking history")
// Now resolve the alert by setting system back to up
system.Set("status", "up")
err = hub.SaveNoValidate(system)
assert.NoError(t, err)
time.Sleep(200 * time.Millisecond)
// Check that alert is no longer triggered
triggeredCount, err = hub.CountRecords("alerts", dbx.HashExp{"triggered": true, "id": alert.Id})
assert.NoError(t, err)
assert.Zero(t, triggeredCount, "Alert should not be triggered after system is back up")
// Check that alert history record is now resolved
historyRecord, err = hub.FindFirstRecordByFilter("alerts_history", "alert_id={:alert_id}", dbx.Params{"alert_id": alert.Id})
assert.NoError(t, err)
assert.NotNil(t, historyRecord, "Alert history record should still exist")
assert.NotNil(t, historyRecord.Get("resolved"), "Alert history should be resolved")
// Test deleting a triggered alert resolves its history
// Create another system and alert
systems2, err := beszelTests.CreateSystems(hub, 1, user.Id, "up")
assert.NoError(t, err)
system2 := systems2[0]
system2.Set("name", "test-system-2") // Rename for clarity
err = hub.SaveNoValidate(system2)
assert.NoError(t, err)
alert2, err := beszelTests.CreateRecord(hub, "alerts", map[string]any{
"name": "Status",
"system": system2.Id,
"user": user.Id,
"min": 1,
})
assert.NoError(t, err)
// Set system2 to down to trigger alert
system2.Set("status", "down")
err = hub.SaveNoValidate(system2)
assert.NoError(t, err)
// Wait for alert to trigger
time.Sleep(time.Second * 75)
// Verify alert is triggered and history record exists
triggeredCount, err = hub.CountRecords("alerts", dbx.HashExp{"triggered": true, "id": alert2.Id})
assert.NoError(t, err)
assert.EqualValues(t, 1, triggeredCount, "Second alert should be triggered")
historyCount, err = hub.CountRecords("alerts_history", dbx.HashExp{"alert_id": alert2.Id})
assert.NoError(t, err)
assert.EqualValues(t, 1, historyCount, "Should have 1 alert history record for second alert")
// Delete the triggered alert
err = hub.Delete(alert2)
assert.NoError(t, err)
// Check that alert history record is resolved after deletion
historyRecord2, err := hub.FindFirstRecordByFilter("alerts_history", "alert_id={:alert_id}", dbx.Params{"alert_id": alert2.Id})
assert.NoError(t, err)
assert.NotNil(t, historyRecord2, "Alert history record should still exist after alert deletion")
assert.NotNil(t, historyRecord2.Get("resolved"), "Alert history should be resolved after alert deletion")
// Verify total history count is correct (2 records total)
totalHistoryCount, err := hub.CountRecords("alerts_history", nil)
assert.NoError(t, err)
assert.EqualValues(t, 2, totalHistoryCount, "Should have 2 total alert history records")
})
}

View File

@@ -0,0 +1,55 @@
package alerts
import (
"sync"
"time"
"github.com/pocketbase/pocketbase/core"
)
func (am *AlertManager) GetAlertManager() *AlertManager {
return am
}
func (am *AlertManager) GetPendingAlerts() *sync.Map {
return &am.pendingAlerts
}
func (am *AlertManager) GetPendingAlertsCount() int {
count := 0
am.pendingAlerts.Range(func(key, value any) bool {
count++
return true
})
return count
}
// ProcessPendingAlerts manually processes all expired alerts (for testing)
func (am *AlertManager) ProcessPendingAlerts() ([]*core.Record, error) {
now := time.Now()
var lastErr error
var processedAlerts []*core.Record
am.pendingAlerts.Range(func(key, value any) bool {
info := value.(*alertInfo)
if now.After(info.expireTime) {
// Downtime delay has passed, process alert
if err := am.sendStatusAlert("down", info.systemName, info.alertRecord); err != nil {
lastErr = err
}
processedAlerts = append(processedAlerts, info.alertRecord)
am.pendingAlerts.Delete(key)
}
return true
})
return processedAlerts, lastErr
}
// ForceExpirePendingAlerts sets all pending alerts to expire immediately (for testing)
func (am *AlertManager) ForceExpirePendingAlerts() {
now := time.Now()
am.pendingAlerts.Range(func(key, value any) bool {
info := value.(*alertInfo)
info.expireTime = now.Add(-time.Second) // Set to 1 second ago
return true
})
}

View File

@@ -39,6 +39,7 @@ type Stats struct {
// TODO: remove other load fields in future release in favor of load avg array // TODO: remove other load fields in future release in favor of load avg array
LoadAvg [3]float64 `json:"la,omitempty" cbor:"28,keyasint"` LoadAvg [3]float64 `json:"la,omitempty" cbor:"28,keyasint"`
Battery [2]uint8 `json:"bat,omitzero" cbor:"29,keyasint,omitzero"` // [percent, charge state, current] Battery [2]uint8 `json:"bat,omitzero" cbor:"29,keyasint,omitzero"` // [percent, charge state, current]
MaxMem float64 `json:"mm,omitempty" cbor:"30,keyasint,omitempty"`
} }
type GPUData struct { type GPUData struct {

View File

@@ -0,0 +1,140 @@
package ghupdate
import (
"archive/tar"
"archive/zip"
"compress/gzip"
"fmt"
"io"
"os"
"path/filepath"
"strings"
)
// extract extracts an archive file to the destination directory.
// Supports .zip and .tar.gz files based on the file extension.
func extract(srcPath, destDir string) error {
if strings.HasSuffix(srcPath, ".tar.gz") {
return extractTarGz(srcPath, destDir)
}
// Default to zip extraction
return extractZip(srcPath, destDir)
}
// extractTarGz extracts a tar.gz archive to the destination directory.
func extractTarGz(srcPath, destDir string) error {
src, err := os.Open(srcPath)
if err != nil {
return err
}
defer src.Close()
gz, err := gzip.NewReader(src)
if err != nil {
return err
}
defer gz.Close()
tr := tar.NewReader(gz)
for {
header, err := tr.Next()
if err == io.EOF {
break
}
if err != nil {
return err
}
if header.Typeflag == tar.TypeDir {
if err := os.MkdirAll(filepath.Join(destDir, header.Name), 0755); err != nil {
return err
}
continue
}
if err := os.MkdirAll(filepath.Dir(filepath.Join(destDir, header.Name)), 0755); err != nil {
return err
}
outFile, err := os.Create(filepath.Join(destDir, header.Name))
if err != nil {
return err
}
if _, err := io.Copy(outFile, tr); err != nil {
outFile.Close()
return err
}
outFile.Close()
}
return nil
}
// extractZip extracts the zip archive at "src" to "dest".
//
// Note that only dirs and regular files will be extracted.
// Symbolic links, named pipes, sockets, or any other irregular files
// are skipped because they come with too many edge cases and ambiguities.
func extractZip(src, dest string) error {
zr, err := zip.OpenReader(src)
if err != nil {
return err
}
defer zr.Close()
// normalize dest path to check later for Zip Slip
dest = filepath.Clean(dest) + string(os.PathSeparator)
for _, f := range zr.File {
err := extractFile(f, dest)
if err != nil {
return err
}
}
return nil
}
// extractFile extracts the provided zipFile into "basePath/zipFileName" path,
// creating all the necessary path directories.
func extractFile(zipFile *zip.File, basePath string) error {
path := filepath.Join(basePath, zipFile.Name)
// check for Zip Slip
if !strings.HasPrefix(path, basePath) {
return fmt.Errorf("invalid file path: %s", path)
}
r, err := zipFile.Open()
if err != nil {
return err
}
defer r.Close()
// allow only dirs or regular files
if zipFile.FileInfo().IsDir() {
if err := os.MkdirAll(path, os.ModePerm); err != nil {
return err
}
} else if zipFile.FileInfo().Mode().IsRegular() {
// ensure that the file path directories are created
if err := os.MkdirAll(filepath.Dir(path), os.ModePerm); err != nil {
return err
}
f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, zipFile.Mode())
if err != nil {
return err
}
defer f.Close()
_, err = io.Copy(f, r)
if err != nil {
return err
}
}
return nil
}

View File

@@ -0,0 +1,348 @@
// Package ghupdate implements a new command to self update the current
// executable with the latest GitHub release. This is based on PocketBase's
// ghupdate package with modifications.
package ghupdate
import (
"beszel"
"context"
"encoding/json"
"fmt"
"io"
"log/slog"
"net/http"
"os"
"path/filepath"
"runtime"
"strings"
"github.com/blang/semver"
)
// Minimal color functions using ANSI escape codes
const (
colorReset = "\033[0m"
ColorYellow = "\033[33m"
ColorGreen = "\033[32m"
colorCyan = "\033[36m"
colorGray = "\033[90m"
)
func ColorPrint(color, text string) {
fmt.Println(color + text + colorReset)
}
func ColorPrintf(color, format string, args ...interface{}) {
fmt.Printf(color+format+colorReset+"\n", args...)
}
// HttpClient is a base HTTP client interface (usually used for test purposes).
type HttpClient interface {
Do(req *http.Request) (*http.Response, error)
}
// Config defines the config options of the ghupdate plugin.
//
// NB! This plugin is considered experimental and its config options may change in the future.
type Config struct {
// Owner specifies the account owner of the repository (default to "pocketbase").
Owner string
// Repo specifies the name of the repository (default to "pocketbase").
Repo string
// ArchiveExecutable specifies the name of the executable file in the release archive
// (default to "pocketbase"; an additional ".exe" check is also performed as a fallback).
ArchiveExecutable string
// Optional context to use when fetching and downloading the latest release.
Context context.Context
// The HTTP client to use when fetching and downloading the latest release.
// Defaults to `http.DefaultClient`.
HttpClient HttpClient
// The data directory to use when fetching and downloading the latest release.
DataDir string
// UseMirror specifies whether to use the beszel.dev mirror instead of GitHub API.
// When false (default), always uses api.github.com. When true, uses gh.beszel.dev.
UseMirror bool
}
type updater struct {
config Config
currentVersion string
}
func Update(config Config) (updated bool, err error) {
p := &updater{
currentVersion: beszel.Version,
config: config,
}
return p.update()
}
func (p *updater) update() (updated bool, err error) {
ColorPrint(ColorYellow, "Fetching release information...")
if p.config.DataDir == "" {
p.config.DataDir = os.TempDir()
}
if p.config.Owner == "" {
p.config.Owner = "henrygd"
}
if p.config.Repo == "" {
p.config.Repo = "beszel"
}
if p.config.Context == nil {
p.config.Context = context.Background()
}
if p.config.HttpClient == nil {
p.config.HttpClient = http.DefaultClient
}
var latest *release
var useMirror bool
// Determine the API endpoint based on UseMirror flag
apiURL := fmt.Sprintf("https://api.github.com/repos/%s/%s/releases/latest", p.config.Owner, p.config.Repo)
if p.config.UseMirror {
useMirror = true
apiURL = fmt.Sprintf("https://gh.beszel.dev/repos/%s/%s/releases/latest?api=true", p.config.Owner, p.config.Repo)
ColorPrint(ColorYellow, "Using mirror for update.")
}
latest, err = fetchLatestRelease(
p.config.Context,
p.config.HttpClient,
apiURL,
)
if err != nil {
return false, err
}
currentVersion := semver.MustParse(strings.TrimPrefix(p.currentVersion, "v"))
newVersion := semver.MustParse(strings.TrimPrefix(latest.Tag, "v"))
if newVersion.LTE(currentVersion) {
ColorPrintf(ColorGreen, "You already have the latest version %s.", p.currentVersion)
return false, nil
}
suffix := archiveSuffix(p.config.ArchiveExecutable, runtime.GOOS, runtime.GOARCH)
asset, err := latest.findAssetBySuffix(suffix)
if err != nil {
return false, err
}
releaseDir := filepath.Join(p.config.DataDir, ".beszel_update")
defer os.RemoveAll(releaseDir)
ColorPrintf(ColorYellow, "Downloading %s...", asset.Name)
// download the release asset
assetPath := filepath.Join(releaseDir, asset.Name)
if err := downloadFile(p.config.Context, p.config.HttpClient, asset.DownloadUrl, assetPath, useMirror); err != nil {
return false, err
}
ColorPrintf(ColorYellow, "Extracting %s...", asset.Name)
extractDir := filepath.Join(releaseDir, "extracted_"+asset.Name)
defer os.RemoveAll(extractDir)
// Extract the archive (automatically detects format)
if err := extract(assetPath, extractDir); err != nil {
return false, err
}
ColorPrint(ColorYellow, "Replacing the executable...")
oldExec, err := os.Executable()
if err != nil {
return false, err
}
renamedOldExec := oldExec + ".old"
defer os.Remove(renamedOldExec)
newExec := filepath.Join(extractDir, p.config.ArchiveExecutable)
if _, err := os.Stat(newExec); err != nil {
// try again with an .exe extension
newExec = newExec + ".exe"
if _, fallbackErr := os.Stat(newExec); fallbackErr != nil {
return false, fmt.Errorf("the executable in the extracted path is missing or it is inaccessible: %v, %v", err, fallbackErr)
}
}
// rename the current executable
if err := os.Rename(oldExec, renamedOldExec); err != nil {
return false, fmt.Errorf("failed to rename the current executable: %w", err)
}
tryToRevertExecChanges := func() {
if revertErr := os.Rename(renamedOldExec, oldExec); revertErr != nil {
slog.Debug(
"Failed to revert executable",
slog.String("old", renamedOldExec),
slog.String("new", oldExec),
slog.String("error", revertErr.Error()),
)
}
}
// replace with the extracted binary
if err := os.Rename(newExec, oldExec); err != nil {
// If rename fails due to cross-device link, try copying instead
if isCrossDeviceError(err) {
if err := copyFile(newExec, oldExec); err != nil {
tryToRevertExecChanges()
return false, fmt.Errorf("failed replacing the executable: %w", err)
}
} else {
tryToRevertExecChanges()
return false, fmt.Errorf("failed replacing the executable: %w", err)
}
}
ColorPrint(colorGray, "---")
ColorPrint(ColorGreen, "Update completed successfully!")
// print the release notes
if latest.Body != "" {
fmt.Print("\n")
releaseNotes := strings.TrimSpace(strings.Replace(latest.Body, "> _To update the prebuilt executable you can run `./"+p.config.ArchiveExecutable+" update`._", "", 1))
ColorPrint(colorCyan, releaseNotes)
fmt.Print("\n")
}
return true, nil
}
func fetchLatestRelease(
ctx context.Context,
client HttpClient,
url string,
) (*release, error) {
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, err
}
res, err := client.Do(req)
if err != nil {
return nil, err
}
defer res.Body.Close()
rawBody, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
// http.Client doesn't treat non 2xx responses as error
if res.StatusCode >= 400 {
return nil, fmt.Errorf(
"(%d) failed to fetch latest releases:\n%s",
res.StatusCode,
string(rawBody),
)
}
result := &release{}
if err := json.Unmarshal(rawBody, result); err != nil {
return nil, err
}
return result, nil
}
func downloadFile(
ctx context.Context,
client HttpClient,
url string,
destPath string,
useMirror bool,
) error {
if useMirror {
url = strings.Replace(url, "github.com", "gh.beszel.dev", 1)
}
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return err
}
res, err := client.Do(req)
if err != nil {
return err
}
defer res.Body.Close()
// http.Client doesn't treat non 2xx responses as error
if res.StatusCode >= 400 {
return fmt.Errorf("(%d) failed to send download file request", res.StatusCode)
}
// ensure that the dest parent dir(s) exist
if err := os.MkdirAll(filepath.Dir(destPath), os.ModePerm); err != nil {
return err
}
dest, err := os.Create(destPath)
if err != nil {
return err
}
defer dest.Close()
if _, err := io.Copy(dest, res.Body); err != nil {
return err
}
return nil
}
// isCrossDeviceError checks if the error is due to a cross-device link
func isCrossDeviceError(err error) bool {
return err != nil && (strings.Contains(err.Error(), "cross-device") ||
strings.Contains(err.Error(), "EXDEV"))
}
// copyFile copies a file from src to dst, preserving permissions
func copyFile(src, dst string) error {
sourceFile, err := os.Open(src)
if err != nil {
return err
}
defer sourceFile.Close()
destFile, err := os.Create(dst)
if err != nil {
return err
}
defer destFile.Close()
// Copy the file contents
if _, err := io.Copy(destFile, sourceFile); err != nil {
return err
}
// Preserve the original file permissions
sourceInfo, err := sourceFile.Stat()
if err != nil {
return err
}
return destFile.Chmod(sourceInfo.Mode())
}
func archiveSuffix(binaryName, goos, goarch string) string {
if goos == "windows" {
return fmt.Sprintf("%s_%s_%s.zip", binaryName, goos, goarch)
}
return fmt.Sprintf("%s_%s_%s.tar.gz", binaryName, goos, goarch)
}

View File

@@ -0,0 +1,45 @@
package ghupdate
import (
"path/filepath"
"testing"
)
func TestReleaseFindAssetBySuffix(t *testing.T) {
r := release{
Assets: []*releaseAsset{
{Name: "test1.zip", Id: 1},
{Name: "test2.zip", Id: 2},
{Name: "test22.zip", Id: 22},
{Name: "test3.zip", Id: 3},
},
}
asset, err := r.findAssetBySuffix("2.zip")
if err != nil {
t.Fatalf("Expected nil, got err: %v", err)
}
if asset.Id != 2 {
t.Fatalf("Expected asset with id %d, got %v", 2, asset)
}
}
func TestExtractFailure(t *testing.T) {
testDir := t.TempDir()
// Test with missing zip file
missingZipPath := filepath.Join(testDir, "missing_test.zip")
extractedPath := filepath.Join(testDir, "zip_extract")
if err := extract(missingZipPath, extractedPath); err == nil {
t.Fatal("Expected Extract to fail due to missing zip file")
}
// Test with missing tar.gz file
missingTarPath := filepath.Join(testDir, "missing_test.tar.gz")
if err := extract(missingTarPath, extractedPath); err == nil {
t.Fatal("Expected Extract to fail due to missing tar.gz file")
}
}

View File

@@ -0,0 +1,36 @@
package ghupdate
import (
"errors"
"strings"
)
type releaseAsset struct {
Name string `json:"name"`
DownloadUrl string `json:"browser_download_url"`
Id int `json:"id"`
Size int `json:"size"`
}
type release struct {
Name string `json:"name"`
Tag string `json:"tag_name"`
Published string `json:"published_at"`
Url string `json:"html_url"`
Body string `json:"body"`
Assets []*releaseAsset `json:"assets"`
Id int `json:"id"`
}
// findAssetBySuffix returns the first available asset containing the specified suffix.
func (r *release) findAssetBySuffix(suffix string) (*releaseAsset, error) {
if suffix != "" {
for _, asset := range r.Assets {
if strings.HasSuffix(asset.Name, suffix) {
return asset, nil
}
}
}
return nil, errors.New("missing asset containing " + suffix)
}

View File

@@ -8,13 +8,10 @@ import (
"beszel/internal/hub/systems" "beszel/internal/hub/systems"
"beszel/internal/records" "beszel/internal/records"
"beszel/internal/users" "beszel/internal/users"
"beszel/site"
"crypto/ed25519" "crypto/ed25519"
"encoding/pem" "encoding/pem"
"fmt" "fmt"
"io/fs"
"net/http" "net/http"
"net/http/httputil"
"net/url" "net/url"
"os" "os"
"path" "path"
@@ -115,6 +112,8 @@ func (h *Hub) initialize(e *core.ServeEvent) error {
// set URL if BASE_URL env is set // set URL if BASE_URL env is set
if h.appURL != "" { if h.appURL != "" {
settings.Meta.AppURL = h.appURL settings.Meta.AppURL = h.appURL
} else {
h.appURL = settings.Meta.AppURL
} }
if err := e.App.Save(settings); err != nil { if err := e.App.Save(settings); err != nil {
return err return err
@@ -164,55 +163,6 @@ func (h *Hub) initialize(e *core.ServeEvent) error {
return nil return nil
} }
// startServer sets up the server for Beszel
func (h *Hub) startServer(se *core.ServeEvent) error {
// TODO: exclude dev server from production binary
switch h.IsDev() {
case true:
proxy := httputil.NewSingleHostReverseProxy(&url.URL{
Scheme: "http",
Host: "localhost:5173",
})
se.Router.GET("/{path...}", func(e *core.RequestEvent) error {
proxy.ServeHTTP(e.Response, e.Request)
return nil
})
default:
// parse app url
parsedURL, err := url.Parse(h.appURL)
if err != nil {
return err
}
// fix base paths in html if using subpath
basePath := strings.TrimSuffix(parsedURL.Path, "/") + "/"
indexFile, _ := fs.ReadFile(site.DistDirFS, "index.html")
indexContent := strings.ReplaceAll(string(indexFile), "./", basePath)
indexContent = strings.Replace(indexContent, "{{V}}", beszel.Version, 1)
indexContent = strings.Replace(indexContent, "{{HUB_URL}}", h.appURL, 1)
// set up static asset serving
staticPaths := [2]string{"/static/", "/assets/"}
serveStatic := apis.Static(site.DistDirFS, false)
// get CSP configuration
csp, cspExists := GetEnv("CSP")
// add route
se.Router.GET("/{path...}", func(e *core.RequestEvent) error {
// serve static assets if path is in staticPaths
for i := range staticPaths {
if strings.Contains(e.Request.URL.Path, staticPaths[i]) {
e.Response.Header().Set("Cache-Control", "public, max-age=2592000")
return serveStatic(e)
}
}
if cspExists {
e.Response.Header().Del("X-Frame-Options")
e.Response.Header().Set("Content-Security-Policy", csp)
}
return e.HTML(http.StatusOK, indexContent)
})
}
return nil
}
// registerCronJobs sets up scheduled tasks // registerCronJobs sets up scheduled tasks
func (h *Hub) registerCronJobs(_ *core.ServeEvent) error { func (h *Hub) registerCronJobs(_ *core.ServeEvent) error {
// delete old system_stats and alerts_history records once every hour // delete old system_stats and alerts_history records once every hour

View File

@@ -5,6 +5,7 @@ package hub_test
import ( import (
beszelTests "beszel/internal/tests" beszelTests "beszel/internal/tests"
"beszel/migrations"
"testing" "testing"
"bytes" "bytes"
@@ -534,6 +535,115 @@ func TestApiRoutesAuthentication(t *testing.T) {
} }
} }
func TestFirstUserCreation(t *testing.T) {
t.Run("CreateUserEndpoint available when no users exist", func(t *testing.T) {
hub, _ := beszelTests.NewTestHub(t.TempDir())
defer hub.Cleanup()
hub.StartHub()
testAppFactoryExisting := func(t testing.TB) *pbTests.TestApp {
return hub.TestApp
}
scenarios := []beszelTests.ApiScenario{
{
Name: "POST /create-user - should be available when no users exist",
Method: http.MethodPost,
URL: "/api/beszel/create-user",
Body: jsonReader(map[string]any{
"email": "firstuser@example.com",
"password": "password123",
}),
ExpectedStatus: 200,
ExpectedContent: []string{"User created"},
TestAppFactory: testAppFactoryExisting,
BeforeTestFunc: func(t testing.TB, app *pbTests.TestApp, e *core.ServeEvent) {
userCount, err := hub.CountRecords("users")
require.NoError(t, err)
require.Zero(t, userCount, "Should start with no users")
superusers, err := hub.FindAllRecords(core.CollectionNameSuperusers)
require.NoError(t, err)
require.EqualValues(t, 1, len(superusers), "Should start with one temporary superuser")
require.EqualValues(t, migrations.TempAdminEmail, superusers[0].GetString("email"), "Should have created one temporary superuser")
},
AfterTestFunc: func(t testing.TB, app *pbTests.TestApp, res *http.Response) {
userCount, err := hub.CountRecords("users")
require.NoError(t, err)
require.EqualValues(t, 1, userCount, "Should have created one user")
superusers, err := hub.FindAllRecords(core.CollectionNameSuperusers)
require.NoError(t, err)
require.EqualValues(t, 1, len(superusers), "Should have created one superuser")
require.EqualValues(t, "firstuser@example.com", superusers[0].GetString("email"), "Should have created one superuser")
},
},
{
Name: "POST /create-user - should not be available when users exist",
Method: http.MethodPost,
URL: "/api/beszel/create-user",
Body: jsonReader(map[string]any{
"email": "firstuser@example.com",
"password": "password123",
}),
ExpectedStatus: 404,
ExpectedContent: []string{"wasn't found"},
TestAppFactory: testAppFactoryExisting,
},
}
for _, scenario := range scenarios {
scenario.Test(t)
}
})
t.Run("CreateUserEndpoint not available when USER_EMAIL, USER_PASSWORD are set", func(t *testing.T) {
os.Setenv("BESZEL_HUB_USER_EMAIL", "me@example.com")
os.Setenv("BESZEL_HUB_USER_PASSWORD", "password123")
defer os.Unsetenv("BESZEL_HUB_USER_EMAIL")
defer os.Unsetenv("BESZEL_HUB_USER_PASSWORD")
hub, _ := beszelTests.NewTestHub(t.TempDir())
defer hub.Cleanup()
hub.StartHub()
testAppFactory := func(t testing.TB) *pbTests.TestApp {
return hub.TestApp
}
scenario := beszelTests.ApiScenario{
Name: "POST /create-user - should not be available when USER_EMAIL, USER_PASSWORD are set",
Method: http.MethodPost,
URL: "/api/beszel/create-user",
ExpectedStatus: 404,
ExpectedContent: []string{"wasn't found"},
TestAppFactory: testAppFactory,
BeforeTestFunc: func(t testing.TB, app *pbTests.TestApp, e *core.ServeEvent) {
users, err := hub.FindAllRecords("users")
require.NoError(t, err)
require.EqualValues(t, 1, len(users), "Should start with one user")
require.EqualValues(t, "me@example.com", users[0].GetString("email"), "Should have created one user")
superusers, err := hub.FindAllRecords(core.CollectionNameSuperusers)
require.NoError(t, err)
require.EqualValues(t, 1, len(superusers), "Should start with one superuser")
require.EqualValues(t, "me@example.com", superusers[0].GetString("email"), "Should have created one superuser")
},
AfterTestFunc: func(t testing.TB, app *pbTests.TestApp, res *http.Response) {
users, err := hub.FindAllRecords("users")
require.NoError(t, err)
require.EqualValues(t, 1, len(users), "Should still have one user")
require.EqualValues(t, "me@example.com", users[0].GetString("email"), "Should have created one user")
superusers, err := hub.FindAllRecords(core.CollectionNameSuperusers)
require.NoError(t, err)
require.EqualValues(t, 1, len(superusers), "Should still have one superuser")
require.EqualValues(t, "me@example.com", superusers[0].GetString("email"), "Should have created one superuser")
},
}
scenario.Test(t)
})
}
func TestCreateUserEndpointAvailability(t *testing.T) { func TestCreateUserEndpointAvailability(t *testing.T) {
t.Run("CreateUserEndpoint available when no users exist", func(t *testing.T) { t.Run("CreateUserEndpoint available when no users exist", func(t *testing.T) {
hub, _ := beszelTests.NewTestHub(t.TempDir()) hub, _ := beszelTests.NewTestHub(t.TempDir())

View File

@@ -0,0 +1,79 @@
//go:build development
package hub
import (
"beszel"
"fmt"
"io"
"log/slog"
"net/http"
"net/http/httputil"
"net/url"
"strings"
"github.com/pocketbase/pocketbase/core"
)
// Wraps http.RoundTripper to modify dev proxy HTML responses
type responseModifier struct {
transport http.RoundTripper
hub *Hub
}
func (rm *responseModifier) RoundTrip(req *http.Request) (*http.Response, error) {
resp, err := rm.transport.RoundTrip(req)
if err != nil {
return resp, err
}
// Only modify HTML responses
contentType := resp.Header.Get("Content-Type")
if !strings.Contains(contentType, "text/html") {
return resp, nil
}
body, err := io.ReadAll(resp.Body)
if err != nil {
return resp, err
}
resp.Body.Close()
// Create a new response with the modified body
modifiedBody := rm.modifyHTML(string(body))
resp.Body = io.NopCloser(strings.NewReader(modifiedBody))
resp.ContentLength = int64(len(modifiedBody))
resp.Header.Set("Content-Length", fmt.Sprintf("%d", len(modifiedBody)))
return resp, nil
}
func (rm *responseModifier) modifyHTML(html string) string {
parsedURL, err := url.Parse(rm.hub.appURL)
if err != nil {
return html
}
// fix base paths in html if using subpath
basePath := strings.TrimSuffix(parsedURL.Path, "/") + "/"
html = strings.ReplaceAll(html, "./", basePath)
html = strings.Replace(html, "{{V}}", beszel.Version, 1)
html = strings.Replace(html, "{{HUB_URL}}", rm.hub.appURL, 1)
return html
}
// startServer sets up the development server for Beszel
func (h *Hub) startServer(se *core.ServeEvent) error {
slog.Info("starting server", "appURL", h.appURL)
proxy := httputil.NewSingleHostReverseProxy(&url.URL{
Scheme: "http",
Host: "localhost:5173",
})
proxy.Transport = &responseModifier{
transport: http.DefaultTransport,
hub: h,
}
se.Router.GET("/{path...}", func(e *core.RequestEvent) error {
proxy.ServeHTTP(e.Response, e.Request)
return nil
})
return nil
}

View File

@@ -0,0 +1,51 @@
//go:build !development
package hub
import (
"beszel"
"beszel/site"
"io/fs"
"net/http"
"net/url"
"strings"
"github.com/pocketbase/pocketbase/apis"
"github.com/pocketbase/pocketbase/core"
)
// startServer sets up the production server for Beszel
func (h *Hub) startServer(se *core.ServeEvent) error {
// parse app url
parsedURL, err := url.Parse(h.appURL)
if err != nil {
return err
}
// fix base paths in html if using subpath
basePath := strings.TrimSuffix(parsedURL.Path, "/") + "/"
indexFile, _ := fs.ReadFile(site.DistDirFS, "index.html")
html := strings.ReplaceAll(string(indexFile), "./", basePath)
html = strings.Replace(html, "{{V}}", beszel.Version, 1)
html = strings.Replace(html, "{{HUB_URL}}", h.appURL, 1)
// set up static asset serving
staticPaths := [2]string{"/static/", "/assets/"}
serveStatic := apis.Static(site.DistDirFS, false)
// get CSP configuration
csp, cspExists := GetEnv("CSP")
// add route
se.Router.GET("/{path...}", func(e *core.RequestEvent) error {
// serve static assets if path is in staticPaths
for i := range staticPaths {
if strings.Contains(e.Request.URL.Path, staticPaths[i]) {
e.Response.Header().Set("Cache-Control", "public, max-age=2592000")
return serveStatic(e)
}
}
if cspExists {
e.Response.Header().Del("X-Frame-Options")
e.Response.Header().Set("Content-Security-Policy", csp)
}
return e.HTML(http.StatusOK, html)
})
return nil
}

View File

@@ -29,7 +29,7 @@ func TestSystemManagerNew(t *testing.T) {
user, err := tests.CreateUser(hub, "test@test.com", "testtesttest") user, err := tests.CreateUser(hub, "test@test.com", "testtesttest")
require.NoError(t, err) require.NoError(t, err)
synctest.Run(func() { synctest.Test(t, func(t *testing.T) {
sm.Initialize() sm.Initialize()
record, err := tests.CreateRecord(hub, "systems", map[string]any{ record, err := tests.CreateRecord(hub, "systems", map[string]any{
@@ -110,9 +110,11 @@ func TestSystemManagerNew(t *testing.T) {
err = hub.Delete(record) err = hub.Delete(record)
require.NoError(t, err) require.NoError(t, err)
assert.False(t, sm.HasSystem(record.Id), "System should not exist in the store after deletion") assert.False(t, sm.HasSystem(record.Id), "System should not exist in the store after deletion")
})
testOld(t, hub) testOld(t, hub)
synctest.Test(t, func(t *testing.T) {
time.Sleep(time.Second) time.Sleep(time.Second)
synctest.Wait() synctest.Wait()

View File

@@ -100,3 +100,10 @@ func (sm *SystemManager) SetSystemStatusInDB(systemID string, status string) boo
return true return true
} }
// TESTING ONLY: RemoveAllSystems removes all systems from the store
func (sm *SystemManager) RemoveAllSystems() {
for _, system := range sm.systems.GetAll() {
sm.RemoveSystem(system.Id)
}
}

View File

@@ -1,57 +1,85 @@
package hub package hub
import ( import (
"beszel" "beszel/internal/ghupdate"
"fmt" "fmt"
"log"
"os" "os"
"strings" "os/exec"
"github.com/blang/semver"
"github.com/rhysd/go-github-selfupdate/selfupdate"
"github.com/spf13/cobra" "github.com/spf13/cobra"
) )
// Update updates beszel to the latest version // Update updates beszel to the latest version
func Update(_ *cobra.Command, _ []string) { func Update(cmd *cobra.Command, _ []string) {
var latest *selfupdate.Release dataDir := os.TempDir()
var found bool
var err error // set dataDir to ./beszel_data if it exists
currentVersion := semver.MustParse(beszel.Version) if _, err := os.Stat("./beszel_data"); err == nil {
fmt.Println("beszel", currentVersion) dataDir = "./beszel_data"
fmt.Println("Checking for updates...") }
updater, _ := selfupdate.NewUpdater(selfupdate.Config{
Filters: []string{"beszel_"}, // Check if china-mirrors flag is set
useMirror, _ := cmd.Flags().GetBool("china-mirrors")
updated, err := ghupdate.Update(ghupdate.Config{
ArchiveExecutable: "beszel",
DataDir: dataDir,
UseMirror: useMirror,
}) })
latest, found, err = updater.DetectLatest("henrygd/beszel")
if err != nil { if err != nil {
fmt.Println("Error checking for updates:", err) log.Fatal(err)
os.Exit(1)
} }
if !updated {
if !found {
fmt.Println("No updates found")
os.Exit(0)
}
fmt.Println("Latest version:", latest.Version)
if latest.Version.LTE(currentVersion) {
fmt.Println("You are up to date")
return return
} }
var binaryPath string // make sure the file is executable
fmt.Printf("Updating from %s to %s...\n", currentVersion, latest.Version) exePath, err := os.Executable()
binaryPath, err = os.Executable() if err == nil {
if err != nil { if err := os.Chmod(exePath, 0755); err != nil {
fmt.Println("Error getting binary path:", err) fmt.Printf("Warning: failed to set executable permissions: %v\n", err)
os.Exit(1) }
} }
err = selfupdate.UpdateTo(latest.AssetURL, binaryPath)
if err != nil { // Try to restart the service if it's running
fmt.Println("Please try rerunning with sudo. Error:", err) restartService()
os.Exit(1) }
}
fmt.Printf("Successfully updated to %s\n\n%s\n", latest.Version, strings.TrimSpace(latest.ReleaseNotes)) // restartService attempts to restart the beszel service
func restartService() {
// Check if we're running as a service by looking for systemd
if _, err := exec.LookPath("systemctl"); err == nil {
// Check if beszel service exists and is active
cmd := exec.Command("systemctl", "is-active", "beszel.service")
if err := cmd.Run(); err == nil {
ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel service...")
restartCmd := exec.Command("systemctl", "restart", "beszel.service")
if err := restartCmd.Run(); err != nil {
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: Failed to restart service: %v\n", err)
ghupdate.ColorPrint(ghupdate.ColorYellow, "Please restart the service manually: sudo systemctl restart beszel")
} else {
ghupdate.ColorPrint(ghupdate.ColorGreen, "Service restarted successfully")
}
return
}
}
// Check for OpenRC (Alpine Linux)
if _, err := exec.LookPath("rc-service"); err == nil {
cmd := exec.Command("rc-service", "beszel", "status")
if err := cmd.Run(); err == nil {
ghupdate.ColorPrint(ghupdate.ColorYellow, "Restarting beszel service...")
restartCmd := exec.Command("rc-service", "beszel", "restart")
if err := restartCmd.Run(); err != nil {
ghupdate.ColorPrintf(ghupdate.ColorYellow, "Warning: Failed to restart service: %v\n", err)
ghupdate.ColorPrint(ghupdate.ColorYellow, "Please restart the service manually: sudo rc-service beszel restart")
} else {
ghupdate.ColorPrint(ghupdate.ColorGreen, "Service restarted successfully")
}
return
}
}
ghupdate.ColorPrint(ghupdate.ColorYellow, "Service restart not attempted. If running as a service, restart manually.")
} }

View File

@@ -214,6 +214,7 @@ func (rm *RecordManager) AverageSystemStats(db dbx.Builder, records RecordIds) *
sum.Battery[1] = stats.Battery[1] sum.Battery[1] = stats.Battery[1]
// Set peak values // Set peak values
sum.MaxCpu = max(sum.MaxCpu, stats.MaxCpu, stats.Cpu) sum.MaxCpu = max(sum.MaxCpu, stats.MaxCpu, stats.Cpu)
sum.MaxMem = max(sum.MaxMem, stats.MaxMem, stats.MemUsed)
sum.MaxNetworkSent = max(sum.MaxNetworkSent, stats.MaxNetworkSent, stats.NetworkSent) sum.MaxNetworkSent = max(sum.MaxNetworkSent, stats.MaxNetworkSent, stats.NetworkSent)
sum.MaxNetworkRecv = max(sum.MaxNetworkRecv, stats.MaxNetworkRecv, stats.NetworkRecv) sum.MaxNetworkRecv = max(sum.MaxNetworkRecv, stats.MaxNetworkRecv, stats.NetworkRecv)
sum.MaxDiskReadPs = max(sum.MaxDiskReadPs, stats.MaxDiskReadPs, stats.DiskReadPs) sum.MaxDiskReadPs = max(sum.MaxDiskReadPs, stats.MaxDiskReadPs, stats.DiskReadPs)

View File

@@ -96,3 +96,31 @@ func ClearCollection(t testing.TB, app core.App, collectionName string) error {
assert.EqualValues(t, recordCount, 0, "should have 0 records after clearing") assert.EqualValues(t, recordCount, 0, "should have 0 records after clearing")
return err return err
} }
func (h *TestHub) Cleanup() {
h.GetAlertManager().StopWorker()
h.GetSystemManager().RemoveAllSystems()
h.TestApp.Cleanup()
}
func CreateSystems(app core.App, count int, userId string, status string) ([]*core.Record, error) {
systems := make([]*core.Record, 0, count)
for i := range count {
system, err := CreateRecord(app, "systems", map[string]any{
"name": fmt.Sprintf("test-system-%d", i),
"host": fmt.Sprintf("127.0.0.%d", i),
"port": "33914",
"users": []string{userId},
})
if err != nil {
return nil, err
}
system.Set("status", status)
err = app.SaveNoValidate(system)
if err != nil {
return nil, err
}
systems = append(systems, system)
}
return systems, nil
}

View File

@@ -1,6 +1,8 @@
package migrations package migrations
import ( import (
"os"
"github.com/pocketbase/pocketbase/core" "github.com/pocketbase/pocketbase/core"
m "github.com/pocketbase/pocketbase/migrations" m "github.com/pocketbase/pocketbase/migrations"
) )
@@ -19,11 +21,51 @@ func init() {
if err := app.Save(settings); err != nil { if err := app.Save(settings); err != nil {
return err return err
} }
// create superuser // create superuser
collection, _ := app.FindCollectionByNameOrId(core.CollectionNameSuperusers) superuserCollection, _ := app.FindCollectionByNameOrId(core.CollectionNameSuperusers)
user := core.NewRecord(collection) superUser := core.NewRecord(superuserCollection)
user.SetEmail(TempAdminEmail)
user.SetRandomPassword() // set email
return app.Save(user) email, _ := GetEnv("USER_EMAIL")
password, _ := GetEnv("USER_PASSWORD")
didProvideUserDetails := email != "" && password != ""
// set superuser email
if email == "" {
email = TempAdminEmail
}
superUser.SetEmail(email)
// set superuser password
if password != "" {
superUser.SetPassword(password)
} else {
superUser.SetRandomPassword()
}
// if user details are provided, we create a regular user as well
if didProvideUserDetails {
usersCollection, _ := app.FindCollectionByNameOrId("users")
user := core.NewRecord(usersCollection)
user.SetEmail(email)
user.SetPassword(password)
user.SetVerified(true)
err := app.Save(user)
if err != nil {
return err
}
}
return app.Save(superUser)
}, nil) }, nil)
} }
// GetEnv retrieves an environment variable with a "BESZEL_HUB_" prefix, or falls back to the unprefixed key.
func GetEnv(key string) (value string, exists bool) {
if value, exists = os.LookupEnv("BESZEL_HUB_" + key); exists {
return value, exists
}
// Fallback to the old unprefixed key
return os.LookupEnv(key)
}

Binary file not shown.

File diff suppressed because it is too large Load Diff

View File

@@ -1,10 +1,10 @@
{ {
"name": "beszel", "name": "beszel",
"private": true, "private": true,
"version": "0.12.3", "version": "0.12.7",
"type": "module", "type": "module",
"scripts": { "scripts": {
"dev": "vite", "dev": "vite --host",
"build": "lingui extract --overwrite && lingui compile && vite build", "build": "lingui extract --overwrite && lingui compile && vite build",
"preview": "vite preview", "preview": "vite preview",
"sync": "lingui extract --overwrite && lingui compile", "sync": "lingui extract --overwrite && lingui compile",
@@ -33,6 +33,7 @@
"@radix-ui/react-toast": "^1.2.15", "@radix-ui/react-toast": "^1.2.15",
"@radix-ui/react-tooltip": "^1.2.8", "@radix-ui/react-tooltip": "^1.2.8",
"@tanstack/react-table": "^8.21.3", "@tanstack/react-table": "^8.21.3",
"@tanstack/react-virtual": "^3.13.12",
"class-variance-authority": "^0.7.1", "class-variance-authority": "^0.7.1",
"clsx": "^2.1.1", "clsx": "^2.1.1",
"cmdk": "^1.1.1", "cmdk": "^1.1.1",
@@ -43,7 +44,7 @@
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"recharts": "^2.15.4", "recharts": "^2.15.4",
"tailwind-merge": "^2.6.0", "tailwind-merge": "^3.3.1",
"valibot": "^0.42.1" "valibot": "^0.42.1"
}, },
"devDependencies": { "devDependencies": {
@@ -51,17 +52,15 @@
"@lingui/swc-plugin": "^5.6.1", "@lingui/swc-plugin": "^5.6.1",
"@lingui/vite-plugin": "^5.4.1", "@lingui/vite-plugin": "^5.4.1",
"@tailwindcss/container-queries": "^0.1.1", "@tailwindcss/container-queries": "^0.1.1",
"@tailwindcss/postcss": "^4.1.12", "@tailwindcss/vite": "^4.1.12",
"@types/bun": "^1.2.20", "@types/bun": "^1.2.20",
"@types/react": "^18.3.24", "@types/react": "^19.1.11",
"@types/react-dom": "^18.3.7", "@types/react-dom": "^19.1.7",
"@vitejs/plugin-react-swc": "^3.11.0", "@vitejs/plugin-react-swc": "^4.0.1",
"postcss": "^8.5.6",
"tailwindcss": "^4.1.12", "tailwindcss": "^4.1.12",
"tailwindcss-rtl": "^0.9.0",
"tw-animate-css": "^1.3.7", "tw-animate-css": "^1.3.7",
"typescript": "^5.9.2", "typescript": "^5.9.2",
"vite": "^6.3.5" "vite": "^7.1.3"
}, },
"overrides": { "overrides": {
"@nanostores/router": { "@nanostores/router": {

View File

@@ -1,5 +0,0 @@
export default {
plugins: {
"@tailwindcss/postcss": {},
},
}

View File

@@ -13,8 +13,9 @@ import {
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs" import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { $publicKey, pb } from "@/lib/stores" import { $publicKey } from "@/lib/stores"
import { cn, generateToken, isReadOnlyUser, tokenMap, useLocalStorage } from "@/lib/utils" import { cn, generateToken, tokenMap, useBrowserStorage } from "@/lib/utils"
import { pb, isReadOnlyUser } from "@/lib/api"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import { ChevronDownIcon, ExternalLinkIcon, PlusIcon } from "lucide-react" import { ChevronDownIcon, ExternalLinkIcon, PlusIcon } from "lucide-react"
import { memo, useEffect, useRef, useState } from "react" import { memo, useEffect, useRef, useState } from "react"
@@ -76,7 +77,7 @@ export const SystemDialog = ({ setOpen, system }: { setOpen: (open: boolean) =>
const port = useRef<HTMLInputElement>(null) const port = useRef<HTMLInputElement>(null)
const [hostValue, setHostValue] = useState(system?.host ?? "") const [hostValue, setHostValue] = useState(system?.host ?? "")
const isUnixSocket = hostValue.startsWith("/") const isUnixSocket = hostValue.startsWith("/")
const [tab, setTab] = useLocalStorage("as-tab", "docker") const [tab, setTab] = useBrowserStorage("as-tab", "docker")
const [token, setToken] = useState(system?.token ?? "") const [token, setToken] = useState(system?.token ?? "")
useEffect(() => { useEffect(() => {
@@ -96,7 +97,7 @@ export const SystemDialog = ({ setOpen, system }: { setOpen: (open: boolean) =>
tokenMap.set(system.id, token) tokenMap.set(system.id, token)
setToken(token) setToken(token)
})() })()
}, [system?.id]) }, [system?.id, nextSystemToken])
async function handleSubmit(e: SubmitEvent) { async function handleSubmit(e: SubmitEvent) {
e.preventDefault() e.preventDefault()
@@ -132,7 +133,7 @@ export const SystemDialog = ({ setOpen, system }: { setOpen: (open: boolean) =>
> >
<Tabs defaultValue={tab} onValueChange={setTab}> <Tabs defaultValue={tab} onValueChange={setTab}>
<DialogHeader> <DialogHeader>
<DialogTitle className="mb-2"> <DialogTitle className="mb-2 max-w-100 truncate pr-8">
{system ? `${t`Edit`} ${system?.name}` : <Trans>Add New System</Trans>} {system ? `${t`Edit`} ${system?.name}` : <Trans>Add New System</Trans>}
</DialogTitle> </DialogTitle>
<TabsList className="grid w-full grid-cols-2"> <TabsList className="grid w-full grid-cols-2">

View File

@@ -16,7 +16,9 @@ export const alertsHistoryColumns: ColumnDef<AlertsHistoryRecord>[] = [
<Trans>System</Trans> <Trans>System</Trans>
</Button> </Button>
), ),
cell: ({ row }) => <span className="ps-2">{row.original.expand?.system?.name || row.original.system}</span>, cell: ({ row }) => (
<div className="ps-2 max-w-60 truncate">{row.original.expand?.system?.name || row.original.system}</div>
),
filterFn: (row, _, filterValue) => { filterFn: (row, _, filterValue) => {
const display = row.original.expand?.system?.name || row.original.system || "" const display = row.original.expand?.system?.name || row.original.system || ""
return display.toLowerCase().includes(filterValue.toLowerCase()) return display.toLowerCase().includes(filterValue.toLowerCase())

View File

@@ -1,6 +1,6 @@
import { t } from "@lingui/core/macro" import { t } from "@lingui/core/macro"
import { Trans, Plural } from "@lingui/react/macro" import { Trans, Plural } from "@lingui/react/macro"
import { $alerts, $systems, pb } from "@/lib/stores" import { $alerts, $systems } from "@/lib/stores"
import { cn, debounce } from "@/lib/utils" import { cn, debounce } from "@/lib/utils"
import { alertInfo } from "@/lib/alerts" import { alertInfo } from "@/lib/alerts"
import { Switch } from "@/components/ui/switch" import { Switch } from "@/components/ui/switch"
@@ -15,6 +15,7 @@ import { Tabs, TabsList, TabsTrigger, TabsContent } from "@/components/ui/tabs"
import { ServerIcon, GlobeIcon } from "lucide-react" import { ServerIcon, GlobeIcon } from "lucide-react"
import { $router, Link } from "@/components/router" import { $router, Link } from "@/components/router"
import { DialogHeader } from "@/components/ui/dialog" import { DialogHeader } from "@/components/ui/dialog"
import { pb } from "@/lib/api"
const Slider = lazy(() => import("@/components/ui/slider")) const Slider = lazy(() => import("@/components/ui/slider"))
@@ -95,7 +96,7 @@ export const AlertDialogContent = memo(function AlertDialogContent({ system }: {
<TabsList className="mb-1 -mt-0.5"> <TabsList className="mb-1 -mt-0.5">
<TabsTrigger value="system"> <TabsTrigger value="system">
<ServerIcon className="me-2 h-3.5 w-3.5" /> <ServerIcon className="me-2 h-3.5 w-3.5" />
{system.name} <span className="truncate max-w-60">{system.name}</span>
</TabsTrigger> </TabsTrigger>
<TabsTrigger value="global"> <TabsTrigger value="global">
<GlobeIcon className="me-1.5 h-3.5 w-3.5" /> <GlobeIcon className="me-1.5 h-3.5 w-3.5" />

View File

@@ -1,13 +1,14 @@
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts" import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart" import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { useYAxisWidth, cn, formatShortDate, chartMargin } from "@/lib/utils" import { cn, formatShortDate, chartMargin } from "@/lib/utils"
import { useYAxisWidth } from "./hooks"
import { ChartData, SystemStatsRecord } from "@/types" import { ChartData, SystemStatsRecord } from "@/types"
import { useMemo } from "react" import { useMemo } from "react"
export type DataPoint = { export type DataPoint = {
label: string label: string
dataKey: (data: SystemStatsRecord) => number | undefined dataKey: (data: SystemStatsRecord) => number | undefined
color: string color: number | string
opacity: number opacity: number
} }
@@ -70,7 +71,7 @@ export default function AreaChartDefault({
} }
/> />
{dataPoints?.map((dataPoint, i) => { {dataPoints?.map((dataPoint, i) => {
const color = `hsl(var(--chart-${dataPoint.color}))` const color = `var(--chart-${dataPoint.color})`
return ( return (
<Area <Area
key={i} key={i}

View File

@@ -1,23 +1,26 @@
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts" import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart" import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { memo, useMemo } from "react" import { memo, useMemo } from "react"
import { useYAxisWidth, cn, formatShortDate, chartMargin, toFixedFloat, formatBytes, decimalString } from "@/lib/utils" import { cn, formatShortDate, chartMargin, toFixedFloat, formatBytes, decimalString } from "@/lib/utils"
// import Spinner from '../spinner' // import Spinner from '../spinner'
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import { $containerFilter, $userSettings } from "@/lib/stores" import { $containerFilter, $userSettings } from "@/lib/stores"
import { ChartData } from "@/types" import { ChartData } from "@/types"
import { Separator } from "../ui/separator" import { Separator } from "../ui/separator"
import { ChartType, Unit } from "@/lib/enums" import { ChartType, Unit } from "@/lib/enums"
import { useYAxisWidth } from "./hooks"
export default memo(function ContainerChart({ export default memo(function ContainerChart({
dataKey, dataKey,
chartData, chartData,
chartType, chartType,
chartConfig,
unit = "%", unit = "%",
}: { }: {
dataKey: string dataKey: string
chartData: ChartData chartData: ChartData
chartType: ChartType chartType: ChartType
chartConfig: ChartConfig
unit?: string unit?: string
}) { }) {
const filter = useStore($containerFilter) const filter = useStore($containerFilter)
@@ -28,40 +31,6 @@ export default memo(function ContainerChart({
const isNetChart = chartType === ChartType.Network const isNetChart = chartType === ChartType.Network
const chartConfig = useMemo(() => {
const config = {} as Record<string, { label: string; color: string }>
const totalUsage = new Map<string, number>()
// calculate total usage of each container
for (const stats of containerData) {
for (const key in stats) {
if (!key || key === "created") continue
const currentTotal = totalUsage.get(key) ?? 0
const increment = isNetChart
? (stats[key]?.nr ?? 0) + (stats[key]?.ns ?? 0)
: // @ts-ignore
stats[key]?.[dataKey] ?? 0
totalUsage.set(key, currentTotal + increment)
}
}
// Sort keys and generate colors based on usage
const sortedEntries = Array.from(totalUsage.entries()).sort(([, a], [, b]) => b - a)
const length = sortedEntries.length
sortedEntries.forEach(([key], i) => {
const hue = ((i * 360) / length) % 360
config[key] = {
label: key,
color: `hsl(${hue}, 60%, 55%)`,
}
})
return config satisfies ChartConfig
}, [chartData])
const { toolTipFormatter, dataFunction, tickFormatter } = useMemo(() => { const { toolTipFormatter, dataFunction, tickFormatter } = useMemo(() => {
const obj = {} as { const obj = {} as {
toolTipFormatter: (item: any, key: string) => React.ReactNode | string toolTipFormatter: (item: any, key: string) => React.ReactNode | string
@@ -119,7 +88,14 @@ export default memo(function ContainerChart({
return obj return obj
}, []) }, [])
const filterLower = filter?.toLowerCase() // Filter with set lookup
const filteredKeys = useMemo(() => {
if (!filter) {
return new Set<string>()
}
const filterLower = filter.toLowerCase()
return new Set(Object.keys(chartConfig).filter((key) => !key.toLowerCase().includes(filterLower)))
}, [chartConfig, filter])
// console.log('rendered at', new Date()) // console.log('rendered at', new Date())
@@ -162,9 +138,9 @@ export default memo(function ContainerChart({
content={<ChartTooltipContent filter={filter} contentFormatter={toolTipFormatter} />} content={<ChartTooltipContent filter={filter} contentFormatter={toolTipFormatter} />}
/> />
{Object.keys(chartConfig).map((key) => { {Object.keys(chartConfig).map((key) => {
const filtered = filterLower && !key.toLowerCase().includes(filterLower) const filtered = filteredKeys.has(key)
let fillOpacity = filtered ? 0.05 : 0.4 const fillOpacity = filtered ? 0.05 : 0.4
let strokeOpacity = filtered ? 0.1 : 1 const strokeOpacity = filtered ? 0.1 : 1
return ( return (
<Area <Area
key={key} key={key}

View File

@@ -1,10 +1,11 @@
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts" import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart" import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { useYAxisWidth, cn, formatShortDate, decimalString, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils" import { cn, formatShortDate, decimalString, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils"
import { ChartData } from "@/types" import { ChartData } from "@/types"
import { memo } from "react" import { memo } from "react"
import { useLingui } from "@lingui/react/macro" import { useLingui } from "@lingui/react/macro"
import { Unit } from "@/lib/enums" import { Unit } from "@/lib/enums"
import { useYAxisWidth } from "./hooks"
export default memo(function DiskChart({ export default memo(function DiskChart({
dataKey, dataKey,
@@ -69,9 +70,9 @@ export default memo(function DiskChart({
dataKey={dataKey} dataKey={dataKey}
name={t`Disk Usage`} name={t`Disk Usage`}
type="monotoneX" type="monotoneX"
fill="hsl(var(--chart-4))" fill="var(--chart-4)"
fillOpacity={0.4} fillOpacity={0.4}
stroke="hsl(var(--chart-4))" stroke="var(--chart-4)"
// animationDuration={1200} // animationDuration={1200}
isAnimationActive={false} isAnimationActive={false}
/> />

View File

@@ -8,9 +8,10 @@ import {
ChartTooltipContent, ChartTooltipContent,
xAxis, xAxis,
} from "@/components/ui/chart" } from "@/components/ui/chart"
import { useYAxisWidth, cn, formatShortDate, toFixedFloat, decimalString, chartMargin } from "@/lib/utils" import { cn, formatShortDate, toFixedFloat, decimalString, chartMargin } from "@/lib/utils"
import { ChartData } from "@/types" import { ChartData } from "@/types"
import { memo, useMemo } from "react" import { memo, useMemo } from "react"
import { useYAxisWidth } from "./hooks"
export default memo(function GpuPowerChart({ chartData }: { chartData: ChartData }) { export default memo(function GpuPowerChart({ chartData }: { chartData: ChartData }) {
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth() const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()

View File

@@ -0,0 +1,107 @@
import { useMemo, useState } from "react"
import { ChartConfig } from "@/components/ui/chart"
import { ChartData } from "@/types"
/** Chart configurations for CPU, memory, and network usage charts */
export interface ContainerChartConfigs {
cpu: ChartConfig
memory: ChartConfig
network: ChartConfig
}
/**
* Generates chart configurations for container metrics visualization
* @param containerData - Array of container statistics data points
* @returns Chart configurations for CPU, memory, and network metrics
*/
export function useContainerChartConfigs(containerData: ChartData["containerData"]): ContainerChartConfigs {
return useMemo(() => {
const configs = {
cpu: {} as ChartConfig,
memory: {} as ChartConfig,
network: {} as ChartConfig,
}
// Aggregate usage metrics for each container
const totalUsage = {
cpu: new Map<string, number>(),
memory: new Map<string, number>(),
network: new Map<string, number>(),
}
// Process each data point to calculate totals
for (let i = 0; i < containerData.length; i++) {
const stats = containerData[i]
const containerNames = Object.keys(stats)
for (let j = 0; j < containerNames.length; j++) {
const containerName = containerNames[j]
// Skip metadata field
if (containerName === "created") {
continue
}
const containerStats = stats[containerName]
if (!containerStats) {
continue
}
// Accumulate metrics for CPU, memory, and network
const currentCpu = totalUsage.cpu.get(containerName) ?? 0
const currentMemory = totalUsage.memory.get(containerName) ?? 0
const currentNetwork = totalUsage.network.get(containerName) ?? 0
totalUsage.cpu.set(containerName, currentCpu + (containerStats.c ?? 0))
totalUsage.memory.set(containerName, currentMemory + (containerStats.m ?? 0))
totalUsage.network.set(containerName, currentNetwork + (containerStats.nr ?? 0) + (containerStats.ns ?? 0))
}
}
// Generate chart configurations for each metric type
Object.entries(totalUsage).forEach(([chartType, usageMap]) => {
const sortedContainers = Array.from(usageMap.entries()).sort(([, a], [, b]) => b - a)
const chartConfig = {} as Record<string, { label: string; color: string }>
const count = sortedContainers.length
// Generate colors for each container
for (let i = 0; i < count; i++) {
const [containerName] = sortedContainers[i]
const hue = ((i * 360) / count) % 360
chartConfig[containerName] = {
label: containerName,
color: `hsl(${hue}, 60%, 55%)`,
}
}
configs[chartType as keyof typeof configs] = chartConfig
})
return configs
}, [containerData])
}
/** Sets the correct width of the y axis in recharts based on the longest label */
export function useYAxisWidth() {
const [yAxisWidth, setYAxisWidth] = useState(0)
let maxChars = 0
let timeout: ReturnType<typeof setTimeout>
function updateYAxisWidth(str: string) {
if (str.length > maxChars) {
maxChars = str.length
const div = document.createElement("div")
div.className = "text-xs tabular-nums tracking-tighter table sr-only"
div.innerHTML = str
clearTimeout(timeout)
timeout = setTimeout(() => {
document.body.appendChild(div)
const width = div.offsetWidth + 24
if (width > yAxisWidth) {
setYAxisWidth(div.offsetWidth + 24)
}
document.body.removeChild(div)
})
}
return str
}
return { yAxisWidth, updateYAxisWidth }
}

View File

@@ -8,10 +8,11 @@ import {
ChartTooltipContent, ChartTooltipContent,
xAxis, xAxis,
} from "@/components/ui/chart" } from "@/components/ui/chart"
import { useYAxisWidth, cn, formatShortDate, toFixedFloat, decimalString, chartMargin } from "@/lib/utils" import { cn, formatShortDate, toFixedFloat, decimalString, chartMargin } from "@/lib/utils"
import { ChartData, SystemStats } from "@/types" import { ChartData, SystemStats } from "@/types"
import { memo } from "react" import { memo } from "react"
import { t } from "@lingui/core/macro" import { t } from "@lingui/core/macro"
import { useYAxisWidth } from "./hooks"
export default memo(function LoadAverageChart({ chartData }: { chartData: ChartData }) { export default memo(function LoadAverageChart({ chartData }: { chartData: ChartData }) {
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth() const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()

View File

@@ -1,12 +1,13 @@
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts" import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart" import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { useYAxisWidth, cn, decimalString, formatShortDate, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils" import { cn, decimalString, formatShortDate, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils"
import { memo } from "react" import { memo } from "react"
import { ChartData } from "@/types" import { ChartData } from "@/types"
import { useLingui } from "@lingui/react/macro" import { useLingui } from "@lingui/react/macro"
import { Unit } from "@/lib/enums" import { Unit } from "@/lib/enums"
import { useYAxisWidth } from "./hooks"
export default memo(function MemChart({ chartData }: { chartData: ChartData }) { export default memo(function MemChart({ chartData, showMax }: { chartData: ChartData; showMax: boolean }) {
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth() const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()
const { t } = useLingui() const { t } = useLingui()
@@ -66,39 +67,39 @@ export default memo(function MemChart({ chartData }: { chartData: ChartData }) {
<Area <Area
name={t`Used`} name={t`Used`}
order={3} order={3}
dataKey="stats.mu" dataKey={({ stats }) => (showMax ? stats?.mm : stats?.mu)}
type="monotoneX" type="monotoneX"
fill="hsl(var(--chart-2))" fill="var(--chart-2)"
fillOpacity={0.4} fillOpacity={0.4}
stroke="hsl(var(--chart-2))" stroke="var(--chart-2)"
stackId="1" stackId="1"
isAnimationActive={false} isAnimationActive={false}
/> />
{chartData.systemStats.at(-1)?.stats.mz && ( {/* {chartData.systemStats.at(-1)?.stats.mz && ( */}
<Area <Area
name="ZFS ARC" name="ZFS ARC"
order={2} order={2}
dataKey="stats.mz" dataKey={({ stats }) => (showMax ? null : stats?.mz)}
type="monotoneX" type="monotoneX"
fill="hsla(175 60% 45% / 0.8)" fill="hsla(175 60% 45% / 0.8)"
fillOpacity={0.5} fillOpacity={0.5}
stroke="hsla(175 60% 45% / 0.8)" stroke="hsla(175 60% 45% / 0.8)"
stackId="1" stackId="1"
isAnimationActive={false} isAnimationActive={false}
/> />
)} {/* )} */}
<Area <Area
name={t`Cache / Buffers`} name={t`Cache / Buffers`}
order={1} order={1}
dataKey="stats.mb" dataKey={({ stats }) => (showMax ? null : stats?.mb)}
type="monotoneX" type="monotoneX"
fill="hsla(160 60% 45% / 0.5)" fill="hsla(160 60% 45% / 0.5)"
fillOpacity={0.4} fillOpacity={0.4}
// strokeOpacity={1}
stroke="hsla(160 60% 45% / 0.5)" stroke="hsla(160 60% 45% / 0.5)"
stackId="1" stackId="1"
isAnimationActive={false} isAnimationActive={false}
/> />
{/* <ChartLegend content={<ChartLegendContent />} /> */}
</AreaChart> </AreaChart>
</ChartContainer> </ChartContainer>
</div> </div>

View File

@@ -2,11 +2,12 @@ import { t } from "@lingui/core/macro"
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts" import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart" import { ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { useYAxisWidth, cn, formatShortDate, decimalString, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils" import { cn, formatShortDate, decimalString, chartMargin, formatBytes, toFixedFloat } from "@/lib/utils"
import { ChartData } from "@/types" import { ChartData } from "@/types"
import { memo } from "react" import { memo } from "react"
import { $userSettings } from "@/lib/stores" import { $userSettings } from "@/lib/stores"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import { useYAxisWidth } from "./hooks"
export default memo(function SwapChart({ chartData }: { chartData: ChartData }) { export default memo(function SwapChart({ chartData }: { chartData: ChartData }) {
const { yAxisWidth, updateYAxisWidth } = useYAxisWidth() const { yAxisWidth, updateYAxisWidth } = useYAxisWidth()
@@ -58,9 +59,9 @@ export default memo(function SwapChart({ chartData }: { chartData: ChartData })
dataKey="stats.su" dataKey="stats.su"
name={t`Used`} name={t`Used`}
type="monotoneX" type="monotoneX"
fill="hsl(var(--chart-2))" fill="var(--chart-2)"
fillOpacity={0.4} fillOpacity={0.4}
stroke="hsl(var(--chart-2))" stroke="var(--chart-2)"
isAnimationActive={false} isAnimationActive={false}
/> />
</AreaChart> </AreaChart>

View File

@@ -8,19 +8,12 @@ import {
ChartTooltipContent, ChartTooltipContent,
xAxis, xAxis,
} from "@/components/ui/chart" } from "@/components/ui/chart"
import { import { cn, formatShortDate, toFixedFloat, chartMargin, formatTemperature, decimalString } from "@/lib/utils"
useYAxisWidth,
cn,
formatShortDate,
toFixedFloat,
chartMargin,
formatTemperature,
decimalString,
} from "@/lib/utils"
import { ChartData } from "@/types" import { ChartData } from "@/types"
import { memo, useMemo } from "react" import { memo, useMemo } from "react"
import { $temperatureFilter, $userSettings } from "@/lib/stores" import { $temperatureFilter, $userSettings } from "@/lib/stores"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import { useYAxisWidth } from "./hooks"
export default memo(function TemperatureChart({ chartData }: { chartData: ChartData }) { export default memo(function TemperatureChart({ chartData }: { chartData: ChartData }) {
const filter = useStore($temperatureFilter) const filter = useStore($temperatureFilter)

View File

@@ -23,11 +23,13 @@ import {
} from "@/components/ui/command" } from "@/components/ui/command"
import { memo, useEffect, useMemo } from "react" import { memo, useEffect, useMemo } from "react"
import { $systems } from "@/lib/stores" import { $systems } from "@/lib/stores"
import { getHostDisplayValue, isAdmin, listen } from "@/lib/utils" import { getHostDisplayValue, listen } from "@/lib/utils"
import { $router, basePath, navigate, prependBasePath } from "./router" import { $router, basePath, navigate, prependBasePath } from "./router"
import { Trans } from "@lingui/react/macro" import { Trans } from "@lingui/react/macro"
import { t } from "@lingui/core/macro" import { t } from "@lingui/core/macro"
import { getPagePath } from "@nanostores/router" import { getPagePath } from "@nanostores/router"
import { DialogDescription } from "@radix-ui/react-dialog"
import { isAdmin } from "@/lib/api"
export default memo(function CommandPalette({ open, setOpen }: { open: boolean; setOpen: (open: boolean) => void }) { export default memo(function CommandPalette({ open, setOpen }: { open: boolean; setOpen: (open: boolean) => void }) {
useEffect(() => { useEffect(() => {
@@ -54,11 +56,9 @@ export default memo(function CommandPalette({ open, setOpen }: { open: boolean;
) )
return ( return (
<CommandDialog open={open} onOpenChange={setOpen}> <CommandDialog open={open} onOpenChange={setOpen}>
<DialogDescription className="sr-only">Command palette</DialogDescription>
<CommandInput placeholder={t`Search for systems or settings...`} /> <CommandInput placeholder={t`Search for systems or settings...`} />
<CommandList> <CommandList>
<CommandEmpty>
<Trans>No results found.</Trans>
</CommandEmpty>
{systems.length > 0 && ( {systems.length > 0 && (
<> <>
<CommandGroup> <CommandGroup>
@@ -71,7 +71,7 @@ export default memo(function CommandPalette({ open, setOpen }: { open: boolean;
}} }}
> >
<Server className="me-2 size-4" /> <Server className="me-2 size-4" />
<span>{system.name}</span> <span className="max-w-60 truncate">{system.name}</span>
<CommandShortcut>{getHostDisplayValue(system)}</CommandShortcut> <CommandShortcut>{getHostDisplayValue(system)}</CommandShortcut>
</CommandItem> </CommandItem>
))} ))}
@@ -121,6 +121,7 @@ export default memo(function CommandPalette({ open, setOpen }: { open: boolean;
{SettingsShortcut} {SettingsShortcut}
</CommandItem> </CommandItem>
<CommandItem <CommandItem
keywords={[t`Universal token`]}
onSelect={() => { onSelect={() => {
navigate(getPagePath($router, "settings", { name: "tokens" })) navigate(getPagePath($router, "settings", { name: "tokens" }))
setOpen(false) setOpen(false)
@@ -214,6 +215,9 @@ export default memo(function CommandPalette({ open, setOpen }: { open: boolean;
</CommandGroup> </CommandGroup>
</> </>
)} )}
<CommandEmpty>
<Trans>No results found.</Trans>
</CommandEmpty>
</CommandList> </CommandList>
</CommandDialog> </CommandDialog>
) )

View File

@@ -22,7 +22,7 @@ export function LangToggle() {
{languages.map(({ lang, label, e }) => ( {languages.map(({ lang, label, e }) => (
<DropdownMenuItem <DropdownMenuItem
key={lang} key={lang}
className={cn("px-2.5 flex gap-2.5", lang === i18n.locale && "font-semibold")} className={cn("px-2.5 flex gap-2.5 cursor-pointer", lang === i18n.locale && "bg-accent/70 font-medium")}
onClick={() => dynamicActivate(lang)} onClick={() => dynamicActivate(lang)}
> >
<span>{e}</span> {label} <span>{e}</span> {label}

View File

@@ -5,7 +5,7 @@ import { buttonVariants } from "@/components/ui/button"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { LoaderCircle, LockIcon, LogInIcon, MailIcon } from "lucide-react" import { LoaderCircle, LockIcon, LogInIcon, MailIcon } from "lucide-react"
import { $authenticated, pb } from "@/lib/stores" import { $authenticated } from "@/lib/stores"
import * as v from "valibot" import * as v from "valibot"
import { toast } from "../ui/use-toast" import { toast } from "../ui/use-toast"
import { Dialog, DialogContent, DialogTrigger, DialogHeader, DialogTitle } from "@/components/ui/dialog" import { Dialog, DialogContent, DialogTrigger, DialogHeader, DialogTitle } from "@/components/ui/dialog"
@@ -13,6 +13,7 @@ import { useCallback, useEffect, useState } from "react"
import { AuthMethodsList, AuthProviderInfo, OAuth2AuthConfig } from "pocketbase" import { AuthMethodsList, AuthProviderInfo, OAuth2AuthConfig } from "pocketbase"
import { $router, Link, prependBasePath } from "../router" import { $router, Link, prependBasePath } from "../router"
import { getPagePath } from "@nanostores/router" import { getPagePath } from "@nanostores/router"
import { pb } from "@/lib/api"
const honeypot = v.literal("") const honeypot = v.literal("")
const emailSchema = v.pipe(v.string(), v.email(t`Invalid email address.`)) const emailSchema = v.pipe(v.string(), v.email(t`Invalid email address.`))

View File

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

View File

@@ -1,13 +1,14 @@
import { t } from "@lingui/core/macro"; import { t } from "@lingui/core/macro"
import { UserAuthForm } from "@/components/login/auth-form" import { UserAuthForm } from "@/components/login/auth-form"
import { Logo } from "../logo" import { Logo } from "../logo"
import { useEffect, useMemo, useState } from "react" import { useEffect, useMemo, useState } from "react"
import { pb } from "@/lib/stores"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import ForgotPassword from "./forgot-pass-form" import ForgotPassword from "./forgot-pass-form"
import { $router } from "../router" import { $router } from "../router"
import { AuthMethodsList } from "pocketbase" import { AuthMethodsList } from "pocketbase"
import { useTheme } from "../theme-provider" import { useTheme } from "../theme-provider"
import { pb } from "@/lib/api"
import { ModeToggle } from "../mode-toggle"
export default function () { export default function () {
const page = useStore($router) const page = useStore($router)
@@ -50,8 +51,11 @@ export default function () {
<div <div
className="grid gap-5 w-full px-4 mx-auto" className="grid gap-5 w-full px-4 mx-auto"
// @ts-ignore // @ts-ignore
style={{ maxWidth: "22em", "--border": theme == "light" ? "30 8% 80%" : "220 3% 20%" }} style={{ maxWidth: "22em", "--border": theme == "light" ? "hsl(30, 8%, 70%)" : "hsl(220, 3%, 25%)" }}
> >
<div className="absolute top-3 right-3">
<ModeToggle />
</div>
<div className="text-center"> <div className="text-center">
<h1 className="mb-3"> <h1 className="mb-3">
<Logo className="h-7 fill-foreground mx-auto" /> <Logo className="h-7 fill-foreground mx-auto" />

View File

@@ -1,56 +1,21 @@
import { Trans } from "@lingui/react/macro"; import { t } from "@lingui/core/macro"
import { t } from "@lingui/core/macro"; import { MoonStarIcon, SunIcon } from "lucide-react"
import { LaptopIcon, MoonStarIcon, SunIcon } from "lucide-react"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
import { useTheme } from "@/components/theme-provider" import { useTheme } from "@/components/theme-provider"
import { cn } from "@/lib/utils"
export function ModeToggle() { export function ModeToggle() {
const { theme, setTheme } = useTheme() const { theme, setTheme } = useTheme()
const options = [
{
theme: "light",
Icon: SunIcon,
label: <Trans comment="Light theme">Light</Trans>,
},
{
theme: "dark",
Icon: MoonStarIcon,
label: <Trans comment="Dark theme">Dark</Trans>,
},
{
theme: "system",
Icon: LaptopIcon,
label: <Trans comment="System theme">System</Trans>,
},
]
return ( return (
<DropdownMenu> <Button
<DropdownMenuTrigger asChild> variant={"ghost"}
<Button variant={"ghost"} size="icon" aria-label={t`Toggle theme`}> size="icon"
<SunIcon className="h-[1.2rem] w-[1.2rem] dark:opacity-0" /> aria-label={t`Toggle theme`}
<MoonStarIcon className="absolute h-[1.2rem] w-[1.2rem] opacity-0 dark:opacity-100" /> onClick={() => setTheme(theme === "dark" ? "light" : "dark")}
</Button> >
</DropdownMenuTrigger> <SunIcon className="h-[1.2rem] w-[1.2rem] transition-all -rotate-90 dark:opacity-0 dark:rotate-0" />
<DropdownMenuContent> <MoonStarIcon className="absolute h-[1.2rem] w-[1.2rem] transition-all opacity-0 -rotate-90 dark:opacity-100 dark:rotate-0" />
{options.map((opt) => { </Button>
const selected = opt.theme === theme
return (
<DropdownMenuItem
key={opt.theme}
className={cn("px-2.5", selected ? "font-semibold" : "")}
onClick={() => setTheme(opt.theme as "dark" | "light" | "system")}
>
<opt.Icon className={cn("me-2 h-4 w-4 opacity-80", selected && "opacity-100")} />
{opt.label}
</DropdownMenuItem>
)
})}
</DropdownMenuContent>
</DropdownMenu>
) )
} }

View File

@@ -15,8 +15,8 @@ import { $router, basePath, Link, prependBasePath } from "./router"
import { LangToggle } from "./lang-toggle" import { LangToggle } from "./lang-toggle"
import { ModeToggle } from "./mode-toggle" import { ModeToggle } from "./mode-toggle"
import { Logo } from "./logo" import { Logo } from "./logo"
import { pb } from "@/lib/stores" import { cn, runOnce } from "@/lib/utils"
import { cn, isReadOnlyUser, isAdmin, logOut } from "@/lib/utils" import { isReadOnlyUser, isAdmin, logOut, pb } from "@/lib/api"
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuTrigger, DropdownMenuTrigger,
@@ -36,12 +36,17 @@ const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0
export default function Navbar() { export default function Navbar() {
return ( return (
<div className="flex items-center h-14 md:h-16 bg-card px-4 pe-3 sm:px-6 border border-border/60 bt-0 rounded-md my-4"> <div className="flex items-center h-14 md:h-16 bg-card px-4 pe-3 sm:px-6 border border-border/60 bt-0 rounded-md my-4">
<Link href={basePath} aria-label="Home" className="p-2 ps-0 me-3"> <Link
href={basePath}
aria-label="Home"
className="p-2 ps-0 me-3"
onMouseEnter={runOnce(() => import("@/components/routes/home"))}
>
<Logo className="h-[1.1rem] md:h-5 fill-foreground" /> <Logo className="h-[1.1rem] md:h-5 fill-foreground" />
</Link> </Link>
<SearchButton /> <SearchButton />
<div className="flex items-center ms-auto"> <div className="flex items-center ms-auto" onMouseEnter={() => import("@/components/routes/settings/general")}>
<LangToggle /> <LangToggle />
<ModeToggle /> <ModeToggle />
<Link <Link

View File

@@ -1,39 +1,24 @@
import { Suspense, lazy, memo, useEffect, useMemo } from "react" import { Suspense, memo, useEffect, useMemo } from "react"
import { Card, CardContent, CardHeader, CardTitle } from "../ui/card" import { Card, CardContent, CardHeader, CardTitle } from "../ui/card"
import { $alerts, $systems, pb } from "@/lib/stores" import { $alerts, $allSystemsById } from "@/lib/stores"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import { GithubIcon } from "lucide-react" import { GithubIcon } from "lucide-react"
import { Separator } from "../ui/separator" import { Separator } from "../ui/separator"
import { getSystemNameFromId, updateRecordList, updateSystemList } from "@/lib/utils" import { AlertRecord } from "@/types"
import { AlertRecord, SystemRecord } from "@/types"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { $router, Link } from "../router" import { $router, Link } from "../router"
import { Plural, Trans, useLingui } from "@lingui/react/macro" import { Plural, Trans, useLingui } from "@lingui/react/macro"
import { getPagePath } from "@nanostores/router" import { getPagePath } from "@nanostores/router"
import { alertInfo } from "@/lib/alerts" import { alertInfo } from "@/lib/alerts"
import SystemsTable from "@/components/systems-table/systems-table"
const SystemsTable = lazy(() => import("../systems-table/systems-table")) export default memo(function () {
export const Home = memo(() => {
const { t } = useLingui() const { t } = useLingui()
useEffect(() => { useEffect(() => {
document.title = t`Dashboard` + " / Beszel" document.title = t`Dashboard` + " / Beszel"
}, [t]) }, [t])
useEffect(() => {
// make sure we have the latest list of systems
updateSystemList()
// subscribe to real time updates for systems / alerts
pb.collection<SystemRecord>("systems").subscribe("*", (e) => {
updateRecordList(e, $systems)
})
return () => {
pb.collection("systems").unsubscribe("*")
}
}, [])
return useMemo( return useMemo(
() => ( () => (
<> <>
@@ -42,7 +27,7 @@ export const Home = memo(() => {
<SystemsTable /> <SystemsTable />
</Suspense> </Suspense>
<div className="flex gap-1.5 justify-end items-center pe-3 sm:pe-6 mt-3.5 text-xs opacity-80"> <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 <a
href="https://github.com/henrygd/beszel" href="https://github.com/henrygd/beszel"
target="_blank" target="_blank"
@@ -67,6 +52,7 @@ export const Home = memo(() => {
const ActiveAlerts = () => { const ActiveAlerts = () => {
const alerts = useStore($alerts) const alerts = useStore($alerts)
const systems = useStore($allSystemsById)
const { activeAlerts, alertsKey } = useMemo(() => { const { activeAlerts, alertsKey } = useMemo(() => {
const activeAlerts: AlertRecord[] = [] const activeAlerts: AlertRecord[] = []
@@ -106,11 +92,11 @@ const ActiveAlerts = () => {
return ( return (
<Alert <Alert
key={alert.id} key={alert.id}
className="hover:-translate-y-px duration-200 bg-transparent border-foreground/10 hover:shadow-md shadow-black" 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" /> <info.icon className="h-4 w-4" />
<AlertTitle> <AlertTitle>
{getSystemNameFromId(alert.system)} {info.name().toLowerCase().replace("cpu", "CPU")} {systems[alert.system]?.name} {info.name().toLowerCase().replace("cpu", "CPU")}
</AlertTitle> </AlertTitle>
<AlertDescription> <AlertDescription>
{alert.name === "Status" ? ( {alert.name === "Status" ? (
@@ -123,7 +109,7 @@ const ActiveAlerts = () => {
)} )}
</AlertDescription> </AlertDescription>
<Link <Link
href={getPagePath($router, "system", { name: getSystemNameFromId(alert.system) })} href={getPagePath($router, "system", { name: systems[alert.system]?.name })}
className="absolute inset-0 w-full h-full" className="absolute inset-0 w-full h-full"
aria-label="View system" aria-label="View system"
></Link> ></Link>

View File

@@ -1,4 +1,4 @@
import { pb } from "@/lib/stores" import { pb } from "@/lib/api"
import { cn, formatDuration, formatShortDate } from "@/lib/utils" import { cn, formatDuration, formatShortDate } from "@/lib/utils"
import { alertInfo } from "@/lib/alerts" import { alertInfo } from "@/lib/alerts"
import { AlertsHistoryRecord } from "@/types" import { AlertsHistoryRecord } from "@/types"
@@ -273,13 +273,13 @@ export default function AlertsHistoryDataTable() {
<Table> <Table>
<TableHeader> <TableHeader>
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}> <tr key={headerGroup.id} className="border-border/50">
{headerGroup.headers.map((header) => ( {headerGroup.headers.map((header) => (
<TableHead className="px-2" key={header.id}> <TableHead className="px-2" key={header.id}>
{header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())} {header.isPlaceholder ? null : flexRender(header.column.columnDef.header, header.getContext())}
</TableHead> </TableHead>
))} ))}
</TableRow> </tr>
))} ))}
</TableHeader> </TableHeader>
<TableBody> <TableBody>

View File

@@ -1,17 +1,16 @@
import { t } from "@lingui/core/macro" import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro" import { Trans } from "@lingui/react/macro"
import { isAdmin } from "@/lib/utils"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { redirectPage } from "@nanostores/router" import { redirectPage } from "@nanostores/router"
import { $router } from "@/components/router" import { $router } from "@/components/router"
import { AlertCircleIcon, FileSlidersIcon, LoaderCircleIcon } from "lucide-react" import { AlertCircleIcon, FileSlidersIcon, LoaderCircleIcon } from "lucide-react"
import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert" import { Alert, AlertDescription, AlertTitle } from "@/components/ui/alert"
import { pb } from "@/lib/stores"
import { useState } from "react" import { useState } from "react"
import { Textarea } from "@/components/ui/textarea" import { Textarea } from "@/components/ui/textarea"
import { toast } from "@/components/ui/use-toast" import { toast } from "@/components/ui/use-toast"
import clsx from "clsx" import clsx from "clsx"
import { isAdmin, pb } from "@/lib/api"
export default function ConfigYaml() { export default function ConfigYaml() {
const [configContent, setConfigContent] = useState<string>("") const [configContent, setConfigContent] = useState<string>("")

View File

@@ -1,6 +1,6 @@
import { t } from "@lingui/core/macro" import { t } from "@lingui/core/macro"
import { Trans } from "@lingui/react/macro" import { Trans } from "@lingui/react/macro"
import { useEffect } from "react" import { lazy, useEffect } from "react"
import { Separator } from "../../ui/separator" import { Separator } from "../../ui/separator"
import { SidebarNav } from "./sidebar-nav.tsx" import { SidebarNav } from "./sidebar-nav.tsx"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card.tsx" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card.tsx"
@@ -8,15 +8,23 @@ import { useStore } from "@nanostores/react"
import { $router } from "@/components/router.tsx" import { $router } from "@/components/router.tsx"
import { getPagePath, redirectPage } from "@nanostores/router" import { getPagePath, redirectPage } from "@nanostores/router"
import { BellIcon, FileSlidersIcon, FingerprintIcon, SettingsIcon, AlertOctagonIcon } from "lucide-react" import { BellIcon, FileSlidersIcon, FingerprintIcon, SettingsIcon, AlertOctagonIcon } from "lucide-react"
import { $userSettings, pb } from "@/lib/stores.ts" import { $userSettings } from "@/lib/stores.ts"
import { toast } from "@/components/ui/use-toast.ts" import { toast } from "@/components/ui/use-toast.ts"
import { UserSettings } from "@/types" import { UserSettings } from "@/types"
import General from "./general.tsx"
import Notifications from "./notifications.tsx"
import ConfigYaml from "./config-yaml.tsx"
import { useLingui } from "@lingui/react/macro" import { useLingui } from "@lingui/react/macro"
import Fingerprints from "./tokens-fingerprints.tsx" import { pb } from "@/lib/api"
import AlertsHistoryDataTable from "./alerts-history-data-table"
const generalSettingsImport = () => import("./general.tsx")
const notificationsSettingsImport = () => import("./notifications.tsx")
const configYamlSettingsImport = () => import("./config-yaml.tsx")
const fingerprintsSettingsImport = () => import("./tokens-fingerprints.tsx")
const alertsHistoryDataTableSettingsImport = () => import("./alerts-history-data-table.tsx")
const GeneralSettings = lazy(generalSettingsImport)
const NotificationsSettings = lazy(notificationsSettingsImport)
const ConfigYamlSettings = lazy(configYamlSettingsImport)
const FingerprintsSettings = lazy(fingerprintsSettingsImport)
const AlertsHistoryDataTableSettings = lazy(alertsHistoryDataTableSettingsImport)
export async function saveSettings(newSettings: Partial<UserSettings>) { export async function saveSettings(newSettings: Partial<UserSettings>) {
try { try {
@@ -59,23 +67,27 @@ export default function SettingsLayout() {
title: t`Notifications`, title: t`Notifications`,
href: getPagePath($router, "settings", { name: "notifications" }), href: getPagePath($router, "settings", { name: "notifications" }),
icon: BellIcon, icon: BellIcon,
preload: notificationsSettingsImport,
}, },
{ {
title: t`Tokens & Fingerprints`, title: t`Tokens & Fingerprints`,
href: getPagePath($router, "settings", { name: "tokens" }), href: getPagePath($router, "settings", { name: "tokens" }),
icon: FingerprintIcon, icon: FingerprintIcon,
noReadOnly: true, noReadOnly: true,
preload: fingerprintsSettingsImport,
}, },
{ {
title: t`Alert History`, title: t`Alert History`,
href: getPagePath($router, "settings", { name: "alert-history" }), href: getPagePath($router, "settings", { name: "alert-history" }),
icon: AlertOctagonIcon, icon: AlertOctagonIcon,
preload: alertsHistoryDataTableSettingsImport,
}, },
{ {
title: t`YAML Config`, title: t`YAML Config`,
href: getPagePath($router, "settings", { name: "config" }), href: getPagePath($router, "settings", { name: "config" }),
icon: FileSlidersIcon, icon: FileSlidersIcon,
admin: true, admin: true,
preload: configYamlSettingsImport,
}, },
] ]
@@ -90,7 +102,7 @@ export default function SettingsLayout() {
}, []) }, [])
return ( return (
<Card className="pt-5 px-4 pb-8 min-h-96 sm:pt-6 sm:px-7"> <Card className="pt-5 px-4 pb-8 min-h-96 mb-14 sm:pt-6 sm:px-7">
<CardHeader className="p-0"> <CardHeader className="p-0">
<CardTitle className="mb-1"> <CardTitle className="mb-1">
<Trans>Settings</Trans> <Trans>Settings</Trans>
@@ -120,14 +132,14 @@ function SettingsContent({ name }: { name: string }) {
switch (name) { switch (name) {
case "general": case "general":
return <General userSettings={userSettings} /> return <GeneralSettings userSettings={userSettings} />
case "notifications": case "notifications":
return <Notifications userSettings={userSettings} /> return <NotificationsSettings userSettings={userSettings} />
case "config": case "config":
return <ConfigYaml /> return <ConfigYamlSettings />
case "tokens": case "tokens":
return <Fingerprints /> return <FingerprintsSettings />
case "alert-history": case "alert-history":
return <AlertsHistoryDataTable /> return <AlertsHistoryDataTableSettings />
} }
} }

View File

@@ -3,7 +3,6 @@ import { Trans } from "@lingui/react/macro"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { Input } from "@/components/ui/input" import { Input } from "@/components/ui/input"
import { Label } from "@/components/ui/label" import { Label } from "@/components/ui/label"
import { pb } from "@/lib/stores"
import { Separator } from "@/components/ui/separator" import { Separator } from "@/components/ui/separator"
import { Card } from "@/components/ui/card" import { Card } from "@/components/ui/card"
import { BellIcon, LoaderCircleIcon, PlusIcon, SaveIcon, Trash2Icon } from "lucide-react" import { BellIcon, LoaderCircleIcon, PlusIcon, SaveIcon, Trash2Icon } from "lucide-react"
@@ -13,8 +12,8 @@ import { InputTags } from "@/components/ui/input-tags"
import { UserSettings } from "@/types" import { UserSettings } from "@/types"
import { saveSettings } from "./layout" import { saveSettings } from "./layout"
import * as v from "valibot" import * as v from "valibot"
import { isAdmin } from "@/lib/utils"
import { prependBasePath } from "@/components/router" import { prependBasePath } from "@/components/router"
import { isAdmin, pb } from "@/lib/api"
interface ShoutrrrUrlCardProps { interface ShoutrrrUrlCardProps {
url: string url: string

View File

@@ -1,5 +1,6 @@
import React from "react" import React from "react"
import { cn, isAdmin, isReadOnlyUser } from "@/lib/utils" import { cn } from "@/lib/utils"
import { isAdmin, isReadOnlyUser } from "@/lib/api"
import { buttonVariants } from "../../ui/button" import { buttonVariants } from "../../ui/button"
import { $router, Link, navigate } from "../../router" import { $router, Link, navigate } from "../../router"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
@@ -13,6 +14,7 @@ interface SidebarNavProps extends React.HTMLAttributes<HTMLElement> {
icon?: React.FC<React.SVGProps<SVGSVGElement>> icon?: React.FC<React.SVGProps<SVGSVGElement>>
admin?: boolean admin?: boolean
noReadOnly?: boolean noReadOnly?: boolean
preload?: () => Promise<{ default: React.ComponentType<any> }>
}[] }[]
} }
@@ -52,6 +54,7 @@ export function SidebarNav({ className, items, ...props }: SidebarNavProps) {
} }
return ( return (
<Link <Link
onMouseEnter={() => item.preload?.()}
key={item.href} key={item.href}
href={item.href} href={item.href}
className={cn( className={cn(

View File

@@ -1,6 +1,6 @@
import { Trans, useLingui } from "@lingui/react/macro" import { Trans, useLingui } from "@lingui/react/macro"
import { t } from "@lingui/core/macro" import { t } from "@lingui/core/macro"
import { $publicKey, pb } from "@/lib/stores" import { $publicKey } from "@/lib/stores"
import { memo, useEffect, useMemo, useState } from "react" import { memo, useEffect, useMemo, useState } from "react"
import { Table, TableCell, TableHead, TableBody, TableRow, TableHeader } from "@/components/ui/table" import { Table, TableCell, TableHead, TableBody, TableRow, TableHeader } from "@/components/ui/table"
import { FingerprintRecord } from "@/types" import { FingerprintRecord } from "@/types"
@@ -14,7 +14,8 @@ import {
Trash2Icon, Trash2Icon,
} from "lucide-react" } from "lucide-react"
import { toast } from "@/components/ui/use-toast" import { toast } from "@/components/ui/use-toast"
import { cn, copyToClipboard, generateToken, getHubURL, isReadOnlyUser, tokenMap } from "@/lib/utils" import { cn, copyToClipboard, generateToken, getHubURL, tokenMap } from "@/lib/utils"
import { isReadOnlyUser, pb } from "@/lib/api"
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuContent, DropdownMenuContent,
@@ -271,7 +272,7 @@ const SectionTable = memo(({ fingerprints = [] }: { fingerprints: FingerprintRec
<div className="rounded-md border overflow-hidden w-full mt-4"> <div className="rounded-md border overflow-hidden w-full mt-4">
<Table> <Table>
<TableHeader> <TableHeader>
<TableRow> <tr className="border-border/50">
{headerCols.map((col) => ( {headerCols.map((col) => (
<TableHead key={col.label} style={{ minWidth: col.w }}> <TableHead key={col.label} style={{ minWidth: col.w }}>
<span className="flex items-center gap-2"> <span className="flex items-center gap-2">
@@ -287,12 +288,14 @@ const SectionTable = memo(({ fingerprints = [] }: { fingerprints: FingerprintRec
</span> </span>
</TableHead> </TableHead>
)} )}
</TableRow> </tr>
</TableHeader> </TableHeader>
<TableBody className="whitespace-pre"> <TableBody className="whitespace-pre">
{fingerprints.map((fingerprint, i) => ( {fingerprints.map((fingerprint, i) => (
<TableRow key={i}> <TableRow key={i}>
<TableCell className="font-medium ps-5 py-2">{fingerprint.expand.system.name}</TableCell> <TableCell className="font-medium ps-5 py-2 max-w-60 truncate">
{fingerprint.expand.system.name}
</TableCell>
<TableCell className="font-mono text-[0.95em] py-2">{fingerprint.token}</TableCell> <TableCell className="font-mono text-[0.95em] py-2">{fingerprint.token}</TableCell>
<TableCell className="font-mono text-[0.95em] py-2">{fingerprint.fingerprint}</TableCell> <TableCell className="font-mono text-[0.95em] py-2">{fingerprint.fingerprint}</TableCell>
{!isReadOnly && ( {!isReadOnly && (

View File

@@ -2,17 +2,18 @@ import { t } from "@lingui/core/macro"
import { Plural, Trans } from "@lingui/react/macro" import { Plural, Trans } from "@lingui/react/macro"
import { import {
$systems, $systems,
pb,
$chartTime, $chartTime,
$containerFilter, $containerFilter,
$userSettings, $userSettings,
$direction, $direction,
$maxValues, $maxValues,
$temperatureFilter, $temperatureFilter,
$allSystemsByName,
} from "@/lib/stores" } from "@/lib/stores"
import { ChartData, ChartTimes, ContainerStatsRecord, GPUData, SystemRecord, SystemStatsRecord } from "@/types" import { ChartData, ChartTimes, ContainerStatsRecord, GPUData, SystemRecord, SystemStatsRecord } from "@/types"
import { useContainerChartConfigs } from "@/components/charts/hooks"
import { ChartType, Unit, Os, SystemStatus } from "@/lib/enums" import { ChartType, Unit, Os, SystemStatus } from "@/lib/enums"
import React, { lazy, memo, useCallback, useEffect, useMemo, useRef, useState, type JSX } from "react" import React, { memo, useCallback, useEffect, useMemo, useRef, useState, type JSX } from "react"
import { Card, CardHeader, CardTitle, CardDescription } from "../ui/card" import { Card, CardHeader, CardTitle, CardDescription } from "../ui/card"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import Spinner from "../spinner" import Spinner from "../spinner"
@@ -24,12 +25,12 @@ import {
decimalString, decimalString,
formatBytes, formatBytes,
getHostDisplayValue, getHostDisplayValue,
getPbTimestamp,
listen, listen,
parseSemVer, parseSemVer,
toFixedFloat, toFixedFloat,
useLocalStorage, useBrowserStorage,
} from "@/lib/utils" } from "@/lib/utils"
import { getPbTimestamp, pb } from "@/lib/api"
import { Separator } from "../ui/separator" import { Separator } from "../ui/separator"
import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip" import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "../ui/tooltip"
import { Button } from "../ui/button" import { Button } from "../ui/button"
@@ -42,15 +43,15 @@ import { useLingui } from "@lingui/react/macro"
import { $router, navigate } from "../router" import { $router, navigate } from "../router"
import { getPagePath } from "@nanostores/router" import { getPagePath } from "@nanostores/router"
import { batteryStateTranslations } from "@/lib/i18n" import { batteryStateTranslations } from "@/lib/i18n"
import AreaChartDefault from "@/components/charts/area-chart"
const AreaChartDefault = lazy(() => import("../charts/area-chart")) import ContainerChart from "@/components/charts/container-chart"
const ContainerChart = lazy(() => import("../charts/container-chart")) import MemChart from "@/components/charts/mem-chart"
const MemChart = lazy(() => import("../charts/mem-chart")) import DiskChart from "@/components/charts/disk-chart"
const DiskChart = lazy(() => import("../charts/disk-chart")) import SwapChart from "@/components/charts/swap-chart"
const SwapChart = lazy(() => import("../charts/swap-chart")) import TemperatureChart from "@/components/charts/temperature-chart"
const TemperatureChart = lazy(() => import("../charts/temperature-chart")) import GpuPowerChart from "@/components/charts/gpu-power-chart"
const GpuPowerChart = lazy(() => import("../charts/gpu-power-chart")) import LoadAverageChart from "@/components/charts/load-average-chart"
const LoadAverageChart = lazy(() => import("../charts/load-average-chart")) import { subscribeKeys } from "nanostores"
const cache = new Map<string, any>() const cache = new Map<string, any>()
@@ -119,13 +120,13 @@ function dockerOrPodman(str: string, system: SystemRecord) {
return str return str
} }
export default function SystemDetail({ name }: { name: string }) { export default memo(function SystemDetail({ name }: { name: string }) {
const direction = useStore($direction) const direction = useStore($direction)
const { t } = useLingui() const { t } = useLingui()
const systems = useStore($systems) const systems = useStore($systems)
const chartTime = useStore($chartTime) const chartTime = useStore($chartTime)
const maxValues = useStore($maxValues) const maxValues = useStore($maxValues)
const [grid, setGrid] = useLocalStorage("grid", true) const [grid, setGrid] = useBrowserStorage("grid", true)
const [system, setSystem] = useState({} as SystemRecord) const [system, setSystem] = useState({} as SystemRecord)
const [systemStats, setSystemStats] = useState([] as SystemStatsRecord[]) const [systemStats, setSystemStats] = useState([] as SystemStatsRecord[])
const [containerData, setContainerData] = useState([] as ChartData["containerData"]) const [containerData, setContainerData] = useState([] as ChartData["containerData"])
@@ -151,36 +152,13 @@ export default function SystemDetail({ name }: { name: string }) {
} }
}, [name]) }, [name])
// function resetCharts() { // find matching system and update when it changes
// setSystemStats([])
// setContainerData([])
// }
// useEffect(resetCharts, [chartTime])
// find matching system
useEffect(() => { useEffect(() => {
if (system.id && system.name === name) { return subscribeKeys($allSystemsByName, [name], (newSystems) => {
return const sys = newSystems[name]
} sys?.id && setSystem(sys)
const matchingSystem = systems.find((s) => s.name === name) as SystemRecord
if (matchingSystem) {
setSystem(matchingSystem)
}
}, [name, system, systems])
// update system when new data is available
useEffect(() => {
if (!system.id) {
return
}
pb.collection<SystemRecord>("systems").subscribe(system.id, (e) => {
setSystem(e.record)
}) })
return () => { }, [name])
pb.collection("systems").unsubscribe(system.id)
}
}, [system.id])
const chartData: ChartData = useMemo(() => { const chartData: ChartData = useMemo(() => {
const lastCreated = Math.max( const lastCreated = Math.max(
@@ -197,6 +175,9 @@ export default function SystemDetail({ name }: { name: string }) {
} }
}, [systemStats, containerData, direction]) }, [systemStats, containerData, direction])
// Share chart config computation for all container charts
const containerChartConfigs = useContainerChartConfigs(containerData)
// get stats // get stats
useEffect(() => { useEffect(() => {
if (!system.id || !chartTime) { if (!system.id || !chartTime) {
@@ -287,11 +268,19 @@ export default function SystemDetail({ name }: { name: string }) {
value: system.info.k, value: system.info.k,
}, },
} }
let uptime: React.ReactNode let uptime: React.ReactNode
if (system.info.u < 172800) { if (system.info.u < 3600) {
const hours = Math.trunc(system.info.u / 3600) uptime = (
uptime = <Plural value={hours} one="# hour" other="# hours" /> <Plural
value={Math.trunc(system.info.u / 60)}
one="# minute"
few="# minutes"
many="# minutes"
other="# minutes"
/>
)
} else if (system.info.u < 172800) {
uptime = <Plural value={Math.trunc(system.info.u / 3600)} one="# hour" other="# hours" />
} else { } else {
uptime = <Plural value={Math.trunc(system.info?.u / 86400)} one="# day" other="# days" /> uptime = <Plural value={Math.trunc(system.info?.u / 86400)} one="# day" other="# days" />
} }
@@ -317,7 +306,7 @@ export default function SystemDetail({ name }: { name: string }) {
Icon: any Icon: any
hide?: boolean hide?: boolean
}[] }[]
}, [system.info]) }, [system.info, t])
/** Space for tooltip if more than 12 containers */ /** Space for tooltip if more than 12 containers */
useEffect(() => { useEffect(() => {
@@ -391,7 +380,7 @@ export default function SystemDetail({ name }: { name: string }) {
return ( return (
<> <>
<div id="chartwrap" className="grid gap-4 mb-10 overflow-x-clip"> <div id="chartwrap" className="grid gap-4 mb-14 overflow-x-clip">
{/* system info */} {/* system info */}
<Card> <Card>
<div className="grid xl:flex gap-4 px-4 sm:px-6 pt-3 sm:pt-4 pb-5"> <div className="grid xl:flex gap-4 px-4 sm:px-6 pt-3 sm:pt-4 pb-5">
@@ -486,7 +475,7 @@ export default function SystemDetail({ name }: { name: string }) {
{ {
label: t`CPU Usage`, label: t`CPU Usage`,
dataKey: ({ stats }) => (showMax ? stats?.cpum : stats?.cpu), dataKey: ({ stats }) => (showMax ? stats?.cpum : stats?.cpu),
color: "1", color: 1,
opacity: 0.4, opacity: 0.4,
}, },
]} ]}
@@ -503,7 +492,12 @@ export default function SystemDetail({ name }: { name: string }) {
description={t`Average CPU utilization of containers`} description={t`Average CPU utilization of containers`}
cornerEl={containerFilterBar} cornerEl={containerFilterBar}
> >
<ContainerChart chartData={chartData} dataKey="c" chartType={ChartType.CPU} /> <ContainerChart
chartData={chartData}
dataKey="c"
chartType={ChartType.CPU}
chartConfig={containerChartConfigs.cpu}
/>
</ChartCard> </ChartCard>
)} )}
@@ -512,8 +506,9 @@ export default function SystemDetail({ name }: { name: string }) {
grid={grid} grid={grid}
title={t`Memory Usage`} title={t`Memory Usage`}
description={t`Precise utilization at the recorded time`} description={t`Precise utilization at the recorded time`}
cornerEl={maxValSelect}
> >
<MemChart chartData={chartData} /> <MemChart chartData={chartData} showMax={showMax} />
</ChartCard> </ChartCard>
{containerFilterBar && ( {containerFilterBar && (
@@ -524,7 +519,12 @@ export default function SystemDetail({ name }: { name: string }) {
description={dockerOrPodman(t`Memory usage of docker containers`, system)} description={dockerOrPodman(t`Memory usage of docker containers`, system)}
cornerEl={containerFilterBar} cornerEl={containerFilterBar}
> >
<ContainerChart chartData={chartData} dataKey="m" chartType={ChartType.Memory} /> <ContainerChart
chartData={chartData}
dataKey="m"
chartType={ChartType.Memory}
chartConfig={containerChartConfigs.memory}
/>
</ChartCard> </ChartCard>
)} )}
@@ -546,13 +546,13 @@ export default function SystemDetail({ name }: { name: string }) {
{ {
label: t({ message: "Write", comment: "Disk write" }), label: t({ message: "Write", comment: "Disk write" }),
dataKey: ({ stats }) => (showMax ? stats?.dwm : stats?.dw), dataKey: ({ stats }) => (showMax ? stats?.dwm : stats?.dw),
color: "3", color: 3,
opacity: 0.3, opacity: 0.3,
}, },
{ {
label: t({ message: "Read", comment: "Disk read" }), label: t({ message: "Read", comment: "Disk read" }),
dataKey: ({ stats }) => (showMax ? stats?.drm : stats?.dr), dataKey: ({ stats }) => (showMax ? stats?.drm : stats?.dr),
color: "1", color: 1,
opacity: 0.3, opacity: 0.3,
}, },
]} ]}
@@ -587,7 +587,7 @@ export default function SystemDetail({ name }: { name: string }) {
} }
return data?.stats?.b?.[0] ?? data?.stats?.ns * 1024 * 1024 return data?.stats?.b?.[0] ?? data?.stats?.ns * 1024 * 1024
}, },
color: "5", color: 5,
opacity: 0.2, opacity: 0.2,
}, },
{ {
@@ -598,7 +598,7 @@ export default function SystemDetail({ name }: { name: string }) {
} }
return data?.stats?.b?.[1] ?? data?.stats?.nr * 1024 * 1024 return data?.stats?.b?.[1] ?? data?.stats?.nr * 1024 * 1024
}, },
color: "2", color: 2,
opacity: 0.2, opacity: 0.2,
}, },
]} ]}
@@ -626,8 +626,12 @@ export default function SystemDetail({ name }: { name: string }) {
description={dockerOrPodman(t`Network traffic of docker containers`, system)} description={dockerOrPodman(t`Network traffic of docker containers`, system)}
cornerEl={containerFilterBar} cornerEl={containerFilterBar}
> >
{/* @ts-ignore */} <ContainerChart
<ContainerChart chartData={chartData} chartType={ChartType.Network} dataKey="n" /> chartData={chartData}
chartType={ChartType.Network}
dataKey="n"
chartConfig={containerChartConfigs.network}
/>
</ChartCard> </ChartCard>
</div> </div>
)} )}
@@ -687,7 +691,7 @@ export default function SystemDetail({ name }: { name: string }) {
{ {
label: t`Charge`, label: t`Charge`,
dataKey: ({ stats }) => stats?.bat?.[0], dataKey: ({ stats }) => stats?.bat?.[0],
color: "1", color: 1,
opacity: 0.35, opacity: 0.35,
}, },
]} ]}
@@ -730,7 +734,7 @@ export default function SystemDetail({ name }: { name: string }) {
{ {
label: t`Usage`, label: t`Usage`,
dataKey: ({ stats }) => stats?.g?.[id]?.u ?? 0, dataKey: ({ stats }) => stats?.g?.[id]?.u ?? 0,
color: "1", color: 1,
opacity: 0.35, opacity: 0.35,
}, },
]} ]}
@@ -750,7 +754,7 @@ export default function SystemDetail({ name }: { name: string }) {
{ {
label: t`Usage`, label: t`Usage`,
dataKey: ({ stats }) => stats?.g?.[id]?.mu ?? 0, dataKey: ({ stats }) => stats?.g?.[id]?.mu ?? 0,
color: "2", color: 2,
opacity: 0.25, opacity: 0.25,
}, },
]} ]}
@@ -802,13 +806,13 @@ export default function SystemDetail({ name }: { name: string }) {
{ {
label: t`Write`, label: t`Write`,
dataKey: ({ stats }) => stats?.efs?.[extraFsName]?.[showMax ? "wm" : "w"] ?? 0, dataKey: ({ stats }) => stats?.efs?.[extraFsName]?.[showMax ? "wm" : "w"] ?? 0,
color: "3", color: 3,
opacity: 0.3, opacity: 0.3,
}, },
{ {
label: t`Read`, label: t`Read`,
dataKey: ({ stats }) => stats?.efs?.[extraFsName]?.[showMax ? "rm" : "r"] ?? 0, dataKey: ({ stats }) => stats?.efs?.[extraFsName]?.[showMax ? "rm" : "r"] ?? 0,
color: "1", color: 1,
opacity: 0.3, opacity: 0.3,
}, },
]} ]}
@@ -834,7 +838,7 @@ export default function SystemDetail({ name }: { name: string }) {
{bottomSpacing > 0 && <span className="block" style={{ height: bottomSpacing }} />} {bottomSpacing > 0 && <span className="block" style={{ height: bottomSpacing }} />}
</> </>
) )
} })
function FilterBar({ store = $containerFilter }: { store?: typeof $containerFilter }) { function FilterBar({ store = $containerFilter }: { store?: typeof $containerFilter }) {
const containerFilter = useStore(store) const containerFilter = useStore(store)

View File

@@ -23,12 +23,11 @@ import {
formatBytes, formatBytes,
formatTemperature, formatTemperature,
getMeterState, getMeterState,
isReadOnlyUser,
parseSemVer, parseSemVer,
} from "@/lib/utils" } from "@/lib/utils"
import { EthernetIcon, GpuIcon, HourglassIcon, ThermometerIcon } from "../ui/icons" import { EthernetIcon, GpuIcon, HourglassIcon, ThermometerIcon } from "../ui/icons"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import { $userSettings, pb } from "@/lib/stores" import { $longestSystemNameLen, $userSettings } from "@/lib/stores"
import { Trans, useLingui } from "@lingui/react/macro" import { Trans, useLingui } from "@lingui/react/macro"
import { useMemo, useRef, useState } from "react" import { useMemo, useRef, useState } from "react"
import { memo } from "react" import { memo } from "react"
@@ -57,6 +56,7 @@ import { t } from "@lingui/core/macro"
import { MeterState, SystemStatus } from "@/lib/enums" import { MeterState, SystemStatus } from "@/lib/enums"
import { $router, Link } from "../router" import { $router, Link } from "../router"
import { getPagePath } from "@nanostores/router" import { getPagePath } from "@nanostores/router"
import { isReadOnlyUser, pb } from "@/lib/api"
const STATUS_COLORS = { const STATUS_COLORS = {
[SystemStatus.Up]: "bg-green-500", [SystemStatus.Up]: "bg-green-500",
@@ -72,7 +72,8 @@ const STATUS_COLORS = {
export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnDef<SystemRecord>[] { export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnDef<SystemRecord>[] {
return [ return [
{ {
size: 200, // size: 200,
size: 100,
minSize: 0, minSize: 0,
accessorKey: "name", accessorKey: "name",
id: "system", id: "system",
@@ -111,11 +112,15 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
Icon: ServerIcon, Icon: ServerIcon,
cell: (info) => { cell: (info) => {
const { name } = info.row.original const { name } = info.row.original
const longestName = useStore($longestSystemNameLen)
return ( return (
<> <>
<span className="flex gap-2 items-center font-medium text-sm text-nowrap md:ps-1 md:pe-5"> <span className="flex gap-2 items-center font-medium text-sm text-nowrap md:ps-1">
<IndicatorDot system={info.row.original} /> <IndicatorDot system={info.row.original} />
{name} {/* NOTE: change to 1 ch if switching to monospace font */}
<span className="truncate" style={{ width: `${longestName / 1.1}ch` }}>
{name}
</span>
</span> </span>
<Link <Link
href={getPagePath($router, "system", { name })} href={getPagePath($router, "system", { name })}
@@ -269,7 +274,7 @@ export default function SystemsTableColumns(viewMode: "table" | "grid"): ColumnD
} }
const system = info.row.original const system = info.row.original
return ( return (
<span className={cn("flex gap-2 items-center md:pe-5 tabular-nums", viewMode === "table" && "ps-0.5")}> <span className={cn("flex gap-1.5 items-center md:pe-5 tabular-nums", viewMode === "table" && "ps-0.5")}>
<IndicatorDot <IndicatorDot
system={system} system={system}
className={ className={
@@ -318,22 +323,18 @@ function sortableHeader(context: HeaderContext<SystemRecord, unknown>) {
function TableCellWithMeter(info: CellContext<SystemRecord, unknown>) { function TableCellWithMeter(info: CellContext<SystemRecord, unknown>) {
const val = Number(info.getValue()) || 0 const val = Number(info.getValue()) || 0
const threshold = getMeterState(val) const threshold = getMeterState(val)
const meterClass = cn(
"h-full",
(info.row.original.status !== SystemStatus.Up && STATUS_COLORS.paused) ||
(threshold === MeterState.Good && STATUS_COLORS.up) ||
(threshold === MeterState.Warn && STATUS_COLORS.pending) ||
STATUS_COLORS.down
)
return ( return (
<div className="flex gap-2 items-center tabular-nums tracking-tight"> <div className="flex gap-2 items-center tabular-nums tracking-tight w-full">
<span className="min-w-8">{decimalString(val, val >= 10 ? 1 : 2)}%</span> <span className="min-w-8 shrink-0">{decimalString(val, val >= 10 ? 1 : 2)}%</span>
<span className="grow min-w-8 block bg-muted h-[1em] relative rounded-sm overflow-hidden"> <span className="flex-1 min-w-8 grid bg-muted h-[1em] rounded-sm overflow-hidden">
<span <span className={meterClass} style={{ width: `${val}%` }}></span>
className={cn(
"absolute inset-0 w-full h-full origin-left",
(info.row.original.status !== SystemStatus.Up && STATUS_COLORS.paused) ||
(threshold === MeterState.Good && STATUS_COLORS.up) ||
(threshold === MeterState.Warn && STATUS_COLORS.pending) ||
STATUS_COLORS.down
)}
style={{
transform: `scalex(${val / 100})`,
}}
></span>
</span> </span>
</div> </div>
) )

View File

@@ -11,11 +11,8 @@ import {
Row, Row,
Table as TableType, Table as TableType,
} from "@tanstack/react-table" } from "@tanstack/react-table"
import { TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table"
import { Button } from "@/components/ui/button" import { Button } from "@/components/ui/button"
import { import {
DropdownMenu, DropdownMenu,
DropdownMenuCheckboxItem, DropdownMenuCheckboxItem,
@@ -36,33 +33,65 @@ import {
ArrowUpIcon, ArrowUpIcon,
Settings2Icon, Settings2Icon,
EyeIcon, EyeIcon,
FilterIcon,
} from "lucide-react" } from "lucide-react"
import { memo, useEffect, useMemo, useState } from "react" import { memo, useEffect, useMemo, useRef, useState } from "react"
import { $systems } from "@/lib/stores" import { $pausedSystems, $downSystems, $upSystems, $systems } from "@/lib/stores"
import { useStore } from "@nanostores/react" import { useStore } from "@nanostores/react"
import { cn, useLocalStorage } from "@/lib/utils" import { cn, runOnce, useBrowserStorage } from "@/lib/utils"
import { $router, Link } from "../router" import { $router, Link } from "../router"
import { useLingui, Trans } from "@lingui/react/macro" import { useLingui, Trans } from "@lingui/react/macro"
import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card" import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "../ui/card"
import { Input } from "../ui/input" import { Input } from "@/components/ui/input"
import { getPagePath } from "@nanostores/router" import { getPagePath } from "@nanostores/router"
import SystemsTableColumns, { ActionsButton, IndicatorDot } from "./systems-table-columns" import SystemsTableColumns, { ActionsButton, IndicatorDot } from "./systems-table-columns"
import AlertButton from "../alerts/alert-button" import AlertButton from "../alerts/alert-button"
import { SystemStatus } from "@/lib/enums" import { SystemStatus } from "@/lib/enums"
import { useVirtualizer, VirtualItem } from "@tanstack/react-virtual"
type ViewMode = "table" | "grid" type ViewMode = "table" | "grid"
type StatusFilter = "all" | SystemRecord["status"]
const preloadSystemDetail = runOnce(() => import("@/components/routes/system.tsx"))
export default function SystemsTable() { export default function SystemsTable() {
const data = useStore($systems) const data = useStore($systems)
const downSystems = $downSystems.get()
const upSystems = $upSystems.get()
const pausedSystems = $pausedSystems.get()
const { i18n, t } = useLingui() const { i18n, t } = useLingui()
const [filter, setFilter] = useState<string>() const [filter, setFilter] = useState<string>()
const [sorting, setSorting] = useState<SortingState>([{ id: "system", desc: false }]) const [statusFilter, setStatusFilter] = useState<StatusFilter>("all")
const [sorting, setSorting] = useBrowserStorage<SortingState>(
"sortMode",
[{ id: "system", desc: false }],
sessionStorage
)
const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([]) const [columnFilters, setColumnFilters] = useState<ColumnFiltersState>([])
const [columnVisibility, setColumnVisibility] = useLocalStorage<VisibilityState>("cols", {}) const [columnVisibility, setColumnVisibility] = useBrowserStorage<VisibilityState>("cols", {})
const [viewMode, setViewMode] = useLocalStorage<ViewMode>("viewMode", window.innerWidth > 1024 ? "table" : "grid")
const locale = i18n.locale const locale = i18n.locale
// Filter data based on status filter
const filteredData = useMemo(() => {
if (statusFilter === "all") {
return data
}
if (statusFilter === SystemStatus.Up) {
return Object.values(upSystems) ?? []
}
if (statusFilter === SystemStatus.Down) {
return Object.values(downSystems) ?? []
}
return Object.values(pausedSystems) ?? []
}, [data, statusFilter])
const [viewMode, setViewMode] = useBrowserStorage<ViewMode>(
"viewMode",
// show grid view on mobile if there are less than 200 systems (looks better but table is more efficient)
window.innerWidth < 1024 && filteredData.length < 200 ? "grid" : "table"
)
useEffect(() => { useEffect(() => {
if (filter !== undefined) { if (filter !== undefined) {
table.getColumn("system")?.setFilterValue(filter) table.getColumn("system")?.setFilterValue(filter)
@@ -72,7 +101,7 @@ export default function SystemsTable() {
const columnDefs = useMemo(() => SystemsTableColumns(viewMode), [viewMode]) const columnDefs = useMemo(() => SystemsTableColumns(viewMode), [viewMode])
const table = useReactTable({ const table = useReactTable({
data, data: filteredData,
columns: columnDefs, columns: columnDefs,
getCoreRowModel: getCoreRowModel(), getCoreRowModel: getCoreRowModel(),
onSortingChange: setSorting, onSortingChange: setSorting,
@@ -86,7 +115,6 @@ export default function SystemsTable() {
columnVisibility, columnVisibility,
}, },
defaultColumn: { defaultColumn: {
// sortDescFirst: true,
invertSorting: true, invertSorting: true,
sortUndefined: "last", sortUndefined: "last",
minSize: 0, minSize: 0,
@@ -98,19 +126,25 @@ export default function SystemsTable() {
const rows = table.getRowModel().rows const rows = table.getRowModel().rows
const columns = table.getAllColumns() const columns = table.getAllColumns()
const visibleColumns = table.getVisibleLeafColumns() const visibleColumns = table.getVisibleLeafColumns()
const [upSystemsLength, downSystemsLength, pausedSystemsLength] = useMemo(() => {
return [Object.values(upSystems).length, Object.values(downSystems).length, Object.values(pausedSystems).length]
}, [upSystems, downSystems, pausedSystems])
// TODO: hiding temp then gpu messes up table headers // TODO: hiding temp then gpu messes up table headers
const CardHead = useMemo(() => { const CardHead = useMemo(() => {
return ( return (
<CardHeader className="pb-5 px-2 sm:px-6 max-sm:pt-5 max-sm:pb-1"> <CardHeader className="pb-4.5 px-2 sm:px-6 max-sm:pt-5 max-sm:pb-1">
<div className="grid md:flex gap-5 w-full items-end"> <div className="grid md:flex gap-5 w-full items-end">
<div className="px-2 sm:px-1"> <div className="px-2 sm:px-1">
<CardTitle className="mb-2.5"> <CardTitle className="mb-2">
<Trans>All Systems</Trans> <Trans>All Systems</Trans>
</CardTitle> </CardTitle>
<CardDescription> <CardDescription className="flex">
<Trans>Updated in real time. Click on a system to view information.</Trans> <Trans>Click on a system to view more information.</Trans>
</CardDescription> </CardDescription>
</div> </div>
<div className="flex gap-2 ms-auto w-full md:w-80"> <div className="flex gap-2 ms-auto w-full md:w-80">
<Input placeholder={t`Filter...`} onChange={(e) => setFilter(e.target.value)} className="px-4" /> <Input placeholder={t`Filter...`} onChange={(e) => setFilter(e.target.value)} className="px-4" />
<DropdownMenu> <DropdownMenu>
@@ -121,8 +155,8 @@ export default function SystemsTable() {
</Button> </Button>
</DropdownMenuTrigger> </DropdownMenuTrigger>
<DropdownMenuContent align="end" className="h-72 md:h-auto min-w-48 md:min-w-auto overflow-y-auto"> <DropdownMenuContent align="end" className="h-72 md:h-auto min-w-48 md:min-w-auto overflow-y-auto">
<div className="grid grid-cols-1 md:grid-cols-3 divide-y md:divide-s md:divide-y-0"> <div className="grid grid-cols-1 md:grid-cols-4 divide-y md:divide-s md:divide-y-0">
<div> <div className="border-r">
<DropdownMenuLabel className="pt-2 px-3.5 flex items-center gap-2"> <DropdownMenuLabel className="pt-2 px-3.5 flex items-center gap-2">
<LayoutGridIcon className="size-4" /> <LayoutGridIcon className="size-4" />
<Trans>Layout</Trans> <Trans>Layout</Trans>
@@ -144,7 +178,33 @@ export default function SystemsTable() {
</DropdownMenuRadioGroup> </DropdownMenuRadioGroup>
</div> </div>
<div> <div className="border-r">
<DropdownMenuLabel className="pt-2 px-3.5 flex items-center gap-2">
<FilterIcon className="size-4" />
<Trans>Status</Trans>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuRadioGroup
className="px-1 pb-1"
value={statusFilter}
onValueChange={(value) => setStatusFilter(value as StatusFilter)}
>
<DropdownMenuRadioItem value="all" onSelect={(e) => e.preventDefault()}>
<Trans>All Systems</Trans>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="up" onSelect={(e) => e.preventDefault()}>
<Trans>Up ({upSystemsLength})</Trans>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="down" onSelect={(e) => e.preventDefault()}>
<Trans>Down ({downSystemsLength})</Trans>
</DropdownMenuRadioItem>
<DropdownMenuRadioItem value="paused" onSelect={(e) => e.preventDefault()}>
<Trans>Paused ({pausedSystemsLength})</Trans>
</DropdownMenuRadioItem>
</DropdownMenuRadioGroup>
</div>
<div className="border-r">
<DropdownMenuLabel className="pt-2 px-3.5 flex items-center gap-2"> <DropdownMenuLabel className="pt-2 px-3.5 flex items-center gap-2">
<ArrowUpDownIcon className="size-4" /> <ArrowUpDownIcon className="size-4" />
<Trans>Sort By</Trans> <Trans>Sort By</Trans>
@@ -210,7 +270,16 @@ export default function SystemsTable() {
</div> </div>
</CardHeader> </CardHeader>
) )
}, [visibleColumns.length, sorting, viewMode, locale]) }, [
visibleColumns.length,
sorting,
viewMode,
locale,
statusFilter,
upSystemsLength,
downSystemsLength,
pausedSystemsLength,
])
return ( return (
<Card> <Card>
@@ -218,7 +287,7 @@ export default function SystemsTable() {
<div className="p-6 pt-0 max-sm:py-3 max-sm:px-2"> <div className="p-6 pt-0 max-sm:py-3 max-sm:px-2">
{viewMode === "table" ? ( {viewMode === "table" ? (
// table layout // table layout
<div className="rounded-md border overflow-hidden"> <div className="rounded-md">
<AllSystemsTable table={table} rows={rows} colLength={visibleColumns.length} /> <AllSystemsTable table={table} rows={rows} colLength={visibleColumns.length} />
</div> </div>
) : ( ) : (
@@ -240,36 +309,78 @@ export default function SystemsTable() {
) )
} }
const AllSystemsTable = memo( const AllSystemsTable = memo(function ({
({ table, rows, colLength }: { table: TableType<SystemRecord>; rows: Row<SystemRecord>[]; colLength: number }) => { table,
return ( rows,
<Table> colLength,
<SystemsTableHead table={table} colLength={colLength} /> }: {
<TableBody> table: TableType<SystemRecord>
{rows.length ? ( rows: Row<SystemRecord>[]
rows.map((row) => ( colLength: number
<SystemTableRow key={row.original.id} row={row} length={rows.length} colLength={colLength} /> }) {
)) // The virtualizer will need a reference to the scrollable container element
) : ( const scrollRef = useRef<HTMLDivElement>(null)
<TableRow>
<TableCell colSpan={colLength} className="h-24 text-center"> const virtualizer = useVirtualizer<HTMLDivElement, HTMLTableRowElement>({
<Trans>No systems found.</Trans> count: rows.length,
</TableCell> estimateSize: () => (rows.length > 10 ? 56 : 60),
</TableRow> getScrollElement: () => scrollRef.current,
)} overscan: 5,
</TableBody> })
</Table> 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() + 50}px`, paddingTop, paddingBottom }}>
<table className="text-sm w-full h-full">
<SystemsTableHead table={table} colLength={colLength} />
<TableBody onMouseEnter={preloadSystemDetail}>
{rows.length ? (
virtualRows.map((virtualRow) => {
const row = rows[virtualRow.index] as Row<SystemRecord>
return (
<SystemTableRow
key={row.id}
row={row}
virtualRow={virtualRow}
length={rows.length}
colLength={colLength}
/>
)
})
) : (
<TableRow>
<TableCell colSpan={colLength} className="h-37 text-center pointer-events-none">
<Trans>No systems found.</Trans>
</TableCell>
</TableRow>
)}
</TableBody>
</table>
</div>
</div>
)
})
function SystemsTableHead({ table, colLength }: { table: TableType<SystemRecord>; colLength: number }) { function SystemsTableHead({ table, colLength }: { table: TableType<SystemRecord>; colLength: number }) {
const { i18n } = useLingui() const { i18n } = useLingui()
return useMemo(() => { return useMemo(() => {
return ( return (
<TableHeader> <TableHeader className="sticky top-0 z-20 w-full border-b-2">
{table.getHeaderGroups().map((headerGroup) => ( {table.getHeaderGroups().map((headerGroup) => (
<TableRow key={headerGroup.id}> <tr key={headerGroup.id}>
{headerGroup.headers.map((header) => { {headerGroup.headers.map((header) => {
return ( return (
<TableHead className="px-1.5" key={header.id}> <TableHead className="px-1.5" key={header.id}>
@@ -277,41 +388,49 @@ function SystemsTableHead({ table, colLength }: { table: TableType<SystemRecord>
</TableHead> </TableHead>
) )
})} })}
</TableRow> </tr>
))} ))}
</TableHeader> </TableHeader>
) )
}, [i18n.locale, colLength]) }, [i18n.locale, colLength])
} }
const SystemTableRow = memo( const SystemTableRow = memo(function ({
({ row, length, colLength }: { row: Row<SystemRecord>; length: number; colLength: number }) => { row,
const system = row.original virtualRow,
const { t } = useLingui() colLength,
return useMemo(() => { }: {
return ( row: Row<SystemRecord>
<TableRow virtualRow: VirtualItem
// data-state={row.getIsSelected() && "selected"} length: number
className={cn("cursor-pointer transition-opacity relative", { colLength: number
"opacity-50": system.status === SystemStatus.Paused, }) {
})} const system = row.original
> const { t } = useLingui()
{row.getVisibleCells().map((cell) => ( return useMemo(() => {
<TableCell return (
key={cell.id} <TableRow
style={{ // data-state={row.getIsSelected() && "selected"}
width: cell.column.getSize(), className={cn("cursor-pointer transition-opacity relative safari:transform-3d", {
}} "opacity-50": system.status === SystemStatus.Paused,
className={length > 10 ? "py-2" : "py-2.5"} })}
> >
{flexRender(cell.column.columnDef.cell, cell.getContext())} {row.getVisibleCells().map((cell) => (
</TableCell> <TableCell
))} key={cell.id}
</TableRow> style={{
) width: cell.column.getSize(),
}, [system, system.status, colLength, t]) height: virtualRow.size,
} }}
) className="py-0"
>
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</TableCell>
))}
</TableRow>
)
}, [system, system.status, colLength, t])
})
const SystemCard = memo( const SystemCard = memo(
({ row, table, colLength }: { row: Row<SystemRecord>; table: TableType<SystemRecord>; colLength: number }) => { ({ row, table, colLength }: { row: Row<SystemRecord>; table: TableType<SystemRecord>; colLength: number }) => {
@@ -321,6 +440,7 @@ const SystemCard = memo(
return useMemo(() => { return useMemo(() => {
return ( return (
<Card <Card
onMouseEnter={preloadSystemDetail}
key={system.id} key={system.id}
className={cn( className={cn(
"cursor-pointer hover:shadow-md transition-all bg-transparent w-full dark:border-border duration-200 relative", "cursor-pointer hover:shadow-md transition-all bg-transparent w-full dark:border-border duration-200 relative",
@@ -330,13 +450,11 @@ const SystemCard = memo(
)} )}
> >
<CardHeader className="py-1 ps-5 pe-3 bg-muted/30 border-b border-border/60"> <CardHeader className="py-1 ps-5 pe-3 bg-muted/30 border-b border-border/60">
<div className="flex items-center justify-between gap-2"> <div className="flex items-center gap-2 w-full overflow-hidden">
<CardTitle className="text-base tracking-normal shrink-1 text-primary/90 flex items-center min-h-10 gap-2.5 min-w-0"> <CardTitle className="text-base tracking-normal text-primary/90 flex items-center min-w-0 flex-1 gap-2.5">
<div className="flex items-center gap-2.5 min-w-0"> <div className="flex items-center gap-2.5 min-w-0 flex-1">
<IndicatorDot system={system} /> <IndicatorDot system={system} />
<CardTitle className="text-[.95em]/normal tracking-normal truncate text-primary/90"> <span className="text-[.95em]/normal tracking-normal text-primary/90 truncate">{system.name}</span>
{system.name}
</CardTitle>
</div> </div>
</CardTitle> </CardTitle>
{table.getColumn("actions")?.getIsVisible() && ( {table.getColumn("actions")?.getIsVisible() && (
@@ -347,23 +465,33 @@ const SystemCard = memo(
)} )}
</div> </div>
</CardHeader> </CardHeader>
<CardContent className="grid gap-2.5 text-sm px-5 pt-3.5 pb-4"> <CardContent className="text-sm px-5 pt-3.5 pb-4">
{table.getAllColumns().map((column) => { <div className="grid gap-2.5" style={{ gridTemplateColumns: "24px minmax(80px, max-content) 1fr" }}>
if (!column.getIsVisible() || column.id === "system" || column.id === "actions") return null {table.getAllColumns().map((column) => {
const cell = row.getAllCells().find((cell) => cell.column.id === column.id) if (!column.getIsVisible() || column.id === "system" || column.id === "actions") return null
if (!cell) return null const cell = row.getAllCells().find((cell) => cell.column.id === column.id)
// @ts-ignore if (!cell) return null
const { Icon, name } = column.columnDef as ColumnDef<SystemRecord, unknown> // @ts-ignore
return ( const { Icon, name } = column.columnDef as ColumnDef<SystemRecord, unknown>
<div key={column.id} className="flex items-center gap-3"> return (
{Icon && <Icon className="size-4 text-muted-foreground" />} <>
<div className="flex items-center gap-3 flex-1"> <div key={`${column.id}-icon`} className="flex items-center">
<span className="text-muted-foreground min-w-16">{name()}:</span> {column.id === "lastSeen" ? (
<div className="flex-1">{flexRender(cell.column.columnDef.cell, cell.getContext())}</div> <EyeIcon className="size-4 text-muted-foreground" />
</div> ) : (
</div> Icon && <Icon className="size-4 text-muted-foreground" />
) )}
})} </div>
<div key={`${column.id}-label`} className="flex items-center text-muted-foreground pr-3">
{name()}:
</div>
<div key={`${column.id}-value`} className="flex items-center">
{flexRender(cell.column.columnDef.cell, cell.getContext())}
</div>
</>
)
})}
</div>
</CardContent> </CardContent>
<Link <Link
href={getPagePath($router, "system", { name: row.original.name })} href={getPagePath($router, "system", { name: row.original.name })}

View File

@@ -267,7 +267,7 @@ const ChartLegendContent = React.forwardRef<
<div <div
ref={ref} ref={ref}
className={cn( className={cn(
"flex items-center justify-center gap-4 gap-y-1 flex-wrap", "flex items-center justify-center gap-4 gap-y-1 flex-wrap ps-4",
verticalAlign === "top" ? "pb-3" : "pt-3", verticalAlign === "top" ? "pb-3" : "pt-3",
className className
)} )}

View File

@@ -1,33 +1,41 @@
import * as React from "react" import * as React from "react"
import { DialogTitle, type DialogProps } from "@radix-ui/react-dialog"
import { Command as CommandPrimitive } from "cmdk" import { Command as CommandPrimitive } from "cmdk"
import { Search } from "lucide-react" import { SearchIcon } from "lucide-react"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
import { Dialog, DialogContent } from "@/components/ui/dialog" import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog"
const Command = React.forwardRef< function Command({ className, ...props }: React.ComponentProps<typeof CommandPrimitive>) {
React.ElementRef<typeof CommandPrimitive>, return (
React.ComponentPropsWithoutRef<typeof CommandPrimitive> <CommandPrimitive
>(({ className, ...props }, ref) => ( data-slot="command"
<CommandPrimitive className={cn("bg-card flex h-full w-full flex-col overflow-hidden rounded-md", className)}
ref={ref} {...props}
className={cn("flex h-full w-full flex-col overflow-hidden bg-card", className)} />
{...props} )
/> }
))
Command.displayName = CommandPrimitive.displayName
interface CommandDialogProps extends DialogProps {} function CommandDialog({
title = "Command Palette",
const CommandDialog = ({ children, ...props }: CommandDialogProps) => { description = "Search for a command to run...",
children,
className,
showCloseButton = true,
...props
}: React.ComponentProps<typeof Dialog> & {
title?: string
description?: string
className?: string
showCloseButton?: boolean
}) {
return ( return (
<Dialog {...props}> <Dialog {...props}>
<DialogContent className="overflow-hidden p-0 shadow-lg"> <DialogHeader className="sr-only">
<div className="sr-only"> <DialogTitle>{title}</DialogTitle>
<DialogTitle>Command</DialogTitle> <DialogDescription>{description}</DialogDescription>
</div> </DialogHeader>
<Command className="[&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-group]]:px-2 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5"> <DialogContent className={cn("overflow-hidden p-0", className)}>
<Command className="[&_[cmdk-group-heading]]:text-muted-foreground **:data-[slot=command-input-wrapper]:h-12 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group]]:px-2 [&_[cmdk-group]:not([hidden])_~[cmdk-group]]:pt-0 [&_[cmdk-input-wrapper]_svg]:h-5 [&_[cmdk-input-wrapper]_svg]:w-5 [&_[cmdk-input]]:h-12 [&_[cmdk-item]]:px-2 [&_[cmdk-item]]:py-3 [&_[cmdk-item]_svg]:h-5 [&_[cmdk-item]_svg]:w-5">
{children} {children}
</Command> </Command>
</DialogContent> </DialogContent>
@@ -35,89 +43,81 @@ const CommandDialog = ({ children, ...props }: CommandDialogProps) => {
) )
} }
const CommandInput = React.forwardRef< function CommandInput({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Input>) {
React.ElementRef<typeof CommandPrimitive.Input>, return (
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Input> <div data-slot="command-input-wrapper" className="flex h-9 items-center gap-2 border-b px-3">
>(({ className, ...props }, ref) => ( <SearchIcon className="size-4 shrink-0 opacity-50" />
<div className="flex items-center border-b px-3" cmdk-input-wrapper=""> <CommandPrimitive.Input
<Search className="me-2 h-4 w-4 shrink-0 opacity-50" /> data-slot="command-input"
<CommandPrimitive.Input className={cn(
ref={ref} "placeholder:text-muted-foreground flex h-10 w-full rounded-md bg-transparent py-3 text-sm outline-hidden disabled:cursor-not-allowed disabled:opacity-50",
className
)}
{...props}
/>
</div>
)
}
function CommandList({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.List>) {
return (
<CommandPrimitive.List
data-slot="command-list"
className={cn("max-h-[300px] scroll-py-1 overflow-x-hidden overflow-y-auto", className)}
{...props}
/>
)
}
function CommandEmpty({ ...props }: React.ComponentProps<typeof CommandPrimitive.Empty>) {
return <CommandPrimitive.Empty data-slot="command-empty" className="py-6 text-center text-sm" {...props} />
}
function CommandGroup({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Group>) {
return (
<CommandPrimitive.Group
data-slot="command-group"
className={cn( className={cn(
"flex h-11 w-full rounded-md bg-transparent py-3 text-sm outline-hidden placeholder:text-muted-foreground disabled:cursor-not-allowed disabled:opacity-50", "text-foreground [&_[cmdk-group-heading]]:text-muted-foreground overflow-hidden p-1 [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium",
className className
)} )}
{...props} {...props}
/> />
</div> )
)) }
CommandInput.displayName = CommandPrimitive.Input.displayName function CommandSeparator({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Separator>) {
return (
const CommandList = React.forwardRef< <CommandPrimitive.Separator
React.ElementRef<typeof CommandPrimitive.List>, data-slot="command-separator"
React.ComponentPropsWithoutRef<typeof CommandPrimitive.List> className={cn("bg-border -mx-1 h-px", className)}
>(({ className, ...props }, ref) => ( {...props}
<CommandPrimitive.List />
ref={ref} )
className={cn("max-h-[300px] overflow-y-auto overflow-x-hidden", className)} }
{...props}
/> function CommandItem({ className, ...props }: React.ComponentProps<typeof CommandPrimitive.Item>) {
)) return (
<CommandPrimitive.Item
CommandList.displayName = CommandPrimitive.List.displayName data-slot="command-item"
className={cn(
const CommandEmpty = React.forwardRef< "data-[selected=true]:bg-accent/70 data-[selected=true]:text-accent-foreground [&_svg:not([class*='text-'])]:text-muted-foreground relative flex cursor-default items-center gap-2 rounded-sm px-2 py-1.5 text-sm outline-hidden select-none data-[disabled=true]:pointer-events-none data-[disabled=true]:opacity-50 [&_svg]:pointer-events-none [&_svg]:shrink-0 [&_svg:not([class*='size-'])]:size-4",
React.ElementRef<typeof CommandPrimitive.Empty>, className
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Empty> )}
>((props, ref) => <CommandPrimitive.Empty ref={ref} className="py-6 text-center text-sm" {...props} />) {...props}
/>
CommandEmpty.displayName = CommandPrimitive.Empty.displayName )
}
const CommandGroup = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Group>, function CommandShortcut({ className, ...props }: React.ComponentProps<"span">) {
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Group> return (
>(({ className, ...props }, ref) => ( <span
<CommandPrimitive.Group data-slot="command-shortcut"
ref={ref} className={cn("text-muted-foreground ml-auto text-xs tracking-wide", className)}
className={cn( {...props}
"overflow-hidden p-1 text-foreground [&_[cmdk-group-heading]]:px-2 [&_[cmdk-group-heading]]:py-1.5 [&_[cmdk-group-heading]]:text-xs [&_[cmdk-group-heading]]:font-medium [&_[cmdk-group-heading]]:text-muted-foreground", />
className )
)}
{...props}
/>
))
CommandGroup.displayName = CommandPrimitive.Group.displayName
const CommandSeparator = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Separator>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Separator>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Separator ref={ref} className={cn("-mx-1 h-px bg-border", className)} {...props} />
))
CommandSeparator.displayName = CommandPrimitive.Separator.displayName
const CommandItem = React.forwardRef<
React.ElementRef<typeof CommandPrimitive.Item>,
React.ComponentPropsWithoutRef<typeof CommandPrimitive.Item>
>(({ className, ...props }, ref) => (
<CommandPrimitive.Item
ref={ref}
className={cn(
"relative flex cursor-default opacity-70 select-none items-center rounded-sm px-2 py-1.5 text-sm outline-hidden aria-selected:bg-accent/60 aria-selected:opacity-90 data-[disabled='true']:pointer-events-none data-[disabled='true']:opacity-50",
className
)}
{...props}
/>
))
CommandItem.displayName = CommandPrimitive.Item.displayName
const CommandShortcut = ({ className, ...props }: React.HTMLAttributes<HTMLSpanElement>) => {
return <span className={cn("ms-auto text-xs tracking-wide text-muted-foreground", className)} {...props} />
} }
CommandShortcut.displayName = "CommandShortcut"
export { export {
Command, Command,

View File

@@ -79,7 +79,7 @@ const DropdownMenuItem = React.forwardRef<
<DropdownMenuPrimitive.Item <DropdownMenuPrimitive.Item
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex select-none items-center rounded-sm px-2.5 py-1.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50", "cursor-pointer relative flex select-none items-center rounded-sm px-2.5 py-1.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
inset && "ps-8", inset && "ps-8",
className className
)} )}
@@ -95,7 +95,7 @@ const DropdownMenuCheckboxItem = React.forwardRef<
<DropdownMenuPrimitive.CheckboxItem <DropdownMenuPrimitive.CheckboxItem
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50", "relative flex cursor-pointer select-none items-center rounded-sm py-1.5 ps-8 pe-2.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className className
)} )}
checked={checked} checked={checked}
@@ -118,7 +118,7 @@ const DropdownMenuRadioItem = React.forwardRef<
<DropdownMenuPrimitive.RadioItem <DropdownMenuPrimitive.RadioItem
ref={ref} ref={ref}
className={cn( className={cn(
"relative flex cursor-default select-none items-center rounded-sm py-1.5 ps-8 pe-2 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50", "relative flex cursor-pointer select-none items-center rounded-sm py-1.5 ps-8 pe-2.5 text-sm outline-hidden focus:bg-accent/70 focus:text-accent-foreground data-disabled:pointer-events-none data-disabled:opacity-50",
className className
)} )}
{...props} {...props}

View File

@@ -15,7 +15,7 @@ export function InputCopy({ value, id, name }: { value: string; id: string; name
} }
></div> ></div>
<TooltipProvider delayDuration={100} disableHoverableContent> <TooltipProvider delayDuration={100} disableHoverableContent>
<Tooltip> <Tooltip disableHoverableContent={true}>
<TooltipTrigger asChild> <TooltipTrigger asChild>
<Button <Button
type="button" type="button"

View File

@@ -2,21 +2,19 @@ import * as React from "react"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
export interface InputProps extends React.InputHTMLAttributes<HTMLInputElement> {} function Input({ className, type, ...props }: React.ComponentProps<"input">) {
const Input = React.forwardRef<HTMLInputElement, InputProps>(({ className, type, ...props }, ref) => {
return ( return (
<input <input
type={type} type={type}
data-slot="input"
className={cn( className={cn(
"flex h-10 w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50", "flex h-10 w-full rounded-md border bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-hidden focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
"aria-invalid:ring-destructive/20 dark:aria-invalid:ring-destructive/40 aria-invalid:border-destructive",
className className
)} )}
ref={ref}
{...props} {...props}
/> />
) )
}) }
Input.displayName = "Input"
export { Input } export { Input }

View File

@@ -13,7 +13,11 @@ Table.displayName = "Table"
const TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>( const TableHeader = React.forwardRef<HTMLTableSectionElement, React.HTMLAttributes<HTMLTableSectionElement>>(
({ className, ...props }, ref) => ( ({ className, ...props }, ref) => (
<thead ref={ref} className={cn("bg-muted/30 [&_tr]:border-b", className)} {...props} /> <thead
ref={ref}
className={cn("bg-table-header border-b border-border/50 [&_tr]:border-b", className)}
{...props}
/>
) )
) )
TableHeader.displayName = "TableHeader" TableHeader.displayName = "TableHeader"

View File

@@ -3,26 +3,47 @@ import * as TooltipPrimitive from "@radix-ui/react-tooltip"
import { cn } from "@/lib/utils" import { cn } from "@/lib/utils"
const TooltipProvider = TooltipPrimitive.Provider function TooltipProvider({ delayDuration = 0, ...props }: React.ComponentProps<typeof TooltipPrimitive.Provider>) {
return <TooltipPrimitive.Provider data-slot="tooltip-provider" delayDuration={delayDuration} {...props} />
}
const Tooltip = TooltipPrimitive.Root function Tooltip({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Root>) {
return (
<TooltipProvider>
<TooltipPrimitive.Root data-slot="tooltip" {...props} />
</TooltipProvider>
)
}
const TooltipTrigger = TooltipPrimitive.Trigger function TooltipTrigger({ ...props }: React.ComponentProps<typeof TooltipPrimitive.Trigger>) {
return <TooltipPrimitive.Trigger data-slot="tooltip-trigger" {...props} />
}
const TooltipContent = React.forwardRef< function TooltipContent({
React.ElementRef<typeof TooltipPrimitive.Content>, className,
React.ComponentPropsWithoutRef<typeof TooltipPrimitive.Content> sideOffset = 0,
>(({ className, sideOffset = 4, ...props }, ref) => ( children,
<TooltipPrimitive.Content ...props
ref={ref} }: React.ComponentProps<typeof TooltipPrimitive.Content>) {
sideOffset={sideOffset} return (
className={cn( <TooltipPrimitive.Portal>
"z-50 overflow-hidden rounded-md border bg-popover px-3 py-1.5 text-sm text-popover-foreground shadow-md animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2", <TooltipPrimitive.Content
className data-slot="tooltip-content"
)} sideOffset={sideOffset}
{...props} className={cn(
/> "bg-popover text-popover-foreground border animate-in fade-in-0 zoom-in-95 data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=closed]:zoom-out-95 data-[side=bottom]:slide-in-from-top-2 data-[side=left]:slide-in-from-right-2 data-[side=right]:slide-in-from-left-2 data-[side=top]:slide-in-from-bottom-2 z-50 w-fit origin-(--radix-tooltip-content-transform-origin) rounded-md px-3 py-1.5 text-sm text-balance",
)) className
TooltipContent.displayName = TooltipPrimitive.Content.displayName )}
{...props}
>
{children}
<TooltipPrimitive.Arrow
className="bg-popover border z-50 fill-popover size-2.5 translate-y-[calc(-50%_-_2px)] rotate-45 rounded-[2px] will-change-transform"
style={{ clipPath: "inset(25% 0 0 25%)" }}
/>
</TooltipPrimitive.Content>
</TooltipPrimitive.Portal>
)
}
export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider } export { Tooltip, TooltipTrigger, TooltipContent, TooltipProvider }

View File

@@ -1,73 +1,112 @@
@import "tailwindcss"; @import "tailwindcss";
@import "tw-animate-css"; @import "tw-animate-css";
@config '../tailwind.config.js'; @custom-variant light (&:is(.light *));
@custom-variant dark (&:is(.dark *));
@custom-variant safari (@supports (hanging-punctuation: first) and (-webkit-appearance: none));
@utility link { :root {
@apply text-primary font-medium underline-offset-4 hover:underline; --background: hsl(30 8% 98%);
--foreground: hsl(30 0% 10%);
--card: hsl(30 0% 100%);
--card-foreground: hsl(240 6% 12%);
--popover: hsl(30 0% 100%);
--popover-foreground: hsl(240 10% 6.2%);
--primary: hsl(240 5.88% 10%);
--primary-foreground: hsl(30 0% 100%);
--secondary: hsl(240 4.76% 95.88%);
--secondary-foreground: hsl(240 5.88% 10%);
--muted: hsl(26 6% 94%);
--muted-foreground: hsl(24 2.79% 35.1%);
--accent: hsl(20 23.08% 94%);
--accent-foreground: hsl(240 5.88% 10%);
--destructive: hsl(0 66% 53%);
--destructive-foreground: hsl(0 0% 97%);
--border: hsl(30 8.11% 85.49%);
--input: hsl(30 4.29% 72.55%);
--ring: hsl(30 3.97% 49.41%);
--radius: 0.8rem;
--chart-1: hsl(220 70% 50%);
--chart-2: hsl(160 60% 45%);
--chart-3: hsl(30 80% 55%);
--chart-4: hsl(280 65% 60%);
--chart-5: hsl(340 75% 55%);
--table-header: hsl(225, 6%, 97%);
} }
@utility ns-dialog { .dark {
/* New system dialog width */ color-scheme: dark;
min-width: 30.3rem; --background: hsl(220 5.5% 9%);
:where(:lang(zh), :lang(zh-CN), :lang(ko)) & { --foreground: hsl(220 2% 97%);
min-width: 27.9rem; --card: hsl(220 5.5% 10.5%);
} --card-foreground: hsl(220 2% 97%);
--popover: hsl(220 5.5% 9%);
--popover-foreground: hsl(220 2% 97%);
--primary: hsl(220 2% 96%);
--primary-foreground: hsl(220 4% 10%);
--secondary: hsl(220 4% 16%);
--secondary-foreground: hsl(220 0% 98%);
--muted: hsl(220 6% 16%);
--muted-foreground: hsl(220 4% 67%);
--accent: hsl(220 5% 15.5%);
--accent-foreground: hsl(220 2% 98%);
--destructive: hsl(0 62% 46%);
--border: hsl(220 3% 16%);
--input: hsl(220 4% 22%);
--ring: hsl(220 4% 80%);
--table-header: hsl(220, 6%, 13%);
--radius: 0.8rem;
} }
@layer base { @theme inline {
:root { --font-sans: Inter, InterVariable, sans-serif;
--background: 30 8% 98%;
--foreground: 30 0% 0%;
--card: 30 0% 100%;
--card-foreground: 240 6.67% 2.94%;
--popover: 30 0% 100%;
--popover-foreground: 240 10% 6.2%;
--primary: 240 5.88% 10%;
--primary-foreground: 30 0% 100%;
--secondary: 240 4.76% 95.88%;
--secondary-foreground: 240 5.88% 10%;
--muted: 26 6% 94%;
--muted-foreground: 24 2.79% 35.1%;
--accent: 20 23.08% 94%;
--accent-foreground: 240 5.88% 10%;
--destructive: 0 66% 53%;
--destructive-foreground: 0 0% 98.04%;
--border: 30 8.11% 85.49%;
--input: 30 4.29% 72.55%;
--ring: 30 3.97% 49.41%;
--radius: 0.8rem;
/* charts */
--chart-1: 220 70% 50%;
--chart-2: 160 60% 45%;
--chart-3: 30 80% 55%;
--chart-4: 280 65% 60%;
--chart-5: 340 75% 55%;
}
.dark { --breakpoint-xs: 26.6rem;
color-scheme: dark; --breakpoint-450: 28rem;
--background: 220 5.5% 9%; --breakpoint-2xl: 90rem;
--foreground: 220 2% 97%;
--card: 220 5.5% 10.5%; --radius-sm: calc(var(--radius) - 4px);
--card-foreground: 220 2% 97%; --radius-md: calc(var(--radius) - 2px);
--popover: 220 5.5% 9%; --radius-lg: var(--radius);
--popover-foreground: 220 2% 97%; --radius-xl: calc(var(--radius) + 4px);
--primary: 220 2% 96%;
--primary-foreground: 220 4% 10%; --color-green-50: hsl(140 60% 95%);
--secondary: 220 4% 16%; --color-green-100: hsl(140 50% 90%);
--secondary-foreground: 220 0% 98%; --color-green-200: hsl(140 49% 80%);
--muted: 220 6% 16%; --color-green-300: hsl(140 48% 70%);
--muted-foreground: 220 4% 67%; --color-green-400: hsl(140 49% 60%);
--accent: 220 5% 15.5%; --color-green-500: hsl(140 50% 48%);
--accent-foreground: 220 2% 98%; --color-green-600: hsl(140 52% 38%);
--destructive: 0 62% 46%; --color-green-700: hsl(140 53% 29%);
--destructive-foreground: 0 0% 97%; --color-green-800: hsl(140 54% 20%);
--border: 220 3% 16%; --color-green-900: hsl(140 54% 12%);
--input: 220 4% 22%; --color-green-950: hsl(140 57% 6%);
--ring: 220 4% 80%;
--radius: 0.8rem; --color-background: var(--background);
} --color-foreground: var(--foreground);
--color-card: var(--card);
--color-card-foreground: var(--card-foreground);
--color-popover: var(--popover);
--color-popover-foreground: var(--popover-foreground);
--color-primary: var(--primary);
--color-primary-foreground: var(--primary-foreground);
--color-secondary: var(--secondary);
--color-secondary-foreground: var(--secondary-foreground);
--color-muted: var(--muted);
--color-muted-foreground: var(--muted-foreground);
--color-accent: var(--accent);
--color-accent-foreground: var(--accent-foreground);
--color-destructive: var(--destructive);
--color-destructive-foreground: var(--destructive-foreground);
--color-border: var(--border);
--color-input: var(--input);
--color-ring: var(--ring);
--color-chart-1: var(--chart-1);
--color-chart-2: var(--chart-2);
--color-chart-3: var(--chart-3);
--color-chart-4: var(--chart-4);
--color-chart-5: var(--chart-5);
--color-table-header: var(--table-header);
} }
@layer utilities { @layer utilities {
@@ -88,7 +127,7 @@
@layer base { @layer base {
* { * {
@apply border-border; @apply border-border outline-ring/50;
overflow-anchor: none; overflow-anchor: none;
} }
body { body {
@@ -99,6 +138,22 @@
} }
} }
@utility container {
@apply max-w-360 mx-auto px-4;
}
@utility link {
@apply text-primary font-medium underline-offset-4 hover:underline;
}
@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 { .recharts-tooltip-wrapper {
z-index: 1; z-index: 1;
@apply tabular-nums; @apply tabular-nums;

View File

@@ -1,9 +1,10 @@
import type { AlertInfo, AlertRecord } from "@/types" import type { AlertInfo, AlertRecord } from "@/types"
import type { RecordSubscription } from "pocketbase" import type { RecordSubscription } from "pocketbase"
import { pb, $alerts } from "@/lib/stores" import { $alerts } from "@/lib/stores"
import { EthernetIcon } from "@/components/ui/icons" import { EthernetIcon } from "@/components/ui/icons"
import { ServerIcon, CpuIcon, MemoryStickIcon, HardDriveIcon, ThermometerIcon, HourglassIcon } from "lucide-react" import { ServerIcon, CpuIcon, MemoryStickIcon, HardDriveIcon, ThermometerIcon, HourglassIcon } from "lucide-react"
import { t } from "@lingui/core/macro" import { t } from "@lingui/core/macro"
import { pb } from "./api"
/** Alert info for each alert type */ /** Alert info for each alert type */
export const alertInfo: Record<string, AlertInfo> = { export const alertInfo: Record<string, AlertInfo> = {

View File

@@ -0,0 +1,66 @@
import { ChartTimes, UserSettings } from "@/types"
import { $alerts, $allSystemsByName, $userSettings } from "./stores"
import { toast } from "@/components/ui/use-toast"
import { t } from "@lingui/core/macro"
import { chartTimeData } from "./utils"
import PocketBase from "pocketbase"
import { basePath } from "@/components/router"
/** PocketBase JS Client */
export const pb = new PocketBase(basePath)
export const isAdmin = () => pb.authStore.record?.role === "admin"
export const isReadOnlyUser = () => pb.authStore.record?.role === "readonly"
export const verifyAuth = () => {
pb.collection("users")
.authRefresh()
.catch(() => {
logOut()
toast({
title: t`Failed to authenticate`,
description: t`Please log in again`,
variant: "destructive",
})
})
}
/** Logs the user out by clearing the auth store and unsubscribing from realtime updates. */
export async function logOut() {
$allSystemsByName.set({})
$alerts.set({})
$userSettings.set({} as UserSettings)
sessionStorage.setItem("lo", "t") // prevent auto login on logout
pb.authStore.clear()
pb.realtime.unsubscribe()
}
/** Fetch or create user settings in database */
export async function updateUserSettings() {
try {
const req = await pb.collection("user_settings").getFirstListItem("", { fields: "settings" })
$userSettings.set(req.settings)
return
} catch (e) {
console.error("get settings", e)
}
// create user settings if error fetching existing
try {
const createdSettings = await pb.collection("user_settings").create({ user: pb.authStore.record!.id })
$userSettings.set(createdSettings.settings)
} catch (e) {
console.error("create settings", e)
}
}
export function getPbTimestamp(timeString: ChartTimes, d?: Date) {
d ||= chartTimeData[timeString].getOffset(new Date())
const year = d.getUTCFullYear()
const month = String(d.getUTCMonth() + 1).padStart(2, "0")
const day = String(d.getUTCDate()).padStart(2, "0")
const hours = String(d.getUTCHours()).padStart(2, "0")
const minutes = String(d.getUTCMinutes()).padStart(2, "0")
const seconds = String(d.getUTCSeconds()).padStart(2, "0")
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}

View File

@@ -1,17 +1,23 @@
import PocketBase from "pocketbase" import { atom, computed, map, ReadableAtom } from "nanostores"
import { atom, map } from "nanostores"
import { AlertMap, ChartTimes, SystemRecord, UserSettings } from "@/types" import { AlertMap, ChartTimes, SystemRecord, UserSettings } from "@/types"
import { basePath } from "@/components/router"
import { Unit } from "./enums" import { Unit } from "./enums"
import { pb } from "./api"
/** PocketBase JS Client */
export const pb = new PocketBase(basePath)
/** Store if user is authenticated */ /** Store if user is authenticated */
export const $authenticated = atom(pb.authStore.isValid) export const $authenticated = atom(pb.authStore.isValid)
/** List of system records */ /** Map of system records by name */
export const $systems = atom<SystemRecord[]>([]) export const $allSystemsByName = map<Record<string, SystemRecord>>({})
/** Map of system records by id */
export const $allSystemsById = map<Record<string, SystemRecord>>({})
/** Map of up systems by id */
export const $upSystems = map<Record<string, SystemRecord>>({})
/** Map of down systems by id */
export const $downSystems = map<Record<string, SystemRecord>>({})
/** Map of paused systems by id */
export const $pausedSystems = map<Record<string, SystemRecord>>({})
/** List of all system records */
export const $systems: ReadableAtom<SystemRecord[]> = computed($allSystemsById, Object.values)
/** Map of alert records by system id and alert name */ /** Map of alert records by system id and alert name */
export const $alerts = map<AlertMap>({}) export const $alerts = map<AlertMap>({})
@@ -57,3 +63,8 @@ export const $copyContent = atom("")
/** Direction for localization */ /** Direction for localization */
export const $direction = atom<"ltr" | "rtl">("ltr") export const $direction = atom<"ltr" | "rtl">("ltr")
/** Longest system name length. Used to set table column width. I know this
* is stupid but the table is virtualized and I know this will work.
*/
export const $longestSystemNameLen = atom(8)

View File

@@ -0,0 +1,174 @@
import { SystemRecord } from "@/types"
import { PreinitializedMapStore } from "nanostores"
import { pb, verifyAuth } from "@/lib/api"
import {
$allSystemsByName,
$upSystems,
$downSystems,
$pausedSystems,
$allSystemsById,
$longestSystemNameLen,
} from "@/lib/stores"
import { updateFavicon, FAVICON_DEFAULT, FAVICON_GREEN, FAVICON_RED } from "@/lib/utils"
import { SystemStatus } from "./enums"
const COLLECTION = pb.collection<SystemRecord>("systems")
const FIELDS_DEFAULT = "id,name,host,port,info,status"
/** Maximum system name length for display purposes */
const MAX_SYSTEM_NAME_LENGTH = 20
let initialized = false
let unsub: (() => void) | undefined | void
/** Initialize the systems manager and set up listeners */
export function init() {
if (initialized) {
return
}
initialized = true
// sync system stores on change
$allSystemsById.listen((newSystems, oldSystems, changedKey) => {
const oldSystem = oldSystems[changedKey]
const newSystem = newSystems[changedKey]
// if system is undefined (deleted), remove it from the stores
if (oldSystem && !newSystem?.id) {
removeFromStore(oldSystem, $upSystems)
removeFromStore(oldSystem, $downSystems)
removeFromStore(oldSystem, $pausedSystems)
removeFromStore(oldSystem, $allSystemsById)
}
if (!newSystem) {
onSystemsChanged(newSystems, undefined)
return
}
const newStatus = newSystem.status
if (newStatus === SystemStatus.Up) {
$upSystems.setKey(newSystem.id, newSystem)
removeFromStore(newSystem, $downSystems)
removeFromStore(newSystem, $pausedSystems)
} else if (newStatus === SystemStatus.Down) {
$downSystems.setKey(newSystem.id, newSystem)
removeFromStore(newSystem, $upSystems)
removeFromStore(newSystem, $pausedSystems)
} else if (newStatus === SystemStatus.Paused) {
$pausedSystems.setKey(newSystem.id, newSystem)
removeFromStore(newSystem, $upSystems)
removeFromStore(newSystem, $downSystems)
} else if (newStatus === SystemStatus.Pending) {
removeFromStore(newSystem, $upSystems)
removeFromStore(newSystem, $downSystems)
removeFromStore(newSystem, $pausedSystems)
}
// run things that need to be done when systems change
onSystemsChanged(newSystems, newSystem)
})
}
/** 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
const longestName = $longestSystemNameLen.get()
const nameLen = Math.min(MAX_SYSTEM_NAME_LENGTH, changedSystem?.name.length || 0)
if (nameLen > longestName) {
$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)
}
}
/** Fetch systems from collection */
async function fetchSystems(): Promise<SystemRecord[]> {
try {
return await COLLECTION.getFullList({ sort: "+name", fields: FIELDS_DEFAULT })
} catch (error) {
console.error("Failed to fetch systems:", error)
return []
}
}
/** Add system to both name and ID stores */
export function add(system: SystemRecord) {
$allSystemsByName.setKey(system.name, system)
$allSystemsById.setKey(system.id, system)
}
/** Update system in stores */
export function update(system: SystemRecord) {
// if name changed, make sure old name is removed from the name store
const oldName = $allSystemsById.get()[system.id]?.name
if (oldName !== system.name) {
$allSystemsByName.setKey(oldName, undefined as any)
}
add(system)
}
/** Remove system from stores */
export function remove(system: SystemRecord) {
removeFromStore(system, $allSystemsByName)
removeFromStore(system, $allSystemsById)
removeFromStore(system, $upSystems)
removeFromStore(system, $downSystems)
removeFromStore(system, $pausedSystems)
}
/** Remove system from specific store */
function removeFromStore(system: SystemRecord, store: PreinitializedMapStore<Record<string, SystemRecord>>) {
const key = store === $allSystemsByName ? system.name : system.id
store.setKey(key, undefined as any)
}
/** Action functions for subscription */
const actionFns: Record<string, (system: SystemRecord) => void> = {
create: add,
update: update,
delete: remove,
}
/** Subscribe to real-time system updates from the collection */
export async function subscribe() {
try {
unsub = await COLLECTION.subscribe("*", ({ action, record }) => actionFns[action]?.(record), {
fields: FIELDS_DEFAULT,
})
} catch (error) {
console.error("Failed to subscribe to systems collection:", error)
}
}
/** Refresh all systems with latest data from the hub */
export async function refresh() {
try {
const records = await fetchSystems()
if (!records.length) {
// No systems found, verify authentication
verifyAuth()
return
}
for (const record of records) {
add(record)
}
} catch (error) {
console.error("Failed to refresh systems:", error)
}
}
/** Unsubscribe from real-time system updates */
export const unsubscribe = () => (unsub = unsub?.())

View File

@@ -2,14 +2,16 @@ import { t } from "@lingui/core/macro"
import { toast } from "@/components/ui/use-toast" import { toast } from "@/components/ui/use-toast"
import { type ClassValue, clsx } from "clsx" import { type ClassValue, clsx } from "clsx"
import { twMerge } from "tailwind-merge" import { twMerge } from "tailwind-merge"
import { $alerts, $copyContent, $systems, $userSettings, pb } from "./stores" import { $copyContent, $userSettings } from "./stores"
import type { ChartTimeData, ChartTimes, FingerprintRecord, SemVer, SystemRecord, UserSettings } from "@/types" import type { ChartTimeData, FingerprintRecord, SemVer, SystemRecord } from "@/types"
import { RecordModel, RecordSubscription } from "pocketbase"
import { WritableAtom } from "nanostores"
import { timeDay, timeHour } from "d3-time" import { timeDay, timeHour } from "d3-time"
import { useEffect, useState } from "react" import { useEffect, useState } from "react"
import { prependBasePath } from "@/components/router"
import { MeterState, Unit } from "./enums" import { MeterState, Unit } from "./enums"
import { prependBasePath } from "@/components/router"
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[]) { export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs)) return twMerge(clsx(inputs))
@@ -34,52 +36,6 @@ export async function copyToClipboard(content: string) {
} }
} }
const verifyAuth = () => {
pb.collection("users")
.authRefresh()
.catch(() => {
logOut()
toast({
title: t`Failed to authenticate`,
description: t`Please log in again`,
variant: "destructive",
})
})
}
export const updateSystemList = (() => {
let isFetchingSystems = false
return async () => {
if (isFetchingSystems) {
return
}
isFetchingSystems = true
try {
const records = await pb
.collection<SystemRecord>("systems")
.getFullList({ sort: "+name", fields: "id,name,host,port,info,status" })
if (records.length) {
$systems.set(records)
} else {
verifyAuth()
}
} finally {
isFetchingSystems = false
}
}
})()
/** Logs the user out by clearing the auth store and unsubscribing from realtime updates. */
export async function logOut() {
$systems.set([])
$alerts.set({})
$userSettings.set({} as UserSettings)
sessionStorage.setItem("lo", "t") // prevent auto login on logout
pb.authStore.clear()
pb.realtime.unsubscribe()
}
const hourWithMinutesFormatter = new Intl.DateTimeFormat(undefined, { const hourWithMinutesFormatter = new Intl.DateTimeFormat(undefined, {
hour: "numeric", hour: "numeric",
minute: "numeric", minute: "numeric",
@@ -110,47 +66,6 @@ export const updateFavicon = (newIcon: string) => {
;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = prependBasePath(`/static/${newIcon}`) ;(document.querySelector("link[rel='icon']") as HTMLLinkElement).href = prependBasePath(`/static/${newIcon}`)
} }
export const isAdmin = () => pb.authStore.record?.role === "admin"
export const isReadOnlyUser = () => pb.authStore.record?.role === "readonly"
/** Update systems / alerts list when records change */
export function updateRecordList<T extends RecordModel>(e: RecordSubscription<T>, $store: WritableAtom<T[]>) {
const curRecords = $store.get()
const newRecords = []
if (e.action === "delete") {
for (const server of curRecords) {
if (server.id !== e.record.id) {
newRecords.push(server)
}
}
} else {
let found = 0
for (const server of curRecords) {
if (server.id === e.record.id) {
found = newRecords.push(e.record)
} else {
newRecords.push(server)
}
}
if (!found) {
newRecords.push(e.record)
}
}
$store.set(newRecords)
}
export function getPbTimestamp(timeString: ChartTimes, d?: Date) {
d ||= chartTimeData[timeString].getOffset(new Date())
const year = d.getUTCFullYear()
const month = String(d.getUTCMonth() + 1).padStart(2, "0")
const day = String(d.getUTCDate()).padStart(2, "0")
const hours = String(d.getUTCHours()).padStart(2, "0")
const minutes = String(d.getUTCMinutes()).padStart(2, "0")
const seconds = String(d.getUTCSeconds()).padStart(2, "0")
return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`
}
export const chartTimeData: ChartTimeData = { export const chartTimeData: ChartTimeData = {
"1h": { "1h": {
type: "1m", type: "1m",
@@ -193,32 +108,6 @@ export const chartTimeData: ChartTimeData = {
}, },
} }
/** Sets the correct width of the y axis in recharts based on the longest label */
export function useYAxisWidth() {
const [yAxisWidth, setYAxisWidth] = useState(0)
let maxChars = 0
let timeout: Timer
function updateYAxisWidth(str: string) {
if (str.length > maxChars) {
maxChars = str.length
const div = document.createElement("div")
div.className = "text-xs tabular-nums tracking-tighter table sr-only"
div.innerHTML = str
clearTimeout(timeout)
timeout = setTimeout(() => {
document.body.appendChild(div)
const width = div.offsetWidth + 24
if (width > yAxisWidth) {
setYAxisWidth(div.offsetWidth + 24)
}
document.body.removeChild(div)
})
}
return str
}
return { yAxisWidth, updateYAxisWidth }
}
/** Format number to x decimal places, without trailing zeros */ /** Format number to x decimal places, without trailing zeros */
export function toFixedFloat(num: number, digits: number) { export function toFixedFloat(num: number, digits: number) {
return parseFloat((digits === 0 ? Math.ceil(num) : num).toFixed(digits)) return parseFloat((digits === 0 ? Math.ceil(num) : num).toFixed(digits))
@@ -241,20 +130,20 @@ export function decimalString(num: number, digits = 2) {
return formatter.format(num) return formatter.format(num)
} }
/** Get value from local storage */ /** Get value from local or session storage */
function getStorageValue(key: string, defaultValue: any) { function getStorageValue(key: string, defaultValue: any, storageInterface: Storage = localStorage) {
const saved = localStorage?.getItem(key) const saved = storageInterface?.getItem(key)
return saved ? JSON.parse(saved) : defaultValue return saved ? JSON.parse(saved) : defaultValue
} }
/** Hook to sync value in local storage */ /** Hook to sync value in local or session storage */
export function useLocalStorage<T>(key: string, defaultValue: T) { export function useBrowserStorage<T>(key: string, defaultValue: T, storageInterface: Storage = localStorage) {
key = `besz-${key}` key = `besz-${key}`
const [value, setValue] = useState(() => { const [value, setValue] = useState(() => {
return getStorageValue(key, defaultValue) return getStorageValue(key, defaultValue, storageInterface)
}) })
useEffect(() => { useEffect(() => {
localStorage?.setItem(key, JSON.stringify(value)) storageInterface?.setItem(key, JSON.stringify(value))
}, [key, value]) }, [key, value])
return [value, setValue] return [value, setValue]
@@ -329,24 +218,6 @@ export function formatBytes(
} }
} }
/** Fetch or create user settings in database */
export async function updateUserSettings() {
try {
const req = await pb.collection("user_settings").getFirstListItem("", { fields: "settings" })
$userSettings.set(req.settings)
return
} catch (e) {
console.error("get settings", e)
}
// create user settings if error fetching existing
try {
const createdSettings = await pb.collection("user_settings").create({ user: pb.authStore.record!.id })
$userSettings.set(createdSettings.settings)
} catch (e) {
console.error("create settings", e)
}
}
export const chartMargin = { top: 12 } export const chartMargin = { top: 12 }
/** /**
@@ -357,6 +228,21 @@ export const chartMargin = { top: 12 }
*/ */
export const getHostDisplayValue = (system: SystemRecord): string => system.host.slice(system.host.lastIndexOf("/") + 1) export const getHostDisplayValue = (system: SystemRecord): string => system.host.slice(system.host.lastIndexOf("/") + 1)
// export function formatUptimeString(uptimeSeconds: number): string {
// if (!uptimeSeconds || isNaN(uptimeSeconds)) return ""
// if (uptimeSeconds < 3600) {
// const minutes = Math.trunc(uptimeSeconds / 60)
// return plural({ minutes }, { one: "# minute", other: "# minutes" })
// } else if (uptimeSeconds < 172800) {
// const hours = Math.trunc(uptimeSeconds / 3600)
// console.log(hours)
// return plural({ hours }, { one: "# hour", other: "# hours" })
// } else {
// const days = Math.trunc(uptimeSeconds / 86400)
// return plural({ days }, { one: "# day", other: "# days" })
// }
// }
/** Generate a random token for the agent */ /** Generate a random token for the agent */
export const generateToken = () => { export const generateToken = () => {
try { try {
@@ -436,15 +322,20 @@ export function debounce<T extends (...args: any[]) => any>(func: T, wait: numbe
} }
} }
/* returns the name of a system from its id */ // Cache for runOnce
export const getSystemNameFromId = (() => { const runOnceCache = new WeakMap<Function, { done: boolean; result: unknown }>()
const cache = new Map<string, string>() /** Run a function only once */
return (systemId: string): string => { export function runOnce<T extends (...args: any[]) => any>(fn: T): T {
if (cache.has(systemId)) { return ((...args: Parameters<T>) => {
return cache.get(systemId)! let state = runOnceCache.get(fn)
if (!state) {
state = { done: false, result: undefined }
runOnceCache.set(fn, state)
} }
const sysName = $systems.get().find((s) => s.id === systemId)?.name ?? "" if (!state.done) {
cache.set(systemId, sysName) state.result = fn(...args)
return sysName state.done = true
} }
})() return state.result
}) as T
}

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ar\n" "Language: ar\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Arabic\n" "Language-Team: Arabic\n"
"Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n" "Plural-Forms: nplurals=6; plural=(n==0 ? 0 : n==1 ? 1 : n==2 ? 2 : n%100>=3 && n%100<=10 ? 3 : n%100>=11 && n%100<=99 ? 4 : 5);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# يوم} other {# أيام}}" msgstr "{0, plural, one {# يوم} other {# أيام}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# ساعة} other {# ساعات}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# دقيقة} few {# دقائق} many {# دقيقة} other {# دقيقة}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "تم تحديد {0} من {1} صف" msgstr "تم تحديد {0} من {1} صف"
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# ساعة} other {# ساعات}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 ساعة" msgstr "1 ساعة"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "5 دقائق" msgstr "5 دقائق"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "إجراءات" msgstr "إجراءات"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "وكيل" msgstr "وكيل"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "سجل التنبيهات" msgstr "سجل التنبيهات"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "التنبيهات" msgstr "التنبيهات"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "جميع الأنظمة" msgstr "جميع الأنظمة"
@@ -148,8 +155,8 @@ msgstr "متوسط"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "متوسط استخدام وحدة المعالجة المركزية للحاويات" msgstr "متوسط استخدام وحدة المعالجة المركزية للحاويات"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "المتوسط يتجاوز <0>{value}{0}</0>" msgstr "المتوسط يتجاوز <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "متوسط استخدام وحدة المعالجة المركزية ع
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "متوسط ​​استخدام {0}" msgstr "متوسط ​​استخدام {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "النسخ الاحتياطية" msgstr "النسخ الاحتياطية"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "عرض النطاق الترددي" msgstr "عرض النطاق الترددي"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "البطارية"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "يدعم بيزيل بروتوكول OpenID Connect والعديد من مزوّدي المصادقة عبر بروتوكول OAuth2." msgstr "يدعم بيزيل بروتوكول OpenID Connect والعديد من مزوّدي المصادقة عبر بروتوكول OAuth2."
@@ -202,8 +213,8 @@ msgstr "بايت (كيلوبايت/ثانية، ميجابايت/ثانية، ج
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "ذاكرة التخزين المؤقت / المخازن المؤقتة" msgstr "ذاكرة التخزين المؤقت / المخازن المؤقتة"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "إلغاء" msgstr "إلغاء"
@@ -223,6 +234,15 @@ msgstr "تغيير وحدات عرض المقاييس."
msgid "Change general application options." msgid "Change general application options."
msgstr "تغيير خيارات التطبيق العامة." msgstr "تغيير خيارات التطبيق العامة."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "الشحن"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "قيد الشحن"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "خيارات الرسم البياني" msgstr "خيارات الرسم البياني"
@@ -239,6 +259,10 @@ msgstr "تحقق من السجلات لمزيد من التفاصيل."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "تحقق من خدمة الإشعارات الخاصة بك" msgstr "تحقق من خدمة الإشعارات الخاصة بك"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr "انقر على نظام لعرض مزيد من المعلومات."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "انقر للنسخ" msgstr "انقر للنسخ"
@@ -261,8 +285,8 @@ msgstr "تأكيد كلمة المرور"
msgid "Connection is down" msgid "Connection is down"
msgstr "الاتصال مقطوع" msgstr "الاتصال مقطوع"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "متابعة" msgstr "متابعة"
@@ -320,9 +344,9 @@ msgstr "نسخ YAML"
msgid "CPU" msgid "CPU"
msgstr "المعالج" msgstr "المعالج"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "استخدام وحدة المعالجة المركزية" msgstr "استخدام وحدة المعالجة المركزية"
@@ -339,10 +363,10 @@ msgstr "أنشئت"
msgid "Critical (%)" msgid "Critical (%)"
msgstr "حرج (%)" msgstr "حرج (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "داكن" msgstr "الحالة الحالية"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "لوحة التحكم"
msgid "Default time period" msgid "Default time period"
msgstr "الفترة الزمنية الافتراضية" msgstr "الفترة الزمنية الافتراضية"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "حذف" msgstr "حذف"
@@ -362,6 +386,11 @@ msgstr "حذف"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "حذف البصمة" msgstr "حذف البصمة"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "قيد التفريغ"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "القرص" msgstr "القرص"
@@ -374,9 +403,9 @@ msgstr "إدخال/إخراج القرص"
msgid "Disk unit" msgid "Disk unit"
msgstr "وحدة القرص" msgstr "وحدة القرص"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "استخدام القرص" msgstr "استخدام القرص"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "التوثيق" msgstr "التوثيق"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "معطل" msgstr "معطل"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "معطل ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "المدة" msgstr "المدة"
@@ -417,8 +450,8 @@ msgstr "المدة"
msgid "Edit" msgid "Edit"
msgstr "تعديل" msgstr "تعديل"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "البريد الإشباكي" msgstr "البريد الإشباكي"
@@ -426,6 +459,11 @@ msgstr "البريد الإشباكي"
msgid "Email notifications" msgid "Email notifications"
msgstr "إشعارات البريد الإشباكي" msgstr "إشعارات البريد الإشباكي"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "فارغة"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "أدخل عنوان البريد الإشباكي لإعادة تعيين كلمة المرور" msgstr "أدخل عنوان البريد الإشباكي لإعادة تعيين كلمة المرور"
@@ -434,11 +472,11 @@ msgstr "أدخل عنوان البريد الإشباكي لإعادة تعيي
msgid "Enter email address..." msgid "Enter email address..."
msgstr "أدخل عنوان البريد الإشباكي..." msgstr "أدخل عنوان البريد الإشباكي..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "خطأ" msgstr "خطأ"
@@ -469,12 +507,12 @@ msgstr "تصدير تكوين الأنظمة الحالية الخاصة بك."
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "فهرنهايت (°ف)" msgstr "فهرنهايت (°ف)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "فشل في المصادقة" msgstr "فشل في المصادقة"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "فشل في حفظ الإعدادات" msgstr "فشل في حفظ الإعدادات"
@@ -482,13 +520,13 @@ msgstr "فشل في حفظ الإعدادات"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "فشل في إرسال إشعار الاختبار" msgstr "فشل في إرسال إشعار الاختبار"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "فشل في تحديث التنبيه" msgstr "فشل في تحديث التنبيه"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "تصفية..." msgstr "تصفية..."
@@ -496,7 +534,7 @@ msgstr "تصفية..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "البصمة" msgstr "البصمة"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "لمدة <0>{min}</0> {min, plural, one {دقيقة} other {دقائق}}" msgstr "لمدة <0>{min}</0> {min, plural, one {دقيقة} other {دقائق}}"
@@ -504,9 +542,14 @@ msgstr "لمدة <0>{min}</0> {min, plural, one {دقيقة} other {دقائق}}
msgid "Forgot password?" msgid "Forgot password?"
msgstr "هل نسيت كلمة المرور؟" msgstr "هل نسيت كلمة المرور؟"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "ممتلئة"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "عام" msgstr "عام"
@@ -528,6 +571,11 @@ msgstr "أمر Homebrew"
msgid "Host / IP" msgid "Host / IP"
msgstr "مضيف / IP" msgstr "مضيف / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "خاملة"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." msgid "If you've lost the password to your admin account, you may reset it using the following command."
msgstr "إذا فقدت كلمة المرور لحساب المسؤول الخاص بك، يمكنك إعادة تعيينها باستخدام الأمر التالي." msgstr "إذا فقدت كلمة المرور لحساب المسؤول الخاص بك، يمكنك إعادة تعيينها باستخدام الأمر التالي."
@@ -549,24 +597,19 @@ msgstr "اللغة"
msgid "Layout" msgid "Layout"
msgstr "التخطيط" msgstr "التخطيط"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "فاتح"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "متوسط التحميل" msgstr "متوسط التحميل"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "متوسط التحميل 15 دقيقة" msgstr "متوسط التحميل 15 دقيقة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "متوسط التحميل 1 دقيقة" msgstr "متوسط التحميل 1 دقيقة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "متوسط التحميل 5 دقائق" msgstr "متوسط التحميل 5 دقائق"
@@ -583,13 +626,13 @@ msgstr "تسجيل الخروج"
msgid "Login" msgid "Login"
msgstr "تسجيل الدخول" msgstr "تسجيل الدخول"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "فشل محاولة تسجيل الدخول" msgstr "فشل محاولة تسجيل الدخول"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "السجلات" msgstr "السجلات"
@@ -614,8 +657,8 @@ msgstr "الحد الأقصى دقيقة"
msgid "Memory" msgid "Memory"
msgstr "الذاكرة" msgstr "الذاكرة"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "استخدام الذاكرة" msgstr "استخدام الذاكرة"
@@ -623,8 +666,8 @@ msgstr "استخدام الذاكرة"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "استخدام الذاكرة لحاويات دوكر" msgstr "استخدام الذاكرة لحاويات دوكر"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "الاسم" msgstr "الاسم"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "لم يتم العثور على أنظمة." msgstr "لم يتم العثور على أنظمة."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "الإشعارات" msgstr "الإشعارات"
@@ -672,9 +715,9 @@ msgstr "دعم OAuth 2 / OIDC"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "في كل إعادة تشغيل، سيتم تحديث الأنظمة في قاعدة البيانات لتتطابق مع الأنظمة المعرفة في الملف." msgstr "في كل إعادة تشغيل، سيتم تحديث الأنظمة في قاعدة البيانات لتتطابق مع الأنظمة المعرفة في الملف."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "فتح القائمة" msgstr "فتح القائمة"
@@ -682,7 +725,7 @@ msgstr "فتح القائمة"
msgid "Or continue with" msgid "Or continue with"
msgstr "أو المتابعة باستخدام" msgstr "أو المتابعة باستخدام"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "الكتابة فوق التنبيهات الحالية" msgstr "الكتابة فوق التنبيهات الحالية"
@@ -725,16 +768,20 @@ msgstr "إيقاف مؤقت"
msgid "Paused" msgid "Paused"
msgstr "متوقف مؤقتا" msgstr "متوقف مؤقتا"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "متوقف مؤقتا ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "يرجى <0>تكوين خادم SMTP</0> لضمان تسليم التنبيهات." msgstr "يرجى <0>تكوين خادم SMTP</0> لضمان تسليم التنبيهات."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "يرجى التحقق من السجلات لمزيد من التفاصيل." msgstr "يرجى التحقق من السجلات لمزيد من التفاصيل."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "يرجى التحقق من بيانات الاعتماد الخاصة بك والمحاولة مرة أخرى" msgstr "يرجى التحقق من بيانات الاعتماد الخاصة بك والمحاولة مرة أخرى"
@@ -746,7 +793,7 @@ msgstr "يرجى إنشاء حساب مسؤول"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "يرجى تمكين النوافذ المنبثقة لهذا الموقع" msgstr "يرجى تمكين النوافذ المنبثقة لهذا الموقع"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "يرجى تسجيل الدخول مرة أخرى" msgstr "يرجى تسجيل الدخول مرة أخرى"
@@ -812,8 +859,8 @@ msgstr "صفوف لكل صفحة"
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "احفظ العنوان باستخدام مفتاح الإدخال أو الفاصلة. اتركه فارغًا لتعطيل إشعارات البريد الإشباكي." msgstr "احفظ العنوان باستخدام مفتاح الإدخال أو الفاصلة. اتركه فارغًا لتعطيل إشعارات البريد الإشباكي."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "حفظ الإعدادات" msgstr "حفظ الإعدادات"
@@ -829,7 +876,7 @@ msgstr "بحث"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "البحث عن الأنظمة أو الإعدادات..." msgstr "البحث عن الأنظمة أو الإعدادات..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "راجع <0>إعدادات الإشعارات</0> لتكوين كيفية تلقي التنبيهات." msgstr "راجع <0>إعدادات الإشعارات</0> لتكوين كيفية تلقي التنبيهات."
@@ -873,7 +920,8 @@ msgstr "الترتيب حسب"
msgid "State" msgid "State"
msgstr "الحالة" msgstr "الحالة"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "الحالة" msgstr "الحالة"
@@ -885,12 +933,10 @@ msgstr "مساحة التبديل المستخدمة من قبل النظام"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "استخدام التبديل" msgstr "استخدام التبديل"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "النظام" msgstr "النظام"
@@ -915,8 +961,8 @@ msgstr "جدول"
msgid "Temp" msgid "Temp"
msgstr "درجة الحرارة" msgstr "درجة الحرارة"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "درجة الحرارة" msgstr "درجة الحرارة"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "رمز مميز" msgstr "رمز مميز"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "الرموز المميزة والبصمات" msgstr "الرموز المميزة والبصمات"
@@ -988,39 +1034,39 @@ msgstr "تسمح الرموز المميزة للوكلاء بالاتصال و
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "تُستخدم الرموز المميزة والبصمات للمصادقة على اتصالات WebSocket إلى المحور." msgstr "تُستخدم الرموز المميزة والبصمات للمصادقة على اتصالات WebSocket إلى المحور."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "يتم التفعيل عندما يتجاوز متوسط التحميل لمدة دقيقة واحدة عتبة معينة" msgstr "يتم التفعيل عندما يتجاوز متوسط التحميل لمدة دقيقة واحدة عتبة معينة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "يتم التفعيل عندما يتجاوز متوسط التحميل لمدة 15 دقيقة عتبة معينة" msgstr "يتم التفعيل عندما يتجاوز متوسط التحميل لمدة 15 دقيقة عتبة معينة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "يتم التفعيل عندما يتجاوز متوسط التحميل لمدة 5 دقائق عتبة معينة" msgstr "يتم التفعيل عندما يتجاوز متوسط التحميل لمدة 5 دقائق عتبة معينة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "يتم التفعيل عندما يتجاوز أي مستشعر عتبة معينة" msgstr "يتم التفعيل عندما <EFBFBD><EFBFBD>تجاوز أي مستشعر عتبة معينة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "يتم التفعيل عندما يتجاوز الجمع بين الصعود/الهبوط عتبة معينة" msgstr "يتم التفعيل عندما يتجاوز الجمع بين الصعود/الهبوط عتبة معينة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "يتم التفعيل عندما يتجاوز استخدام وحدة المعالجة المركزية عتبة معينة" msgstr "يتم التفعيل عندما يتجاوز استخدام وحدة المعالجة المركزية عتبة معينة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "يتم التفعيل عندما يتجاوز استخدام الذاكرة عتبة معينة" msgstr "يتم التفعيل عندما يتجاوز استخدام الذاكرة عتبة معينة"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "يتم التفعيل عندما يتغير الحالة بين التشغيل والإيقاف" msgstr "يتم التفعيل عندما يتغير الحالة بين التشغيل والإيقاف"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "يتم التفعيل عندما يتجاوز استخدام أي قرص عتبة معينة" msgstr "يتم التفعيل عندما يتجاوز استخدام أي قرص عتبة معينة"
@@ -1029,19 +1075,25 @@ msgstr "يتم التفعيل عندما يتجاوز استخدام أي قرص
msgid "Unit preferences" msgid "Unit preferences"
msgstr "تفضيلات الوحدة" msgstr "تفضيلات الوحدة"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "رمز مميز عالمي" msgstr "رمز مميز عالمي"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "غير معروفة"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "قيد التشغيل" msgstr "قيد التشغيل"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "محدث في الوقت الحقيقي. انقر على نظام لعرض المعلومات." msgstr "قيد التشغيل ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "الاستخدام"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "استخدام القسم الجذر" msgstr "استخدام القسم الجذر"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "مستخدم" msgstr "مستخدم"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "المستخدمون" msgstr "المستخدمون"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: bg\n" "Language: bg\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Bulgarian\n" "Language-Team: Bulgarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -23,15 +23,21 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# ден} other {# дни}}" msgstr "{0, plural, one {# ден} other {# дни}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# час} other {# часа}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# минута} few {# минути} many {# минути} other {# минути}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr "{0} от {1} селектирани."
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# час} other {# часа}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
@@ -40,7 +46,7 @@ msgstr "1 час"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "1 min" msgid "1 min"
msgstr "" msgstr "1 минута"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 week" msgid "1 week"
@@ -53,7 +59,7 @@ msgstr "12 часа"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "15 min" msgid "15 min"
msgstr "" msgstr "15 минути"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "24 hours" msgid "24 hours"
@@ -66,18 +72,18 @@ msgstr "30 дни"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "5 min" msgid "5 min"
msgstr "" msgstr "5 минути"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Действия" msgstr "Действия"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Active" msgid "Active"
msgstr "" msgstr "Активен"
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
msgid "Active Alerts" msgid "Active Alerts"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Агент" msgstr "Агент"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "" msgstr "История на нотификациите"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Тревоги" msgstr "Тревоги"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Всички системи" msgstr "Всички системи"
@@ -134,7 +141,7 @@ msgstr "Сигурен ли си, че искаш да изтриеш {name}?"
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Are you sure?" msgid "Are you sure?"
msgstr "" msgstr "Сигурни ли сте?"
#: src/components/copy-to-clipboard.tsx #: src/components/copy-to-clipboard.tsx
msgid "Automatic copy requires a secure context." msgid "Automatic copy requires a secure context."
@@ -148,8 +155,8 @@ msgstr "Средно"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Средно използване на процесора на контейнерите" msgstr "Средно използване на процесора на контейнерите"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "Средната стойност надхвърля <0>{value}{0}</0>" msgstr "Средната стойност надхвърля <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Средно използване на процесора на цяла
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Средно използване на {0}" msgstr "Средно използване на {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Архиви" msgstr "Архиви"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Bandwidth на мрежата" msgstr "Bandwidth на мрежата"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Батерия"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel поддържа OpenID Connect и много други OAuth2 доставчици за удостоверяване." msgstr "Beszel поддържа OpenID Connect и много други OAuth2 доставчици за удостоверяване."
@@ -191,19 +202,19 @@ msgstr "Двоичен код"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)" msgid "Bits (Kbps, Mbps, Gbps)"
msgstr "" msgstr "Бита (Kbps, Mbps, Gbps)"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)" msgid "Bytes (KB/s, MB/s, GB/s)"
msgstr "" msgstr "Байта (KB/s, MB/s, GB/s)"
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Кеш / Буфери" msgstr "Кеш / Буфери"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Откажи" msgstr "Откажи"
@@ -213,16 +224,25 @@ msgstr "Внимание - възможност за загуба на данн
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Celsius (°C)" msgid "Celsius (°C)"
msgstr "" msgstr "Целзий (°C)"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Change display units for metrics." msgid "Change display units for metrics."
msgstr "" msgstr "Промяна на единиците за показване на метриките."
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Change general application options." msgid "Change general application options."
msgstr "Смени общите опции на приложението." msgstr "Смени общите опции на приложението."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Заряд"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Зареждане"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Опции на диаграмата" msgstr "Опции на диаграмата"
@@ -239,6 +259,10 @@ msgstr "Провери log-овете за повече информация."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Провери услугата си за удостоверяване" msgstr "Провери услугата си за удостоверяване"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr "Кликнете върху система, за да видите повече информация."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Настисни за да копираш" msgstr "Настисни за да копираш"
@@ -259,10 +283,10 @@ msgstr "Потвърди парола"
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
msgid "Connection is down" msgid "Connection is down"
msgstr "" msgstr "Връзката е прекъсната"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Продължи" msgstr "Продължи"
@@ -285,7 +309,7 @@ msgstr "Копирай docker run"
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgctxt "Environment variables" msgctxt "Environment variables"
msgid "Copy env" msgid "Copy env"
msgstr "" msgstr "Копирай еnv"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Copy host" msgid "Copy host"
@@ -306,23 +330,23 @@ msgstr "Копирай текста"
#: src/components/add-system.tsx #: src/components/add-system.tsx
msgid "Copy the installation command for the agent below, or register agents automatically with a <0>universal token</0>." msgid "Copy the installation command for the agent below, or register agents automatically with a <0>universal token</0>."
msgstr "" msgstr "Копирайте командата за инсталиране на агента по-долу или регистрирайте агентите автоматично с <0>универсален токен</0>."
#: src/components/add-system.tsx #: 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>." 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 "Копирайте съдържанието на<0>docker-compose.yml</0> за агента по-долу или регистрирайте агентите автоматично с <1>универсален токен</1>."
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Copy YAML" msgid "Copy YAML"
msgstr "" msgstr "Копирай YAML"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "CPU" msgid "CPU"
msgstr "Процесор" msgstr "Процесор"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "Употреба на процесор" msgstr "Употреба на процесор"
@@ -333,16 +357,16 @@ msgstr "Създай акаунт"
#. Context: date created #. Context: date created
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Created" msgid "Created"
msgstr "" msgstr "Създаден"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Критично (%)" msgstr "Критично (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Тъмно" msgstr "Текущо състояние"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,14 +377,19 @@ msgstr "Табло"
msgid "Default time period" msgid "Default time period"
msgstr "Времеви диапазон по подразбиране" msgstr "Времеви диапазон по подразбиране"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Изтрий" msgstr "Изтрий"
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "" msgstr "Изтрий пръстов отпечатък"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Разреждане"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
@@ -372,11 +401,11 @@ msgstr "Диск I/O"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Disk unit" msgid "Disk unit"
msgstr "" msgstr "Единица за диск"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Използване на диск" msgstr "Използване на диск"
@@ -401,24 +430,28 @@ msgid "Documentation"
msgstr "Документация" msgstr "Документация"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "" msgstr "Офлайн"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Офлайн ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "" msgstr "Продължителност"
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Edit" msgid "Edit"
msgstr "" msgstr "Редактирай"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Имейл" msgstr "Имейл"
@@ -426,6 +459,11 @@ msgstr "Имейл"
msgid "Email notifications" msgid "Email notifications"
msgstr "Имейл нотификации" msgstr "Имейл нотификации"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Празна"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Въведи имейл адрес за да нулираш паролата" msgstr "Въведи имейл адрес за да нулираш паролата"
@@ -434,11 +472,11 @@ msgstr "Въведи имейл адрес за да нулираш парола
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Въведи имейл адрес..." msgstr "Въведи имейл адрес..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Грешка" msgstr "Грешка"
@@ -455,7 +493,7 @@ msgstr "Съществуващи системи които не са дефин
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Export" msgid "Export"
msgstr "" msgstr "Експортиране"
#: src/components/routes/settings/config-yaml.tsx #: src/components/routes/settings/config-yaml.tsx
msgid "Export configuration" msgid "Export configuration"
@@ -467,14 +505,14 @@ msgstr "Експортирай конфигурацията на системи
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "" msgstr "Фаренхайт (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Неуспешно удостоверяване" msgstr "Неуспешно удостоверяване"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Неуспешно запазване на настройки" msgstr "Неуспешно запазване на настройки"
@@ -482,21 +520,21 @@ msgstr "Неуспешно запазване на настройки"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Неуспешно изпрати тестова нотификация" msgstr "Неуспешно изпрати тестова нотификация"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Неуспешно обнови тревога" msgstr "Неуспешно обнови тревога"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Филтрирай..." msgstr "Филтрирай..."
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Fingerprint" msgid "Fingerprint"
msgstr "" msgstr "Пръстов отпечатък"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "За <0>{min}</0> {min, plural, one {минута} other {минути}}" msgstr "За <0>{min}</0> {min, plural, one {минута} other {минути}}"
@@ -504,9 +542,14 @@ msgstr "За <0>{min}</0> {min, plural, one {минута} other {минути}}
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Забравена парола?" msgstr "Забравена парола?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Пълна"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Общо" msgstr "Общо"
@@ -528,6 +571,11 @@ msgstr "Команда Homebrew"
msgid "Host / IP" msgid "Host / IP"
msgstr "Хост / IP" msgstr "Хост / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Неактивна"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." msgid "If you've lost the password to your admin account, you may reset it using the following command."
msgstr "Ако си загубил паролата до администраторския акаунт, можеш да я нулираш със следващата команда." msgstr "Ако си загубил паролата до администраторския акаунт, можеш да я нулираш със следващата команда."
@@ -549,31 +597,26 @@ msgstr "Език"
msgid "Layout" msgid "Layout"
msgstr "Подреждане" msgstr "Подреждане"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Светъл"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "" msgstr "Средно натоварване"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "" msgstr "Средно натоварване 15 минути"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "" msgstr "Средно натоварване 1 минута"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "" msgstr "Средно натоварване 5 минути"
#. Short label for load average #. Short label for load average
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Load Avg" msgid "Load Avg"
msgstr "" msgstr "Средно натоварване"
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Log Out" msgid "Log Out"
@@ -583,13 +626,13 @@ msgstr "Изход"
msgid "Login" msgid "Login"
msgstr "Вход" msgstr "Вход"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Неуспешен опит за вход" msgstr "Неуспешен опит за вход"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Логове" msgstr "Логове"
@@ -603,7 +646,7 @@ msgstr "Управление на предпочитанията за показ
#: src/components/add-system.tsx #: src/components/add-system.tsx
msgid "Manual setup instructions" msgid "Manual setup instructions"
msgstr "" msgstr "Инструкции за ръчна настройка"
#. Chart select field. Please try to keep this short. #. Chart select field. Please try to keep this short.
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
@@ -614,8 +657,8 @@ msgstr "Максимум 1 минута"
msgid "Memory" msgid "Memory"
msgstr "Памет" msgstr "Памет"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Употреба на паметта" msgstr "Употреба на паметта"
@@ -623,8 +666,8 @@ msgstr "Употреба на паметта"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Използването на памет от docker контейнерите" msgstr "Използването на памет от docker контейнерите"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Име" msgstr "Име"
@@ -643,7 +686,7 @@ msgstr "Мрежов трафик на публични интерфейси"
#. Context: Bytes or bits #. Context: Bytes or bits
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Network unit" msgid "Network unit"
msgstr "" msgstr "Единица за измерване на скорост"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
msgid "No results found." msgid "No results found."
@@ -651,7 +694,7 @@ msgstr "Няма намерени резултати."
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "No results." msgid "No results."
msgstr "" msgstr "Няма резултати."
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Няма намерени системи." msgstr "Няма намерени системи."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Нотификации" msgstr "Нотификации"
@@ -672,9 +715,9 @@ msgstr "Поддръжка на OAuth 2 / OIDC"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "На всеки рестарт, системите в датабазата ще бъдат обновени да съвпадат със системите зададени във файла." msgstr "На всеки рестарт, системите в датабазата ще бъдат обновени да съвпадат със системите зададени във файла."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Отвори менюто" msgstr "Отвори менюто"
@@ -682,7 +725,7 @@ msgstr "Отвори менюто"
msgid "Or continue with" msgid "Or continue with"
msgstr "Или продължи с" msgstr "Или продължи с"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Презапиши съществуващи тревоги" msgstr "Презапиши съществуващи тревоги"
@@ -694,7 +737,7 @@ msgstr "Страница"
#. placeholder {1}: table.getPageCount() #. placeholder {1}: table.getPageCount()
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Page {0} of {1}" msgid "Page {0} of {1}"
msgstr "" msgstr "Страница {0} от {1}"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
msgid "Pages / Settings" msgid "Pages / Settings"
@@ -711,7 +754,7 @@ msgstr "Паролата трябва да е поне 8 символа."
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Password must be less than 72 bytes." msgid "Password must be less than 72 bytes."
msgstr "" msgstr "Паролата трябва да е по-малка от 72 байта."
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "Password reset request received" msgid "Password reset request received"
@@ -725,16 +768,20 @@ msgstr "Пауза"
msgid "Paused" msgid "Paused"
msgstr "На пауза" msgstr "На пауза"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "На пауза ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Моля <0>конфигурурай SMTP сървър</0> за да се подсигуриш, че тревогите са доставени." msgstr "Моля <0>конфигурурай SMTP сървър</0> за да се подсигуриш, че тревогите са доставени."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Моля провери log-овете за повече информация." msgstr "Моля провери log-овете за повече информация."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Моля провери дадената информация и опитай отново" msgstr "Моля провери дадената информация и опитай отново"
@@ -746,7 +793,7 @@ msgstr "Моля създай администраторски акаунт"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Моля активирай изскачащите прозорци за този сайт" msgstr "Моля активирай изскачащите прозорци за този сайт"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Моля влез отново" msgstr "Моля влез отново"
@@ -794,7 +841,7 @@ msgstr "Нулиране на парола"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Resolved" msgid "Resolved"
msgstr "" msgstr "Решен"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Resume" msgid "Resume"
@@ -802,24 +849,24 @@ msgstr "Възобнови"
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Rotate token" msgid "Rotate token"
msgstr "" msgstr "Пресъздаване на идентификатора"
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Rows per page" msgid "Rows per page"
msgstr "" msgstr "Редове на страница"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Запази адреса с enter или запетая. Остави празно за да изключиш нотификациите чрез имейл." msgstr "Запази адреса с enter или запетая. Остави празно за да изключиш нотификациите чрез имейл."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Запази настройките" msgstr "Запази настройките"
#: src/components/add-system.tsx #: src/components/add-system.tsx
msgid "Save system" msgid "Save system"
msgstr "" msgstr "Запази система"
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Search" msgid "Search"
@@ -829,7 +876,7 @@ msgstr "Търси"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Търси за системи или настройки..." msgstr "Търси за системи или настройки..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Виж <0>настройките за нотификациите</0> за да конфигурираш как получаваш тревоги." msgstr "Виж <0>настройките за нотификациите</0> за да конфигурираш как получаваш тревоги."
@@ -871,9 +918,10 @@ msgstr "Сортиране по"
#. Context: alert state (active or resolved) #. Context: alert state (active or resolved)
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "State" msgid "State"
msgstr "" msgstr "Състояние"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Статус" msgstr "Статус"
@@ -885,18 +933,16 @@ msgstr "Изполван swap от системата"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Използване на swap" msgstr "Използване на swap"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "Система" msgstr "Система"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "System load averages over time" msgid "System load averages over time"
msgstr "" msgstr "Средно натоварване на системата във времето"
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Systems" msgid "Systems"
@@ -913,16 +959,16 @@ msgstr "Таблица"
#. Temperature label in systems table #. Temperature label in systems table
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Temp" msgid "Temp"
msgstr "" msgstr "Температура"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Температура" msgstr "Температура"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Temperature unit" msgid "Temperature unit"
msgstr "" msgstr "Единица за температура"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Temperatures of system sensors" msgid "Temperatures of system sensors"
@@ -946,7 +992,7 @@ msgstr "Това действие не може да бъде отменено.
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "This will permanently delete all selected records from the database." msgid "This will permanently delete all selected records from the database."
msgstr "" msgstr "Това ще доведе до трайно изтриване на всички избрани записи от базата данни."
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Throughput of {extraFsName}" msgid "Throughput of {extraFsName}"
@@ -972,76 +1018,82 @@ msgstr "Включи тема"
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token" msgid "Token"
msgstr "" msgstr "Токен"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "" msgstr "Токен & Пръстов отпечатък"
#: src/components/routes/settings/tokens-fingerprints.tsx #: 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." msgid "Tokens allow agents to connect and register. Fingerprints are stable identifiers unique to each system, set on first connection."
msgstr "" msgstr "Токените позволяват на агентите да се свързват и регистрират. Отпечатъците са стабилни идентификатори, уникални за всяка система, които се задават при първото свързване."
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "" msgstr "Токените и пръстовите отпечатъци се използват за удостоверяване на WebSocket връзките към концентратора."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "" msgstr "Задейства се, когато употребата на паметта за 1 минута надвиши зададен праг"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "" msgstr "Задейства се, когато употребата на паметта за 15 минута надвиши зададен праг"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "" msgstr "Задейства се, когато употребата на паметта за 5 минута надвиши зададен праг"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Задейства се, когато някой даден сензор надвиши зададен праг" msgstr "Задейства се, когато някой даден сензор надвиши зададен праг"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Задейства се, когато комбинираното качване/сваляне надвиши зададен праг" msgstr "Задейства се, когато комбинираното качване/сваляне надвиши зададен праг"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Задейства се, когато употребата на процесора надвиши зададен праг" msgstr "Задейства се, когато употребата на процесора надвиши зададен праг"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Задейства се, когато употребата на паметта надвиши зададен праг" msgstr "Задейства се, когато употребата на паметта надвиши зададен праг"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Задейства се, когато статуса превключва между долу и горе" msgstr "Задейства се, когато статуса превключва между долу и горе"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Задейства се, когато употребата на някой диск надивши зададен праг" msgstr "Задейства се, когато употребата на някой диск надивши зададен праг"
#. Temperature / network units #. Temperature / network units
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Unit preferences" msgid "Unit preferences"
msgstr "" msgstr "Предпочитания на единицата"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "" msgstr "Универсален тоукън"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Неизвестна"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "" msgstr "Нагоре"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Актуализира се в реално време. Натисни на система за да видиш информация." msgstr "Нагоре ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,19 +1110,19 @@ msgstr "Употреба"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Употреба на root partition-а" msgstr "Употреба на root partition-а"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Използвани" msgstr "Използвани"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Потребители" msgstr "Потребители"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Value" msgid "Value"
msgstr "" msgstr "Стойност"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "View" msgid "View"
@@ -1078,7 +1130,7 @@ msgstr "Изглед"
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts." msgid "View your 200 most recent alerts."
msgstr "" msgstr "Прегледайте последните си 200 сигнала."
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Visible Fields" msgid "Visible Fields"
@@ -1106,7 +1158,7 @@ msgstr "Webhook / Пуш нотификации"
#: src/components/routes/settings/tokens-fingerprints.tsx #: 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." msgid "When enabled, this token allows agents to self-register without prior system creation. Expires after one hour or on hub restart."
msgstr "" msgstr "Когато е активиран, този символ позволява на агентите да се регистрират сами без предварително създаване на система. Изтича след един час или при рестартиране на хъба."
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: cs\n" "Language: cs\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-08-04 01:51\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Czech\n" "Language-Team: Czech\n"
"Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n" "Plural-Forms: nplurals=4; plural=(n==1) ? 0 : (n>=2 && n<=4) ? 1 : 3;\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# den} few {# dny} other {# dní}}" msgstr "{0, plural, one {# den} few {# dny} other {# dní}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# Hodina} few {# Hodiny} many {# Hodin} other {# Hodin}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# minuta} few {# minuty} many {# minut} other {# minut}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "{0} z {1} vybraných řádků." msgstr "{0} z {1} vybraných řádků."
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# Hodina} few {# Hodiny} many {# Hodin} other {# Hodin}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 hodina" msgstr "1 hodina"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "5 min" msgstr "5 min"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Akce" msgstr "Akce"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Agent" msgstr "Agent"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "Historie upozornění" msgstr "Historie upozornění"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Výstrahy" msgstr "Výstrahy"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Všechny systémy" msgstr "Všechny systémy"
@@ -148,8 +155,8 @@ msgstr "Průměr"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Průměrné využití CPU kontejnerů" msgstr "Průměrné využití CPU kontejnerů"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "Průměr je vyšší než <0>{value}{0}</0>" msgstr "Průměr je vyšší než <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Průměrné využití CPU v celém systému"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Průměrné využití {0}" msgstr "Průměrné využití {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Zálohy" msgstr "Zálohy"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Přenos" msgstr "Přenos"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Baterie"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel podporuje OpenID Connect a mnoho poskytovatelů OAuth2 ověřování." msgstr "Beszel podporuje OpenID Connect a mnoho poskytovatelů OAuth2 ověřování."
@@ -202,8 +213,8 @@ msgstr "Bytes (KB/s, MB/s, GB/s)"
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Cache / vyrovnávací paměť" msgstr "Cache / vyrovnávací paměť"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Zrušit" msgstr "Zrušit"
@@ -223,6 +234,15 @@ msgstr "Změnit jednotky zobrazení metrik."
msgid "Change general application options." msgid "Change general application options."
msgstr "Změnit obecné nastavení aplikace." msgstr "Změnit obecné nastavení aplikace."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Nabíjení"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Nabíjení"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Možnosti grafu" msgstr "Možnosti grafu"
@@ -239,6 +259,10 @@ msgstr "Pro více informací zkontrolujte logy."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Zkontrolujte službu upozornění" msgstr "Zkontrolujte službu upozornění"
#: 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í."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Klikněte pro zkopírování" msgstr "Klikněte pro zkopírování"
@@ -261,8 +285,8 @@ msgstr "Potvrdit heslo"
msgid "Connection is down" msgid "Connection is down"
msgstr "Připojení je nedostupné" msgstr "Připojení je nedostupné"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Pokračovat" msgstr "Pokračovat"
@@ -320,9 +344,9 @@ msgstr "Kopírovat YAML"
msgid "CPU" msgid "CPU"
msgstr "Procesor" msgstr "Procesor"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "Využití procesoru" msgstr "Využití procesoru"
@@ -339,10 +363,10 @@ msgstr "Vytvořeno"
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Kritické (%)" msgstr "Kritické (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Tmavý" msgstr "Aktuální stav"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Přehled"
msgid "Default time period" msgid "Default time period"
msgstr "Výchozí doba" msgstr "Výchozí doba"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Odstranit" msgstr "Odstranit"
@@ -362,6 +386,11 @@ msgstr "Odstranit"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "Smazat identifikátor" msgstr "Smazat identifikátor"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Vybíjení"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Disk" msgstr "Disk"
@@ -374,9 +403,9 @@ msgstr "Disk I/O"
msgid "Disk unit" msgid "Disk unit"
msgstr "Disková jednotka" msgstr "Disková jednotka"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Využití disku" msgstr "Využití disku"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "Dokumentace" msgstr "Dokumentace"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "Nefunkční" msgstr "Nefunkční"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Nefunkční ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "Doba trvání" msgstr "Doba trvání"
@@ -417,8 +450,8 @@ msgstr "Doba trvání"
msgid "Edit" msgid "Edit"
msgstr "Upravit" msgstr "Upravit"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -426,6 +459,11 @@ msgstr "Email"
msgid "Email notifications" msgid "Email notifications"
msgstr "Emailová upozornění" msgstr "Emailová upozornění"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Prázdná"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Zadejte e-mailovou adresu pro obnovu hesla" msgstr "Zadejte e-mailovou adresu pro obnovu hesla"
@@ -434,11 +472,11 @@ msgstr "Zadejte e-mailovou adresu pro obnovu hesla"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Zadejte e-mailovou adresu..." msgstr "Zadejte e-mailovou adresu..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Chyba" msgstr "Chyba"
@@ -469,12 +507,12 @@ msgstr "Exportovat aktuální konfiguraci systémů."
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "Fahrenheita (°F)" msgstr "Fahrenheita (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Ověření se nezdařilo" msgstr "Ověření se nezdařilo"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Nepodařilo se uložit nastavení" msgstr "Nepodařilo se uložit nastavení"
@@ -482,13 +520,13 @@ msgstr "Nepodařilo se uložit nastavení"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Nepodařilo se odeslat testovací oznámení" msgstr "Nepodařilo se odeslat testovací oznámení"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Nepodařilo se aktualizovat upozornění" msgstr "Nepodařilo se aktualizovat upozornění"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Filtr..." msgstr "Filtr..."
@@ -496,7 +534,7 @@ msgstr "Filtr..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "Otisk" msgstr "Otisk"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "Za <0>{min}</0> {min, plural, one {minutu} few {minuty} other {minut}}" msgstr "Za <0>{min}</0> {min, plural, one {minutu} few {minuty} other {minut}}"
@@ -504,9 +542,14 @@ msgstr "Za <0>{min}</0> {min, plural, one {minutu} few {minuty} other {minut}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Zapomněli jste heslo?" msgstr "Zapomněli jste heslo?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Plná"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Obecné" msgstr "Obecné"
@@ -528,6 +571,11 @@ msgstr "Homebrew příkaz"
msgid "Host / IP" msgid "Host / IP"
msgstr "Hostitel / IP" msgstr "Hostitel / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Neaktivní"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "Pokud jste ztratili heslo k vašemu účtu správce, můžete jej obnovit pomocí následujícího příkazu."
@@ -549,24 +597,19 @@ msgstr "Jazyk"
msgid "Layout" msgid "Layout"
msgstr "Rozvržení" msgstr "Rozvržení"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Světlý"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "Průměrné vytížení" msgstr "Průměrné vytížení"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "Průměrná zátěž 15m" msgstr "Průměrná zátěž 15m"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "Průměrná zátěž 1m" msgstr "Průměrná zátěž 1m"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "Průměrná zátěž 5m" msgstr "Průměrná zátěž 5m"
@@ -583,13 +626,13 @@ msgstr "Odhlásit"
msgid "Login" msgid "Login"
msgstr "Přihlásit" msgstr "Přihlásit"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Pokus o přihlášení selhal" msgstr "Pokus o přihlášení selhal"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Logy" msgstr "Logy"
@@ -614,8 +657,8 @@ msgstr "Max. 1 min"
msgid "Memory" msgid "Memory"
msgstr "Paměť" msgstr "Paměť"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Využití paměti" msgstr "Využití paměti"
@@ -623,8 +666,8 @@ msgstr "Využití paměti"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Využití paměti docker kontejnerů" msgstr "Využití paměti docker kontejnerů"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Název" msgstr "Název"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Nenalezeny žádné systémy." msgstr "Nenalezeny žádné systémy."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Upozornění" msgstr "Upozornění"
@@ -672,9 +715,9 @@ msgstr "Podpora OAuth 2 / OIDC"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "Při každém restartu budou systémy v databázi aktualizovány tak, aby odpovídaly systémům definovaným v souboru." msgstr "Při každém restartu budou systémy v databázi aktualizovány tak, aby odpovídaly systémům definovaným v souboru."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Otevřít menu" msgstr "Otevřít menu"
@@ -682,7 +725,7 @@ msgstr "Otevřít menu"
msgid "Or continue with" msgid "Or continue with"
msgstr "Nebo pokračujte s" msgstr "Nebo pokračujte s"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Přepsat existující upozornění" msgstr "Přepsat existující upozornění"
@@ -725,16 +768,20 @@ msgstr "Pozastavit"
msgid "Paused" msgid "Paused"
msgstr "Pozastaveno" msgstr "Pozastaveno"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Pozastaveno ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "<0>nakonfigurujte SMTP server</0> pro zajištění toho, aby byla upozornění doručena." msgstr "<0>nakonfigurujte SMTP server</0> pro zajištění toho, aby byla upozornění doručena."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Pro více informací zkontrolujte logy." msgstr "Pro více informací zkontrolujte logy."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Zkontrolujte prosím Vaše přihlašovací údaje a zkuste to znovu" msgstr "Zkontrolujte prosím Vaše přihlašovací údaje a zkuste to znovu"
@@ -746,7 +793,7 @@ msgstr "Vytvořte si prosím účet administrátora"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Prosím povolte vyskakovací okna pro tento web" msgstr "Prosím povolte vyskakovací okna pro tento web"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Přihlaste se prosím znovu" msgstr "Přihlaste se prosím znovu"
@@ -812,8 +859,8 @@ msgstr "Řádků na stránku"
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Adresu uložte pomocí klávesy enter nebo čárky. Pro deaktivaci e-mailových oznámení ponechte prázdné pole." msgstr "Adresu uložte pomocí klávesy enter nebo čárky. Pro deaktivaci e-mailových oznámení ponechte prázdné pole."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Uložit nastavení" msgstr "Uložit nastavení"
@@ -829,7 +876,7 @@ msgstr "Hledat"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Hledat systémy nebo nastavení..." msgstr "Hledat systémy nebo nastavení..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Podívejte se na <0>nastavení upozornění</0> pro nastavení toho, jak přijímáte upozornění." msgstr "Podívejte se na <0>nastavení upozornění</0> pro nastavení toho, jak přijímáte upozornění."
@@ -873,7 +920,8 @@ msgstr "Seřadit podle"
msgid "State" msgid "State"
msgstr "Stav" msgstr "Stav"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Stav" msgstr "Stav"
@@ -885,12 +933,10 @@ msgstr "Swap prostor využívaný systémem"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Swap využití" msgstr "Swap využití"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "Systém" msgstr "Systém"
@@ -915,8 +961,8 @@ msgstr "Tabulka"
msgid "Temp" msgid "Temp"
msgstr "Teplota" msgstr "Teplota"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Teplota" msgstr "Teplota"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "Token" msgstr "Token"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "Tokeny & Otisky" msgstr "Tokeny & Otisky"
@@ -988,39 +1034,39 @@ msgstr "Tokeny umožňují agentům připojení a registraci. Otisky jsou stabil
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "Tokeny a otisky slouží k ověření připojení WebSocket k uzlu." msgstr "Tokeny a otisky slouží k ověření připojení WebSocket k uzlu."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "Spustí se, když využití paměti během 1 minuty překročí prahovou hodnotu" msgstr "Spustí se, když využití paměti během 1 minuty překročí prahovou hodnotu"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "Spustí se, když využití paměti během 15 minut překročí prahovou hodnotu" msgstr "Spustí se, když využití paměti během 15 minut překročí prahovou hodnotu"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "Spustí se, když využití paměti během 5 minut překročí prahovou hodnotu" msgstr "Spustí se, když využití paměti během 5 minut překročí prahovou hodnotu"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Spustí se, když některý senzor překročí prahovou hodnotu" msgstr "Spustí se, když některý senzor překročí prahovou hodnotu"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Spustí se, když kombinace up/down překročí prahovou hodnotu" msgstr "Spustí se, když kombinace up/down překročí prahovou hodnotu"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Spustí se, když využití procesoru překročí prahovou hodnotu" msgstr "Spustí se, když využití procesoru překročí prahovou hodnotu"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Spustí se, když využití paměti překročí prahovou hodnotu" msgstr "Spustí se, když využití paměti překročí prahovou hodnotu"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Spouští se, když se změní dostupnost" msgstr "Spouští se, když se změní dostupnost"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Spustí se, když využití disku překročí prahovou hodnotu" msgstr "Spustí se, když využití disku překročí prahovou hodnotu"
@@ -1029,19 +1075,25 @@ msgstr "Spustí se, když využití disku překročí prahovou hodnotu"
msgid "Unit preferences" msgid "Unit preferences"
msgstr "Předvolby jednotek" msgstr "Předvolby jednotek"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "Univerzální token" msgstr "Univerzální token"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Neznámá"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "Funkční" msgstr "Funkční"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Aktualizováno v reálném čase. Klepnutím na systém zobrazíte informace." msgstr "Funkční ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "Využití"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Využití kořenového oddílu" msgstr "Využití kořenového oddílu"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Využito" msgstr "Využito"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Uživatelé" msgstr "Uživatelé"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: da\n" "Language: da\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Danish\n" "Language-Team: Danish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# day} other {# days}}" msgstr "{0, plural, one {# day} other {# days}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# hour} other {# hours}}"
#. 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 ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr ""
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# hour} other {# hours}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 time" msgstr "1 time"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "" msgstr ""
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Handlinger" msgstr "Handlinger"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Agent" msgstr "Agent"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "" msgstr ""
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Alarmer" msgstr "Alarmer"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Alle systemer" msgstr "Alle systemer"
@@ -148,8 +155,8 @@ msgstr "Gennemsnitlig"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Gennemsnitlig CPU udnyttelse af containere" msgstr "Gennemsnitlig CPU udnyttelse af containere"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "Gennemsnit overstiger <0>{value}{0}</0>" msgstr "Gennemsnit overstiger <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Gennemsnitlig systembaseret CPU-udnyttelse"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Gennemsnitlig udnyttelse af {0}" msgstr "Gennemsnitlig udnyttelse af {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Sikkerhedskopier" msgstr "Sikkerhedskopier"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Båndbredde" msgstr "Båndbredde"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Batteri"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel understøtter OpenID Connect og mange OAuth2 godkendelsesudbydere." msgstr "Beszel understøtter OpenID Connect og mange OAuth2 godkendelsesudbydere."
@@ -202,8 +213,8 @@ msgstr ""
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Cache / Buffere" msgstr "Cache / Buffere"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Fortryd" msgstr "Fortryd"
@@ -223,6 +234,15 @@ msgstr ""
msgid "Change general application options." msgid "Change general application options."
msgstr "Skift generelle applikationsindstillinger." msgstr "Skift generelle applikationsindstillinger."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Opladning"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Oplader"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Diagrammuligheder" msgstr "Diagrammuligheder"
@@ -239,6 +259,10 @@ msgstr "Tjek logfiler for flere detaljer."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Tjek din notifikationstjeneste" msgstr "Tjek din notifikationstjeneste"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr ""
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Klik for at kopiere" msgstr "Klik for at kopiere"
@@ -261,8 +285,8 @@ msgstr "Bekræft adgangskode"
msgid "Connection is down" msgid "Connection is down"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Forsæt" msgstr "Forsæt"
@@ -320,9 +344,9 @@ msgstr ""
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "CPU forbrug" msgstr "CPU forbrug"
@@ -339,10 +363,10 @@ msgstr ""
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Kritisk (%)" msgstr "Kritisk (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Mørk" msgstr "Nuværende tilstand"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Oversigtspanel"
msgid "Default time period" msgid "Default time period"
msgstr "Standard tidsperiode" msgstr "Standard tidsperiode"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Slet" msgstr "Slet"
@@ -362,6 +386,11 @@ msgstr "Slet"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "" msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Aflader"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Disk" msgstr "Disk"
@@ -374,9 +403,9 @@ msgstr "Disk I/O"
msgid "Disk unit" msgid "Disk unit"
msgstr "" msgstr ""
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Diskforbrug" msgstr "Diskforbrug"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "Dokumentation" msgstr "Dokumentation"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "Nede" msgstr "Nede"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr ""
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "" msgstr ""
@@ -417,8 +450,8 @@ msgstr ""
msgid "Edit" msgid "Edit"
msgstr "Rediger" msgstr "Rediger"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "E-mail" msgstr "E-mail"
@@ -426,6 +459,11 @@ msgstr "E-mail"
msgid "Email notifications" msgid "Email notifications"
msgstr "Email-notifikationer" msgstr "Email-notifikationer"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Tom"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Indtast e-mailadresse for at nulstille adgangskoden" msgstr "Indtast e-mailadresse for at nulstille adgangskoden"
@@ -434,11 +472,11 @@ msgstr "Indtast e-mailadresse for at nulstille adgangskoden"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Indtast e-mailadresse..." msgstr "Indtast e-mailadresse..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Fejl" msgstr "Fejl"
@@ -469,12 +507,12 @@ msgstr "Eksporter din nuværende systemkonfiguration."
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Kunne ikke godkende" msgstr "Kunne ikke godkende"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Kunne ikke gemme indstillinger" msgstr "Kunne ikke gemme indstillinger"
@@ -482,13 +520,13 @@ msgstr "Kunne ikke gemme indstillinger"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Afsendelse af testnotifikation mislykkedes" msgstr "Afsendelse af testnotifikation mislykkedes"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Kunne ikke opdatere alarm" msgstr "Kunne ikke opdatere alarm"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Filter..." msgstr "Filter..."
@@ -496,7 +534,7 @@ msgstr "Filter..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "" msgstr ""
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "For <0>{min}</0> {min, plural, one {minut} other {minutter}}" msgstr "For <0>{min}</0> {min, plural, one {minut} other {minutter}}"
@@ -504,9 +542,14 @@ msgstr "For <0>{min}</0> {min, plural, one {minut} other {minutter}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Glemt adgangskode?" msgstr "Glemt adgangskode?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Fuldt opladt"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Generelt" msgstr "Generelt"
@@ -528,6 +571,11 @@ msgstr "Homebrew-kommando"
msgid "Host / IP" msgid "Host / IP"
msgstr "Vært / IP" msgstr "Vært / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Inaktiv"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "Hvis du har mistet adgangskoden til din administratorkonto, kan du nulstille den ved hjælp af følgende kommando."
@@ -549,24 +597,19 @@ msgstr "Sprog"
msgid "Layout" msgid "Layout"
msgstr "Layout" msgstr "Layout"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Lys"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "" msgstr ""
@@ -583,13 +626,13 @@ msgstr "Log ud"
msgid "Login" msgid "Login"
msgstr "Log ind" msgstr "Log ind"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Loginforsøg mislykkedes" msgstr "Loginforsøg mislykkedes"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Logs" msgstr "Logs"
@@ -614,8 +657,8 @@ msgstr "Maks. 1 min"
msgid "Memory" msgid "Memory"
msgstr "Hukommelse" msgstr "Hukommelse"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Hukommelsesforbrug" msgstr "Hukommelsesforbrug"
@@ -623,8 +666,8 @@ msgstr "Hukommelsesforbrug"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Hukommelsesforbrug af dockercontainere" msgstr "Hukommelsesforbrug af dockercontainere"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Navn" msgstr "Navn"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Ingen systemer fundet." msgstr "Ingen systemer fundet."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Notifikationer" msgstr "Notifikationer"
@@ -672,9 +715,9 @@ msgstr "OAuth 2 / OIDC understøttelse"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "Ved hver genstart vil systemer i databasen blive opdateret til at matche de systemer, der er defineret i filen." msgstr "Ved hver genstart vil systemer i databasen blive opdateret til at matche de systemer, der er defineret i filen."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Åbn menu" msgstr "Åbn menu"
@@ -682,7 +725,7 @@ msgstr "Åbn menu"
msgid "Or continue with" msgid "Or continue with"
msgstr "Eller fortsæt med" msgstr "Eller fortsæt med"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Overskriv eksisterende alarmer" msgstr "Overskriv eksisterende alarmer"
@@ -725,16 +768,20 @@ msgstr "Pause"
msgid "Paused" msgid "Paused"
msgstr "Sat på pause" msgstr "Sat på pause"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Konfigurer <0>en SMTP server</0> for at sikre at alarmer bliver leveret." msgstr "Konfigurer <0>en SMTP server</0> for at sikre at alarmer bliver leveret."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Tjek logfiler for flere detaljer." msgstr "Tjek logfiler for flere detaljer."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Tjek dine legitimationsoplysninger og prøv igen" msgstr "Tjek dine legitimationsoplysninger og prøv igen"
@@ -746,7 +793,7 @@ msgstr "Opret venligst en administratorkonto"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Aktiver pop-ups for dette websted" msgstr "Aktiver pop-ups for dette websted"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Log venligst ind igen" msgstr "Log venligst ind igen"
@@ -812,8 +859,8 @@ msgstr ""
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Gem adresse ved hjælp af enter eller komma. Lad feltet stå tomt for at deaktivere e-mail-meddelelser." msgstr "Gem adresse ved hjælp af enter eller komma. Lad feltet stå tomt for at deaktivere e-mail-meddelelser."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Gem indstillinger" msgstr "Gem indstillinger"
@@ -829,7 +876,7 @@ msgstr "Søg"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Søg efter systemer eller indstillinger..." msgstr "Søg efter systemer eller indstillinger..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Se <0>meddelelsesindstillinger</0> for at konfigurere, hvordan du modtager alarmer." msgstr "Se <0>meddelelsesindstillinger</0> for at konfigurere, hvordan du modtager alarmer."
@@ -873,7 +920,8 @@ msgstr "Sorter efter"
msgid "State" msgid "State"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Status"
@@ -885,12 +933,10 @@ msgstr "Swap plads brugt af systemet"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Swap forbrug" msgstr "Swap forbrug"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "System" msgstr "System"
@@ -915,8 +961,8 @@ msgstr "Tabel"
msgid "Temp" msgid "Temp"
msgstr "Temperatur" msgstr "Temperatur"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Temperatur" msgstr "Temperatur"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "" msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "" msgstr ""
@@ -988,39 +1034,39 @@ msgstr ""
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Udløser når en sensor overstiger en tærskel" msgstr "Udløser når en sensor overstiger en tærskel"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Udløses når de kombinerede op/ned overstiger en tærskel" msgstr "Udløses når de kombinerede op/ned overstiger en tærskel"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Udløser når CPU-forbrug overstiger en tærskel" msgstr "Udløser når CPU-forbrug overstiger en tærskel"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Udløser når hukommelsesforbruget overstiger en tærskel" msgstr "Udløser når hukommelsesforbruget overstiger en tærskel"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Udløser når status skifter mellem op og ned" msgstr "Udløser når status skifter mellem op og ned"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Udløser når brugen af en disk overstiger en tærskel" msgstr "Udløser når brugen af en disk overstiger en tærskel"
@@ -1029,19 +1075,25 @@ msgstr "Udløser når brugen af en disk overstiger en tærskel"
msgid "Unit preferences" msgid "Unit preferences"
msgstr "" msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "" msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Ukendt"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "Oppe" msgstr "Oppe"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Opdateret i realtid. Klik på et system for at se information." msgstr ""
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "Forbrug"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Brug af rodpartition" msgstr "Brug af rodpartition"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Brugt" msgstr "Brugt"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Brugere" msgstr "Brugere"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: de\n" "Language: de\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: German\n" "Language-Team: German\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# Tag} other {# Tage}}" msgstr "{0, plural, one {# Tag} other {# Tage}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# Stunde} other {# Stunden}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# Minute} other {# Minuten}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "{0} von {1} Zeile(n) ausgewählt." msgstr "{0} von {1} Zeile(n) ausgewählt."
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# Stunde} other {# Stunden}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 Stunde" msgstr "1 Stunde"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "5 Min" msgstr "5 Min"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Aktionen" msgstr "Aktionen"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Agent" msgstr "Agent"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "Alarm-Verlauf" msgstr "Alarm-Verlauf"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Warnungen" msgstr "Warnungen"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Alle Systeme" msgstr "Alle Systeme"
@@ -148,8 +155,8 @@ msgstr "Durchschnitt"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Durchschnittliche CPU-Auslastung der Container" msgstr "Durchschnittliche CPU-Auslastung der Container"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "Durchschnitt überschreitet <0>{value}{0}</0>" msgstr "Durchschnitt überschreitet <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Durchschnittliche systemweite CPU-Auslastung"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Durchschnittliche Auslastung von {0}" msgstr "Durchschnittliche Auslastung von {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Backups" msgstr "Backups"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Bandbreite" msgstr "Bandbreite"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Batterie"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel unterstützt OpenID Connect und viele OAuth2-Authentifizierungsanbieter." msgstr "Beszel unterstützt OpenID Connect und viele OAuth2-Authentifizierungsanbieter."
@@ -202,8 +213,8 @@ msgstr "Bytes (KB/s, MB/s, GB/s)"
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Cache / Puffer" msgstr "Cache / Puffer"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Abbrechen" msgstr "Abbrechen"
@@ -223,6 +234,15 @@ msgstr "Anzeigeeinheiten der Werte ändern."
msgid "Change general application options." msgid "Change general application options."
msgstr "Allgemeine Anwendungsoptionen ändern." msgstr "Allgemeine Anwendungsoptionen ändern."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Ladung"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Wird geladen"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Diagrammoptionen" msgstr "Diagrammoptionen"
@@ -239,6 +259,10 @@ msgstr "Überprüfe die Protokolle für weitere Details."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Überprüfe deinen Benachrichtigungsdienst" msgstr "Überprüfe deinen Benachrichtigungsdienst"
#: 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."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Zum Kopieren klicken" msgstr "Zum Kopieren klicken"
@@ -261,8 +285,8 @@ msgstr "Passwort bestätigen"
msgid "Connection is down" msgid "Connection is down"
msgstr "Verbindung unterbrochen" msgstr "Verbindung unterbrochen"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Fortfahren" msgstr "Fortfahren"
@@ -320,9 +344,9 @@ msgstr "YAML kopieren"
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "CPU-Auslastung" msgstr "CPU-Auslastung"
@@ -339,10 +363,10 @@ msgstr "Erstellt"
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Kritisch (%)" msgstr "Kritisch (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Dunkel" msgstr "Aktueller Zustand"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Dashboard"
msgid "Default time period" msgid "Default time period"
msgstr "Standardzeitraum" msgstr "Standardzeitraum"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Löschen" msgstr "Löschen"
@@ -362,6 +386,11 @@ msgstr "Löschen"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "Fingerabdruck löschen" msgstr "Fingerabdruck löschen"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Wird entladen"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Festplatte" msgstr "Festplatte"
@@ -374,9 +403,9 @@ msgstr "Festplatten-I/O"
msgid "Disk unit" msgid "Disk unit"
msgstr "Festplatteneinheit" msgstr "Festplatteneinheit"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Festplattennutzung" msgstr "Festplattennutzung"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "Dokumentation" msgstr "Dokumentation"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "Offline" msgstr "Offline"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Offline ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "Dauer" msgstr "Dauer"
@@ -417,8 +450,8 @@ msgstr "Dauer"
msgid "Edit" msgid "Edit"
msgstr "Bearbeiten" msgstr "Bearbeiten"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "E-Mail" msgstr "E-Mail"
@@ -426,6 +459,11 @@ msgstr "E-Mail"
msgid "Email notifications" msgid "Email notifications"
msgstr "E-Mail-Benachrichtigungen" msgstr "E-Mail-Benachrichtigungen"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Leer"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "E-Mail-Adresse eingeben, um das Passwort zurückzusetzen" msgstr "E-Mail-Adresse eingeben, um das Passwort zurückzusetzen"
@@ -434,11 +472,11 @@ msgstr "E-Mail-Adresse eingeben, um das Passwort zurückzusetzen"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "E-Mail-Adresse eingeben..." msgstr "E-Mail-Adresse eingeben..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Fehler" msgstr "Fehler"
@@ -469,12 +507,12 @@ msgstr "Exportiere die aktuelle Systemkonfiguration."
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "Fahrenheit (°F)" msgstr "Fahrenheit (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Authentifizierung fehlgeschlagen" msgstr "Authentifizierung fehlgeschlagen"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Einstellungen konnten nicht gespeichert werden" msgstr "Einstellungen konnten nicht gespeichert werden"
@@ -482,13 +520,13 @@ msgstr "Einstellungen konnten nicht gespeichert werden"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Testbenachrichtigung konnte nicht gesendet werden" msgstr "Testbenachrichtigung konnte nicht gesendet werden"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Warnung konnte nicht aktualisiert werden" msgstr "Warnung konnte nicht aktualisiert werden"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Filter..." msgstr "Filter..."
@@ -496,7 +534,7 @@ msgstr "Filter..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "Fingerabdruck" msgstr "Fingerabdruck"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "Für <0>{min}</0> {min, plural, one {Minute} other {Minuten}}" msgstr "Für <0>{min}</0> {min, plural, one {Minute} other {Minuten}}"
@@ -504,9 +542,14 @@ msgstr "Für <0>{min}</0> {min, plural, one {Minute} other {Minuten}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Passwort vergessen?" msgstr "Passwort vergessen?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Voll"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Allgemein" msgstr "Allgemein"
@@ -528,6 +571,11 @@ msgstr "Homebrew-Befehl"
msgid "Host / IP" msgid "Host / IP"
msgstr "Host / IP" msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Untätig"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "Wenn du das Passwort für dein Administratorkonto verloren hast, kannst du es mit dem folgenden Befehl zurücksetzen."
@@ -549,31 +597,26 @@ msgstr "Sprache"
msgid "Layout" msgid "Layout"
msgstr "Anordnung" msgstr "Anordnung"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Hell"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "Durchschnittliche Systemlast" msgstr "Durchschnittliche Systemlast"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "Durchschnittliche Systemlast 15 Min" msgstr "Durchschnittliche Systemlast 15 Min"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "Durchschnittliche Systemlast 1 Min" msgstr "Durchschnittliche Systemlast 1 Min"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "Durchschnittliche Systemlast 5 Min" msgstr "Durchschnittliche Systemlast 5 Min"
#. Short label for load average #. Short label for load average
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Load Avg" msgid "Load Avg"
msgstr "Durchschnittliche Last" msgstr "Systemlast"
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Log Out" msgid "Log Out"
@@ -583,13 +626,13 @@ msgstr "Abmelden"
msgid "Login" msgid "Login"
msgstr "Anmelden" msgstr "Anmelden"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Anmeldeversuch fehlgeschlagen" msgstr "Anmeldeversuch fehlgeschlagen"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Protokolle" msgstr "Protokolle"
@@ -614,8 +657,8 @@ msgstr "Max 1 Min"
msgid "Memory" msgid "Memory"
msgstr "Arbeitsspeicher" msgstr "Arbeitsspeicher"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Arbeitsspeichernutzung" msgstr "Arbeitsspeichernutzung"
@@ -623,8 +666,8 @@ msgstr "Arbeitsspeichernutzung"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Arbeitsspeichernutzung der Docker-Container" msgstr "Arbeitsspeichernutzung der Docker-Container"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Keine Systeme gefunden." msgstr "Keine Systeme gefunden."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Benachrichtigungen" msgstr "Benachrichtigungen"
@@ -672,9 +715,9 @@ msgstr "OAuth 2 / OIDC-Unterstützung"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "Bei jedem Neustart werden die Systeme in der Datenbank aktualisiert, um den in der Datei definierten Systemen zu entsprechen." msgstr "Bei jedem Neustart werden die Systeme in der Datenbank aktualisiert, um den in der Datei definierten Systemen zu entsprechen."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Menü öffnen" msgstr "Menü öffnen"
@@ -682,7 +725,7 @@ msgstr "Menü öffnen"
msgid "Or continue with" msgid "Or continue with"
msgstr "Oder fortfahren mit" msgstr "Oder fortfahren mit"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Bestehende Warnungen überschreiben" msgstr "Bestehende Warnungen überschreiben"
@@ -725,16 +768,20 @@ msgstr "Pause"
msgid "Paused" msgid "Paused"
msgstr "Pausiert" msgstr "Pausiert"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Pausiert ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Bitte <0>konfiguriere einen SMTP-Server</0>, um sicherzustellen, dass Warnungen zugestellt werden." msgstr "Bitte <0>konfiguriere einen SMTP-Server</0>, um sicherzustellen, dass Warnungen zugestellt werden."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Bitte überprüfe die Protokolle für weitere Details." msgstr "Bitte überprüfe die Protokolle für weitere Details."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Bitte überprüfe deine Anmeldedaten und versuche es erneut" msgstr "Bitte überprüfe deine Anmeldedaten und versuche es erneut"
@@ -746,7 +793,7 @@ msgstr "Bitte erstelle ein Administratorkonto"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Bitte aktiviere Pop-ups für diese Seite" msgstr "Bitte aktiviere Pop-ups für diese Seite"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Bitte melde dich erneut an" msgstr "Bitte melde dich erneut an"
@@ -756,7 +803,7 @@ msgstr "In der <0>Dokumentation</0> findest du weitere Anweisungen."
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Please sign in to your account" msgid "Please sign in to your account"
msgstr "Bitte melde dich bei beinem Konto an" msgstr "Bitte melde dich bei deinem Konto an"
#: src/components/add-system.tsx #: src/components/add-system.tsx
msgid "Port" msgid "Port"
@@ -812,8 +859,8 @@ msgstr "Zeilen pro Seite"
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Adresse mit der Enter-Taste oder Komma speichern. Leer lassen, um E-Mail-Benachrichtigungen zu deaktivieren." msgstr "Adresse mit der Enter-Taste oder Komma speichern. Leer lassen, um E-Mail-Benachrichtigungen zu deaktivieren."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Einstellungen speichern" msgstr "Einstellungen speichern"
@@ -829,7 +876,7 @@ msgstr "Suche"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Nach Systemen oder Einstellungen suchen..." msgstr "Nach Systemen oder Einstellungen suchen..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Siehe <0>Benachrichtigungseinstellungen</0>, um zu konfigurieren, wie du Warnungen erhältst." msgstr "Siehe <0>Benachrichtigungseinstellungen</0>, um zu konfigurieren, wie du Warnungen erhältst."
@@ -873,7 +920,8 @@ msgstr "Sortieren nach"
msgid "State" msgid "State"
msgstr "Status" msgstr "Status"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Status"
@@ -885,12 +933,10 @@ msgstr "Vom System genutzter Swap-Speicher"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Swap-Nutzung" msgstr "Swap-Nutzung"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "System" msgstr "System"
@@ -915,8 +961,8 @@ msgstr "Tabelle"
msgid "Temp" msgid "Temp"
msgstr "Temperatur" msgstr "Temperatur"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Temperatur" msgstr "Temperatur"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "Token" msgstr "Token"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "Tokens & Fingerabdrücke" msgstr "Tokens & Fingerabdrücke"
@@ -988,39 +1034,39 @@ msgstr "Tokens ermöglichen es Agents, sich zu verbinden und zu registrieren. Fi
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "Tokens und Fingerabdrücke werden verwendet, um WebSocket-Verbindungen zum Hub zu authentifizieren." msgstr "Tokens und Fingerabdrücke werden verwendet, um WebSocket-Verbindungen zum Hub zu authentifizieren."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "Löst aus, wenn der Lastdurchschnitt der letzten Minute einen Schwellenwert überschreitet" msgstr "Löst aus, wenn der Lastdurchschnitt der letzten Minute einen Schwellenwert überschreitet"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "Löst aus, wenn der Lastdurchschnitt der letzten 15 Minuten einen Schwellenwert überschreitet" msgstr "Löst aus, wenn der Lastdurchschnitt der letzten 15 Minuten einen Schwellenwert überschreitet"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "Löst aus, wenn der Lastdurchschnitt der letzten 5 Minuten einen Schwellenwert überschreitet" msgstr "Löst aus, wenn der Lastdurchschnitt der letzten 5 Minuten einen Schwellenwert überschreitet"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Löst aus, wenn ein Sensor einen Schwellenwert überschreitet" msgstr "Löst aus, wenn ein Sensor einen Schwellenwert überschreitet"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Löst aus, wenn die kombinierte Auf-/Abwärtsbewegung einen Schwellenwert überschreitet" msgstr "Löst aus, wenn die kombinierte Auf-/Abwärtsbewegung einen Schwellenwert überschreitet"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Löst aus, wenn die CPU-Auslastung einen Schwellenwert überschreitet" msgstr "Löst aus, wenn die CPU-Auslastung einen Schwellenwert überschreitet"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Löst aus, wenn die Arbeitsspeichernutzung einen Schwellenwert überschreitet" msgstr "Löst aus, wenn die Arbeitsspeichernutzung einen Schwellenwert überschreitet"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Löst aus, wenn der Status zwischen online und offline wechselt" msgstr "Löst aus, wenn der Status zwischen online und offline wechselt"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Löst aus, wenn die Nutzung einer Festplatte einen Schwellenwert überschreitet" msgstr "Löst aus, wenn die Nutzung einer Festplatte einen Schwellenwert überschreitet"
@@ -1029,19 +1075,25 @@ msgstr "Löst aus, wenn die Nutzung einer Festplatte einen Schwellenwert übersc
msgid "Unit preferences" msgid "Unit preferences"
msgstr "Einheiten" msgstr "Einheiten"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "Universeller Token" msgstr "Universeller Token"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Unbekannt"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "aktiv" msgstr "aktiv"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "In Echtzeit aktualisiert. Klicke auf ein System, um Informationen anzuzeigen." msgstr "aktiv ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "Nutzung"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Nutzung der Root-Partition" msgstr "Nutzung der Root-Partition"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Verwendet" msgstr "Verwendet"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Benutzer" msgstr "Benutzer"

View File

@@ -18,16 +18,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# day} other {# days}}" msgstr "{0, plural, one {# day} other {# days}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# hour} other {# hours}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "{0} of {1} row(s) selected." msgstr "{0} of {1} row(s) selected."
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# hour} other {# hours}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 hour" msgstr "1 hour"
@@ -64,8 +70,8 @@ msgid "5 min"
msgstr "5 min" msgstr "5 min"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Actions" msgstr "Actions"
@@ -108,18 +114,19 @@ msgid "Agent"
msgstr "Agent" msgstr "Agent"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "Alert History" msgstr "Alert History"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Alerts" msgstr "Alerts"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "All Systems" msgstr "All Systems"
@@ -143,8 +150,8 @@ msgstr "Average"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Average CPU utilization of containers" msgstr "Average CPU utilization of containers"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "Average exceeds <0>{value}{0}</0>" msgstr "Average exceeds <0>{value}{0}</0>"
@@ -161,16 +168,20 @@ msgstr "Average system-wide CPU utilization"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Average utilization of {0}" msgstr "Average utilization of {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Backups" msgstr "Backups"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Bandwidth" msgstr "Bandwidth"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Battery"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgstr "Beszel supports OpenID Connect and many OAuth2 authentication providers."
@@ -197,8 +208,8 @@ msgstr "Bytes (KB/s, MB/s, GB/s)"
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Cache / Buffers" msgstr "Cache / Buffers"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Cancel" msgstr "Cancel"
@@ -218,6 +229,15 @@ msgstr "Change display units for metrics."
msgid "Change general application options." msgid "Change general application options."
msgstr "Change general application options." msgstr "Change general application options."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Charge"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Charging"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Chart options" msgstr "Chart options"
@@ -234,6 +254,10 @@ msgstr "Check logs for more details."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Check your notification service" msgstr "Check your notification service"
#: 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."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Click to copy" msgstr "Click to copy"
@@ -256,8 +280,8 @@ msgstr "Confirm password"
msgid "Connection is down" msgid "Connection is down"
msgstr "Connection is down" msgstr "Connection is down"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Continue" msgstr "Continue"
@@ -315,9 +339,9 @@ msgstr "Copy YAML"
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "CPU Usage" msgstr "CPU Usage"
@@ -334,10 +358,10 @@ msgstr "Created"
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Critical (%)" msgstr "Critical (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Dark" msgstr "Current state"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -348,8 +372,8 @@ msgstr "Dashboard"
msgid "Default time period" msgid "Default time period"
msgstr "Default time period" msgstr "Default time period"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Delete" msgstr "Delete"
@@ -357,6 +381,11 @@ msgstr "Delete"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "Delete fingerprint" msgstr "Delete fingerprint"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Discharging"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Disk" msgstr "Disk"
@@ -369,9 +398,9 @@ msgstr "Disk I/O"
msgid "Disk unit" msgid "Disk unit"
msgstr "Disk unit" msgstr "Disk unit"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Disk Usage" msgstr "Disk Usage"
@@ -396,13 +425,17 @@ msgid "Documentation"
msgstr "Documentation" msgstr "Documentation"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "Down" msgstr "Down"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Down ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "Duration" msgstr "Duration"
@@ -412,8 +445,8 @@ msgstr "Duration"
msgid "Edit" msgid "Edit"
msgstr "Edit" msgstr "Edit"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -421,6 +454,11 @@ msgstr "Email"
msgid "Email notifications" msgid "Email notifications"
msgstr "Email notifications" msgstr "Email notifications"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Empty"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Enter email address to reset password" msgstr "Enter email address to reset password"
@@ -429,11 +467,11 @@ msgstr "Enter email address to reset password"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Enter email address..." msgstr "Enter email address..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Error" msgstr "Error"
@@ -464,12 +502,12 @@ msgstr "Export your current systems configuration."
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "Fahrenheit (°F)" msgstr "Fahrenheit (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Failed to authenticate" msgstr "Failed to authenticate"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Failed to save settings" msgstr "Failed to save settings"
@@ -477,13 +515,13 @@ msgstr "Failed to save settings"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Failed to send test notification" msgstr "Failed to send test notification"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Failed to update alert" msgstr "Failed to update alert"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Filter..." msgstr "Filter..."
@@ -491,7 +529,7 @@ msgstr "Filter..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "Fingerprint" msgstr "Fingerprint"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgstr "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
@@ -499,9 +537,14 @@ msgstr "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Forgot password?" msgstr "Forgot password?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Full"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "General" msgstr "General"
@@ -523,6 +566,11 @@ msgstr "Homebrew command"
msgid "Host / IP" msgid "Host / IP"
msgstr "Host / IP" msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Idle"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "If you've lost the password to your admin account, you may reset it using the following command."
@@ -544,24 +592,19 @@ msgstr "Language"
msgid "Layout" msgid "Layout"
msgstr "Layout" msgstr "Layout"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Light"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "Load Average" msgstr "Load Average"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "Load Average 15m" msgstr "Load Average 15m"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "Load Average 1m" msgstr "Load Average 1m"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "Load Average 5m" msgstr "Load Average 5m"
@@ -578,13 +621,13 @@ msgstr "Log Out"
msgid "Login" msgid "Login"
msgstr "Login" msgstr "Login"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Login attempt failed" msgstr "Login attempt failed"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Logs" msgstr "Logs"
@@ -609,8 +652,8 @@ msgstr "Max 1 min"
msgid "Memory" msgid "Memory"
msgstr "Memory" msgstr "Memory"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Memory Usage" msgstr "Memory Usage"
@@ -618,8 +661,8 @@ msgstr "Memory Usage"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Memory usage of docker containers" msgstr "Memory usage of docker containers"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Name" msgstr "Name"
@@ -654,8 +697,8 @@ msgid "No systems found."
msgstr "No systems found." msgstr "No systems found."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Notifications" msgstr "Notifications"
@@ -667,9 +710,9 @@ msgstr "OAuth 2 / OIDC support"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "On each restart, systems in the database will be updated to match the systems defined in the file." msgstr "On each restart, systems in the database will be updated to match the systems defined in the file."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Open menu" msgstr "Open menu"
@@ -677,7 +720,7 @@ msgstr "Open menu"
msgid "Or continue with" msgid "Or continue with"
msgstr "Or continue with" msgstr "Or continue with"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Overwrite existing alerts" msgstr "Overwrite existing alerts"
@@ -720,16 +763,20 @@ msgstr "Pause"
msgid "Paused" msgid "Paused"
msgstr "Paused" msgstr "Paused"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Paused ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgstr "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Please check logs for more details." msgstr "Please check logs for more details."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Please check your credentials and try again" msgstr "Please check your credentials and try again"
@@ -741,7 +788,7 @@ msgstr "Please create an admin account"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Please enable pop-ups for this site" msgstr "Please enable pop-ups for this site"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Please log in again" msgstr "Please log in again"
@@ -807,8 +854,8 @@ msgstr "Rows per page"
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Save address using enter key or comma. Leave blank to disable email notifications." msgstr "Save address using enter key or comma. Leave blank to disable email notifications."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Save Settings" msgstr "Save Settings"
@@ -824,7 +871,7 @@ msgstr "Search"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Search for systems or settings..." msgstr "Search for systems or settings..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "See <0>notification settings</0> to configure how you receive alerts." msgstr "See <0>notification settings</0> to configure how you receive alerts."
@@ -868,7 +915,8 @@ msgstr "Sort By"
msgid "State" msgid "State"
msgstr "State" msgstr "State"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Status"
@@ -880,12 +928,10 @@ msgstr "Swap space used by the system"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Swap Usage" msgstr "Swap Usage"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "System" msgstr "System"
@@ -910,8 +956,8 @@ msgstr "Table"
msgid "Temp" msgid "Temp"
msgstr "Temp" msgstr "Temp"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Temperature" msgstr "Temperature"
@@ -970,8 +1016,8 @@ msgid "Token"
msgstr "Token" msgstr "Token"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "Tokens & Fingerprints" msgstr "Tokens & Fingerprints"
@@ -983,39 +1029,39 @@ msgstr "Tokens allow agents to connect and register. Fingerprints are stable ide
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgstr "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "Triggers when 1 minute load average exceeds a threshold" msgstr "Triggers when 1 minute load average exceeds a threshold"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "Triggers when 15 minute load average exceeds a threshold" msgstr "Triggers when 15 minute load average exceeds a threshold"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "Triggers when 5 minute load average exceeds a threshold" msgstr "Triggers when 5 minute load average exceeds a threshold"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Triggers when any sensor exceeds a threshold" msgstr "Triggers when any sensor exceeds a threshold"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Triggers when combined up/down exceeds a threshold" msgstr "Triggers when combined up/down exceeds a threshold"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Triggers when CPU usage exceeds a threshold" msgstr "Triggers when CPU usage exceeds a threshold"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Triggers when memory usage exceeds a threshold" msgstr "Triggers when memory usage exceeds a threshold"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Triggers when status switches between up and down" msgstr "Triggers when status switches between up and down"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Triggers when usage of any disk exceeds a threshold" msgstr "Triggers when usage of any disk exceeds a threshold"
@@ -1024,19 +1070,25 @@ msgstr "Triggers when usage of any disk exceeds a threshold"
msgid "Unit preferences" msgid "Unit preferences"
msgstr "Unit preferences" msgstr "Unit preferences"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "Universal token" msgstr "Universal token"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Unknown"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "Up" msgstr "Up"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Updated in real time. Click on a system to view information." msgstr "Up ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1053,13 +1105,13 @@ msgstr "Usage"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Usage of root partition" msgstr "Usage of root partition"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Used" msgstr "Used"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Users" msgstr "Users"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: es\n" "Language: es\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Spanish\n" "Language-Team: Spanish\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# día} other {# días}}" msgstr "{0, plural, one {# día} other {# días}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# hora} other {# horas}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# minuto} other {# minutos}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "{0} de {1} fila(s) seleccionada(s)." msgstr "{0} de {1} fila(s) seleccionada(s)."
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# hora} other {# horas}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 hora" msgstr "1 hora"
@@ -40,7 +46,7 @@ msgstr "1 hora"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "1 min" msgid "1 min"
msgstr "" msgstr "1 min"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 week" msgid "1 week"
@@ -53,7 +59,7 @@ msgstr "12 horas"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "15 min" msgid "15 min"
msgstr "" msgstr "15 min"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "24 hours" msgid "24 hours"
@@ -66,11 +72,11 @@ msgstr "30 días"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "5 min" msgid "5 min"
msgstr "" msgstr "5 min"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Acciones" msgstr "Acciones"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Agente" msgstr "Agente"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "Historial de Alertas" msgstr "Historial de Alertas"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Alertas" msgstr "Alertas"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Todos los Sistemas" msgstr "Todos los Sistemas"
@@ -148,8 +155,8 @@ msgstr "Promedio"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Utilización promedio de CPU de los contenedores" msgstr "Utilización promedio de CPU de los contenedores"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "El promedio excede <0>{value}{0}</0>" msgstr "El promedio excede <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Utilización promedio de CPU del sistema"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Uso promedio de {0}" msgstr "Uso promedio de {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Copias de Seguridad" msgstr "Copias de Seguridad"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Ancho de banda" msgstr "Ancho de banda"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Batería"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel admite OpenID Connect y muchos proveedores de autenticación OAuth2." msgstr "Beszel admite OpenID Connect y muchos proveedores de autenticación OAuth2."
@@ -191,19 +202,19 @@ msgstr "Binario"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)" msgid "Bits (Kbps, Mbps, Gbps)"
msgstr "" msgstr "Bits (Kbps, Mbps, Gbps)"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)" msgid "Bytes (KB/s, MB/s, GB/s)"
msgstr "" msgstr "Bytes (KB/s, MB/s, GB/s)"
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Caché / Buffers" msgstr "Caché / Buffers"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Cancelar" msgstr "Cancelar"
@@ -213,7 +224,7 @@ msgstr "Precaución - posible pérdida de datos"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Celsius (°C)" msgid "Celsius (°C)"
msgstr "" msgstr "Celsius (°C)"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Change display units for metrics." msgid "Change display units for metrics."
@@ -223,6 +234,15 @@ msgstr "Cambiar las unidades de visualización de las métricas."
msgid "Change general application options." msgid "Change general application options."
msgstr "Cambiar las opciones generales de la aplicación." msgstr "Cambiar las opciones generales de la aplicación."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Carga"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Cargando"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Opciones de Gráficos" msgstr "Opciones de Gráficos"
@@ -239,6 +259,10 @@ msgstr "Revise los registros para más detalles."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Verifique su servicio de notificaciones" msgstr "Verifique su servicio de notificaciones"
#: 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."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Haga clic para copiar" msgstr "Haga clic para copiar"
@@ -261,8 +285,8 @@ msgstr "Confirmar contraseña"
msgid "Connection is down" msgid "Connection is down"
msgstr "La conexión está caída" msgstr "La conexión está caída"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Continuar" msgstr "Continuar"
@@ -320,9 +344,9 @@ msgstr "Copiar YAML"
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "Uso de CPU" msgstr "Uso de CPU"
@@ -339,10 +363,10 @@ msgstr "Creado"
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Crítico (%)" msgstr "Crítico (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Oscuro" msgstr "Estado actual"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Tablero"
msgid "Default time period" msgid "Default time period"
msgstr "Período de tiempo predeterminado" msgstr "Período de tiempo predeterminado"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Eliminar" msgstr "Eliminar"
@@ -362,6 +386,11 @@ msgstr "Eliminar"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "Eliminar huella digital" msgstr "Eliminar huella digital"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Descargando"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Disco" msgstr "Disco"
@@ -374,9 +403,9 @@ msgstr "E/S de Disco"
msgid "Disk unit" msgid "Disk unit"
msgstr "Unidad de disco" msgstr "Unidad de disco"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Uso de Disco" msgstr "Uso de Disco"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "Documentación" msgstr "Documentación"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "Abajo" msgstr "Abajo"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Abajo ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "Duración" msgstr "Duración"
@@ -417,8 +450,8 @@ msgstr "Duración"
msgid "Edit" msgid "Edit"
msgstr "Editar" msgstr "Editar"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Correo electrónico" msgstr "Correo electrónico"
@@ -426,6 +459,11 @@ msgstr "Correo electrónico"
msgid "Email notifications" msgid "Email notifications"
msgstr "Notificaciones por correo" msgstr "Notificaciones por correo"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Vacía"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Ingrese la dirección de correo electrónico para restablecer la contraseña" msgstr "Ingrese la dirección de correo electrónico para restablecer la contraseña"
@@ -434,11 +472,11 @@ msgstr "Ingrese la dirección de correo electrónico para restablecer la contras
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Ingrese dirección de correo..." msgstr "Ingrese dirección de correo..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Error" msgstr "Error"
@@ -467,14 +505,14 @@ msgstr "Exporte la configuración actual de sus sistemas."
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "" msgstr "Fahrenheit (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Error al autenticar" msgstr "Error al autenticar"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Error al guardar la configuración" msgstr "Error al guardar la configuración"
@@ -482,13 +520,13 @@ msgstr "Error al guardar la configuración"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Error al enviar la notificación de prueba" msgstr "Error al enviar la notificación de prueba"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Error al actualizar la alerta" msgstr "Error al actualizar la alerta"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Filtrar..." msgstr "Filtrar..."
@@ -496,7 +534,7 @@ msgstr "Filtrar..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "Huella dactilar" msgstr "Huella dactilar"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "Por <0>{min}</0> {min, plural, one {minuto} other {minutos}}" msgstr "Por <0>{min}</0> {min, plural, one {minuto} other {minutos}}"
@@ -504,9 +542,14 @@ msgstr "Por <0>{min}</0> {min, plural, one {minuto} other {minutos}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "¿Olvidó su contraseña?" msgstr "¿Olvidó su contraseña?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Llena"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "General" msgstr "General"
@@ -528,6 +571,11 @@ msgstr "Comando Homebrew"
msgid "Host / IP" msgid "Host / IP"
msgstr "Host / IP" msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Inactiva"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "Si ha perdido la contraseña de su cuenta de administrador, puede restablecerla usando el siguiente comando."
@@ -549,24 +597,19 @@ msgstr "Idioma"
msgid "Layout" msgid "Layout"
msgstr "Diseño" msgstr "Diseño"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Claro"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "Carga Media" msgstr "Carga Media"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "Carga media 15m" msgstr "Carga media 15m"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "Carga media 1m" msgstr "Carga media 1m"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "Carga media 5m" msgstr "Carga media 5m"
@@ -583,13 +626,13 @@ msgstr "Cerrar Sesión"
msgid "Login" msgid "Login"
msgstr "Iniciar sesión" msgstr "Iniciar sesión"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Intento de inicio de sesión fallido" msgstr "Intento de inicio de sesión fallido"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Registros" msgstr "Registros"
@@ -614,8 +657,8 @@ msgstr "Máx 1 min"
msgid "Memory" msgid "Memory"
msgstr "Memoria" msgstr "Memoria"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Uso de Memoria" msgstr "Uso de Memoria"
@@ -623,8 +666,8 @@ msgstr "Uso de Memoria"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Uso de memoria de los contenedores de Docker" msgstr "Uso de memoria de los contenedores de Docker"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Nombre" msgstr "Nombre"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "No se encontraron sistemas." msgstr "No se encontraron sistemas."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Notificaciones" msgstr "Notificaciones"
@@ -672,9 +715,9 @@ msgstr "Soporte para OAuth 2 / OIDC"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "En cada reinicio, los sistemas en la base de datos se actualizarán para coincidir con los sistemas definidos en el archivo." msgstr "En cada reinicio, los sistemas en la base de datos se actualizarán para coincidir con los sistemas definidos en el archivo."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Abrir menú" msgstr "Abrir menú"
@@ -682,7 +725,7 @@ msgstr "Abrir menú"
msgid "Or continue with" msgid "Or continue with"
msgstr "O continuar con" msgstr "O continuar con"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Sobrescribir alertas existentes" msgstr "Sobrescribir alertas existentes"
@@ -725,16 +768,20 @@ msgstr "Pausar"
msgid "Paused" msgid "Paused"
msgstr "Pausado" msgstr "Pausado"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "Pausado ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Por favor, <0>configure un servidor SMTP</0> para asegurar que las alertas sean entregadas." msgstr "Por favor, <0>configure un servidor SMTP</0> para asegurar que las alertas sean entregadas."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Por favor, revise los registros para más detalles." msgstr "Por favor, revise los registros para más detalles."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Por favor, verifique sus credenciales e intente de nuevo" msgstr "Por favor, verifique sus credenciales e intente de nuevo"
@@ -746,7 +793,7 @@ msgstr "Por favor, cree una cuenta de administrador"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Por favor, habilite las ventanas emergentes para este sitio" msgstr "Por favor, habilite las ventanas emergentes para este sitio"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Por favor, inicie sesión de nuevo" msgstr "Por favor, inicie sesión de nuevo"
@@ -812,8 +859,8 @@ msgstr "Filas por página"
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Guarde la dirección usando la tecla enter o coma. Deje en blanco para desactivar las notificaciones por correo." msgstr "Guarde la dirección usando la tecla enter o coma. Deje en blanco para desactivar las notificaciones por correo."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Guardar Configuración" msgstr "Guardar Configuración"
@@ -829,7 +876,7 @@ msgstr "Buscar"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Buscar sistemas o configuraciones..." msgstr "Buscar sistemas o configuraciones..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Consulte <0>configuración de notificaciones</0> para configurar cómo recibe alertas." msgstr "Consulte <0>configuración de notificaciones</0> para configurar cómo recibe alertas."
@@ -873,7 +920,8 @@ msgstr "Ordenar por"
msgid "State" msgid "State"
msgstr "Estado" msgstr "Estado"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Estado" msgstr "Estado"
@@ -885,12 +933,10 @@ msgstr "Espacio de swap utilizado por el sistema"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Uso de Swap" msgstr "Uso de Swap"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "Sistema" msgstr "Sistema"
@@ -915,8 +961,8 @@ msgstr "Tabla"
msgid "Temp" msgid "Temp"
msgstr "Temperatura" msgstr "Temperatura"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Temperatura" msgstr "Temperatura"
@@ -972,11 +1018,11 @@ msgstr "Alternar tema"
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Token" msgid "Token"
msgstr "" msgstr "Token"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "Tokens y Huellas Digitales" msgstr "Tokens y Huellas Digitales"
@@ -988,39 +1034,39 @@ msgstr "Los tokens permiten que los agentes se conecten y registren. Las huellas
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "Los tokens y las huellas digitales se utilizan para autenticar las conexiones WebSocket al hub." msgstr "Los tokens y las huellas digitales se utilizan para autenticar las conexiones WebSocket al hub."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "Se activa cuando la carga media de 1 minuto supera un umbral" msgstr "Se activa cuando la carga media de 1 minuto supera un umbral"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "Se activa cuando la carga media de 15 minutos supera un umbral" msgstr "Se activa cuando la carga media de 15 minutos supera un umbral"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "Se activa cuando la carga media de 5 minutos supera un umbral" msgstr "Se activa cuando la carga media de 5 minutos supera un umbral"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Se activa cuando cualquier sensor supera un umbral" msgstr "Se activa cuando cualquier sensor supera un umbral"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Se activa cuando la suma de subida/bajada supera un umbral" msgstr "Se activa cuando la suma de subida/bajada supera un umbral"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Se activa cuando el uso de CPU supera un umbral" msgstr "Se activa cuando el uso de CPU supera un umbral"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Se activa cuando el uso de memoria supera un umbral" msgstr "Se activa cuando el uso de memoria supera un umbral"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Se activa cuando el estado cambia entre activo e inactivo" msgstr "Se activa cuando el estado cambia entre activo e inactivo"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Se activa cuando el uso de cualquier disco supera un umbral" msgstr "Se activa cuando el uso de cualquier disco supera un umbral"
@@ -1029,19 +1075,25 @@ msgstr "Se activa cuando el uso de cualquier disco supera un umbral"
msgid "Unit preferences" msgid "Unit preferences"
msgstr "Preferencias de unidad" msgstr "Preferencias de unidad"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "Token universal" msgstr "Token universal"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Desconocida"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "Activo" msgstr "Activo"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Actualizado en tiempo real. Haga clic en un sistema para ver la información." msgstr "Activo ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "Uso"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Uso de la partición raíz" msgstr "Uso de la partición raíz"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Usado" msgstr "Usado"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Usuarios" msgstr "Usuarios"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: fa\n" "Language: fa\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Persian\n" "Language-Team: Persian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# روز} other {# روز}}" msgstr "{0, plural, one {# روز} other {# روز}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# ساعت} other {# ساعت}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# دقیقه} few {# دقیقه} many {# دقیقه} other {# دقیقه}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "{0} از {1} ردیف انتخاب شده است." msgstr "{0} از {1} ردیف انتخاب شده است."
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# ساعت} other {# ساعت}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "۱ ساعت" msgstr "۱ ساعت"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "۵ دقیقه" msgstr "۵ دقیقه"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "عملیات" msgstr "عملیات"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "عامل" msgstr "عامل"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "تاریخچه هشدارها" msgstr "تاریخچه هشدارها"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "هشدارها" msgstr "هشدارها"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "همه سیستم‌ها" msgstr "همه سیستم‌ها"
@@ -148,8 +155,8 @@ msgstr "میانگین"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "میانگین استفاده از CPU کانتینرها" msgstr "میانگین استفاده از CPU کانتینرها"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "میانگین از <0>{value}{0}</0> فراتر رفته است" msgstr "میانگین از <0>{value}{0}</0> فراتر رفته است"
@@ -166,16 +173,20 @@ msgstr "میانگین استفاده از CPU در کل سیستم"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "میانگین استفاده از {0}" msgstr "میانگین استفاده از {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "پشتیبان‌گیری‌ها" msgstr "پشتیبان‌گیری‌ها"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "پهنای باند" msgstr "پهنای باند"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "باتری"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "بِزل از OpenID Connect و بسیاری از ارائه‌دهندگان احراز هویت OAuth2 پشتیبانی می‌کند." msgstr "بِزل از OpenID Connect و بسیاری از ارائه‌دهندگان احراز هویت OAuth2 پشتیبانی می‌کند."
@@ -202,8 +213,8 @@ msgstr "بایت (کیلوبایت بر ثانیه، مگابایت بر ثان
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "حافظه پنهان / بافرها" msgstr "حافظه پنهان / بافرها"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "لغو" msgstr "لغو"
@@ -223,6 +234,15 @@ msgstr "تغییر واحدهای نمایش برای معیارها."
msgid "Change general application options." msgid "Change general application options."
msgstr "تغییر گزینه‌های کلی برنامه." msgstr "تغییر گزینه‌های کلی برنامه."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "شارژ"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "در حال شارژ"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "گزینه‌های نمودار" msgstr "گزینه‌های نمودار"
@@ -239,6 +259,10 @@ msgstr "برای جزئیات بیشتر، لاگ‌ها را بررسی کنی
msgid "Check your notification service" msgid "Check your notification service"
msgstr "سرویس اطلاع‌رسانی خود را بررسی کنید" msgstr "سرویس اطلاع‌رسانی خود را بررسی کنید"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr "برای مشاهده اطلاعات بیشتر روی یک سیستم کلیک کنید."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "برای کپی کردن کلیک کنید" msgstr "برای کپی کردن کلیک کنید"
@@ -261,8 +285,8 @@ msgstr "تأیید رمز عبور"
msgid "Connection is down" msgid "Connection is down"
msgstr "اتصال قطع است" msgstr "اتصال قطع است"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "ادامه" msgstr "ادامه"
@@ -320,9 +344,9 @@ msgstr "کپی YAML"
msgid "CPU" msgid "CPU"
msgstr "پردازنده" msgstr "پردازنده"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "میزان استفاده از پردازنده" msgstr "میزان استفاده از پردازنده"
@@ -339,10 +363,10 @@ msgstr "ایجاد شده"
msgid "Critical (%)" msgid "Critical (%)"
msgstr "بحرانی (%)" msgstr "بحرانی (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "تیره" msgstr "وضعیت فعلی"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "داشبورد"
msgid "Default time period" msgid "Default time period"
msgstr "بازه زمانی پیش‌فرض" msgstr "بازه زمانی پیش‌فرض"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "حذف" msgstr "حذف"
@@ -362,6 +386,11 @@ msgstr "حذف"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "حذف اثر انگشت" msgstr "حذف اثر انگشت"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "در حال تخلیه"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "دیسک" msgstr "دیسک"
@@ -374,9 +403,9 @@ msgstr "ورودی/خروجی دیسک"
msgid "Disk unit" msgid "Disk unit"
msgstr "واحد دیسک" msgstr "واحد دیسک"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "میزان استفاده از دیسک" msgstr "میزان استفاده از دیسک"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "مستندات" msgstr "مستندات"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "قطع" msgstr "قطع"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "قطع ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "مدت زمان" msgstr "مدت زمان"
@@ -417,8 +450,8 @@ msgstr "مدت زمان"
msgid "Edit" msgid "Edit"
msgstr "ویرایش" msgstr "ویرایش"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "ایمیل" msgstr "ایمیل"
@@ -426,6 +459,11 @@ msgstr "ایمیل"
msgid "Email notifications" msgid "Email notifications"
msgstr "اعلان‌های ایمیلی" msgstr "اعلان‌های ایمیلی"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "خالی"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "آدرس ایمیل را برای بازنشانی رمز عبور وارد کنید" msgstr "آدرس ایمیل را برای بازنشانی رمز عبور وارد کنید"
@@ -434,11 +472,11 @@ msgstr "آدرس ایمیل را برای بازنشانی رمز عبور وا
msgid "Enter email address..." msgid "Enter email address..."
msgstr "آدرس ایمیل را وارد کنید..." msgstr "آدرس ایمیل را وارد کنید..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "خطا" msgstr "خطا"
@@ -469,12 +507,12 @@ msgstr "پیکربندی سیستم‌های فعلی خود را خارج کن
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "فارنهایت (°F)" msgstr "فارنهایت (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "احراز هویت ناموفق بود" msgstr "احراز هویت ناموفق بود"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "ذخیره تنظیمات ناموفق بود" msgstr "ذخیره تنظیمات ناموفق بود"
@@ -482,13 +520,13 @@ msgstr "ذخیره تنظیمات ناموفق بود"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "ارسال اعلان آزمایشی ناموفق بود" msgstr "ارسال اعلان آزمایشی ناموفق بود"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "به‌روزرسانی هشدار ناموفق بود" msgstr "به‌روزرسانی هشدار ناموفق بود"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "فیلتر..." msgstr "فیلتر..."
@@ -496,7 +534,7 @@ msgstr "فیلتر..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "اثر انگشت" msgstr "اثر انگشت"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "برای <0>{min}</0> {min, plural, one {دقیقه} other {دقیقه}}" msgstr "برای <0>{min}</0> {min, plural, one {دقیقه} other {دقیقه}}"
@@ -504,9 +542,14 @@ msgstr "برای <0>{min}</0> {min, plural, one {دقیقه} other {دقیقه}}
msgid "Forgot password?" msgid "Forgot password?"
msgstr "رمز عبور را فراموش کرده‌اید؟" msgstr "رمز عبور را فراموش کرده‌اید؟"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "پر"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "عمومی" msgstr "عمومی"
@@ -528,6 +571,11 @@ msgstr "دستور Homebrew"
msgid "Host / IP" msgid "Host / IP"
msgstr "میزبان / IP" msgstr "میزبان / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "بیکار"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." msgid "If you've lost the password to your admin account, you may reset it using the following command."
msgstr "اگر رمز عبور حساب مدیر خود را گم کرده‌اید، می‌توانید آن را با استفاده از دستور زیر بازنشانی کنید." msgstr "اگر رمز عبور حساب مدیر خود را گم کرده‌اید، می‌توانید آن را با استفاده از دستور زیر بازنشانی کنید."
@@ -549,24 +597,19 @@ msgstr "زبان"
msgid "Layout" msgid "Layout"
msgstr "طرح‌بندی" msgstr "طرح‌بندی"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "روشن"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "میانگین بار" msgstr "میانگین بار"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "میانگین بار ۱۵ دقیقه" msgstr "میانگین بار ۱۵ دقیقه"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "میانگین بار ۱ دقیقه" msgstr "میانگین بار ۱ دقیقه"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "میانگین بار ۵ دقیقه" msgstr "میانگین بار ۵ دقیقه"
@@ -583,13 +626,13 @@ msgstr "خروج"
msgid "Login" msgid "Login"
msgstr "ورود" msgstr "ورود"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "تلاش برای ورود ناموفق بود" msgstr "تلاش برای ورود ناموفق بود"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "لاگ‌ها" msgstr "لاگ‌ها"
@@ -614,8 +657,8 @@ msgstr "حداکثر ۱ دقیقه"
msgid "Memory" msgid "Memory"
msgstr "حافظه" msgstr "حافظه"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "میزان استفاده از حافظه" msgstr "میزان استفاده از حافظه"
@@ -623,8 +666,8 @@ msgstr "میزان استفاده از حافظه"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "میزان استفاده از حافظه کانتینرهای داکر" msgstr "میزان استفاده از حافظه کانتینرهای داکر"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "نام" msgstr "نام"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "هیچ سیستمی یافت نشد." msgstr "هیچ سیستمی یافت نشد."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "اعلان‌ها" msgstr "اعلان‌ها"
@@ -672,9 +715,9 @@ msgstr "پشتیبانی از OAuth 2 / OIDC"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "در هر بار راه‌اندازی مجدد، سیستم‌های موجود در پایگاه داده با سیستم‌های تعریف شده در فایل مطابقت داده می‌شوند." msgstr "در هر بار راه‌اندازی مجدد، سیستم‌های موجود در پایگاه داده با سیستم‌های تعریف شده در فایل مطابقت داده می‌شوند."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "باز کردن منو" msgstr "باز کردن منو"
@@ -682,7 +725,7 @@ msgstr "باز کردن منو"
msgid "Or continue with" msgid "Or continue with"
msgstr "یا ادامه با" msgstr "یا ادامه با"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "بازنویسی هشدارهای موجود" msgstr "بازنویسی هشدارهای موجود"
@@ -725,16 +768,20 @@ msgstr "توقف"
msgid "Paused" msgid "Paused"
msgstr "مکث شده" msgstr "مکث شده"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "مکث شده ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "لطفاً برای اطمینان از تحویل هشدارها، یک <0>سرور SMTP پیکربندی کنید</0>." msgstr "لطفاً برای اطمینان از تحویل هشدارها، یک <0>سرور SMTP پیکربندی کنید</0>."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "لطفاً برای جزئیات بیشتر، لاگ‌ها را بررسی کنید." msgstr "لطفاً برای جزئیات بیشتر، لاگ‌ها را بررسی کنید."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "لطفاً اعتبارنامه‌های خود را بررسی کرده و دوباره تلاش کنید." msgstr "لطفاً اعتبارنامه‌های خود را بررسی کرده و دوباره تلاش کنید."
@@ -746,7 +793,7 @@ msgstr "لطفاً یک حساب مدیر ایجاد کنید"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "لطفاً پنجره‌های بازشو را برای این سایت فعال کنید" msgstr "لطفاً پنجره‌های بازشو را برای این سایت فعال کنید"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "لطفاً دوباره وارد شوید" msgstr "لطفاً دوباره وارد شوید"
@@ -812,8 +859,8 @@ msgstr "ردیف در هر صفحه"
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "آدرس را با استفاده از کلید Enter یا کاما ذخیره کنید. برای غیرفعال کردن اعلان‌های ایمیلی، خالی بگذارید." msgstr "آدرس را با استفاده از کلید Enter یا کاما ذخیره کنید. برای غیرفعال کردن اعلان‌های ایمیلی، خالی بگذارید."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "ذخیره تنظیمات" msgstr "ذخیره تنظیمات"
@@ -829,7 +876,7 @@ msgstr "جستجو"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "جستجو برای سیستم‌ها یا تنظیمات..." msgstr "جستجو برای سیستم‌ها یا تنظیمات..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "برای پیکربندی نحوه دریافت هشدارها، به <0>تنظیمات اعلان</0> مراجعه کنید." msgstr "برای پیکربندی نحوه دریافت هشدارها، به <0>تنظیمات اعلان</0> مراجعه کنید."
@@ -873,7 +920,8 @@ msgstr "مرتب‌سازی بر اساس"
msgid "State" msgid "State"
msgstr "وضعیت" msgstr "وضعیت"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "وضعیت" msgstr "وضعیت"
@@ -885,12 +933,10 @@ msgstr "فضای Swap استفاده شده توسط سیستم"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "میزان استفاده از Swap" msgstr "میزان استفاده از Swap"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "سیستم" msgstr "سیستم"
@@ -915,8 +961,8 @@ msgstr "جدول"
msgid "Temp" msgid "Temp"
msgstr "دما" msgstr "دما"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "دما" msgstr "دما"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "توکن" msgstr "توکن"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "توکن‌ها و اثرات انگشت" msgstr "توکن‌ها و اثرات انگشت"
@@ -988,39 +1034,39 @@ msgstr "توکن‌ها به عامل‌ها اجازه اتصال و ثبت‌
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "توکن‌ها و اثرات انگشت برای احراز هویت اتصالات WebSocket به هاب استفاده می‌شوند." msgstr "توکن‌ها و اثرات انگشت برای احراز هویت اتصالات WebSocket به هاب استفاده می‌شوند."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "هنگامی که میانگین بار ۱ دقیقه‌ای از یک آستانه فراتر رود، فعال می‌شود" msgstr "هنگامی که میانگین بار ۱ دقیقه‌ای از یک آستانه فراتر رود، فعال می‌شود"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "هنگامی که میانگین بار ۱۵ دقیقه‌ای از یک آستانه فراتر رود، فعال می‌شود" msgstr "هنگامی که میانگین بار ۱۵ دقیقه‌ای از یک آستانه فراتر رود، فعال می‌شود"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "هنگامی که میانگین بار ۵ دقیقه‌ای از یک آستانه فراتر رود، فعال می‌شود" msgstr "هنگامی که میانگین بار ۵ دقیقه‌ای از یک آستانه فراتر رود، فعال می‌شود"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "هنگامی که هر حسگری از یک آستانه فراتر رود، فعال می‌شود" msgstr "هنگامی که هر حسگری از یک آستانه فراتر رود، فعال می‌شود"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "هنگامی که مجموع بالا/پایین از یک آستانه فراتر رود، فعال می‌شود" msgstr "هنگامی که مجموع بالا/پایین از یک آستانه فراتر رود، فعال می‌شود"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "هنگامی که میزان استفاده از CPU از یک آستانه فراتر رود، فعال می‌شود" msgstr "هنگامی که میزان استفاده از CPU از یک آستانه فراتر رود، فعال می‌شود"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "هنگامی که میزان استفاده از حافظه از یک آستانه فراتر رود، فعال می‌شود" msgstr "هنگامی که میزان استفاده از حافظه از یک آستانه فراتر رود، فعال می‌شود"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "هنگامی که وضعیت بین بالا و پایین تغییر می‌کند، فعال می‌شود" msgstr "هنگامی که وضعیت بین بالا و پایین تغییر می‌کند، فعال می‌شود"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "هنگامی که استفاده از هر دیسکی از یک آستانه فراتر رود، فعال می‌شود" msgstr "هنگامی که استفاده از هر دیسکی از یک آستانه فراتر رود، فعال می‌شود"
@@ -1029,19 +1075,25 @@ msgstr "هنگامی که استفاده از هر دیسکی از یک آستا
msgid "Unit preferences" msgid "Unit preferences"
msgstr "تنظیمات واحدها" msgstr "تنظیمات واحدها"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "توکن جهانی" msgstr "توکن جهانی"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "ناشناخته"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "فعال" msgstr "فعال"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "به صورت لحظه‌ای به‌روزرسانی می‌شود. برای مشاهده اطلاعات، روی یک سیستم کلیک کنید." msgstr "فعال ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "میزان استفاده"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "میزان استفاده از پارتیشن ریشه" msgstr "میزان استفاده از پارتیشن ریشه"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "استفاده شده" msgstr "استفاده شده"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "کاربران" msgstr "کاربران"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: fr\n" "Language: fr\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: French\n" "Language-Team: French\n"
"Plural-Forms: nplurals=2; plural=(n > 1);\n" "Plural-Forms: nplurals=2; plural=(n > 1);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# jour} other {# jours}}" msgstr "{0, plural, one {# jour} other {# jours}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
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 ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr ""
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# heure} other {# heures}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 heure" msgstr "1 heure"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "" msgstr ""
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Actions" msgstr "Actions"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Agent" msgstr "Agent"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "" msgstr ""
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Alertes" msgstr "Alertes"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Tous les systèmes" msgstr "Tous les systèmes"
@@ -148,8 +155,8 @@ msgstr "Moyenne"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Utilisation moyenne du CPU des conteneurs" msgstr "Utilisation moyenne du CPU des conteneurs"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "La moyenne dépasse <0>{value}{0}</0>" msgstr "La moyenne dépasse <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Utilisation moyenne du CPU à l'échelle du système"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Utilisation moyenne de {0}" msgstr "Utilisation moyenne de {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Sauvegardes" msgstr "Sauvegardes"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Bande passante" msgstr "Bande passante"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Batterie"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel prend en charge OpenID Connect et de nombreux fournisseurs d'authentification OAuth2." msgstr "Beszel prend en charge OpenID Connect et de nombreux fournisseurs d'authentification OAuth2."
@@ -202,8 +213,8 @@ msgstr ""
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Cache / Tampons" msgstr "Cache / Tampons"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Annuler" msgstr "Annuler"
@@ -223,6 +234,15 @@ msgstr ""
msgid "Change general application options." msgid "Change general application options."
msgstr "Modifier les options générales de l'application." msgstr "Modifier les options générales de l'application."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Charge"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "En charge"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Options de graphique" msgstr "Options de graphique"
@@ -239,6 +259,10 @@ msgstr "Vérifiez les journaux pour plus de détails."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Vérifiez votre service de notification" msgstr "Vérifiez votre service de notification"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr ""
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Cliquez pour copier" msgstr "Cliquez pour copier"
@@ -261,8 +285,8 @@ msgstr "Confirmer le mot de passe"
msgid "Connection is down" msgid "Connection is down"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Continuer" msgstr "Continuer"
@@ -320,9 +344,9 @@ msgstr "Copier YAML"
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "Utilisation du CPU" msgstr "Utilisation du CPU"
@@ -339,10 +363,10 @@ msgstr ""
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Critique (%)" msgstr "Critique (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Sombre" msgstr "État actuel"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Tableau de bord"
msgid "Default time period" msgid "Default time period"
msgstr "Période par défaut" msgstr "Période par défaut"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Supprimer" msgstr "Supprimer"
@@ -362,6 +386,11 @@ msgstr "Supprimer"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "Supprimer l'empreinte" msgstr "Supprimer l'empreinte"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "En décharge"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Disque" msgstr "Disque"
@@ -374,9 +403,9 @@ msgstr "Entrée/Sortie disque"
msgid "Disk unit" msgid "Disk unit"
msgstr "" msgstr ""
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Utilisation du disque" msgstr "Utilisation du disque"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "Documentation" msgstr "Documentation"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "Injoignable" msgstr "Injoignable"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr ""
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "" msgstr ""
@@ -417,8 +450,8 @@ msgstr ""
msgid "Edit" msgid "Edit"
msgstr "Éditer" msgstr "Éditer"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -426,6 +459,11 @@ msgstr "Email"
msgid "Email notifications" msgid "Email notifications"
msgstr "Notifications par email" msgstr "Notifications par email"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Vide"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Entrez l'adresse email pour réinitialiser le mot de passe" msgstr "Entrez l'adresse email pour réinitialiser le mot de passe"
@@ -434,11 +472,11 @@ msgstr "Entrez l'adresse email pour réinitialiser le mot de passe"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Entrez l'adresse email..." msgstr "Entrez l'adresse email..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Erreur" msgstr "Erreur"
@@ -469,12 +507,12 @@ msgstr "Exportez la configuration actuelle de vos systèmes."
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Échec de l'authentification" msgstr "Échec de l'authentification"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Échec de l'enregistrement des paramètres" msgstr "Échec de l'enregistrement des paramètres"
@@ -482,13 +520,13 @@ msgstr "Échec de l'enregistrement des paramètres"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Échec de l'envoi de la notification de test" msgstr "Échec de l'envoi de la notification de test"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Échec de la mise à jour de l'alerte" msgstr "Échec de la mise à jour de l'alerte"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Filtrer..." msgstr "Filtrer..."
@@ -496,7 +534,7 @@ msgstr "Filtrer..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "" msgstr ""
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "Pour <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgstr "Pour <0>{min}</0> {min, plural, one {minute} other {minutes}}"
@@ -504,9 +542,14 @@ msgstr "Pour <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Mot de passe oublié ?" msgstr "Mot de passe oublié ?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Pleine"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Général" msgstr "Général"
@@ -528,6 +571,11 @@ msgstr "Commande Homebrew"
msgid "Host / IP" msgid "Host / IP"
msgstr "Hôte / IP" msgstr "Hôte / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Inactive"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "Si vous avez perdu le mot de passe de votre compte administrateur, vous pouvez le réinitialiser en utilisant la commande suivante."
@@ -549,24 +597,19 @@ msgstr "Langue"
msgid "Layout" msgid "Layout"
msgstr "Disposition" msgstr "Disposition"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Clair"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "" msgstr ""
@@ -583,13 +626,13 @@ msgstr "Déconnexion"
msgid "Login" msgid "Login"
msgstr "Connexion" msgstr "Connexion"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Échec de la tentative de connexion" msgstr "Échec de la tentative de connexion"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Journaux" msgstr "Journaux"
@@ -614,8 +657,8 @@ msgstr "Max 1 min"
msgid "Memory" msgid "Memory"
msgstr "Mémoire" msgstr "Mémoire"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Utilisation de la mémoire" msgstr "Utilisation de la mémoire"
@@ -623,8 +666,8 @@ msgstr "Utilisation de la mémoire"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Utilisation de la mémoire des conteneurs Docker" msgstr "Utilisation de la mémoire des conteneurs Docker"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Nom" msgstr "Nom"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Aucun système trouvé." msgstr "Aucun système trouvé."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Notifications" msgstr "Notifications"
@@ -672,9 +715,9 @@ msgstr "Support OAuth 2 / OIDC"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "À chaque redémarrage, les systèmes dans la base de données seront mis à jour pour correspondre aux systèmes définis dans le fichier." msgstr "À chaque redémarrage, les systèmes dans la base de données seront mis à jour pour correspondre aux systèmes définis dans le fichier."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Ouvrir le menu" msgstr "Ouvrir le menu"
@@ -682,7 +725,7 @@ msgstr "Ouvrir le menu"
msgid "Or continue with" msgid "Or continue with"
msgstr "Ou continuer avec" msgstr "Ou continuer avec"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Écraser les alertes existantes" msgstr "Écraser les alertes existantes"
@@ -725,16 +768,20 @@ msgstr "Pause"
msgid "Paused" msgid "Paused"
msgstr "En pause" msgstr "En pause"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Veuillez <0>configurer un serveur SMTP</0> pour garantir la livraison des alertes." msgstr "Veuillez <0>configurer un serveur SMTP</0> pour garantir la livraison des alertes."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Veuillez vérifier les journaux pour plus de détails." msgstr "Veuillez vérifier les journaux pour plus de détails."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Veuillez vérifier vos identifiants et réessayer" msgstr "Veuillez vérifier vos identifiants et réessayer"
@@ -746,7 +793,7 @@ msgstr "Veuillez créer un compte administrateur"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Veuillez activer les pop-ups pour ce site" msgstr "Veuillez activer les pop-ups pour ce site"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Veuillez vous reconnecter" msgstr "Veuillez vous reconnecter"
@@ -812,8 +859,8 @@ msgstr ""
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Enregistrez l'adresse en utilisant la touche Entrée ou la virgule. Laissez vide pour désactiver les notifications par email." msgstr "Enregistrez l'adresse en utilisant la touche Entrée ou la virgule. Laissez vide pour désactiver les notifications par email."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Enregistrer les paramètres" msgstr "Enregistrer les paramètres"
@@ -829,7 +876,7 @@ msgstr "Recherche"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Rechercher des systèmes ou des paramètres..." msgstr "Rechercher des systèmes ou des paramètres..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Voir les <0>paramètres de notification</0> pour configurer comment vous recevez les alertes." msgstr "Voir les <0>paramètres de notification</0> pour configurer comment vous recevez les alertes."
@@ -873,7 +920,8 @@ msgstr "Trier par"
msgid "State" msgid "State"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Statut" msgstr "Statut"
@@ -885,12 +933,10 @@ msgstr "Espace Swap utilisé par le système"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Utilisation du swap" msgstr "Utilisation du swap"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "Système" msgstr "Système"
@@ -915,8 +961,8 @@ msgstr "Tableau"
msgid "Temp" msgid "Temp"
msgstr "Temp." msgstr "Temp."
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Température" msgstr "Température"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "" msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "Tokens et Empreintes" msgstr "Tokens et Empreintes"
@@ -988,39 +1034,39 @@ msgstr "Les tokens permettent aux agents de se connecter et de s'enregistrer. Le
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "Les tokens et les empreintes sont utilisés pour authentifier les connexions WebSocket vers le hub." msgstr "Les tokens et les empreintes sont utilisés pour authentifier les connexions WebSocket vers le hub."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Déclenchement lorsque tout capteur dépasse un seuil" msgstr "Déclenchement lorsque tout capteur dépasse un seuil"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Déclenchement lorsque le montant/descendant combinée dépasse un seuil" msgstr "Déclenchement lorsque le montant/descendant combinée dépasse un seuil"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Déclenchement lorsque l'utilisation du CPU dépasse un seuil" msgstr "Déclenchement lorsque l'utilisation du CPU dépasse un seuil"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Déclenchement lorsque l'utilisation de la mémoire dépasse un seuil" msgstr "Déclenchement lorsque l'utilisation de la mémoire dépasse un seuil"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Se déclenche lorsque le statut passe de \"Joignable\" à \"Injoignable\"" msgstr "Se déclenche lorsque le statut passe de \"Joignable\" à \"Injoignable\""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Déclenchement lorsque l'utilisation de tout disque dépasse un seuil" msgstr "Déclenchement lorsque l'utilisation de tout disque dépasse un seuil"
@@ -1029,19 +1075,25 @@ msgstr "Déclenchement lorsque l'utilisation de tout disque dépasse un seuil"
msgid "Unit preferences" msgid "Unit preferences"
msgstr "" msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "Token universel" msgstr "Token universel"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Inconnue"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "Joignable" msgstr "Joignable"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Mis à jour en temps réel. Cliquez sur un système pour voir les informations." msgstr ""
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "Utilisation"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Utilisation de la partition racine" msgstr "Utilisation de la partition racine"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Utilisé" msgstr "Utilisé"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Utilisateurs" msgstr "Utilisateurs"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: hr\n" "Language: hr\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Croatian\n" "Language-Team: Croatian\n"
"Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n" "Plural-Forms: nplurals=3; plural=(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# dan} other {# dani}}" msgstr "{0, plural, one {# dan} other {# dani}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
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 ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr ""
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# sat} other {# sati}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 sat" msgstr "1 sat"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "" msgstr ""
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Akcije" msgstr "Akcije"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Agent" msgstr "Agent"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "" msgstr ""
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Upozorenja" msgstr "Upozorenja"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Svi Sistemi" msgstr "Svi Sistemi"
@@ -148,8 +155,8 @@ msgstr "Prosjek"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Prosječna iskorištenost procesora u spremnicima" msgstr "Prosječna iskorištenost procesora u spremnicima"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "Prosjek premašuje <0>{value}{0}</0>" msgstr "Prosjek premašuje <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Prosječna iskorištenost procesora na cijelom sustavu"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "" msgstr ""
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Sigurnosne kopije" msgstr "Sigurnosne kopije"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Propusnost" msgstr "Propusnost"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Baterija"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel podržava OpenID Connect i mnoge druge OAuth2 davatalje autentifikacije." msgstr "Beszel podržava OpenID Connect i mnoge druge OAuth2 davatalje autentifikacije."
@@ -202,8 +213,8 @@ msgstr ""
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Predmemorija / Međuspremnici" msgstr "Predmemorija / Međuspremnici"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Otkaži" msgstr "Otkaži"
@@ -223,6 +234,15 @@ msgstr ""
msgid "Change general application options." msgid "Change general application options."
msgstr "Promijenite opće opcije aplikacije." msgstr "Promijenite opće opcije aplikacije."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Punjenje"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Puni se"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Opcije grafikona" msgstr "Opcije grafikona"
@@ -239,6 +259,10 @@ msgstr "Provjerite logove za više detalja."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Provjerite Vaš servis notifikacija" msgstr "Provjerite Vaš servis notifikacija"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr ""
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Pritisnite za kopiranje" msgstr "Pritisnite za kopiranje"
@@ -261,8 +285,8 @@ msgstr "Potvrdite lozinku"
msgid "Connection is down" msgid "Connection is down"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Nastavite" msgstr "Nastavite"
@@ -320,9 +344,9 @@ msgstr ""
msgid "CPU" msgid "CPU"
msgstr "Procesor" msgstr "Procesor"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "Iskorištenost procesora" msgstr "Iskorištenost procesora"
@@ -339,10 +363,10 @@ msgstr ""
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Kritično (%)" msgstr "Kritično (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Tamno" msgstr "Trenutno stanje"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Nadzorna ploča"
msgid "Default time period" msgid "Default time period"
msgstr "Zadano vremensko razdoblje" msgstr "Zadano vremensko razdoblje"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Izbriši" msgstr "Izbriši"
@@ -362,6 +386,11 @@ msgstr "Izbriši"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "" msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Prazni se"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Disk" msgstr "Disk"
@@ -374,9 +403,9 @@ msgstr "Disk I/O"
msgid "Disk unit" msgid "Disk unit"
msgstr "" msgstr ""
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Iskorištenost Diska" msgstr "Iskorištenost Diska"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "Dokumentacija" msgstr "Dokumentacija"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr ""
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "" msgstr ""
@@ -417,8 +450,8 @@ msgstr ""
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -426,6 +459,11 @@ msgstr "Email"
msgid "Email notifications" msgid "Email notifications"
msgstr "Email notifikacije" msgstr "Email notifikacije"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Prazna"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Unesite email adresu za resetiranje lozinke" msgstr "Unesite email adresu za resetiranje lozinke"
@@ -434,11 +472,11 @@ msgstr "Unesite email adresu za resetiranje lozinke"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Unesite email adresu..." msgstr "Unesite email adresu..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Greška" msgstr "Greška"
@@ -469,12 +507,12 @@ msgstr "Izvoz trenutne sistemske konfiguracije."
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Provjera autentičnosti nije uspjela" msgstr "Provjera autentičnosti nije uspjela"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Neuspješno snimanje postavki" msgstr "Neuspješno snimanje postavki"
@@ -482,13 +520,13 @@ msgstr "Neuspješno snimanje postavki"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Neuspješno slanje testne notifikacije" msgstr "Neuspješno slanje testne notifikacije"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Ažuriranje upozorenja nije uspjelo" msgstr "Ažuriranje upozorenja nije uspjelo"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Filter..." msgstr "Filter..."
@@ -496,7 +534,7 @@ msgstr "Filter..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "" msgstr ""
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "Za <0>{min}</0> {min, plural, one {minutu} other {minute}}" msgstr "Za <0>{min}</0> {min, plural, one {minutu} other {minute}}"
@@ -504,9 +542,14 @@ msgstr "Za <0>{min}</0> {min, plural, one {minutu} other {minute}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Zaboravljena lozinka?" msgstr "Zaboravljena lozinka?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Puna"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Općenito" msgstr "Općenito"
@@ -528,6 +571,11 @@ msgstr "Homebrew naredba"
msgid "Host / IP" msgid "Host / IP"
msgstr "Host / IP" msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Neaktivna"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "Ako ste izgubili lozinku za svoj administratorski račun, možete ju resetirati pomoću sljedeće naredbe."
@@ -549,24 +597,19 @@ msgstr "Jezik"
msgid "Layout" msgid "Layout"
msgstr "Izgled" msgstr "Izgled"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Svijetlo"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "" msgstr ""
@@ -583,13 +626,13 @@ msgstr "Odjava"
msgid "Login" msgid "Login"
msgstr "Prijava" msgstr "Prijava"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Pokušaj prijave nije uspio" msgstr "Pokušaj prijave nije uspio"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Logovi" msgstr "Logovi"
@@ -614,8 +657,8 @@ msgstr "Maksimalno 1 minuta"
msgid "Memory" msgid "Memory"
msgstr "Memorija" msgstr "Memorija"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Upotreba memorije" msgstr "Upotreba memorije"
@@ -623,8 +666,8 @@ msgstr "Upotreba memorije"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Upotreba memorije Docker spremnika" msgstr "Upotreba memorije Docker spremnika"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Ime" msgstr "Ime"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Nije pronađen nijedan sustav." msgstr "Nije pronađen nijedan sustav."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Obavijesti" msgstr "Obavijesti"
@@ -672,9 +715,9 @@ msgstr "Podrška za OAuth 2 / OIDC"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "Prilikom svakog ponovnog pokretanja, sustavi u bazi podataka biti će ažurirani kako bi odgovarali sustavima definiranim u datoteci." msgstr "Prilikom svakog ponovnog pokretanja, sustavi u bazi podataka biti će ažurirani kako bi odgovarali sustavima definiranim u datoteci."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Otvori menu" msgstr "Otvori menu"
@@ -682,7 +725,7 @@ msgstr "Otvori menu"
msgid "Or continue with" msgid "Or continue with"
msgstr "Ili nastavi sa" msgstr "Ili nastavi sa"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Prebrišite postojeća upozorenja" msgstr "Prebrišite postojeća upozorenja"
@@ -725,16 +768,20 @@ msgstr "Pauza"
msgid "Paused" msgid "Paused"
msgstr "Pauzirano" msgstr "Pauzirano"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Molimo <0>konfigurirajte SMTP server</0> kako biste osigurali isporuku upozorenja." msgstr "Molimo <0>konfigurirajte SMTP server</0> kako biste osigurali isporuku upozorenja."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Za više detalja provjerite logove." msgstr "Za više detalja provjerite logove."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Provjerite svoje podatke i pokušajte ponovno" msgstr "Provjerite svoje podatke i pokušajte ponovno"
@@ -746,7 +793,7 @@ msgstr "Molimo kreirajte administratorski račun"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Omogućite skočne prozore za ovu stranicu" msgstr "Omogućite skočne prozore za ovu stranicu"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Molimo prijavite se ponovno" msgstr "Molimo prijavite se ponovno"
@@ -812,8 +859,8 @@ msgstr ""
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Spremite adresu pomoću tipke enter ili zareza. Ostavite prazno kako biste onemogućili obavijesti e-poštom." msgstr "Spremite adresu pomoću tipke enter ili zareza. Ostavite prazno kako biste onemogućili obavijesti e-poštom."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Spremi Postavke" msgstr "Spremi Postavke"
@@ -829,7 +876,7 @@ msgstr "Pretraži"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Pretraži za sisteme ili postavke..." msgstr "Pretraži za sisteme ili postavke..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Pogledajte <0>postavke obavijesti</0> da biste konfigurirali način primanja upozorenja." msgstr "Pogledajte <0>postavke obavijesti</0> da biste konfigurirali način primanja upozorenja."
@@ -873,7 +920,8 @@ msgstr "Sortiraj po"
msgid "State" msgid "State"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Status" msgstr "Status"
@@ -885,12 +933,10 @@ msgstr "Swap prostor uzet od strane sistema"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Swap Iskorištenost" msgstr "Swap Iskorištenost"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "Sistem" msgstr "Sistem"
@@ -915,8 +961,8 @@ msgstr "Tablica"
msgid "Temp" msgid "Temp"
msgstr "" msgstr ""
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Temperatura" msgstr "Temperatura"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "" msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "" msgstr ""
@@ -988,39 +1034,39 @@ msgstr ""
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Pokreće se kada bilo koji senzor prijeđe prag" msgstr "Pokreće se kada bilo koji senzor prijeđe prag"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Pokreće se kada kombinacija gore/dolje premaši prag" msgstr "Pokreće se kada kombinacija gore/dolje premaši prag"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Pokreće se kada iskorištenost procesora premaši prag" msgstr "Pokreće se kada iskorištenost procesora premaši prag"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Pokreće se kada iskorištenost memorije premaši prag" msgstr "Pokreće se kada iskorištenost memorije premaši prag"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Pokreće se kada se status sistema promijeni" msgstr "Pokreće se kada se status sistema promijeni"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Pokreće se kada iskorištenost bilo kojeg diska premaši prag" msgstr "Pokreće se kada iskorištenost bilo kojeg diska premaši prag"
@@ -1029,19 +1075,25 @@ msgstr "Pokreće se kada iskorištenost bilo kojeg diska premaši prag"
msgid "Unit preferences" msgid "Unit preferences"
msgstr "" msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "" msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Nepoznata"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Ažurirano odmah. Kliknite na sistem za više informacija." msgstr ""
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "Iskorištenost"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Iskorištenost root datotečnog sustava" msgstr "Iskorištenost root datotečnog sustava"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Iskorišteno" msgstr "Iskorišteno"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Korisnici" msgstr "Korisnici"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: hu\n" "Language: hu\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Hungarian\n" "Language-Team: Hungarian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# nap} other {# nap}}" msgstr "{0, plural, one {# nap} other {# nap}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
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 ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr ""
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# óra} other {# óra}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 óra" msgstr "1 óra"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "" msgstr ""
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Műveletek" msgstr "Műveletek"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Ügynök" msgstr "Ügynök"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "" msgstr ""
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Riasztások" msgstr "Riasztások"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Minden rendszer" msgstr "Minden rendszer"
@@ -148,8 +155,8 @@ msgstr "Átlag"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Konténerek átlagos CPU kihasználtsága" msgstr "Konténerek átlagos CPU kihasználtsága"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "Az átlag meghaladja a <0>{value}{0}</0> értéket" msgstr "Az átlag meghaladja a <0>{value}{0}</0> értéket"
@@ -166,16 +173,20 @@ msgstr "Rendszerszintű CPU átlagos kihasználtság"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "{0} átlagos kihasználtsága" msgstr "{0} átlagos kihasználtsága"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Biztonsági mentések" msgstr "Biztonsági mentések"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Sávszélesség" msgstr "Sávszélesség"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Akkumulátor"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "A Beszel támogatja az OpenID Connect-et és számos OAuth2 hitelesítési szolgáltatót." msgstr "A Beszel támogatja az OpenID Connect-et és számos OAuth2 hitelesítési szolgáltatót."
@@ -202,8 +213,8 @@ msgstr ""
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Gyorsítótár / Pufferelések" msgstr "Gyorsítótár / Pufferelések"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Mégsem" msgstr "Mégsem"
@@ -223,6 +234,15 @@ msgstr ""
msgid "Change general application options." msgid "Change general application options."
msgstr "Általános alkalmazásbeállítások módosítása." msgstr "Általános alkalmazásbeállítások módosítása."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Töltés"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Töltődik"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Diagram beállítások" msgstr "Diagram beállítások"
@@ -239,6 +259,10 @@ msgstr "Ellenőrizd a naplót a további részletekért."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Ellenőrizd az értesítési szolgáltatásodat" msgstr "Ellenőrizd az értesítési szolgáltatásodat"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr ""
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Kattints a másoláshoz" msgstr "Kattints a másoláshoz"
@@ -261,8 +285,8 @@ msgstr "Jelszó megerősítése"
msgid "Connection is down" msgid "Connection is down"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Tovább" msgstr "Tovább"
@@ -320,9 +344,9 @@ msgstr ""
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "CPU használat" msgstr "CPU használat"
@@ -339,10 +363,10 @@ msgstr ""
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Kritikus (%)" msgstr "Kritikus (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Sötét" msgstr "Jelenlegi állapot"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Áttekintés"
msgid "Default time period" msgid "Default time period"
msgstr "Alapértelmezett időszak" msgstr "Alapértelmezett időszak"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Törlés" msgstr "Törlés"
@@ -362,6 +386,11 @@ msgstr "Törlés"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "" msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Kisül"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Lemez" msgstr "Lemez"
@@ -374,9 +403,9 @@ msgstr "Lemez I/O"
msgid "Disk unit" msgid "Disk unit"
msgstr "" msgstr ""
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Lemezhasználat" msgstr "Lemezhasználat"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "Dokumentáció" msgstr "Dokumentáció"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr ""
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "" msgstr ""
@@ -417,8 +450,8 @@ msgstr ""
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -426,6 +459,11 @@ msgstr "Email"
msgid "Email notifications" msgid "Email notifications"
msgstr "E-mail értesítések" msgstr "E-mail értesítések"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Üres"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "E-mail cím megadása a jelszó visszaállításához" msgstr "E-mail cím megadása a jelszó visszaállításához"
@@ -434,11 +472,11 @@ msgstr "E-mail cím megadása a jelszó visszaállításához"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Adja meg az e-mail címet..." msgstr "Adja meg az e-mail címet..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Hiba" msgstr "Hiba"
@@ -469,12 +507,12 @@ msgstr "Exportálja a jelenlegi rendszerkonfigurációt."
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Hitelesítés sikertelen" msgstr "Hitelesítés sikertelen"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Nem sikerült menteni a beállításokat" msgstr "Nem sikerült menteni a beállításokat"
@@ -482,13 +520,13 @@ msgstr "Nem sikerült menteni a beállításokat"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Teszt értesítés elküldése sikertelen" msgstr "Teszt értesítés elküldése sikertelen"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Nem sikerült frissíteni a riasztást" msgstr "Nem sikerült frissíteni a riasztást"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Szűrő..." msgstr "Szűrő..."
@@ -496,7 +534,7 @@ msgstr "Szűrő..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "" msgstr ""
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "A <0>{min}</0> {min, plural, one {perc} other {percek}}" msgstr "A <0>{min}</0> {min, plural, one {perc} other {percek}}"
@@ -504,9 +542,14 @@ msgstr "A <0>{min}</0> {min, plural, one {perc} other {percek}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Elfelejtette a jelszavát?" msgstr "Elfelejtette a jelszavát?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Tele"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Általános" msgstr "Általános"
@@ -528,6 +571,11 @@ msgstr "Homebrew parancs"
msgid "Host / IP" msgid "Host / IP"
msgstr "Állomás / IP" msgstr "Állomás / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Tétlen"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "Ha elvesztette az admin fiók jelszavát, a következő paranccsal állíthatja vissza."
@@ -549,24 +597,19 @@ msgstr "Nyelv"
msgid "Layout" msgid "Layout"
msgstr "Elrendezés" msgstr "Elrendezés"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Világos"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "" msgstr ""
@@ -583,13 +626,13 @@ msgstr "Kijelentkezés"
msgid "Login" msgid "Login"
msgstr "Bejelentkezés" msgstr "Bejelentkezés"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Bejelentkezés sikertelen" msgstr "Bejelentkezés sikertelen"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Naplók" msgstr "Naplók"
@@ -614,8 +657,8 @@ msgstr "Maximum 1 perc"
msgid "Memory" msgid "Memory"
msgstr "RAM" msgstr "RAM"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Memóriahasználat" msgstr "Memóriahasználat"
@@ -623,8 +666,8 @@ msgstr "Memóriahasználat"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Docker konténerek memória használata" msgstr "Docker konténerek memória használata"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Név" msgstr "Név"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Nem található rendszer." msgstr "Nem található rendszer."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Értesítések" msgstr "Értesítések"
@@ -672,9 +715,9 @@ msgstr "OAuth 2 / OIDC támogatás"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "Minden újraindításkor az adatbázisban lévő rendszerek frissítésre kerülnek, hogy megfeleljenek a fájlban meghatározott rendszereknek." msgstr "Minden újraindításkor az adatbázisban lévő rendszerek frissítésre kerülnek, hogy megfeleljenek a fájlban meghatározott rendszereknek."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Menü megnyitása" msgstr "Menü megnyitása"
@@ -682,7 +725,7 @@ msgstr "Menü megnyitása"
msgid "Or continue with" msgid "Or continue with"
msgstr "Vagy folytasd ezzel" msgstr "Vagy folytasd ezzel"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Felülírja a meglévő riasztásokat" msgstr "Felülírja a meglévő riasztásokat"
@@ -725,16 +768,20 @@ msgstr "Szüneteltetés"
msgid "Paused" msgid "Paused"
msgstr "Szüneteltetve" msgstr "Szüneteltetve"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Kérjük, <0>konfigurálj egy SMTP szervert</0> az értesítések kézbesítésének biztosítása érdekében." msgstr "Kérjük, <0>konfigurálj egy SMTP szervert</0> az értesítések kézbesítésének biztosítása érdekében."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Kérjük, ellenőrizd a naplókat a további részletekért." msgstr "Kérjük, ellenőrizd a naplókat a további részletekért."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Kérjük, ellenőrizze a hitelesítő adatait, és próbálja újra" msgstr "Kérjük, ellenőrizze a hitelesítő adatait, és próbálja újra"
@@ -746,7 +793,7 @@ msgstr "Kérjük, hozzon létre egy admin fiókot"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Kérjük, engedélyezze a felugró ablakokat ezen az oldalon" msgstr "Kérjük, engedélyezze a felugró ablakokat ezen az oldalon"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Kérjük jelentkezz be újra" msgstr "Kérjük jelentkezz be újra"
@@ -812,8 +859,8 @@ msgstr ""
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Mentse el a címet az Enter billentyű vagy a vessző használatával. Hagyja üresen az e-mail értesítések letiltásához." msgstr "Mentse el a címet az Enter billentyű vagy a vessző használatával. Hagyja üresen az e-mail értesítések letiltásához."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Beállítások mentése" msgstr "Beállítások mentése"
@@ -829,7 +876,7 @@ msgstr "Keresés"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Keresés rendszerek vagy beállítások után..." msgstr "Keresés rendszerek vagy beállítások után..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Lásd <0>az értesítési beállításokat</0>, hogy konfigurálja, hogyan kap értesítéseket." msgstr "Lásd <0>az értesítési beállításokat</0>, hogy konfigurálja, hogyan kap értesítéseket."
@@ -873,7 +920,8 @@ msgstr "Rendezés"
msgid "State" msgid "State"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Állapot" msgstr "Állapot"
@@ -885,12 +933,10 @@ msgstr "Rendszer által használt swap terület"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Swap használat" msgstr "Swap használat"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "Rendszer" msgstr "Rendszer"
@@ -915,8 +961,8 @@ msgstr "Tábla"
msgid "Temp" msgid "Temp"
msgstr "" msgstr ""
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Hőmérséklet" msgstr "Hőmérséklet"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "" msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "" msgstr ""
@@ -988,39 +1034,39 @@ msgstr ""
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Bekapcsol, ha bármelyik érzékelő túllép egy küszöbértéket" msgstr "Bekapcsol, ha bármelyik érzékelő túllép egy küszöbértéket"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Bekapcsol, ha bármelyik érzékelő túllép egy küszöbértéket" msgstr "Bekapcsol, ha bármelyik érzékelő túllép egy küszöbértéket"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Bekapcsol, ha a CPU érzékelő túllép egy küszöbértéket" msgstr "Bekapcsol, ha a CPU érzékelő túllép egy küszöbértéket"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Bekapcsol, ha a Ram érzékelő túllép egy küszöbértéket" msgstr "Bekapcsol, ha a Ram érzékelő túllép egy küszöbértéket"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Bekapcsol, amikor az állapot fel és le között változik" msgstr "Bekapcsol, amikor az állapot fel és le között változik"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Bekapcsol, ha a lemez érzékelő túllép egy küszöbértéket" msgstr "Bekapcsol, ha a lemez érzékelő túllép egy küszöbértéket"
@@ -1029,19 +1075,25 @@ msgstr "Bekapcsol, ha a lemez érzékelő túllép egy küszöbértéket"
msgid "Unit preferences" msgid "Unit preferences"
msgstr "" msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "" msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Ismeretlen"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Valós időben frissítve. Kattintson egy rendszerre az információk megtekintéséhez." msgstr ""
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "Használat"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Root partíció kihasználtsága" msgstr "Root partíció kihasználtsága"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Felhasznált" msgstr "Felhasznált"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Felhasználók" msgstr "Felhasználók"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: is\n" "Language: is\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Icelandic\n" "Language-Team: Icelandic\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# dagur} other {# dagar}}" msgstr "{0, plural, one {# dagur} other {# dagar}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# klukkustund} other {# klukkustundir}}"
#. 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 ""
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr ""
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# klukkustund} other {# klukkustundir}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1 klukkustund" msgstr "1 klukkustund"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "" msgstr ""
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Aðgerðir" msgstr "Aðgerðir"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "" msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "" msgstr ""
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Tilkynningar" msgstr "Tilkynningar"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Öll kerfi" msgstr "Öll kerfi"
@@ -148,8 +155,8 @@ msgstr "Meðal"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Meðal örgjörva notkun container-a." msgstr "Meðal örgjörva notkun container-a."
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "Meðaltal er yfir <0>{value}{0}</0>" msgstr "Meðaltal er yfir <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Meðal nýting örgjörva yfir allt kerfið"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Meðal notkun af {0}" msgstr "Meðal notkun af {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Öryggisafrit" msgstr "Öryggisafrit"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Gangnaflutningsgeta" msgstr "Gangnaflutningsgeta"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Rafhlaða"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel styður OpenID Connect og margar OAuth2 auðkenningarveitendur." msgstr "Beszel styður OpenID Connect og margar OAuth2 auðkenningarveitendur."
@@ -202,8 +213,8 @@ msgstr ""
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Skyndiminni / Biðminni" msgstr "Skyndiminni / Biðminni"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Hætta við" msgstr "Hætta við"
@@ -223,6 +234,15 @@ msgstr ""
msgid "Change general application options." msgid "Change general application options."
msgstr "Breyta almennum stillingum." msgstr "Breyta almennum stillingum."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Hleðsla"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "Hleðst"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Valkostir fyrir línurit" msgstr "Valkostir fyrir línurit"
@@ -239,6 +259,10 @@ msgstr "Skoðaðu logga til að sjá meiri upplýsingar."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Athugaðu tilkynningaþjónustuna þína" msgstr "Athugaðu tilkynningaþjónustuna þína"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr ""
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Smelltu til að afrita" msgstr "Smelltu til að afrita"
@@ -261,8 +285,8 @@ msgstr "Staðfestu lykilorð"
msgid "Connection is down" msgid "Connection is down"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Halda áfram" msgstr "Halda áfram"
@@ -320,9 +344,9 @@ msgstr ""
msgid "CPU" msgid "CPU"
msgstr "Örgjörvi" msgstr "Örgjörvi"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "Örgjörva notkun" msgstr "Örgjörva notkun"
@@ -339,10 +363,10 @@ msgstr ""
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Kritískt (%)" msgstr "Kritískt (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Dökkt" msgstr "Núverandi ástand"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Yfirlitssíða"
msgid "Default time period" msgid "Default time period"
msgstr "Sjálfgefið tímabil" msgstr "Sjálfgefið tímabil"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Eyða" msgstr "Eyða"
@@ -362,6 +386,11 @@ msgstr "Eyða"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "" msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "Ryðst"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Diskur" msgstr "Diskur"
@@ -374,9 +403,9 @@ msgstr ""
msgid "Disk unit" msgid "Disk unit"
msgstr "" msgstr ""
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Diskanotkun" msgstr "Diskanotkun"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "Skjal" msgstr "Skjal"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr ""
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "" msgstr ""
@@ -417,8 +450,8 @@ msgstr ""
msgid "Edit" msgid "Edit"
msgstr "" msgstr ""
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Netfang" msgstr "Netfang"
@@ -426,6 +459,11 @@ msgstr "Netfang"
msgid "Email notifications" msgid "Email notifications"
msgstr "Tilkynningar í tölvupósti" msgstr "Tilkynningar í tölvupósti"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Tóm"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Settu netfang til að endursetja lykilorð" msgstr "Settu netfang til að endursetja lykilorð"
@@ -434,11 +472,11 @@ msgstr "Settu netfang til að endursetja lykilorð"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Settu inn Netfang..." msgstr "Settu inn Netfang..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Villa" msgstr "Villa"
@@ -469,12 +507,12 @@ msgstr ""
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Villa í auðkenningu" msgstr "Villa í auðkenningu"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Villa við að vista stillingar" msgstr "Villa við að vista stillingar"
@@ -482,13 +520,13 @@ msgstr "Villa við að vista stillingar"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Villa í sendingu prufu skilaboða" msgstr "Villa í sendingu prufu skilaboða"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Mistókst að uppfæra tilkynningu" msgstr "Mistókst að uppfæra tilkynningu"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Sía..." msgstr "Sía..."
@@ -496,7 +534,7 @@ msgstr "Sía..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "" msgstr ""
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "" msgstr ""
@@ -504,9 +542,14 @@ msgstr ""
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Gleymt lykilorð?" msgstr "Gleymt lykilorð?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Full"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Almennt" msgstr "Almennt"
@@ -528,6 +571,11 @@ msgstr "Homebrew skipun"
msgid "Host / IP" msgid "Host / IP"
msgstr "Host / IP" msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Aðgerðalaus"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." msgid "If you've lost the password to your admin account, you may reset it using the following command."
msgstr "" msgstr ""
@@ -549,24 +597,19 @@ msgstr "Tungumál"
msgid "Layout" msgid "Layout"
msgstr "" msgstr ""
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Ljóst"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "" msgstr ""
@@ -583,13 +626,13 @@ msgstr "Útskrá"
msgid "Login" msgid "Login"
msgstr "Innskrá" msgstr "Innskrá"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Innskránings tilraun misheppnaðist" msgstr "Innskránings tilraun misheppnaðist"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Loggar" msgstr "Loggar"
@@ -614,8 +657,8 @@ msgstr "Mest 1 mínúta"
msgid "Memory" msgid "Memory"
msgstr "Minni" msgstr "Minni"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Minnisnotkun" msgstr "Minnisnotkun"
@@ -623,8 +666,8 @@ msgstr "Minnisnotkun"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Minnisnotkun docker kerfa" msgstr "Minnisnotkun docker kerfa"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Nafn" msgstr "Nafn"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Engin kerfi fundust." msgstr "Engin kerfi fundust."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Tilkynningar" msgstr "Tilkynningar"
@@ -672,9 +715,9 @@ msgstr "OAuth 2 / OIDC stuðningur"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "" msgstr ""
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Opna valmynd" msgstr "Opna valmynd"
@@ -682,7 +725,7 @@ msgstr "Opna valmynd"
msgid "Or continue with" msgid "Or continue with"
msgstr "Eða halda áfram með" msgstr "Eða halda áfram með"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Yfirskrifa núverandi tilkynningu" msgstr "Yfirskrifa núverandi tilkynningu"
@@ -725,16 +768,20 @@ msgstr "Pása"
msgid "Paused" msgid "Paused"
msgstr "Í bið" msgstr "Í bið"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr ""
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "" msgstr ""
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Skoðaðu logga til að sjá meiri upplýsingar." msgstr "Skoðaðu logga til að sjá meiri upplýsingar."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Vinsamlegast farðu yfir upplýsingarnar þínar og reyndu aftur" msgstr "Vinsamlegast farðu yfir upplýsingarnar þínar og reyndu aftur"
@@ -746,7 +793,7 @@ msgstr "Vinsamlegast búðu til admin aðgang"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Vinsamlegast skráðu þið inn aftur" msgstr "Vinsamlegast skráðu þið inn aftur"
@@ -812,8 +859,8 @@ msgstr ""
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "" msgstr ""
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Vista stillingar" msgstr "Vista stillingar"
@@ -829,7 +876,7 @@ msgstr "Leita"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Leita að kerfum eða stillingum..." msgstr "Leita að kerfum eða stillingum..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "" msgstr ""
@@ -873,7 +920,8 @@ msgstr "Raða eftir"
msgid "State" msgid "State"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Staða" msgstr "Staða"
@@ -885,12 +933,10 @@ msgstr ""
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Skipti minni" msgstr "Skipti minni"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "Kerfi" msgstr "Kerfi"
@@ -915,8 +961,8 @@ msgstr "Tafla"
msgid "Temp" msgid "Temp"
msgstr "" msgstr ""
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Hitastig" msgstr "Hitastig"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "" msgstr ""
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "" msgstr ""
@@ -988,39 +1034,39 @@ msgstr ""
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "" msgstr ""
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Virkjast þegar einhver skynjari fer yfir þröskuld" msgstr "Virkjast þegar einhver skynjari fer yfir þröskuld"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Virkjast þegar samanlagt sent/móttekið fer yfir þröskuld" msgstr "Virkjast þegar samanlagt sent/móttekið fer yfir þröskuld"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Virkjast þegar örgjörva notkun fer yfir þröskuld" msgstr "Virkjast þegar örgjörva notkun fer yfir þröskuld"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Virkjast þegar minnisnotkun fer yfir þröskuld" msgstr "Virkjast þegar minnisnotkun fer yfir þröskuld"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Virkjast þegar staða breytist milli virkur og óvirkur" msgstr "Virkjast þegar staða breytist milli virkur og óvirkur"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Virkjast þegar diska notkun fer yfir þröskuld" msgstr "Virkjast þegar diska notkun fer yfir þröskuld"
@@ -1029,19 +1075,25 @@ msgstr "Virkjast þegar diska notkun fer yfir þröskuld"
msgid "Unit preferences" msgid "Unit preferences"
msgstr "" msgstr ""
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "" msgstr ""
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Óþekkt"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "" msgstr ""
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Uppfærist í rauntíma. Veldu kerfi til að skoða upplýsingar." msgstr ""
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr ""
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "" msgstr ""
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Notað" msgstr "Notað"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Notendur" msgstr "Notendur"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: it\n" "Language: it\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Italian\n" "Language-Team: Italian\n"
"Plural-Forms: nplurals=2; plural=(n != 1);\n" "Plural-Forms: nplurals=2; plural=(n != 1);\n"
@@ -23,15 +23,21 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# giorno} other {# giorni}}" msgstr "{0, plural, one {# giorno} other {# giorni}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# ora} other {# ore}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# minuto} other {# minuti}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "" msgstr "{0} di {1} righe selezionate."
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# ora} other {# ore}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
@@ -40,7 +46,7 @@ msgstr "1 ora"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "1 min" msgid "1 min"
msgstr "" msgstr "1 min"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 week" msgid "1 week"
@@ -53,7 +59,7 @@ msgstr "12 ore"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "15 min" msgid "15 min"
msgstr "" msgstr "15 min"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "24 hours" msgid "24 hours"
@@ -66,18 +72,18 @@ msgstr "30 giorni"
#. Load average #. Load average
#: src/components/charts/load-average-chart.tsx #: src/components/charts/load-average-chart.tsx
msgid "5 min" msgid "5 min"
msgstr "" msgstr "5 min"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "Azioni" msgstr "Azioni"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Active" msgid "Active"
msgstr "" msgstr "Attivo"
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
msgid "Active Alerts" msgid "Active Alerts"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "Agente" msgstr "Agente"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "" msgstr "Cronologia Avvisi"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "Avvisi" msgstr "Avvisi"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "Tutti i Sistemi" msgstr "Tutti i Sistemi"
@@ -134,7 +141,7 @@ msgstr "Sei sicuro di voler eliminare {name}?"
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Are you sure?" msgid "Are you sure?"
msgstr "" msgstr "Sei sicuro?"
#: src/components/copy-to-clipboard.tsx #: src/components/copy-to-clipboard.tsx
msgid "Automatic copy requires a secure context." msgid "Automatic copy requires a secure context."
@@ -148,8 +155,8 @@ msgstr "Media"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Utilizzo medio della CPU dei container" msgstr "Utilizzo medio della CPU dei container"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "La media supera <0>{value}{0}</0>" msgstr "La media supera <0>{value}{0}</0>"
@@ -166,16 +173,20 @@ msgstr "Utilizzo medio della CPU a livello di sistema"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "Utilizzo medio di {0}" msgstr "Utilizzo medio di {0}"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "Backup" msgstr "Backup"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "Larghezza di banda" msgstr "Larghezza di banda"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "Batteria"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel supporta OpenID Connect e molti provider di autenticazione OAuth2." msgstr "Beszel supporta OpenID Connect e molti provider di autenticazione OAuth2."
@@ -191,19 +202,19 @@ msgstr "Binario"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bits (Kbps, Mbps, Gbps)" msgid "Bits (Kbps, Mbps, Gbps)"
msgstr "" msgstr "Bit (Kbps, Mbps, Gbps)"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Bytes (KB/s, MB/s, GB/s)" msgid "Bytes (KB/s, MB/s, GB/s)"
msgstr "" msgstr "Byte (KB/s, MB/s, GB/s)"
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "Cache / Buffer" msgstr "Cache / Buffer"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "Annulla" msgstr "Annulla"
@@ -213,16 +224,25 @@ msgstr "Attenzione - possibile perdita di dati"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Celsius (°C)" msgid "Celsius (°C)"
msgstr "" msgstr "Celsius (°C)"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Change display units for metrics." msgid "Change display units for metrics."
msgstr "" msgstr "Modifica le unità di visualizzazione per le metriche."
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Change general application options." msgid "Change general application options."
msgstr "Modifica le opzioni generali dell'applicazione." msgstr "Modifica le opzioni generali dell'applicazione."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "Carica"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "In carica"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "Opzioni del grafico" msgstr "Opzioni del grafico"
@@ -239,6 +259,10 @@ msgstr "Controlla i log per maggiori dettagli."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "Controlla il tuo servizio di notifica" msgstr "Controlla il tuo servizio di notifica"
#: 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."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "Clicca per copiare" msgstr "Clicca per copiare"
@@ -259,10 +283,10 @@ msgstr "Conferma password"
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
msgid "Connection is down" msgid "Connection is down"
msgstr "" msgstr "La connessione è interrotta"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "Continua" msgstr "Continua"
@@ -320,9 +344,9 @@ msgstr "Copia YAML"
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "Utilizzo CPU" msgstr "Utilizzo CPU"
@@ -333,16 +357,16 @@ msgstr "Crea account"
#. Context: date created #. Context: date created
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Created" msgid "Created"
msgstr "" msgstr "Creato"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Critical (%)" msgid "Critical (%)"
msgstr "Critico (%)" msgstr "Critico (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "Scuro" msgstr "Stato attuale"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "Cruscotto"
msgid "Default time period" msgid "Default time period"
msgstr "Periodo di tempo predefinito" msgstr "Periodo di tempo predefinito"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "Elimina" msgstr "Elimina"
@@ -362,6 +386,11 @@ msgstr "Elimina"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "Elimina impronta digitale" msgstr "Elimina impronta digitale"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "In scarica"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "Disco" msgstr "Disco"
@@ -372,11 +401,11 @@ msgstr "I/O Disco"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Disk unit" msgid "Disk unit"
msgstr "" msgstr "Unità disco"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "Utilizzo Disco" msgstr "Utilizzo Disco"
@@ -401,24 +430,28 @@ msgid "Documentation"
msgstr "Documentazione" msgstr "Documentazione"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "Offline" msgstr "Offline"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "Offline ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "" msgstr "Durata"
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Edit" msgid "Edit"
msgstr "Modifica" msgstr "Modifica"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "Email" msgstr "Email"
@@ -426,6 +459,11 @@ msgstr "Email"
msgid "Email notifications" msgid "Email notifications"
msgstr "Notifiche email" msgstr "Notifiche email"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "Vuota"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "Inserisci l'indirizzo email per reimpostare la password" msgstr "Inserisci l'indirizzo email per reimpostare la password"
@@ -434,11 +472,11 @@ msgstr "Inserisci l'indirizzo email per reimpostare la password"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "Inserisci l'indirizzo email..." msgstr "Inserisci l'indirizzo email..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "Errore" msgstr "Errore"
@@ -455,7 +493,7 @@ msgstr "I sistemi esistenti non definiti in <0>config.yml</0> verranno eliminati
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Export" msgid "Export"
msgstr "" msgstr "Esporta"
#: src/components/routes/settings/config-yaml.tsx #: src/components/routes/settings/config-yaml.tsx
msgid "Export configuration" msgid "Export configuration"
@@ -467,14 +505,14 @@ msgstr "Esporta la configurazione attuale dei tuoi sistemi."
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "" msgstr "Fahrenheit (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "Autenticazione fallita" msgstr "Autenticazione fallita"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "Salvataggio delle impostazioni fallito" msgstr "Salvataggio delle impostazioni fallito"
@@ -482,21 +520,21 @@ msgstr "Salvataggio delle impostazioni fallito"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "Invio della notifica di test fallito" msgstr "Invio della notifica di test fallito"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "Aggiornamento dell'avviso fallito" msgstr "Aggiornamento dell'avviso fallito"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "Filtra..." msgstr "Filtra..."
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Fingerprint" msgid "Fingerprint"
msgstr "" msgstr "Impronta digitale"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "Per <0>{min}</0> {min, plural, one {minuto} other {minuti}}" msgstr "Per <0>{min}</0> {min, plural, one {minuto} other {minuti}}"
@@ -504,9 +542,14 @@ msgstr "Per <0>{min}</0> {min, plural, one {minuto} other {minuti}}"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "Password dimenticata?" msgstr "Password dimenticata?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "Piena"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "Generale" msgstr "Generale"
@@ -528,6 +571,11 @@ msgstr "Comando Homebrew"
msgid "Host / IP" msgid "Host / IP"
msgstr "Host / IP" msgstr "Host / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "Inattiva"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." 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." msgstr "Se hai perso la password del tuo account amministratore, puoi reimpostarla utilizzando il seguente comando."
@@ -549,31 +597,26 @@ msgstr "Lingua"
msgid "Layout" msgid "Layout"
msgstr "Aspetto" msgstr "Aspetto"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "Chiaro"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "" msgstr "Carico medio"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "Caricamento medio 15m" msgstr "Caricamento medio 15m"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "" msgstr "Caricamento medio 1m"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "Caricamento medio 5m" msgstr "Caricamento medio 5m"
#. Short label for load average #. Short label for load average
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Load Avg" msgid "Load Avg"
msgstr "" msgstr "Carico Medio"
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Log Out" msgid "Log Out"
@@ -583,13 +626,13 @@ msgstr "Disconnetti"
msgid "Login" msgid "Login"
msgstr "Accedi" msgstr "Accedi"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "Tentativo di accesso fallito" msgstr "Tentativo di accesso fallito"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "Log" msgstr "Log"
@@ -614,8 +657,8 @@ msgstr "Max 1 min"
msgid "Memory" msgid "Memory"
msgstr "Memoria" msgstr "Memoria"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "Utilizzo Memoria" msgstr "Utilizzo Memoria"
@@ -623,8 +666,8 @@ msgstr "Utilizzo Memoria"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Utilizzo della memoria dei container Docker" msgstr "Utilizzo della memoria dei container Docker"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "Nome" msgstr "Nome"
@@ -643,7 +686,7 @@ msgstr "Traffico di rete delle interfacce pubbliche"
#. Context: Bytes or bits #. Context: Bytes or bits
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Network unit" msgid "Network unit"
msgstr "" msgstr "Unità rete"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
msgid "No results found." msgid "No results found."
@@ -651,7 +694,7 @@ msgstr "Nessun risultato trovato."
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "No results." msgid "No results."
msgstr "" msgstr "Nessun risultato."
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "Nessun sistema trovato." msgstr "Nessun sistema trovato."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "Notifiche" msgstr "Notifiche"
@@ -672,9 +715,9 @@ msgstr "Supporto OAuth 2 / OIDC"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "Ad ogni riavvio, i sistemi nel database verranno aggiornati per corrispondere ai sistemi definiti nel file." msgstr "Ad ogni riavvio, i sistemi nel database verranno aggiornati per corrispondere ai sistemi definiti nel file."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "Apri menu" msgstr "Apri menu"
@@ -682,7 +725,7 @@ msgstr "Apri menu"
msgid "Or continue with" msgid "Or continue with"
msgstr "Oppure continua con" msgstr "Oppure continua con"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "Sovrascrivi avvisi esistenti" msgstr "Sovrascrivi avvisi esistenti"
@@ -694,7 +737,7 @@ msgstr "Pagina"
#. placeholder {1}: table.getPageCount() #. placeholder {1}: table.getPageCount()
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Page {0} of {1}" msgid "Page {0} of {1}"
msgstr "" msgstr "Pagina {0} di {1}"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
msgid "Pages / Settings" msgid "Pages / Settings"
@@ -725,16 +768,20 @@ msgstr "Pausa"
msgid "Paused" msgid "Paused"
msgstr "In pausa" msgstr "In pausa"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "In pausa ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "Si prega di <0>configurare un server SMTP</0> per garantire la consegna degli avvisi." msgstr "Si prega di <0>configurare un server SMTP</0> per garantire la consegna degli avvisi."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "Si prega di controllare i log per maggiori dettagli." msgstr "Si prega di controllare i log per maggiori dettagli."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "Si prega di controllare le credenziali e riprovare" msgstr "Si prega di controllare le credenziali e riprovare"
@@ -746,7 +793,7 @@ msgstr "Si prega di creare un account amministratore"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "Si prega di abilitare i pop-up per questo sito" msgstr "Si prega di abilitare i pop-up per questo sito"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "Si prega di accedere nuovamente" msgstr "Si prega di accedere nuovamente"
@@ -794,7 +841,7 @@ msgstr "Reimposta Password"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Resolved" msgid "Resolved"
msgstr "" msgstr "Risolto"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Resume" msgid "Resume"
@@ -806,14 +853,14 @@ msgstr "Ruota token"
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "Rows per page" msgid "Rows per page"
msgstr "" msgstr "Righe per pagina"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Salva l'indirizzo usando il tasto invio o la virgola. Lascia vuoto per disabilitare le notifiche email." msgstr "Salva l'indirizzo usando il tasto invio o la virgola. Lascia vuoto per disabilitare le notifiche email."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "Salva Impostazioni" msgstr "Salva Impostazioni"
@@ -829,7 +876,7 @@ msgstr "Cerca"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "Cerca sistemi o impostazioni..." msgstr "Cerca sistemi o impostazioni..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "Vedi <0>impostazioni di notifica</0> per configurare come ricevere gli avvisi." msgstr "Vedi <0>impostazioni di notifica</0> per configurare come ricevere gli avvisi."
@@ -871,9 +918,10 @@ msgstr "Ordina per"
#. Context: alert state (active or resolved) #. Context: alert state (active or resolved)
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "State" msgid "State"
msgstr "" msgstr "Stato"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "Stato" msgstr "Stato"
@@ -885,18 +933,16 @@ msgstr "Spazio di swap utilizzato dal sistema"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "Utilizzo Swap" msgstr "Utilizzo Swap"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "Sistema" msgstr "Sistema"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "System load averages over time" msgid "System load averages over time"
msgstr "" msgstr "Medie di carico del sistema nel tempo"
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Systems" msgid "Systems"
@@ -915,14 +961,14 @@ msgstr "Tabella"
msgid "Temp" msgid "Temp"
msgstr "Temperatura" msgstr "Temperatura"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "Temperatura" msgstr "Temperatura"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Temperature unit" msgid "Temperature unit"
msgstr "" msgstr "Unità temperatura"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Temperatures of system sensors" msgid "Temperatures of system sensors"
@@ -946,7 +992,7 @@ msgstr "Questa azione non può essere annullata. Questo eliminerà permanentemen
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "This will permanently delete all selected records from the database." msgid "This will permanently delete all selected records from the database."
msgstr "" msgstr "Questo eliminerà permanentemente tutti i record selezionati dal database."
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Throughput of {extraFsName}" msgid "Throughput of {extraFsName}"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "Token" msgstr "Token"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "Token e Impronte Digitali" msgstr "Token e Impronte Digitali"
@@ -988,60 +1034,66 @@ msgstr "I token consentono agli agenti di connettersi e registrarsi. Le impronte
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "I token e le impronte digitali vengono utilizzati per autenticare le connessioni WebSocket all'hub." msgstr "I token e le impronte digitali vengono utilizzati per autenticare le connessioni WebSocket all'hub."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "" msgstr "Si attiva quando la media di carico di 1 minuto supera una soglia"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "" msgstr "Si attiva quando la media di carico di 15 minuti supera una soglia"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "" msgstr "Si attiva quando la media di carico di 5 minuti supera una soglia"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "Attiva quando un sensore supera una soglia" msgstr "Attiva quando un sensore supera una soglia"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "Attiva quando il combinato up/down supera una soglia" msgstr "Attiva quando il combinato up/down supera una soglia"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "Attiva quando l'utilizzo della CPU supera una soglia" msgstr "Attiva quando l'utilizzo della CPU supera una soglia"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "Attiva quando l'utilizzo della memoria supera una soglia" msgstr "Attiva quando l'utilizzo della memoria supera una soglia"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "Attiva quando lo stato passa tra up e down" msgstr "Attiva quando lo stato passa tra up e down"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "Attiva quando l'utilizzo di un disco supera una soglia" msgstr "Attiva quando l'utilizzo di un disco supera una soglia"
#. Temperature / network units #. Temperature / network units
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Unit preferences" msgid "Unit preferences"
msgstr "" msgstr "Preferenze unità"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "Token universale" msgstr "Token universale"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "Sconosciuta"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "Attivo" msgstr "Attivo"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "Aggiornato in tempo reale. Clicca su un sistema per visualizzare le informazioni." msgstr "Attivo ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,19 +1110,19 @@ msgstr "Utilizzo"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "Utilizzo della partizione root" msgstr "Utilizzo della partizione root"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "Utilizzato" msgstr "Utilizzato"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "Utenti" msgstr "Utenti"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Value" msgid "Value"
msgstr "" msgstr "Valore"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "View" msgid "View"
@@ -1078,7 +1130,7 @@ msgstr "Vista"
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "View your 200 most recent alerts." msgid "View your 200 most recent alerts."
msgstr "" msgstr "Visualizza i tuoi 200 avvisi più recenti."
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Visible Fields" msgid "Visible Fields"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ja\n" "Language: ja\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-28 23:21\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Japanese\n" "Language-Team: Japanese\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# 日} other {# 日}}" msgstr "{0, plural, one {# 日} other {# 日}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# 時間} other {# 時間}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# 分} few {# 分} many {# 分} other {# 分}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "{1}行のうち{0}行が選択されました。" msgstr "{1}行のうち{0}行が選択されました。"
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# 時間} other {# 時間}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1時間" msgstr "1時間"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "5分" msgstr "5分"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "アクション" msgstr "アクション"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "エージェント" msgstr "エージェント"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "アラート履歴" msgstr "アラート履歴"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "アラート" msgstr "アラート"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "すべてのシステム" msgstr "すべてのシステム"
@@ -148,8 +155,8 @@ msgstr "平均"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "コンテナの平均CPU使用率" msgstr "コンテナの平均CPU使用率"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "平均が<0>{value}{0}</0>を超えています" msgstr "平均が<0>{value}{0}</0>を超えています"
@@ -166,16 +173,20 @@ msgstr "システム全体の平均CPU使用率"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "{0}の平均使用率" msgstr "{0}の平均使用率"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "バックアップ" msgstr "バックアップ"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "帯域幅" msgstr "帯域幅"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "バッテリー"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "BeszelはOpenID Connectと多くのOAuth2認証プロバイダーをサポートしています。" msgstr "BeszelはOpenID Connectと多くのOAuth2認証プロバイダーをサポートしています。"
@@ -202,8 +213,8 @@ msgstr "バイト (KB/s, MB/s, GB/s)"
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "キャッシュ / バッファ" msgstr "キャッシュ / バッファ"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "キャンセル" msgstr "キャンセル"
@@ -213,7 +224,7 @@ msgstr "注意 - データ損失の可能性"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Celsius (°C)" msgid "Celsius (°C)"
msgstr "セルシウス (°C)" msgstr "摂氏 (°C)"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Change display units for metrics." msgid "Change display units for metrics."
@@ -223,6 +234,15 @@ msgstr "メトリックの表示単位を変更します。"
msgid "Change general application options." msgid "Change general application options."
msgstr "一般的なアプリケーションオプションを変更します。" msgstr "一般的なアプリケーションオプションを変更します。"
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "充電"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "充電中"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "チャートオプション" msgstr "チャートオプション"
@@ -239,6 +259,10 @@ msgstr "詳細についてはログを確認してください。"
msgid "Check your notification service" msgid "Check your notification service"
msgstr "通知サービスを確認してください" msgstr "通知サービスを確認してください"
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr "システムをクリックして詳細を表示します。"
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "クリックしてコピー" msgstr "クリックしてコピー"
@@ -261,8 +285,8 @@ msgstr "パスワードを確認"
msgid "Connection is down" msgid "Connection is down"
msgstr "接続が切断されました" msgstr "接続が切断されました"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "続行" msgstr "続行"
@@ -298,7 +322,7 @@ msgstr "Linuxコマンドをコピー"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Copy name" msgid "Copy name"
msgstr "名前をコピー" msgstr "名前をコピーする"
#: src/components/copy-to-clipboard.tsx #: src/components/copy-to-clipboard.tsx
msgid "Copy text" msgid "Copy text"
@@ -320,9 +344,9 @@ msgstr "YAMLをコピー"
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "CPU使用率" msgstr "CPU使用率"
@@ -337,12 +361,12 @@ msgstr "作成日"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Critical (%)" msgid "Critical (%)"
msgstr "クリティカル (%)" msgstr "致命的 (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "ダーク" msgstr "現在の状態"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "ダッシュボード"
msgid "Default time period" msgid "Default time period"
msgstr "デフォルトの期間" msgstr "デフォルトの期間"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "削除" msgstr "削除"
@@ -362,6 +386,11 @@ msgstr "削除"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "フィンガープリントを削除" msgstr "フィンガープリントを削除"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "放電中"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "ディスク" msgstr "ディスク"
@@ -374,9 +403,9 @@ msgstr "ディスクI/O"
msgid "Disk unit" msgid "Disk unit"
msgstr "ディスク単位" msgstr "ディスク単位"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "ディスク使用率" msgstr "ディスク使用率"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "ドキュメント" msgstr "ドキュメント"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "停止" msgstr "停止"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "停止 ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "期間" msgstr "期間"
@@ -417,8 +450,8 @@ msgstr "期間"
msgid "Edit" msgid "Edit"
msgstr "編集" msgstr "編集"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "メール" msgstr "メール"
@@ -426,6 +459,11 @@ msgstr "メール"
msgid "Email notifications" msgid "Email notifications"
msgstr "メール通知" msgstr "メール通知"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "空"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "パスワードをリセットするためにメールアドレスを入力してください" msgstr "パスワードをリセットするためにメールアドレスを入力してください"
@@ -434,11 +472,11 @@ msgstr "パスワードをリセットするためにメールアドレスを入
msgid "Enter email address..." msgid "Enter email address..."
msgstr "メールアドレスを入力..." msgstr "メールアドレスを入力..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "エラー" msgstr "エラー"
@@ -469,12 +507,12 @@ msgstr "現在のシステム設定をエクスポートします。"
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "華氏 (°F)" msgstr "華氏 (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "認証に失敗しました" msgstr "認証に失敗しました"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "設定の保存に失敗しました" msgstr "設定の保存に失敗しました"
@@ -482,13 +520,13 @@ msgstr "設定の保存に失敗しました"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "テスト通知の送信に失敗しました" msgstr "テスト通知の送信に失敗しました"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "アラートの更新に失敗しました" msgstr "アラートの更新に失敗しました"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "フィルター..." msgstr "フィルター..."
@@ -496,7 +534,7 @@ msgstr "フィルター..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "フィンガープリント" msgstr "フィンガープリント"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "<0>{min}</0> {min, plural, one {分} other {分}}の間" msgstr "<0>{min}</0> {min, plural, one {分} other {分}}の間"
@@ -504,9 +542,14 @@ msgstr "<0>{min}</0> {min, plural, one {分} other {分}}の間"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "パスワードをお忘れですか?" msgstr "パスワードをお忘れですか?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "満充電"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "一般" msgstr "一般"
@@ -528,6 +571,11 @@ msgstr "Homebrew コマンド"
msgid "Host / IP" msgid "Host / IP"
msgstr "ホスト / IP" msgstr "ホスト / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "アイドル"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." msgid "If you've lost the password to your admin account, you may reset it using the following command."
msgstr "管理者アカウントのパスワードを忘れた場合は、次のコマンドを使用してリセットできます。" msgstr "管理者アカウントのパスワードを忘れた場合は、次のコマンドを使用してリセットできます。"
@@ -549,31 +597,26 @@ msgstr "言語"
msgid "Layout" msgid "Layout"
msgstr "レイアウト" msgstr "レイアウト"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "ライト"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "ロードアベレージ" msgstr "負荷平均"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "ロードアベレージ (15分)" msgstr "負荷平均 (15分)"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "ロードアベレージ (1分)" msgstr "負荷平均 (1分)"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "ロードアベレージ (5分)" msgstr "負荷平均 (5分)"
#. Short label for load average #. Short label for load average
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Load Avg" msgid "Load Avg"
msgstr "ロードアベレージ" msgstr "負荷平均"
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Log Out" msgid "Log Out"
@@ -583,13 +626,13 @@ msgstr "ログアウト"
msgid "Login" msgid "Login"
msgstr "ログイン" msgstr "ログイン"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "ログイン試行に失敗しました" msgstr "ログイン試行に失敗しました"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "ログ" msgstr "ログ"
@@ -614,8 +657,8 @@ msgstr "最大1分"
msgid "Memory" msgid "Memory"
msgstr "メモリ" msgstr "メモリ"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "メモリ使用率" msgstr "メモリ使用率"
@@ -623,8 +666,8 @@ msgstr "メモリ使用率"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Dockerコンテナのメモリ使用率" msgstr "Dockerコンテナのメモリ使用率"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "名前" msgstr "名前"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "システムが見つかりませんでした。" msgstr "システムが見つかりませんでした。"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "通知" msgstr "通知"
@@ -672,9 +715,9 @@ msgstr "OAuth 2 / OIDCサポート"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "再起動のたびに、データベース内のシステムはファイルに定義されたシステムに一致するように更新されます。" msgstr "再起動のたびに、データベース内のシステムはファイルに定義されたシステムに一致するように更新されます。"
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "メニューを開く" msgstr "メニューを開く"
@@ -682,7 +725,7 @@ msgstr "メニューを開く"
msgid "Or continue with" msgid "Or continue with"
msgstr "または、以下の方法でログイン" msgstr "または、以下の方法でログイン"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "既存のアラートを上書き" msgstr "既存のアラートを上書き"
@@ -725,16 +768,20 @@ msgstr "一時停止"
msgid "Paused" msgid "Paused"
msgstr "一時停止中" msgstr "一時停止中"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "一時停止 ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "アラートが配信されるように<0>SMTPサーバーを設定</0>してください。" msgstr "アラートが配信されるように<0>SMTPサーバーを設定</0>してください。"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "詳細についてはログを確認してください。" msgstr "詳細についてはログを確認してください。"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "資格情報を確認して再試行してください" msgstr "資格情報を確認して再試行してください"
@@ -746,7 +793,7 @@ msgstr "管理者アカウントを作成してください"
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "このサイトのポップアップを有効にしてください" msgstr "このサイトのポップアップを有効にしてください"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "再度ログインしてください" msgstr "再度ログインしてください"
@@ -812,8 +859,8 @@ msgstr "ページあたりの行数"
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Enterキーまたはカンマを使用してアドレスを保存します。空白のままにするとメール通知が無効になります。" msgstr "Enterキーまたはカンマを使用してアドレスを保存します。空白のままにするとメール通知が無効になります。"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "設定を保存" msgstr "設定を保存"
@@ -829,7 +876,7 @@ msgstr "検索"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "システムまたは設定を検索..." msgstr "システムまたは設定を検索..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "アラートの受信方法を設定するには<0>通知設定</0>を参照してください。" msgstr "アラートの受信方法を設定するには<0>通知設定</0>を参照してください。"
@@ -839,7 +886,7 @@ msgstr "送信"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Set percentage thresholds for meter colors." msgid "Set percentage thresholds for meter colors."
msgstr "メーターの色パーセンテージのしきい値を設定します。" msgstr "メーターの色を変更するしきい値(パーセンテージを設定します。"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Sets the default time range for charts when a system is viewed." msgid "Sets the default time range for charts when a system is viewed."
@@ -873,7 +920,8 @@ msgstr "並び替え基準"
msgid "State" msgid "State"
msgstr "状態" msgstr "状態"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "ステータス" msgstr "ステータス"
@@ -885,18 +933,16 @@ msgstr "システムが使用するスワップ領域"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "スワップ使用量" msgstr "スワップ使用量"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "システム" msgstr "システム"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "System load averages over time" msgid "System load averages over time"
msgstr "システムのロードアベレージの推移" msgstr "システムの負荷平均の推移"
#: src/components/navbar.tsx #: src/components/navbar.tsx
msgid "Systems" msgid "Systems"
@@ -915,8 +961,8 @@ msgstr "テーブル"
msgid "Temp" msgid "Temp"
msgstr "温度" msgstr "温度"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "温度" msgstr "温度"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "トークン" msgstr "トークン"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "トークンとフィンガープリント" msgstr "トークンとフィンガープリント"
@@ -988,39 +1034,39 @@ msgstr "トークンはエージェントの接続と登録を可能にします
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "トークンとフィンガープリントは、ハブへのWebSocket接続の認証に使用されます。" msgstr "トークンとフィンガープリントは、ハブへのWebSocket接続の認証に使用されます。"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "1分間のロードアベレージがしきい値を超えたときにトリガーされます" msgstr "1分間の負荷平均がしきい値を超えたときにトリガーされます"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "15分間のロードアベレージがしきい値を超えたときにトリガーされます" msgstr "15分間の負荷平均がしきい値を超えたときにトリガーされます"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "5分間のロードアベレージがしきい値を超えたときにトリガーされます" msgstr "5分間の負荷平均がしきい値を超えたときにトリガーされます"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "センサーがしきい値を超えたときにトリガーされます" msgstr "センサーがしきい値を超えたときにトリガーされます"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "上り/下りの合計がしきい値を超えたときにトリガーされます" msgstr "上り/下りの合計がしきい値を超えたときにトリガーされます"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "CPU使用率がしきい値を超えたときにトリガーされます" msgstr "CPU使用率がしきい値を超えたときにトリガーされます"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "メモリ使用率がしきい値を超えたときにトリガーされます" msgstr "メモリ使用率がしきい値を超えたときにトリガーされます"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "ステータスが上から下に切り替わるときにトリガーされます" msgstr "ステータスが上から下に切り替わるときにトリガーされます"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "ディスクの使用量がしきい値を超えたときにトリガーされます" msgstr "ディスクの使用量がしきい値を超えたときにトリガーされます"
@@ -1029,19 +1075,25 @@ msgstr "ディスクの使用量がしきい値を超えたときにトリガー
msgid "Unit preferences" msgid "Unit preferences"
msgstr "単位の設定" msgstr "単位の設定"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "ユニバーサルトークン" msgstr "ユニバーサルトークン"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "不明"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "正常" msgstr "正常"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "リアルタイムで更新されます。システムをクリックして情報を表示します。" msgstr "正常 ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "使用量"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "ルートパーティションの使用量" msgstr "ルートパーティションの使用量"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "使用中" msgstr "使用中"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "ユーザー" msgstr "ユーザー"

View File

@@ -8,7 +8,7 @@ msgstr ""
"Language: ko\n" "Language: ko\n"
"Project-Id-Version: beszel\n" "Project-Id-Version: beszel\n"
"Report-Msgid-Bugs-To: \n" "Report-Msgid-Bugs-To: \n"
"PO-Revision-Date: 2025-07-25 22:44\n" "PO-Revision-Date: 2025-08-31 15:44\n"
"Last-Translator: \n" "Last-Translator: \n"
"Language-Team: Korean\n" "Language-Team: Korean\n"
"Plural-Forms: nplurals=1; plural=0;\n" "Plural-Forms: nplurals=1; plural=0;\n"
@@ -23,16 +23,22 @@ msgstr ""
msgid "{0, plural, one {# day} other {# days}}" msgid "{0, plural, one {# day} other {# days}}"
msgstr "{0, plural, one {# 일} other {# 일}}" msgstr "{0, plural, one {# 일} other {# 일}}"
#. placeholder {0}: Math.trunc(system.info.u / 3600)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# hour} other {# hours}}"
msgstr "{0, plural, one {# 시간} other {# 시간}}"
#. placeholder {0}: Math.trunc(system.info.u / 60)
#: src/components/routes/system.tsx
msgid "{0, plural, one {# minute} few {# minutes} many {# minutes} other {# minutes}}"
msgstr "{0, plural, one {# 분} few {# 분} many {# 분} other {# 분}}"
#. placeholder {0}: table.getFilteredSelectedRowModel().rows.length #. placeholder {0}: table.getFilteredSelectedRowModel().rows.length
#. placeholder {1}: table.getFilteredRowModel().rows.length #. placeholder {1}: table.getFilteredRowModel().rows.length
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
msgid "{0} of {1} row(s) selected." msgid "{0} of {1} row(s) selected."
msgstr "{1}개의 행 중 {0}개가 선택되었습니다." msgstr "{1}개의 행 중 {0}개가 선택되었습니다."
#: src/components/routes/system.tsx
msgid "{hours, plural, one {# hour} other {# hours}}"
msgstr "{hours, plural, one {# 시간} other {# 시간}}"
#: src/lib/utils.ts #: src/lib/utils.ts
msgid "1 hour" msgid "1 hour"
msgstr "1시간" msgstr "1시간"
@@ -69,8 +75,8 @@ msgid "5 min"
msgstr "5분" msgstr "5분"
#. Table column #. Table column
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Actions" msgid "Actions"
msgstr "작업" msgstr "작업"
@@ -113,18 +119,19 @@ msgid "Agent"
msgstr "에이전트" msgstr "에이전트"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/layout.tsx
msgid "Alert History" msgid "Alert History"
msgstr "알림 기록" msgstr "알림 기록"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alert-button.tsx
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Alerts" msgid "Alerts"
msgstr "알림" msgstr "알림"
#: src/components/alerts/alerts-sheet.tsx
#: src/components/systems-table/systems-table.tsx
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
#: src/components/alerts/alert-button.tsx
msgid "All Systems" msgid "All Systems"
msgstr "모든 시스템" msgstr "모든 시스템"
@@ -148,8 +155,8 @@ msgstr "평균"
msgid "Average CPU utilization of containers" msgid "Average CPU utilization of containers"
msgstr "Docker 컨테이너의 평균 CPU 사용량" msgstr "Docker 컨테이너의 평균 CPU 사용량"
#. placeholder {0}: data.alert.unit #. placeholder {0}: alertData.unit
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Average exceeds <0>{value}{0}</0>" msgid "Average exceeds <0>{value}{0}</0>"
msgstr "평균이 <0>{value}{0}</0>을(를) 초과합니다" msgstr "평균이 <0>{value}{0}</0>을(를) 초과합니다"
@@ -166,16 +173,20 @@ msgstr "시스템 전체의 평균 CPU 사용량"
msgid "Average utilization of {0}" msgid "Average utilization of {0}"
msgstr "평균 {0} 사용량" msgstr "평균 {0} 사용량"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Backups" msgid "Backups"
msgstr "백업" msgstr "백업"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Bandwidth" msgid "Bandwidth"
msgstr "대역폭" msgstr "대역폭"
#: src/components/routes/system.tsx
msgid "Battery"
msgstr "배터리"
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers." msgid "Beszel supports OpenID Connect and many OAuth2 authentication providers."
msgstr "Beszel은 OpenID Connect 및 많은 OAuth2 인증 제공자를 지원합니다." msgstr "Beszel은 OpenID Connect 및 많은 OAuth2 인증 제공자를 지원합니다."
@@ -202,8 +213,8 @@ msgstr "바이트 (KB/s, MB/s, GB/s)"
msgid "Cache / Buffers" msgid "Cache / Buffers"
msgstr "캐시 / 버퍼" msgstr "캐시 / 버퍼"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Cancel" msgid "Cancel"
msgstr "취소" msgstr "취소"
@@ -223,6 +234,15 @@ msgstr "메트릭의 표시 단위를 변경합니다."
msgid "Change general application options." msgid "Change general application options."
msgstr "일반 애플리케이션 옵션 변경." msgstr "일반 애플리케이션 옵션 변경."
#: src/components/routes/system.tsx
msgid "Charge"
msgstr "충전"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Charging"
msgstr "충전 중"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Chart options" msgid "Chart options"
msgstr "차트 옵션" msgstr "차트 옵션"
@@ -239,6 +259,10 @@ msgstr "자세한 내용은 로그를 확인하세요."
msgid "Check your notification service" msgid "Check your notification service"
msgstr "알림 서비스를 확인하세요." msgstr "알림 서비스를 확인하세요."
#: src/components/systems-table/systems-table.tsx
msgid "Click on a system to view more information."
msgstr "더 많은 정보를 보려면 시스템을 클릭하세요."
#: src/components/ui/input-copy.tsx #: src/components/ui/input-copy.tsx
msgid "Click to copy" msgid "Click to copy"
msgstr "클릭하여 복사" msgstr "클릭하여 복사"
@@ -261,8 +285,8 @@ msgstr "비밀번호 확인"
msgid "Connection is down" msgid "Connection is down"
msgstr "연결이 끊겼습니다" msgstr "연결이 끊겼습니다"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Continue" msgid "Continue"
msgstr "계속" msgstr "계속"
@@ -320,9 +344,9 @@ msgstr "YAML 복사"
msgid "CPU" msgid "CPU"
msgstr "CPU" msgstr "CPU"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "CPU Usage" msgid "CPU Usage"
msgstr "CPU 사용량" msgstr "CPU 사용량"
@@ -337,12 +361,12 @@ msgstr "생성됨"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Critical (%)" msgid "Critical (%)"
msgstr "치명적 (%)" msgstr "위험 (%)"
#. Dark theme #. Context: Battery state
#: src/components/mode-toggle.tsx #: src/components/routes/system.tsx
msgid "Dark" msgid "Current state"
msgstr "어둡게" msgstr "현재 상태"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/home.tsx #: src/components/routes/home.tsx
@@ -353,8 +377,8 @@ msgstr "대시보드"
msgid "Default time period" msgid "Default time period"
msgstr "기본 기간" msgstr "기본 기간"
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Delete" msgid "Delete"
msgstr "삭제" msgstr "삭제"
@@ -362,6 +386,11 @@ msgstr "삭제"
msgid "Delete fingerprint" msgid "Delete fingerprint"
msgstr "지문 삭제" msgstr "지문 삭제"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Discharging"
msgstr "방전 중"
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
msgid "Disk" msgid "Disk"
msgstr "디스크" msgstr "디스크"
@@ -374,9 +403,9 @@ msgstr "디스크 I/O"
msgid "Disk unit" msgid "Disk unit"
msgstr "디스크 단위" msgstr "디스크 단위"
#: src/lib/utils.ts
#: src/components/routes/system.tsx
#: src/components/charts/disk-chart.tsx #: src/components/charts/disk-chart.tsx
#: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Disk Usage" msgid "Disk Usage"
msgstr "디스크 사용량" msgstr "디스크 사용량"
@@ -401,13 +430,17 @@ msgid "Documentation"
msgstr "문서" msgstr "문서"
#. Context: System is down #. Context: System is down
#: src/lib/utils.ts
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "Down" msgid "Down"
msgstr "오프라인" msgstr "오프라인"
#: src/components/systems-table/systems-table.tsx
msgid "Down ({downSystemsLength})"
msgstr "오프라인 ({downSystemsLength})"
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
msgid "Duration" msgid "Duration"
msgstr "기간" msgstr "기간"
@@ -417,8 +450,8 @@ msgstr "기간"
msgid "Edit" msgid "Edit"
msgstr "수정" msgstr "수정"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Email" msgid "Email"
msgstr "이메일" msgstr "이메일"
@@ -426,6 +459,11 @@ msgstr "이메일"
msgid "Email notifications" msgid "Email notifications"
msgstr "이메일 알림" msgstr "이메일 알림"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Empty"
msgstr "빔"
#: src/components/login/login.tsx #: src/components/login/login.tsx
msgid "Enter email address to reset password" msgid "Enter email address to reset password"
msgstr "비밀번호를 재설정하려면 이메일 주소를 입력하세요" msgstr "비밀번호를 재설정하려면 이메일 주소를 입력하세요"
@@ -434,11 +472,11 @@ msgstr "비밀번호를 재설정하려면 이메일 주소를 입력하세요"
msgid "Enter email address..." msgid "Enter email address..."
msgstr "이메일 주소 입력..." msgstr "이메일 주소 입력..."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/settings/config-yaml.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Error" msgid "Error"
msgstr "오류" msgstr "오류"
@@ -469,12 +507,12 @@ msgstr "현재 시스템 구성 내보내기"
msgid "Fahrenheit (°F)" msgid "Fahrenheit (°F)"
msgstr "화씨 (°F)" msgstr "화씨 (°F)"
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Failed to authenticate" msgid "Failed to authenticate"
msgstr "인증 실패" msgstr "인증 실패"
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Failed to save settings" msgid "Failed to save settings"
msgstr "설정 저장 실패" msgstr "설정 저장 실패"
@@ -482,13 +520,13 @@ msgstr "설정 저장 실패"
msgid "Failed to send test notification" msgid "Failed to send test notification"
msgstr "테스트 알림 전송 실패" msgstr "테스트 알림 전송 실패"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Failed to update alert" msgid "Failed to update alert"
msgstr "알림 수정 실패" msgstr "알림 수정 실패"
#: src/components/systems-table/systems-table.tsx
#: src/components/routes/system.tsx
#: src/components/routes/settings/alerts-history-data-table.tsx #: src/components/routes/settings/alerts-history-data-table.tsx
#: src/components/routes/system.tsx
#: src/components/systems-table/systems-table.tsx
msgid "Filter..." msgid "Filter..."
msgstr "필터..." msgstr "필터..."
@@ -496,7 +534,7 @@ msgstr "필터..."
msgid "Fingerprint" msgid "Fingerprint"
msgstr "지문" msgstr "지문"
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}" msgid "For <0>{min}</0> {min, plural, one {minute} other {minutes}}"
msgstr "<0>{min}</0> {min, plural, one {분} other {분}} 동안" msgstr "<0>{min}</0> {min, plural, one {분} other {분}} 동안"
@@ -504,9 +542,14 @@ msgstr "<0>{min}</0> {min, plural, one {분} other {분}} 동안"
msgid "Forgot password?" msgid "Forgot password?"
msgstr "비밀번호를 잊으셨나요?" msgstr "비밀번호를 잊으셨나요?"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Full"
msgstr "가득"
#. Context: General settings #. Context: General settings
#: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/layout.tsx
msgid "General" msgid "General"
msgstr "일반" msgstr "일반"
@@ -528,6 +571,11 @@ msgstr "Homebrew 명령어"
msgid "Host / IP" msgid "Host / IP"
msgstr "호스트 / IP" msgstr "호스트 / IP"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Idle"
msgstr "대기"
#: src/components/login/forgot-pass-form.tsx #: src/components/login/forgot-pass-form.tsx
msgid "If you've lost the password to your admin account, you may reset it using the following command." msgid "If you've lost the password to your admin account, you may reset it using the following command."
msgstr "관리자 계정의 비밀번호를 잃어버린 경우, 다음 명령어를 사용하여 재설정할 수 있습니다." msgstr "관리자 계정의 비밀번호를 잃어버린 경우, 다음 명령어를 사용하여 재설정할 수 있습니다."
@@ -549,24 +597,19 @@ msgstr "언어"
msgid "Layout" msgid "Layout"
msgstr "레이아웃" msgstr "레이아웃"
#. Light theme
#: src/components/mode-toggle.tsx
msgid "Light"
msgstr "밝게"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Load Average" msgid "Load Average"
msgstr "부하 평균" msgstr "부하 평균"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 15m" msgid "Load Average 15m"
msgstr "부하 평균 15분" msgstr "부하 평균 15분"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 1m" msgid "Load Average 1m"
msgstr "부하 평균 1분" msgstr "부하 평균 1분"
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Load Average 5m" msgid "Load Average 5m"
msgstr "부하 평균 5분" msgstr "부하 평균 5분"
@@ -583,13 +626,13 @@ msgstr "로그아웃"
msgid "Login" msgid "Login"
msgstr "로그인" msgstr "로그인"
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Login attempt failed" msgid "Login attempt failed"
msgstr "로그인 실패" msgstr "로그인 실패"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Logs" msgid "Logs"
msgstr "로그" msgstr "로그"
@@ -614,8 +657,8 @@ msgstr "1분간 최댓값"
msgid "Memory" msgid "Memory"
msgstr "메모리" msgstr "메모리"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Memory Usage" msgid "Memory Usage"
msgstr "메모리 사용량" msgstr "메모리 사용량"
@@ -623,8 +666,8 @@ msgstr "메모리 사용량"
msgid "Memory usage of docker containers" msgid "Memory usage of docker containers"
msgstr "Docker 컨테이너의 메모리 사용량" msgstr "Docker 컨테이너의 메모리 사용량"
#: src/components/alerts-history-columns.tsx
#: src/components/add-system.tsx #: src/components/add-system.tsx
#: src/components/alerts-history-columns.tsx
msgid "Name" msgid "Name"
msgstr "이름" msgstr "이름"
@@ -659,8 +702,8 @@ msgid "No systems found."
msgstr "시스템을 찾을 수 없습니다." msgstr "시스템을 찾을 수 없습니다."
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Notifications" msgid "Notifications"
msgstr "알림" msgstr "알림"
@@ -672,9 +715,9 @@ msgstr "OAuth 2 / OIDC 지원"
msgid "On each restart, systems in the database will be updated to match the systems defined in the file." msgid "On each restart, systems in the database will be updated to match the systems defined in the file."
msgstr "매 시작 시, 데이터베이스가 파일에 정의된 시스템과 일치하도록 업데이트됩니다." msgstr "매 시작 시, 데이터베이스가 파일에 정의된 시스템과 일치하도록 업데이트됩니다."
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx #: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Open menu" msgid "Open menu"
msgstr "메뉴 열기" msgstr "메뉴 열기"
@@ -682,7 +725,7 @@ msgstr "메뉴 열기"
msgid "Or continue with" msgid "Or continue with"
msgstr "또는 아래 항목으로 진행하기" msgstr "또는 아래 항목으로 진행하기"
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Overwrite existing alerts" msgid "Overwrite existing alerts"
msgstr "기존 알림 덮어쓰기" msgstr "기존 알림 덮어쓰기"
@@ -725,16 +768,20 @@ msgstr "일시 중지"
msgid "Paused" msgid "Paused"
msgstr "일시 정지됨" msgstr "일시 정지됨"
#: src/components/systems-table/systems-table.tsx
msgid "Paused ({pausedSystemsLength})"
msgstr "일시 정지됨 ({pausedSystemsLength})"
#: src/components/routes/settings/notifications.tsx #: src/components/routes/settings/notifications.tsx
msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered." msgid "Please <0>configure an SMTP server</0> to ensure alerts are delivered."
msgstr "알림이 전달되도록 <0>SMTP 서버를 구성</0>하세요." msgstr "알림이 전달되도록 <0>SMTP 서버를 구성</0>하세요."
#: src/components/alerts/alerts-system.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "Please check logs for more details." msgid "Please check logs for more details."
msgstr "자세한 내용은 로그를 확인하세요." msgstr "자세한 내용은 로그를 확인하세요."
#: src/components/login/forgot-pass-form.tsx
#: src/components/login/auth-form.tsx #: src/components/login/auth-form.tsx
#: src/components/login/forgot-pass-form.tsx
msgid "Please check your credentials and try again" msgid "Please check your credentials and try again"
msgstr "자격 증명을 확인하고 다시 시도하세요." msgstr "자격 증명을 확인하고 다시 시도하세요."
@@ -746,7 +793,7 @@ msgstr "관리자 계정을 생성하세요."
msgid "Please enable pop-ups for this site" msgid "Please enable pop-ups for this site"
msgstr "이 사이트에 대해 팝업을 활성화하세요." msgstr "이 사이트에 대해 팝업을 활성화하세요."
#: src/lib/utils.ts #: src/lib/api.ts
msgid "Please log in again" msgid "Please log in again"
msgstr "다시 로그인하세요." msgstr "다시 로그인하세요."
@@ -812,8 +859,8 @@ msgstr "페이지당 행 수"
msgid "Save address using enter key or comma. Leave blank to disable email notifications." msgid "Save address using enter key or comma. Leave blank to disable email notifications."
msgstr "Enter 키 또는 쉼표를 사용하여 주소를 저장하세요. 이메일 알림을 비활성화하려면 비워 두세요." msgstr "Enter 키 또는 쉼표를 사용하여 주소를 저장하세요. 이메일 알림을 비활성화하려면 비워 두세요."
#: src/components/routes/settings/notifications.tsx
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
#: src/components/routes/settings/notifications.tsx
msgid "Save Settings" msgid "Save Settings"
msgstr "설정 저장" msgstr "설정 저장"
@@ -829,7 +876,7 @@ msgstr "검색"
msgid "Search for systems or settings..." msgid "Search for systems or settings..."
msgstr "시스템 또는 설정 검색..." msgstr "시스템 또는 설정 검색..."
#: src/components/alerts/alert-button.tsx #: src/components/alerts/alerts-sheet.tsx
msgid "See <0>notification settings</0> to configure how you receive alerts." msgid "See <0>notification settings</0> to configure how you receive alerts."
msgstr "알림을 받는 방법을 구성하려면 <0>알림 설정</0>을 참조하세요." msgstr "알림을 받는 방법을 구성하려면 <0>알림 설정</0>을 참조하세요."
@@ -839,7 +886,7 @@ msgstr "보냄"
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Set percentage thresholds for meter colors." msgid "Set percentage thresholds for meter colors."
msgstr "미터 색상에 대한 백분율 임계값을 설정합니다." msgstr "그래프 미터 색상 백분율 임계값을 설정합니다."
#: src/components/routes/settings/general.tsx #: src/components/routes/settings/general.tsx
msgid "Sets the default time range for charts when a system is viewed." msgid "Sets the default time range for charts when a system is viewed."
@@ -873,7 +920,8 @@ msgstr "정렬 기준"
msgid "State" msgid "State"
msgstr "상태" msgstr "상태"
#: src/lib/utils.ts #: src/components/systems-table/systems-table.tsx
#: src/lib/alerts.ts
msgid "Status" msgid "Status"
msgstr "상태" msgstr "상태"
@@ -885,12 +933,10 @@ msgstr "시스템에서 사용된 스왑 공간"
msgid "Swap Usage" msgid "Swap Usage"
msgstr "스왑 사용량" msgstr "스왑 사용량"
#. System theme
#: src/lib/utils.ts
#: src/components/mode-toggle.tsx
#: src/components/alerts-history-columns.tsx #: src/components/alerts-history-columns.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/systems-table/systems-table-columns.tsx
#: src/lib/alerts.ts
msgid "System" msgid "System"
msgstr "시스템" msgstr "시스템"
@@ -915,8 +961,8 @@ msgstr "표"
msgid "Temp" msgid "Temp"
msgstr "온도" msgstr "온도"
#: src/lib/utils.ts
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/lib/alerts.ts
msgid "Temperature" msgid "Temperature"
msgstr "온도" msgstr "온도"
@@ -975,8 +1021,8 @@ msgid "Token"
msgstr "토큰" msgstr "토큰"
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
#: src/components/routes/settings/layout.tsx #: src/components/routes/settings/layout.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Tokens & Fingerprints" msgid "Tokens & Fingerprints"
msgstr "토큰 및 지문" msgstr "토큰 및 지문"
@@ -988,39 +1034,39 @@ msgstr "토큰은 에이전트가 연결하고 등록할 수 있도록 합니다
msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub." msgid "Tokens and fingerprints are used to authenticate WebSocket connections to the hub."
msgstr "토큰과 지문은 허브에 대한 WebSocket 연결을 인증하는 데 사용됩니다." msgstr "토큰과 지문은 허브에 대한 WebSocket 연결을 인증하는 데 사용됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 1 minute load average exceeds a threshold" msgid "Triggers when 1 minute load average exceeds a threshold"
msgstr "1분 부하 평균이 임계값을 초과하면 트리거됩니다." msgstr "1분 부하 평균이 임계값을 초과하면 트리거됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 15 minute load average exceeds a threshold" msgid "Triggers when 15 minute load average exceeds a threshold"
msgstr "15분 부하 평균이 임계값을 초과하면 트리거됩니다." msgstr "15분 부하 평균이 임계값을 초과하면 트리거됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when 5 minute load average exceeds a threshold" msgid "Triggers when 5 minute load average exceeds a threshold"
msgstr "5분 부하 평균이 임계값을 초과하면 트리거됩니다." msgstr "5분 부하 평균이 임계값을 초과하면 트리거됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when any sensor exceeds a threshold" msgid "Triggers when any sensor exceeds a threshold"
msgstr "센서가 임계값을 초과할 때 트리거됩니다." msgstr "센서가 임계값을 초과할 때 트리거됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when combined up/down exceeds a threshold" msgid "Triggers when combined up/down exceeds a threshold"
msgstr "업로드와 다운로드 대역폭의 합이 임계값을 초과할 때 트리거됩니다." msgstr "업로드와 다운로드 대역폭의 합이 임계값을 초과할 때 트리거됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when CPU usage exceeds a threshold" msgid "Triggers when CPU usage exceeds a threshold"
msgstr "CPU 사용량이 임계값을 초과할 때 트리거됩니다." msgstr "CPU 사용량이 임계값을 초과할 때 트리거됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when memory usage exceeds a threshold" msgid "Triggers when memory usage exceeds a threshold"
msgstr "메모리 사용량이 임계값을 초과할 때 트리거됩니다." msgstr "메모리 사용량이 임계값을 초과할 때 트리거됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when status switches between up and down" msgid "Triggers when status switches between up and down"
msgstr "시스템의 전원이 켜지거나 꺼질때 트리거됩니다." msgstr "시스템의 전원이 켜지거나 꺼질때 트리거됩니다."
#: src/lib/utils.ts #: src/lib/alerts.ts
msgid "Triggers when usage of any disk exceeds a threshold" msgid "Triggers when usage of any disk exceeds a threshold"
msgstr "디스크 사용량이 임계값을 초과할 때 트리거됩니다." msgstr "디스크 사용량이 임계값을 초과할 때 트리거됩니다."
@@ -1029,19 +1075,25 @@ msgstr "디스크 사용량이 임계값을 초과할 때 트리거됩니다."
msgid "Unit preferences" msgid "Unit preferences"
msgstr "단위 기본 설정" msgstr "단위 기본 설정"
#: src/components/command-palette.tsx
#: src/components/routes/settings/tokens-fingerprints.tsx #: src/components/routes/settings/tokens-fingerprints.tsx
msgid "Universal token" msgid "Universal token"
msgstr "범용 토큰" msgstr "범용 토큰"
#. Context: Battery state
#: src/lib/i18n.ts
msgid "Unknown"
msgstr "알 수 없음"
#. Context: System is up #. Context: System is up
#: src/components/systems-table/systems-table-columns.tsx
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
#: src/components/systems-table/systems-table-columns.tsx
msgid "Up" msgid "Up"
msgstr "온라인" msgstr "온라인"
#: src/components/systems-table/systems-table.tsx #: src/components/systems-table/systems-table.tsx
msgid "Updated in real time. Click on a system to view information." msgid "Up ({upSystemsLength})"
msgstr "실시간으로 업데이트됩니다. 시스템을 클릭하여 정보를 확인하세요." msgstr "온라인 ({upSystemsLength})"
#: src/components/routes/system.tsx #: src/components/routes/system.tsx
msgid "Uptime" msgid "Uptime"
@@ -1058,13 +1110,13 @@ msgstr "사용량"
msgid "Usage of root partition" msgid "Usage of root partition"
msgstr "루트 파티션의 사용량" msgstr "루트 파티션의 사용량"
#: src/components/charts/swap-chart.tsx
#: src/components/charts/mem-chart.tsx #: src/components/charts/mem-chart.tsx
#: src/components/charts/swap-chart.tsx
msgid "Used" msgid "Used"
msgstr "사용됨" msgstr "사용됨"
#: src/components/navbar.tsx
#: src/components/command-palette.tsx #: src/components/command-palette.tsx
#: src/components/navbar.tsx
msgid "Users" msgid "Users"
msgstr "사용자" msgstr "사용자"

Some files were not shown because too many files have changed in this diff Show More