feat(i18n): add multi-language support (ja/ko/vi/ru/zh-TW) with system auto-detection
- Extend AppLanguage to 7 locales: zh-CN, zh-TW, en, ja, ko, vi, ru - Auto-detect system language via navigator.languages; fallback to English - Add BCP47 locale mapping for date formatting and sorting - Create 50 translation JSON files (5 languages × 10 namespaces, 1137 keys each) - Update language selector with native language names - Extend locale key parity test to cover all 7 languages (70 assertions) - Add VNC/RDP desktop, serial terminal, AI agent, port forwarding, and SFTP features - Add credential encryption, host metrics, session backup crypto, and zmodem bridge - Update Rust backend: desktop services, host metrics, SSH/SFTP enhancements
This commit is contained in:
1 parent
fea6d8db04
commit
b0d0e3a5f3
301 files changed
+28002
-2705
No files matched your search
@@ -101,6 +101,34 @@ impl IdResponse {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ShellOutputResponse {
|
||||
pub success: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub data: Option<Vec<u8>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
impl ShellOutputResponse {
|
||||
pub fn ok(data: Vec<u8>) -> Self {
|
||||
Self {
|
||||
success: true,
|
||||
data: Some(data),
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(error: impl Into<String>) -> Self {
|
||||
Self {
|
||||
success: false,
|
||||
data: None,
|
||||
error: Some(error.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct ExecResponse {
|
||||
@@ -212,3 +240,76 @@ pub struct SftpProgressEvent {
|
||||
pub total: u64,
|
||||
pub percentage: u8,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HostDiskMetric {
|
||||
pub mount: String,
|
||||
pub percent: u8,
|
||||
pub used_kb: u64,
|
||||
pub total_kb: u64,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Clone)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HostMetrics {
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub os_pretty_name: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timezone: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub timezone_offset: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub uptime_sec: Option<u64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub cpu_percent: Option<f32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub mem_used_kb: Option<u64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub mem_total_kb: Option<u64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub mem_percent: Option<u8>,
|
||||
pub disks: Vec<HostDiskMetric>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
#[serde(rename_all = "camelCase")]
|
||||
pub struct HostMetricsResponse {
|
||||
pub success: bool,
|
||||
/// True when another ssh_exec (e.g. Agent) holds the connection — caller should keep stale UI.
|
||||
#[serde(default, skip_serializing_if = "std::ops::Not::not")]
|
||||
pub skipped: bool,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub metrics: Option<HostMetrics>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub error: Option<String>,
|
||||
}
|
||||
|
||||
impl HostMetricsResponse {
|
||||
pub fn ok(metrics: HostMetrics) -> Self {
|
||||
Self {
|
||||
success: true,
|
||||
skipped: false,
|
||||
metrics: Some(metrics),
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn skipped() -> Self {
|
||||
Self {
|
||||
success: true,
|
||||
skipped: true,
|
||||
metrics: None,
|
||||
error: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn error(error: impl Into<String>) -> Self {
|
||||
Self {
|
||||
success: false,
|
||||
skipped: false,
|
||||
metrics: None,
|
||||
error: Some(error.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user