Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
171 changes: 30 additions & 141 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@

A real-time Terminal User Interface (TUI) for system monitoring, Docker container management, network diagnostics, and security auditing on Linux servers.

**This fork adds bilingual UI (English / 简体中文) with runtime language switching.**

<p align="center"><img src="docs/images/sample.gif" alt="server-pulse"/></p>

## Features
Expand All @@ -19,6 +21,15 @@ A real-time Terminal User Interface (TUI) for system monitoring, Docker containe
- **Log Viewer** — Filter system logs by time range, service, and log level
- **Network Diagnostics** — Interface stats, ping, traceroute, speed tests, routing table, DNS servers, connection analysis
- **Report Generation** — Generate, save, and load comprehensive system health reports (`~/.server-pulse/reports/`)
- **i18n** — Switch between English and Simplified Chinese at runtime (`L` / `Ctrl+L`); preference saved to `~/.server-pulse/config.json`

## Language

| Key | Action |
|-----|--------|
| `L` or `Ctrl+L` | Toggle English ↔ 中文 |

Default language is Simplified Chinese (中文). After switching, the choice is persisted.

## Requirements

Expand All @@ -29,166 +40,44 @@ A real-time Terminal User Interface (TUI) for system monitoring, Docker containe

## Installation

### Pre-built Binaries (Recommended)

**curl:**
### From source (this fork)

```bash
curl -fsSL https://raw.githubusercontent.com/Server-Pulse/server-pulse/main/scripts/install.sh | bash
```

**wget:**

```bash
wget -qO- https://raw.githubusercontent.com/Server-Pulse/server-pulse/main/scripts/install.sh | bash
```

The install script auto-detects your platform, downloads the latest release, verifies the SHA256 checksum, and installs the binary to `/usr/local/bin/`.

### Manual Download

Download a specific release for Linux amd64:

```bash
sudo wget https://github.com/Server-Pulse/server-pulse/releases/download/vX.X.X/server-pulse-X.X.X-linux-amd64 -O /usr/local/bin/server-pulse
sudo chmod +x /usr/local/bin/server-pulse
git clone https://github.com/zhangyang-crazy-one/server-pulse.git
cd server-pulse
git checkout feat/chinese-ui
make build
sudo mv server-pulse /usr/local/bin/
```

### From Source

#### Prerequisites
- Go 1.24+
- Git
Or:

```bash
git clone https://github.com/Server-Pulse/server-pulse.git
cd server-pulse
make build
sudo mv server-pulse /usr/local/bin/
go build -o server-pulse .
sudo install -m 755 server-pulse /usr/local/bin/server-pulse
```

## Usage

After installation, launch the TUI:

```bash
server-pulse
```

The application opens an interactive dashboard. Use the number keys to jump between the four main sections:

| Key | Section | Description |
|-----|---------|-------------|
| `1` | Monitor | System resources, processes, and containers |
| `2` | Diagnostics | Security checks, performance analysis, and logs |
| `3` | Network | Interfaces, connectivity tests, routing, and protocol analysis |
| `4` | Reporting | Generate and manage system health reports |

## Keybindings

### Global

| Key | Action |
|-----|--------|
| `?` | Toggle help |
| `q` / `Esc` / `Ctrl+C` | Quit |
| `b` | Go back |
| `Tab` / `←` `→` | Navigate tabs |
| `Enter` | Select |

### Process View

| Key | Action |
|-----|--------|
| `/` | Search |
| `s` | Sort by CPU |
| `m` | Sort by memory |
| `k` | Kill process |

### Containers View

| Key | Action |
|-----|--------|
| `/` | Search |
| `Enter` | Open container actions (details, logs, restart, delete, exec shell, etc.) |

### Container Logs

| Key | Action |
|-----|--------|
| `s` | Toggle live streaming |
| `r` | Refresh |
| `Home` / `End` | Jump to start/end |

### Network View
Main shortcuts:

| Key | Action |
|-----|--------|
| `p` | Start ping |
| `t` | Start traceroute |
| `c` | Clear results |

### Diagnostics View

| Key | Action |
|-----|--------|
| `1` `2` `3` | Switch sub-tabs (Security / Performance / Logs) |
| `/` | Search |
| `r` | Reload |
| `Shift+←` `Shift+→` | Switch filters |

### Reporting View

| Key | Action |
|-----|--------|
| `g` | Generate report |
| `s` | Save report |
| `l` | Load saved reports |
| `d` | Delete report |

## Uninstallation

**curl:**

```bash
curl -fsSL https://raw.githubusercontent.com/Server-Pulse/server-pulse/main/scripts/uninstall.sh | bash
```

**wget:**

```bash
wget -qO- https://raw.githubusercontent.com/Server-Pulse/server-pulse/main/scripts/uninstall.sh | bash
```

## Building

1. Clone the repository:
```bash
git clone https://github.com/Server-Pulse/server-pulse.git
cd server-pulse
```

2. Build for your current platform:
```bash
make build
```

3. For cross-platform builds:
```bash
make build-all
```

Build artifacts will be placed in the `_build` directory.
| `1`–`4` | Monitor / Diagnostics / Network / Reporting |
| `L` / `Ctrl+L` | Switch language |
| `?` | Help |
| `q` / `Esc` | Quit |
| `b` | Back |

### Supported Build Targets
## Upstream

| Architecture | Platform |
|-------------|----------|
| amd64 | Linux |
| arm | Linux |
| arm64 | Linux |
| ppc64le | Linux |
- Upstream: https://github.com/Server-Pulse/server-pulse
- Fork: https://github.com/zhangyang-crazy-one/server-pulse

## License

This project is licensed under the [GPL-3.0 License](LICENSE).
GPL-3.0 (same as upstream)
132 changes: 132 additions & 0 deletions i18n/i18n.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
package i18n

import (
"encoding/json"
"os"
"path/filepath"
"sync"
)

type Lang string

const (
En Lang = "en"
Zh Lang = "zh"
)

var (
mu sync.RWMutex
current = Zh
)

type configFile struct {
Language string `json:"language"`
}

func Current() Lang {
mu.RLock()
defer mu.RUnlock()
return current
}

func SetLang(lang Lang) {
if lang != En && lang != Zh {
lang = Zh
}
mu.Lock()
current = lang
mu.Unlock()
_ = Save()
}

func Toggle() Lang {
if Current() == Zh {
SetLang(En)
} else {
SetLang(Zh)
}
return Current()
}

// T translates an English source string when the active language is Chinese.
// Unknown keys fall back to the English source.
func T(s string) string {
if s == "" {
return s
}
mu.RLock()
lang := current
mu.RUnlock()
if lang != Zh {
return s
}
if v, ok := zh[s]; ok {
return v
}
return s
}

func Ts(ss ...string) []string {
out := make([]string, len(ss))
for i, s := range ss {
out[i] = T(s)
}
return out
}

func configPath() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
dir := filepath.Join(home, ".server-pulse")
if err := os.MkdirAll(dir, 0o755); err != nil {
return "", err
}
return filepath.Join(dir, "config.json"), nil
}

func Load() {
path, err := configPath()
if err != nil {
return
}
data, err := os.ReadFile(path)
if err != nil {
return
}
var cfg configFile
if err := json.Unmarshal(data, &cfg); err != nil {
return
}
switch Lang(cfg.Language) {
case En:
mu.Lock()
current = En
mu.Unlock()
case Zh, "":
mu.Lock()
current = Zh
mu.Unlock()
}
}

func Save() error {
path, err := configPath()
if err != nil {
return err
}
cfg := configFile{Language: string(Current())}
data, err := json.MarshalIndent(cfg, "", " ")
if err != nil {
return err
}
return os.WriteFile(path, data, 0o644)
}

func Label() string {
if Current() == Zh {
return "中文"
}
return "English"
}
Loading