diff --git a/internal/service/installer.go b/internal/service/installer.go index 9c01dc6..1511a82 100644 --- a/internal/service/installer.go +++ b/internal/service/installer.go @@ -51,16 +51,16 @@ func (i *installer) Install(ctx context.Context, cfg *types.InstallConfig, progr weight float64 fn func(ctx context.Context, cfg *types.InstallConfig) error }{ - {i18n.T().Get("Checking system requirements"), 0.05, i.checkSystem}, - {i18n.T().Get("Creating www user"), 0.02, i.createUser}, - {i18n.T().Get("Optimizing system settings"), 0.08, i.optimizeSystem}, - {i18n.T().Get("Installing dependencies"), 0.20, i.installDeps}, - {i18n.T().Get("Creating swap file"), 0.05, i.createSwap}, - {i18n.T().Get("Downloading panel"), 0.30, i.downloadPanel}, - {i18n.T().Get("Configuring firewall"), 0.10, i.configureFirewall}, - {i18n.T().Get("Creating systemd service"), 0.10, i.createService}, - {i18n.T().Get("Initializing panel"), 0.08, i.initPanel}, - {i18n.T().Get("Detecting installed apps"), 0.02, i.detectApps}, + {i18n.T.Get("Checking system requirements"), 0.05, i.checkSystem}, + {i18n.T.Get("Creating www user"), 0.02, i.createUser}, + {i18n.T.Get("Optimizing system settings"), 0.08, i.optimizeSystem}, + {i18n.T.Get("Installing dependencies"), 0.20, i.installDeps}, + {i18n.T.Get("Creating swap file"), 0.05, i.createSwap}, + {i18n.T.Get("Downloading panel"), 0.30, i.downloadPanel}, + {i18n.T.Get("Configuring firewall"), 0.10, i.configureFirewall}, + {i18n.T.Get("Creating systemd service"), 0.10, i.createService}, + {i18n.T.Get("Initializing panel"), 0.08, i.initPanel}, + {i18n.T.Get("Detecting installed apps"), 0.02, i.detectApps}, } var currentProgress float64 @@ -75,7 +75,7 @@ func (i *installer) Install(ctx context.Context, cfg *types.InstallConfig, progr progress <- types.Progress{ Step: step.name, Percent: currentProgress, - Message: fmt.Sprintf("%s: %v", i18n.T().Get("Error"), err), + Message: fmt.Sprintf("%s: %v", i18n.T.Get("Error"), err), IsError: true, Error: err, } @@ -86,14 +86,14 @@ func (i *installer) Install(ctx context.Context, cfg *types.InstallConfig, progr progress <- types.Progress{ Step: step.name, Percent: currentProgress, - Message: step.name + " " + i18n.T().Get("completed"), + Message: step.name + " " + i18n.T.Get("completed"), } } progress <- types.Progress{ - Step: i18n.T().Get("Installation complete"), + Step: i18n.T.Get("Installation complete"), Percent: 1.0, - Message: i18n.T().Get("Panel installed successfully"), + Message: i18n.T.Get("Panel installed successfully"), } return nil @@ -113,12 +113,12 @@ func (i *installer) checkSystem(ctx context.Context, cfg *types.InstallConfig) e // 检查OS if info.OS == types.OSUnknown { - return errors.New(i18n.T().Get("Unsupported operating system")) + return errors.New(i18n.T.Get("Unsupported operating system")) } // 检查架构 if info.Arch == types.ArchUnknown { - return errors.New(i18n.T().Get("Unsupported CPU architecture")) + return errors.New(i18n.T.Get("Unsupported CPU architecture")) } // 检查CPU特性 @@ -133,19 +133,19 @@ func (i *installer) checkSystem(ctx context.Context, cfg *types.InstallConfig) e major := 0 _, _ = fmt.Sscanf(parts[0], "%d", &major) if major < 4 { - return errors.New(i18n.T().Get("Kernel version too old, requires 4.x or above")) + return errors.New(i18n.T.Get("Kernel version too old, requires 4.x or above")) } } } // 检查是否64位 if !info.Is64Bit { - return errors.New(i18n.T().Get("Requires 64-bit system")) + return errors.New(i18n.T.Get("Requires 64-bit system")) } // 检查是否已安装 if i.detector.CheckPanelInstalled(cfg.SetupPath) { - return errors.New(i18n.T().Get("Panel is already installed")) + return errors.New(i18n.T.Get("Panel is already installed")) } // 保存系统信息到配置 @@ -201,7 +201,7 @@ func (i *installer) installDeps(ctx context.Context, cfg *types.InstallConfig) e info, _ := i.detector.Detect(ctx) pkgMgr := system.NewPackageManager(info.OS, i.executor) if pkgMgr == nil { - return errors.New(i18n.T().Get("Unsupported operating system")) + return errors.New(i18n.T.Get("Unsupported operating system")) } // 设置镜像源 @@ -274,7 +274,7 @@ func (i *installer) downloadPanel(ctx context.Context, cfg *types.InstallConfig) SetContext(ctx). Get("https://api.acepanel.net/version/latest") if err != nil { - return fmt.Errorf("%s: %w", i18n.T().Get("Failed to get version info"), err) + return fmt.Errorf("%s: %w", i18n.T.Get("Failed to get version info"), err) } var versionResp struct { @@ -289,7 +289,7 @@ func (i *installer) downloadPanel(ctx context.Context, cfg *types.InstallConfig) } if err := json.Unmarshal(resp.Body(), &versionResp); err != nil { - return fmt.Errorf("%s: %w", i18n.T().Get("Failed to parse version info"), err) + return fmt.Errorf("%s: %w", i18n.T.Get("Failed to parse version info"), err) } // 根据架构选择下载链接 @@ -308,23 +308,23 @@ func (i *installer) downloadPanel(ctx context.Context, cfg *types.InstallConfig) } if downloadURL == "" { - return errors.New(i18n.T().Get("No download URL found for architecture %s", arch)) + return errors.New(i18n.T.Get("No download URL found for architecture %s", arch)) } // 下载面板 zipPath := cfg.SetupPath + "/panel/panel.zip" - resp, err = client.R(). + _, err = client.R(). SetContext(ctx). SetOutput(zipPath). Get(downloadURL) if err != nil { - return fmt.Errorf("%s: %w", i18n.T().Get("Failed to download panel"), err) + return fmt.Errorf("%s: %w", i18n.T.Get("Failed to download panel"), err) } // 解压 result, err := i.executor.Run(ctx, "unzip", "-o", zipPath, "-d", cfg.SetupPath+"/panel") if err != nil || result.ExitCode != 0 { - return errors.New(i18n.T().Get("Failed to unzip panel")) + return errors.New(i18n.T.Get("Failed to unzip panel")) } // 删除zip文件 @@ -412,13 +412,13 @@ func (i *installer) initPanel(ctx context.Context, cfg *types.InstallConfig) err // 初始化面板 result, err := i.executor.Run(ctx, "/usr/local/sbin/acepanel", "init") if err != nil || result.ExitCode != 0 { - return errors.New(i18n.T().Get("Failed to initialize panel")) + return errors.New(i18n.T.Get("Failed to initialize panel")) } // 同步 result, err = i.executor.Run(ctx, "/usr/local/sbin/acepanel", "sync") if err != nil || result.ExitCode != 0 { - return errors.New(i18n.T().Get("Failed to sync panel")) + return errors.New(i18n.T.Get("Failed to sync panel")) } return nil diff --git a/internal/service/mounter.go b/internal/service/mounter.go index 2dce67b..9019148 100644 --- a/internal/service/mounter.go +++ b/internal/service/mounter.go @@ -49,16 +49,16 @@ func (m *mounter) Mount(ctx context.Context, cfg *types.MountConfig, progress Pr // 检查磁盘是否存在 if !m.detector.CheckDiskExists(cfg.Disk) { - return errors.New(i18n.T().Get("Disk not found")) + return errors.New(i18n.T.Get("Disk not found")) } // 检查是否为系统盘 if m.detector.IsSystemDisk(cfg.Disk) { - return errors.New(i18n.T().Get("Cannot operate on system disk")) + return errors.New(i18n.T.Get("Cannot operate on system disk")) } // 安装分区工具 - progress(i18n.T().Get("Installing partition tools"), i18n.T().Get("Installing partition tools...")) + progress(i18n.T.Get("Installing partition tools"), i18n.T.Get("Installing partition tools...")) info, _ := m.detector.Detect(ctx) pkgMgr := system.NewPackageManager(info.OS, m.executor) if pkgMgr != nil { @@ -74,7 +74,7 @@ func (m *mounter) Mount(ctx context.Context, cfg *types.MountConfig, progress Pr } // 创建挂载点 - progress(i18n.T().Get("Creating mount point"), i18n.T().Get("Creating %s...", cfg.MountPoint)) + progress(i18n.T.Get("Creating mount point"), i18n.T.Get("Creating %s...", cfg.MountPoint)) if err := os.MkdirAll(cfg.MountPoint, 0755); err != nil { return err } @@ -82,14 +82,14 @@ func (m *mounter) Mount(ctx context.Context, cfg *types.MountConfig, progress Pr // 检查挂载点是否为空 entries, err := os.ReadDir(cfg.MountPoint) if err == nil && len(entries) > 0 { - return errors.New(i18n.T().Get("Mount point is not empty")) + return errors.New(i18n.T.Get("Mount point is not empty")) } // 卸载已有分区 _, _ = m.executor.Run(ctx, "umount", "/dev/"+cfg.Disk+"1") // 删除所有分区 - progress(i18n.T().Get("Deleting existing partitions"), i18n.T().Get("Deleting existing partitions...")) + progress(i18n.T.Get("Deleting existing partitions"), i18n.T.Get("Deleting existing partitions...")) fdiskInput := "" // 获取现有分区数 result, _ := m.executor.Run(ctx, "lsblk", "-no", "NAME", "/dev/"+cfg.Disk) @@ -104,42 +104,42 @@ func (m *mounter) Mount(ctx context.Context, cfg *types.MountConfig, progress Pr _, _ = m.executor.RunWithInput(ctx, fdiskInput, "fdisk", "/dev/"+cfg.Disk) // 创建新分区 - progress(i18n.T().Get("Creating partition"), i18n.T().Get("Creating partition on /dev/%s...", cfg.Disk)) + progress(i18n.T.Get("Creating partition"), i18n.T.Get("Creating partition on /dev/%s...", cfg.Disk)) partitionInput := "g\nn\n1\n\n\nw\n" - result, err = m.executor.RunWithInput(ctx, partitionInput, "fdisk", "/dev/"+cfg.Disk) + _, err = m.executor.RunWithInput(ctx, partitionInput, "fdisk", "/dev/"+cfg.Disk) if err != nil { - return fmt.Errorf("%s: %w", i18n.T().Get("Failed to create partition"), err) + return fmt.Errorf("%s: %w", i18n.T.Get("Failed to create partition"), err) } // 格式化 - progress(i18n.T().Get("Formatting partition"), i18n.T().Get("Formatting /dev/%s1 as %s...", cfg.Disk, cfg.FSType)) + progress(i18n.T.Get("Formatting partition"), i18n.T.Get("Formatting /dev/%s1 as %s...", cfg.Disk, cfg.FSType)) switch cfg.FSType { case types.FSTypeExt4: result, err = m.executor.Run(ctx, "mkfs.ext4", "-F", "/dev/"+cfg.Disk+"1") case types.FSTypeXFS: result, err = m.executor.Run(ctx, "mkfs.xfs", "-f", "/dev/"+cfg.Disk+"1") default: - return errors.New(i18n.T().Get("Unsupported filesystem type: %s", cfg.FSType)) + return errors.New(i18n.T.Get("Unsupported filesystem type: %s", cfg.FSType)) } if err != nil || (result != nil && result.ExitCode != 0) { - return errors.New(i18n.T().Get("Format failed")) + return errors.New(i18n.T.Get("Format failed")) } // 重载systemd _, _ = m.executor.Run(ctx, "systemctl", "daemon-reload") // 挂载 - progress(i18n.T().Get("Mounting partition"), i18n.T().Get("Mounting /dev/%s1 to %s...", cfg.Disk, cfg.MountPoint)) + progress(i18n.T.Get("Mounting partition"), i18n.T.Get("Mounting /dev/%s1 to %s...", cfg.Disk, cfg.MountPoint)) result, err = m.executor.Run(ctx, "mount", "/dev/"+cfg.Disk+"1", cfg.MountPoint) if err != nil || (result != nil && result.ExitCode != 0) { - return errors.New(i18n.T().Get("Mount failed")) + return errors.New(i18n.T.Get("Mount failed")) } // 获取UUID - progress(i18n.T().Get("Updating fstab"), i18n.T().Get("Updating /etc/fstab for auto-mount...")) + progress(i18n.T.Get("Updating fstab"), i18n.T.Get("Updating /etc/fstab for auto-mount...")) result, err = m.executor.Run(ctx, "blkid", "-s", "UUID", "-o", "value", "/dev/"+cfg.Disk+"1") if err != nil || result == nil || result.ExitCode != 0 { - return errors.New(i18n.T().Get("Failed to get UUID")) + return errors.New(i18n.T.Get("Failed to get UUID")) } uuid := strings.TrimSpace(result.Stdout) @@ -164,9 +164,9 @@ func (m *mounter) Mount(ctx context.Context, cfg *types.MountConfig, progress Pr _, _ = m.executor.Run(ctx, "systemctl", "daemon-reload") result, err = m.executor.Run(ctx, "mount", "-a") if err != nil || (result != nil && result.ExitCode != 0) { - return errors.New(i18n.T().Get("fstab configuration error")) + return errors.New(i18n.T.Get("fstab configuration error")) } - progress(i18n.T().Get("Mount complete"), i18n.T().Get("Disk partition and mount successful")) + progress(i18n.T.Get("Mount complete"), i18n.T.Get("Disk partition and mount successful")) return nil } diff --git a/internal/service/uninstaller.go b/internal/service/uninstaller.go index 0b52371..baecf5a 100644 --- a/internal/service/uninstaller.go +++ b/internal/service/uninstaller.go @@ -2,7 +2,7 @@ package service import ( "context" - "fmt" + "errors" "os" "github.com/acepanel/helper/internal/system" @@ -44,25 +44,25 @@ func (u *uninstaller) Uninstall(ctx context.Context, setupPath string, progress // 检查是否已安装 if !u.detector.CheckPanelInstalled(setupPath) { - return fmt.Errorf(i18n.T().Get("Panel is not installed")) + return errors.New(i18n.T.Get("Panel is not installed")) } // 停止服务 - progress(i18n.T().Get("Stopping panel service"), i18n.T().Get("Stopping acepanel service...")) + progress(i18n.T.Get("Stopping panel service"), i18n.T.Get("Stopping acepanel service...")) _ = u.systemd.Stop(ctx, "acepanel") _ = u.systemd.Disable(ctx, "acepanel") // 删除服务文件 - progress(i18n.T().Get("Removing service file"), i18n.T().Get("Removing systemd service file...")) + progress(i18n.T.Get("Removing service file"), i18n.T.Get("Removing systemd service file...")) _ = u.systemd.RemoveServiceFile("acepanel") _ = u.systemd.DaemonReload(ctx) // 删除CLI工具 - progress(i18n.T().Get("Removing CLI tool"), i18n.T().Get("Removing /usr/local/sbin/acepanel...")) + progress(i18n.T.Get("Removing CLI tool"), i18n.T.Get("Removing /usr/local/sbin/acepanel...")) _ = os.Remove("/usr/local/sbin/acepanel") // 移除swap - progress(i18n.T().Get("Removing swap file"), i18n.T().Get("Removing swap file...")) + progress(i18n.T.Get("Removing swap file"), i18n.T.Get("Removing swap file...")) swapFile := setupPath + "/swap" if _, err := os.Stat(swapFile); err == nil { _, _ = u.executor.Run(ctx, "swapoff", swapFile) @@ -74,13 +74,13 @@ func (u *uninstaller) Uninstall(ctx context.Context, setupPath string, progress // 验证fstab result, _ := u.executor.Run(ctx, "mount", "-a") if result != nil && result.ExitCode != 0 { - return fmt.Errorf(i18n.T().Get("fstab configuration error, please check /etc/fstab")) + return errors.New(i18n.T.Get("fstab configuration error, please check /etc/fstab")) } // 删除安装目录 - progress(i18n.T().Get("Removing installation directory"), i18n.T().Get("Removing %s...", setupPath)) + progress(i18n.T.Get("Removing installation directory"), i18n.T.Get("Removing %s...", setupPath)) _ = os.RemoveAll(setupPath) - progress(i18n.T().Get("Uninstallation complete"), i18n.T().Get("Panel uninstalled successfully")) + progress(i18n.T.Get("Uninstallation complete"), i18n.T.Get("Panel uninstalled successfully")) return nil } diff --git a/internal/system/detector.go b/internal/system/detector.go index e647b52..621d173 100644 --- a/internal/system/detector.go +++ b/internal/system/detector.go @@ -234,7 +234,7 @@ func (d *detector) CheckRoot() error { return err } if currentUser.Uid != "0" { - return errors.New(i18n.T().Get("Please run with root privileges")) + return errors.New(i18n.T.Get("Please run with root privileges")) } return nil } @@ -252,7 +252,7 @@ func (d *detector) CheckCPUFeatures(ctx context.Context) error { // 检查是否支持ssse3 (x86-64-v2的标志之一) if !strings.Contains(string(data), "ssse3") { - return errors.New(i18n.T().Get("CPU must support at least x86-64-v2 instruction set")) + return errors.New(i18n.T.Get("CPU must support at least x86-64-v2 instruction set")) } return nil diff --git a/internal/system/firewall.go b/internal/system/firewall.go index db8e17b..045f4ba 100644 --- a/internal/system/firewall.go +++ b/internal/system/firewall.go @@ -41,7 +41,7 @@ func (f *firewall) Install(ctx context.Context) error { } pkgMgr := NewPackageManager(info.OS, f.executor) if pkgMgr == nil { - return fmt.Errorf("%s", i18n.T().Get("Unsupported operating system")) + return fmt.Errorf("%s", i18n.T.Get("Unsupported operating system")) } return pkgMgr.Install(ctx, "firewalld") } @@ -52,7 +52,7 @@ func (f *firewall) Enable(ctx context.Context) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("Failed to enable firewalld"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("Failed to enable firewalld"), result.Stderr) } // 设置默认zone @@ -67,7 +67,7 @@ func (f *firewall) AddPort(ctx context.Context, port int, protocol string) error return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to add port"), portStr, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to add port"), portStr, result.Stderr) } return nil } @@ -79,7 +79,7 @@ func (f *firewall) RemovePort(ctx context.Context, port int, protocol string) er return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to remove port"), portStr, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to remove port"), portStr, result.Stderr) } return nil } @@ -90,7 +90,7 @@ func (f *firewall) Reload(ctx context.Context) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("Failed to reload firewall"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("Failed to reload firewall"), result.Stderr) } return nil } diff --git a/internal/system/package.go b/internal/system/package.go index 39b1153..b983ffe 100644 --- a/internal/system/package.go +++ b/internal/system/package.go @@ -49,7 +49,7 @@ func (m *dnfManager) UpdateCache(ctx context.Context) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("dnf makecache failed"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("dnf makecache failed"), result.Stderr) } return nil } @@ -61,7 +61,7 @@ func (m *dnfManager) Install(ctx context.Context, packages ...string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("dnf install failed"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("dnf install failed"), result.Stderr) } return nil } @@ -73,7 +73,7 @@ func (m *dnfManager) Remove(ctx context.Context, packages ...string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("dnf remove failed"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("dnf remove failed"), result.Stderr) } return nil } @@ -159,7 +159,7 @@ func (m *aptManager) UpdateCache(ctx context.Context) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("apt-get update failed"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("apt-get update failed"), result.Stderr) } return nil } @@ -171,7 +171,7 @@ func (m *aptManager) Install(ctx context.Context, packages ...string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("apt-get install failed"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("apt-get install failed"), result.Stderr) } return nil } @@ -183,7 +183,7 @@ func (m *aptManager) Remove(ctx context.Context, packages ...string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("apt-get remove failed"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("apt-get remove failed"), result.Stderr) } return nil } diff --git a/internal/system/systemd.go b/internal/system/systemd.go index c0dea32..9b04956 100644 --- a/internal/system/systemd.go +++ b/internal/system/systemd.go @@ -46,7 +46,7 @@ func (s *systemd) Start(ctx context.Context, service string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to start"), service, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to start"), service, result.Stderr) } return nil } @@ -57,7 +57,7 @@ func (s *systemd) Stop(ctx context.Context, service string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to stop"), service, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to stop"), service, result.Stderr) } return nil } @@ -68,7 +68,7 @@ func (s *systemd) Enable(ctx context.Context, service string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to enable"), service, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to enable"), service, result.Stderr) } return nil } @@ -79,7 +79,7 @@ func (s *systemd) Disable(ctx context.Context, service string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to disable"), service, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to disable"), service, result.Stderr) } return nil } @@ -90,7 +90,7 @@ func (s *systemd) Restart(ctx context.Context, service string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to restart"), service, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to restart"), service, result.Stderr) } return nil } @@ -106,7 +106,7 @@ func (s *systemd) DaemonReload(ctx context.Context) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s: %s", i18n.T().Get("Failed to daemon-reload"), result.Stderr) + return fmt.Errorf("%s: %s", i18n.T.Get("Failed to daemon-reload"), result.Stderr) } return nil } diff --git a/internal/system/user.go b/internal/system/user.go index 65d64c4..e417587 100644 --- a/internal/system/user.go +++ b/internal/system/user.go @@ -52,7 +52,7 @@ func (u *userManager) CreateUser(ctx context.Context, username, groupname string return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to create user"), username, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to create user"), username, result.Stderr) } return nil } @@ -63,7 +63,7 @@ func (u *userManager) CreateGroup(ctx context.Context, groupname string) error { return err } if result.ExitCode != 0 { - return fmt.Errorf("%s %s: %s", i18n.T().Get("Failed to create group"), groupname, result.Stderr) + return fmt.Errorf("%s %s: %s", i18n.T.Get("Failed to create group"), groupname, result.Stderr) } return nil } diff --git a/internal/ui/app.go b/internal/ui/app.go index 1dfdc01..c8088f3 100644 --- a/internal/ui/app.go +++ b/internal/ui/app.go @@ -2,6 +2,7 @@ package ui import ( "context" + "errors" "fmt" "strings" "time" @@ -220,7 +221,7 @@ func (a *App) updateLanguageSelect(msg tea.Msg) (tea.Model, tea.Cmd) { if a.langForm.State == huh.StateCompleted { locale := gotext.NewLocaleFSWithPath(a.langChoice, embed.LocalesFS, "locales") locale.AddDomain("helper") - i18n.Init(locale) + i18n.T = locale a.state = ViewMainMenu return a, a.initMainMenu() } @@ -238,12 +239,12 @@ func (a *App) initMainMenu() tea.Cmd { a.menuForm = huh.NewForm( huh.NewGroup( huh.NewSelect[MenuChoice](). - Title(i18n.T().Get("Select Operation")). + Title(i18n.T.Get("Select Operation")). Options( - huh.NewOption(i18n.T().Get("Install Panel"), MenuInstall), - huh.NewOption(i18n.T().Get("Uninstall Panel"), MenuUninstall), - huh.NewOption(i18n.T().Get("Disk Partition"), MenuMount), - huh.NewOption(i18n.T().Get("Exit"), MenuExit), + huh.NewOption(i18n.T.Get("Install Panel"), MenuInstall), + huh.NewOption(i18n.T.Get("Uninstall Panel"), MenuUninstall), + huh.NewOption(i18n.T.Get("Disk Partition"), MenuMount), + huh.NewOption(i18n.T.Get("Exit"), MenuExit), ). Value(&a.menuChoice), ), @@ -302,10 +303,10 @@ func (a *App) initInstall() tea.Cmd { a.installForm = huh.NewForm( huh.NewGroup( huh.NewConfirm(). - Title(i18n.T().Get("Confirm Installation")). - Description(i18n.T().Get("Panel will be installed to %s", a.setupPath)). - Affirmative(i18n.T().Get("Yes")). - Negative(i18n.T().Get("No")). + Title(i18n.T.Get("Confirm Installation")). + Description(i18n.T.Get("Panel will be installed to %s", a.setupPath)). + Affirmative(i18n.T.Get("Yes")). + Negative(i18n.T.Get("No")). Value(&a.installConfirmed), ), ).WithTheme(huh.ThemeDracula()) @@ -400,19 +401,19 @@ func (a *App) viewInstall() string { var sb strings.Builder sb.WriteString(RenderLogo()) sb.WriteString("\n") - sb.WriteString(RenderTitle(i18n.T().Get("Install Panel"))) + sb.WriteString(RenderTitle(i18n.T.Get("Install Panel"))) sb.WriteString("\n") if a.installDone { if a.installErr != nil { - sb.WriteString(RenderError(i18n.T().Get("Installation failed"))) + sb.WriteString(RenderError(i18n.T.Get("Installation failed"))) sb.WriteString("\n\n") sb.WriteString(ErrorBoxStyle.Render(a.installErr.Error())) } else { - sb.WriteString(RenderSuccess(i18n.T().Get("Installation successful"))) + sb.WriteString(RenderSuccess(i18n.T.Get("Installation successful"))) } sb.WriteString("\n\n") - sb.WriteString(RenderHelp("Enter", i18n.T().Get("Back"))) + sb.WriteString(RenderHelp("Enter", i18n.T.Get("Back"))) } else if a.installRunning { sb.WriteString(fmt.Sprintf("%s %s\n\n", a.installSpinner.View(), a.installStep)) sb.WriteString(a.installProgress.ViewAs(a.installPercent)) @@ -520,10 +521,10 @@ func (a *App) initUninstallConfirm() { a.uninstallForm = huh.NewForm( huh.NewGroup( huh.NewConfirm(). - Title(i18n.T().Get("Confirm Uninstallation")). - Description(i18n.T().Get("Are you sure you want to uninstall the panel?")). - Affirmative(i18n.T().Get("Yes")). - Negative(i18n.T().Get("No")). + Title(i18n.T.Get("Confirm Uninstallation")). + Description(i18n.T.Get("Are you sure you want to uninstall the panel?")). + Affirmative(i18n.T.Get("Yes")). + Negative(i18n.T.Get("No")). Value(&a.uninstallConfirm), ), ).WithTheme(huh.ThemeDracula()) @@ -551,26 +552,26 @@ func (a *App) viewUninstall() string { var sb strings.Builder sb.WriteString(RenderLogo()) sb.WriteString("\n") - sb.WriteString(RenderTitle(i18n.T().Get("Uninstall Panel"))) + sb.WriteString(RenderTitle(i18n.T.Get("Uninstall Panel"))) sb.WriteString("\n") switch a.uninstallState { case 0: // warning sb.WriteString(WarningBoxStyle.Render( - RenderWarning(i18n.T().Get("High-risk operation")) + "\n\n" + - i18n.T().Get("Please backup all data before uninstalling.") + "\n" + - i18n.T().Get("All data will be cleared and cannot be recovered!"), + RenderWarning(i18n.T.Get("High-risk operation")) + "\n\n" + + i18n.T.Get("Please backup all data before uninstalling.") + "\n" + + i18n.T.Get("All data will be cleared and cannot be recovered!"), )) sb.WriteString("\n\n") - sb.WriteString(RenderHelp("Enter", i18n.T().Get("Continue"), "Esc", i18n.T().Get("Back"))) + sb.WriteString(RenderHelp("Enter", i18n.T.Get("Continue"), "Esc", i18n.T.Get("Back"))) case 1: // countdown sb.WriteString(WarningBoxStyle.Render( fmt.Sprintf("%s\n\n%s %d %s", - i18n.T().Get("For safety, please wait before proceeding"), - i18n.T().Get("Waiting:"), + i18n.T.Get("For safety, please wait before proceeding"), + i18n.T.Get("Waiting:"), a.uninstallCountdown, - i18n.T().Get("seconds"), + i18n.T.Get("seconds"), ), )) sb.WriteString("\n\n") @@ -578,7 +579,7 @@ func (a *App) viewUninstall() string { sb.WriteString(MutedStyle.Render(fmt.Sprintf("Press Enter %d more times to skip", 10-a.uninstallSkipCount))) sb.WriteString("\n") } - sb.WriteString(RenderHelp("Esc", i18n.T().Get("Cancel"), "Enter×10", i18n.T().Get("Skip"))) + sb.WriteString(RenderHelp("Esc", i18n.T.Get("Cancel"), "Enter×10", i18n.T.Get("Skip"))) case 2: // confirm sb.WriteString(a.uninstallForm.View()) @@ -592,16 +593,16 @@ func (a *App) viewUninstall() string { case 4: // done if a.uninstallErr != nil { - sb.WriteString(RenderError(i18n.T().Get("Uninstallation failed"))) + sb.WriteString(RenderError(i18n.T.Get("Uninstallation failed"))) sb.WriteString("\n\n") sb.WriteString(ErrorBoxStyle.Render(a.uninstallErr.Error())) } else { - sb.WriteString(RenderSuccess(i18n.T().Get("Uninstallation successful"))) + sb.WriteString(RenderSuccess(i18n.T.Get("Uninstallation successful"))) sb.WriteString("\n\n") - sb.WriteString(i18n.T().Get("Thank you for using AcePanel.")) + sb.WriteString(i18n.T.Get("Thank you for using AcePanel.")) } sb.WriteString("\n\n") - sb.WriteString(RenderHelp("Enter", i18n.T().Get("Back"))) + sb.WriteString(RenderHelp("Enter", i18n.T.Get("Back"))) } return sb.String() @@ -641,7 +642,7 @@ func (a *App) updateMount(msg tea.Msg) (tea.Model, tea.Cmd) { } if len(msg.disks) == 0 { a.mountDone = true - a.mountErr = fmt.Errorf(i18n.T().Get("No available disks found")) + a.mountErr = errors.New(i18n.T.Get("No available disks found")) return a, nil } a.disks = msg.disks @@ -739,8 +740,8 @@ func (a *App) initDiskForm() { a.mountDiskForm = huh.NewForm( huh.NewGroup( huh.NewSelect[string](). - Title(i18n.T().Get("Select Disk")). - Description(i18n.T().Get("Select a disk to partition and mount")). + Title(i18n.T.Get("Select Disk")). + Description(i18n.T.Get("Select a disk to partition and mount")). Options(options...). Value(&a.mountConfig.Disk), ), @@ -751,12 +752,12 @@ func (a *App) initMountPointForm() { a.mountPointForm = huh.NewForm( huh.NewGroup( huh.NewInput(). - Title(i18n.T().Get("Mount Point")). - Description(i18n.T().Get("Enter the mount point path (e.g. /opt/ace)")). + Title(i18n.T.Get("Mount Point")). + Description(i18n.T.Get("Enter the mount point path (e.g. /opt/ace)")). Value(&a.mountConfig.MountPoint). Validate(func(s string) error { if len(s) == 0 || s[0] != '/' { - return fmt.Errorf(i18n.T().Get("Please enter an absolute path")) + return errors.New(i18n.T.Get("Please enter an absolute path")) } return nil }), @@ -768,10 +769,10 @@ func (a *App) initFSForm() { a.mountFSForm = huh.NewForm( huh.NewGroup( huh.NewSelect[types.FSType](). - Title(i18n.T().Get("File System")). - Description(i18n.T().Get("Select the file system type")). + Title(i18n.T.Get("File System")). + Description(i18n.T.Get("Select the file system type")). Options( - huh.NewOption(fmt.Sprintf("ext4 (%s)", i18n.T().Get("Recommended")), types.FSTypeExt4), + huh.NewOption(fmt.Sprintf("ext4 (%s)", i18n.T.Get("Recommended")), types.FSTypeExt4), huh.NewOption("xfs", types.FSTypeXFS), ). Value(&a.mountConfig.FSType), @@ -784,14 +785,14 @@ func (a *App) initMountConfirmForm() { a.mountConfirmForm = huh.NewForm( huh.NewGroup( huh.NewConfirm(). - Title(i18n.T().Get("Confirm Operation")). - Description(i18n.T().Get("Disk: %s, Mount Point: %s, File System: %s", + Title(i18n.T.Get("Confirm Operation")). + Description(i18n.T.Get("Disk: %s, Mount Point: %s, File System: %s", a.mountConfig.Disk, a.mountConfig.MountPoint, a.mountConfig.FSType, )). - Affirmative(i18n.T().Get("Yes")). - Negative(i18n.T().Get("No")). + Affirmative(i18n.T.Get("Yes")). + Negative(i18n.T.Get("No")). Value(&a.mountConfirmed), ), ).WithTheme(huh.ThemeDracula()) @@ -813,35 +814,35 @@ func (a *App) viewMount() string { var sb strings.Builder sb.WriteString(RenderLogo()) sb.WriteString("\n") - sb.WriteString(RenderTitle(i18n.T().Get("Disk Partition"))) + sb.WriteString(RenderTitle(i18n.T.Get("Disk Partition"))) sb.WriteString("\n") if a.mountDone { if a.mountErr != nil { - sb.WriteString(RenderError(i18n.T().Get("Operation failed"))) + sb.WriteString(RenderError(i18n.T.Get("Operation failed"))) sb.WriteString("\n\n") sb.WriteString(ErrorBoxStyle.Render(a.mountErr.Error())) } else { - sb.WriteString(RenderSuccess(i18n.T().Get("Partition and mount successful"))) + sb.WriteString(RenderSuccess(i18n.T.Get("Partition and mount successful"))) sb.WriteString("\n\n") sb.WriteString(BoxStyle.Render(fmt.Sprintf( "%s: /dev/%s1\n%s: %s\n%s: %s", - i18n.T().Get("Device"), a.mountConfig.Disk, - i18n.T().Get("Mount Point"), a.mountConfig.MountPoint, - i18n.T().Get("File System"), a.mountConfig.FSType, + i18n.T.Get("Device"), a.mountConfig.Disk, + i18n.T.Get("Mount Point"), a.mountConfig.MountPoint, + i18n.T.Get("File System"), a.mountConfig.FSType, ))) } sb.WriteString("\n\n") - sb.WriteString(RenderHelp("Enter", i18n.T().Get("Back"))) + sb.WriteString(RenderHelp("Enter", i18n.T.Get("Back"))) return sb.String() } switch a.mountState { case 0: // loading - sb.WriteString(fmt.Sprintf("%s %s", a.mountSpinner.View(), i18n.T().Get("Loading disk list..."))) + sb.WriteString(fmt.Sprintf("%s %s", a.mountSpinner.View(), i18n.T.Get("Loading disk list..."))) case 1: // select disk - sb.WriteString(i18n.T().Get("Available disks:")) + sb.WriteString(i18n.T.Get("Available disks:")) sb.WriteString("\n\n") for _, disk := range a.disks { sb.WriteString(fmt.Sprintf(" • %s (%s)\n", disk.Name, disk.Size)) @@ -856,7 +857,7 @@ func (a *App) viewMount() string { sb.WriteString(a.mountFSForm.View()) case 4: // confirm - sb.WriteString(WarningBoxStyle.Render(i18n.T().Get("Warning: This will erase all data on the disk!"))) + sb.WriteString(WarningBoxStyle.Render(i18n.T.Get("Warning: This will erase all data on the disk!"))) sb.WriteString("\n\n") sb.WriteString(a.mountConfirmForm.View()) diff --git a/pkg/embed/locales/helper.pot b/pkg/embed/locales/helper.pot deleted file mode 100644 index 45b1017..0000000 --- a/pkg/embed/locales/helper.pot +++ /dev/null @@ -1,398 +0,0 @@ -msgid "" -msgstr "" -"Plural-Forms: nplurals=2; plural=(n != 1);\n" -"MIME-Version: 1.0\n" -"Content-Type: text/plain; charset=UTF-8\n" -"Content-Transfer-Encoding: 8bit\n" -"Language: \n" -"X-Generator: xgotext\n" - -#: internal/ui/app.go:558 -msgid "All data will be cleared and cannot be recovered!" -msgstr "" - -#: internal/ui/app.go:840 -msgid "Available disks:" -msgstr "" - -#: internal/ui/app.go:415 -#: internal/ui/app.go:561 -#: internal/ui/app.go:600 -#: internal/ui/app.go:831 -msgid "Back" -msgstr "" - -#: internal/ui/app.go:577 -msgid "Cancel" -msgstr "" - -#: internal/service/mounter.go:58 -msgid "Cannot operate on system disk" -msgstr "" - -#: internal/service/installer.go:55 -msgid "Checking system requirements" -msgstr "" - -#: internal/service/installer.go:61 -msgid "Configuring firewall" -msgstr "" - -#: internal/ui/app.go:305 -msgid "Confirm Installation" -msgstr "" - -#: internal/ui/app.go:783 -msgid "Confirm Operation" -msgstr "" - -#: internal/ui/app.go:561 -msgid "Continue" -msgstr "" - -#: internal/service/mounter.go:78 -msgid "Creating %s..." -msgstr "" - -#: internal/service/mounter.go:78 -msgid "Creating mount point" -msgstr "" - -#: internal/service/mounter.go:108 -msgid "Creating partition" -msgstr "" - -#: internal/service/mounter.go:108 -msgid "Creating partition on /dev/%s..." -msgstr "" - -#: internal/service/installer.go:59 -msgid "Creating swap file" -msgstr "" - -#: internal/service/installer.go:62 -msgid "Creating systemd service" -msgstr "" - -#: internal/service/installer.go:56 -msgid "Creating www user" -msgstr "" - -#: internal/service/mounter.go:93 -msgid "Deleting existing partitions" -msgstr "" - -#: internal/service/mounter.go:93 -msgid "Deleting existing partitions..." -msgstr "" - -#: internal/service/installer.go:64 -msgid "Detecting installed apps" -msgstr "" - -#: internal/ui/app.go:825 -msgid "Device" -msgstr "" - -#: internal/ui/app.go:245 -#: internal/ui/app.go:812 -msgid "Disk Partition" -msgstr "" - -#: internal/service/mounter.go:53 -msgid "Disk not found" -msgstr "" - -#: internal/service/mounter.go:171 -msgid "Disk partition and mount successful" -msgstr "" - -#: internal/ui/app.go:784 -msgid "Disk: %s, Mount Point: %s, File System: %s" -msgstr "" - -#: internal/service/installer.go:60 -msgid "Downloading panel" -msgstr "" - -#: internal/ui/app.go:522 -msgid "Enter 'y' to confirm uninstallation" -msgstr "" - -#: internal/ui/app.go:751 -msgid "Enter the mount point path (e.g. /opt/ace)" -msgstr "" - -#: internal/service/installer.go:79 -msgid "Error" -msgstr "" - -#: internal/ui/app.go:246 -msgid "Exit" -msgstr "" - -#: internal/service/mounter.go:112 -msgid "Failed to create partition" -msgstr "" - -#: internal/service/mounter.go:143 -msgid "Failed to get UUID" -msgstr "" - -#: internal/ui/app.go:767 -#: internal/ui/app.go:827 -msgid "File System" -msgstr "" - -#: internal/ui/app.go:566 -msgid "For safety, please wait before proceeding" -msgstr "" - -#: internal/service/mounter.go:126 -msgid "Format failed" -msgstr "" - -#: internal/service/mounter.go:116 -msgid "Formatting /dev/%s1 as %s..." -msgstr "" - -#: internal/service/mounter.go:116 -msgid "Formatting partition" -msgstr "" - -#: internal/ui/app.go:556 -msgid "High-risk operation" -msgstr "" - -#: internal/service/installer.go:63 -msgid "Initializing panel" -msgstr "" - -#: internal/ui/app.go:243 -#: internal/ui/app.go:403 -msgid "Install Panel" -msgstr "" - -#: internal/service/installer.go:95 -msgid "Installation complete" -msgstr "" - -#: internal/ui/app.go:408 -msgid "Installation failed" -msgstr "" - -#: internal/ui/app.go:412 -msgid "Installation successful" -msgstr "" - -#: internal/service/installer.go:58 -msgid "Installing dependencies" -msgstr "" - -#: internal/service/mounter.go:62 -msgid "Installing partition tools" -msgstr "" - -#: internal/service/mounter.go:62 -msgid "Installing partition tools..." -msgstr "" - -#: internal/ui/app.go:837 -msgid "Loading disk list..." -msgstr "" - -#: internal/ui/app.go:750 -#: internal/ui/app.go:826 -msgid "Mount Point" -msgstr "" - -#: internal/service/mounter.go:171 -msgid "Mount complete" -msgstr "" - -#: internal/service/mounter.go:136 -msgid "Mount failed" -msgstr "" - -#: internal/service/mounter.go:86 -msgid "Mount point is not empty" -msgstr "" - -#: internal/service/mounter.go:133 -msgid "Mounting /dev/%s1 to %s..." -msgstr "" - -#: internal/service/mounter.go:133 -msgid "Mounting partition" -msgstr "" - -#: internal/ui/app.go:308 -#: internal/ui/app.go:790 -msgid "No" -msgstr "" - -#: internal/ui/app.go:640 -msgid "No available disks found" -msgstr "" - -#: internal/ui/app.go:817 -msgid "Operation failed" -msgstr "" - -#: internal/service/installer.go:57 -msgid "Optimizing system settings" -msgstr "" - -#: internal/service/installer.go:97 -msgid "Panel installed successfully" -msgstr "" - -#: internal/service/uninstaller.go:48 -msgid "Panel is not installed" -msgstr "" - -#: internal/service/uninstaller.go:85 -msgid "Panel uninstalled successfully" -msgstr "" - -#: internal/ui/app.go:306 -msgid "Panel will be installed to %s" -msgstr "" - -#: internal/ui/app.go:821 -msgid "Partition and mount successful" -msgstr "" - -#: internal/ui/app.go:557 -msgid "Please backup all data before uninstalling." -msgstr "" - -#: internal/ui/app.go:755 -msgid "Please enter an absolute path" -msgstr "" - -#: internal/ui/app.go:770 -msgid "Recommended" -msgstr "" - -#: internal/service/uninstaller.go:82 -msgid "Removing %s..." -msgstr "" - -#: internal/service/uninstaller.go:62 -msgid "Removing /usr/local/sbin/acepanel..." -msgstr "" - -#: internal/service/uninstaller.go:62 -msgid "Removing CLI tool" -msgstr "" - -#: internal/service/uninstaller.go:82 -msgid "Removing installation directory" -msgstr "" - -#: internal/service/uninstaller.go:57 -msgid "Removing service file" -msgstr "" - -#: internal/service/uninstaller.go:66 -msgid "Removing swap file" -msgstr "" - -#: internal/service/uninstaller.go:66 -msgid "Removing swap file..." -msgstr "" - -#: internal/service/uninstaller.go:57 -msgid "Removing systemd service file..." -msgstr "" - -#: internal/ui/app.go:738 -msgid "Select Disk" -msgstr "" - -#: internal/ui/app.go:241 -msgid "Select Operation" -msgstr "" - -#: internal/ui/app.go:739 -msgid "Select a disk to partition and mount" -msgstr "" - -#: internal/ui/app.go:768 -msgid "Select the file system type" -msgstr "" - -#: internal/ui/app.go:577 -msgid "Skip" -msgstr "" - -#: internal/service/uninstaller.go:52 -msgid "Stopping acepanel service..." -msgstr "" - -#: internal/service/uninstaller.go:52 -msgid "Stopping panel service" -msgstr "" - -#: internal/ui/app.go:597 -msgid "Thank you for using AcePanel." -msgstr "" - -#: internal/ui/app.go:244 -#: internal/ui/app.go:550 -msgid "Uninstall Panel" -msgstr "" - -#: internal/service/uninstaller.go:85 -msgid "Uninstallation complete" -msgstr "" - -#: internal/ui/app.go:591 -msgid "Uninstallation failed" -msgstr "" - -#: internal/ui/app.go:595 -msgid "Uninstallation successful" -msgstr "" - -#: internal/service/mounter.go:123 -msgid "Unsupported filesystem type: %s" -msgstr "" - -#: internal/service/mounter.go:140 -msgid "Updating /etc/fstab for auto-mount..." -msgstr "" - -#: internal/service/mounter.go:140 -msgid "Updating fstab" -msgstr "" - -#: internal/ui/app.go:567 -msgid "Waiting:" -msgstr "" - -#: internal/ui/app.go:855 -msgid "Warning: This will erase all data on the disk!" -msgstr "" - -#: internal/ui/app.go:307 -#: internal/ui/app.go:789 -msgid "Yes" -msgstr "" - -#: internal/service/installer.go:90 -msgid "completed" -msgstr "" - -#: internal/service/mounter.go:168 -msgid "fstab configuration error" -msgstr "" - -#: internal/service/uninstaller.go:78 -msgid "fstab configuration error, please check /etc/fstab" -msgstr "" - -#: internal/ui/app.go:569 -msgid "seconds" -msgstr "" \ No newline at end of file diff --git a/pkg/i18n/i18n.go b/pkg/i18n/i18n.go index 24d2569..0fbacc0 100644 --- a/pkg/i18n/i18n.go +++ b/pkg/i18n/i18n.go @@ -1,26 +1,9 @@ package i18n import ( - "sync" - "github.com/leonelquinteros/gotext" ) var ( - locale *gotext.Locale - mu sync.RWMutex + T *gotext.Locale ) - -// Init 设置全局 locale -func Init(l *gotext.Locale) { - mu.Lock() - defer mu.Unlock() - locale = l -} - -// T 获取全局 locale -func T() *gotext.Locale { - mu.RLock() - defer mu.RUnlock() - return locale -}