core: init i18n

parent b3fa78cf
......@@ -5,6 +5,7 @@ go 1.25.0
require (
github.com/fatih/color v1.18.0
github.com/godbus/dbus/v5 v5.1.0
github.com/leonelquinteros/gotext v1.7.2
github.com/urfave/cli/v3 v3.4.1
gopkg.in/yaml.v3 v3.0.1
)
......
......@@ -4,6 +4,8 @@ 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/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/leonelquinteros/gotext v1.7.2 h1:bDPndU8nt+/kRo1m4l/1OXiiy2v7Z7dfPQ9+YP7G1Mc=
github.com/leonelquinteros/gotext v1.7.2/go.mod h1:9/haCkm5P7Jay1sxKDGJ5WIg4zkz8oZKw4ekNpALob8=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
......
......@@ -2,10 +2,12 @@ package hyprland
import (
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
"ximperconf/utils"
"context"
"errors"
"fmt"
"os"
"os/exec"
......@@ -23,7 +25,7 @@ func HyprlandFixConfigCommand(ctx context.Context, cmd *cli.Command) error {
manager.FixConfig()
color.Green("Конфигурация исправлена")
color.Green(locale.T("Configuration fixed"))
return nil
}
......@@ -39,7 +41,7 @@ func HyprlandCheckCommand(ctx context.Context, cmd *cli.Command) error {
}
if len(result) == 0 {
color.Green("Ошибок нет")
color.Green(locale.T("No errors"))
return nil
}
......@@ -58,7 +60,7 @@ func HyprlandModuleStatusCommand(ctx context.Context, cmd *cli.Command) error {
info := manager.GetModuleInfo(cmd.Args().Get(0), cmd.Bool("user"))
if !info.Available {
color.Red("недопустимое название для модуля.")
color.Red(locale.T("invalid module name"))
return nil
}
fmt.Println(info.Status.Label)
......@@ -68,7 +70,7 @@ func HyprlandModuleStatusCommand(ctx context.Context, cmd *cli.Command) error {
func HyprlandModuleCheckCommand(ctx context.Context, cmd *cli.Command) error {
if cmd.Args().Get(0) == "" {
return fmt.Errorf("укажите модуль для проверки")
return errors.New(locale.T("specify module name"))
}
manager, err := GetHyprlandManager(ctx)
......@@ -79,7 +81,7 @@ func HyprlandModuleCheckCommand(ctx context.Context, cmd *cli.Command) error {
moduleinfo := manager.GetModuleInfo(cmd.Args().Get(0), cmd.Bool("user"))
if !moduleinfo.Available {
return fmt.Errorf("недопустимое название для модуля")
return errors.New(locale.T("invalid module name"))
}
result, err := manager.CheckModule(cmd.Args().Get(0), cmd.Bool("user"))
......@@ -89,7 +91,7 @@ func HyprlandModuleCheckCommand(ctx context.Context, cmd *cli.Command) error {
}
if len(result) == 0 {
color.Green("Ошибок нет")
color.Green(locale.T("No errors"))
return nil
}
......@@ -182,12 +184,12 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
if config.IsJSON(cmd) {
return ui.PrintJSON([]ModuleInfoJSON{})
}
return fmt.Errorf("нет доступных модулей")
return errors.New(locale.T("no available modules"))
}
type moduleData struct {
info HyprModule
errorNum int
info HyprModule
errorNum int
}
data := make([]moduleData, 0, len(modules))
......@@ -222,7 +224,7 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
parts = append(parts, d.info.Meta.Summary)
}
if d.errorNum > 0 {
parts = append(parts, fmt.Sprintf("(ошибки: %d)", d.errorNum))
parts = append(parts, fmt.Sprintf(locale.T("(errors: %d)"), d.errorNum))
}
name := d.info.Name
if d.info.Meta != nil && d.info.Meta.Group != "" {
......@@ -236,7 +238,7 @@ func HyprlandInfoModulesCommand(ctx context.Context, cmd *cli.Command) error {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Modules",
Title: locale.T("Modules"),
Items: items,
Style: ui.DefaultTreeStyle,
Color: true,
......@@ -258,11 +260,11 @@ func HyprlandModuleEditCommand(ctx context.Context, cmd *cli.Command) error {
info := manager.GetModuleInfo(module, user)
if !info.Available {
return fmt.Errorf("недопустимое название для модуля")
return errors.New(locale.T("invalid module name"))
}
if info.Path == "" {
return fmt.Errorf("модуль '%s' не найден: %s", module, modulefile)
return fmt.Errorf(locale.T("module '%s' not found: %s"), module, modulefile)
}
editor := utils.GetEditor()
......@@ -274,7 +276,7 @@ func HyprlandModuleEditCommand(ctx context.Context, cmd *cli.Command) error {
err = editCmd.Run()
if err != nil {
return fmt.Errorf("не удалось запустить редактор: %s", err.Error())
return fmt.Errorf(locale.T("failed to start editor: %s"), err.Error())
}
return nil
......@@ -283,7 +285,7 @@ func HyprlandModuleEditCommand(ctx context.Context, cmd *cli.Command) error {
func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
module := cmd.Args().Get(0)
if module == "" {
return fmt.Errorf("укажите имя модуля")
return errors.New(locale.T("specify module name"))
}
user := cmd.Bool("user")
......@@ -294,7 +296,7 @@ func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
info := manager.GetModuleInfo(module, user)
if !info.Available {
return fmt.Errorf("недопустимое название для модуля")
return errors.New(locale.T("invalid module name"))
}
errors, _ := manager.CheckModule(module, user)
......@@ -311,30 +313,30 @@ func HyprlandModuleShowCommand(ctx context.Context, cmd *cli.Command) error {
}
blue := color.New(color.FgBlue).SprintFunc()
fmt.Printf("%s: %s\n", blue("Модуль"), info.Name)
fmt.Printf("%s: %s\n", blue(locale.T("Module")), info.Name)
if info.Meta != nil {
if info.Meta.Group != "" {
fmt.Printf("%s: %s\n", blue("Группа"), info.Meta.Group)
fmt.Printf("%s: %s\n", blue(locale.T("Group")), info.Meta.Group)
}
if info.Meta.Summary != "" {
fmt.Printf("%s: %s\n", blue("Краткое"), info.Meta.Summary)
fmt.Printf("%s: %s\n", blue(locale.T("Summary")), info.Meta.Summary)
}
if info.Meta.Description != "" {
fmt.Printf("%s: \n%s\n", blue("Описание"), info.Meta.Description)
fmt.Printf("%s: \n%s\n", blue(locale.T("Description")), info.Meta.Description)
}
}
fmt.Printf("%s: %s\n", blue("Статус"), info.Status.Color("%s %s", info.Status.Symbol, info.Status.Label))
fmt.Printf("%s: %s\n", blue("Путь"), info.Path)
fmt.Printf("%s: %s\n", blue("Путь в конфиге"), info.ConfPath)
fmt.Printf("%s: %d\n", blue("Строка в конфиге"), info.LineNumber)
fmt.Printf("%s: %s\n", blue(locale.T("Status")), info.Status.Color("%s %s", info.Status.Symbol, info.Status.Label))
fmt.Printf("%s: %s\n", blue(locale.T("Path")), info.Path)
fmt.Printf("%s: %s\n", blue(locale.T("Config path")), info.ConfPath)
fmt.Printf("%s: %d\n", blue(locale.T("Config line")), info.LineNumber)
if info.Available {
fmt.Printf("%s: да\n", blue("Доступен"))
fmt.Printf("%s: %s\n", blue(locale.T("Available")), locale.T("yes"))
} else {
fmt.Printf("%s: нет\n", blue("Доступен"))
fmt.Printf("%s: %s\n", blue(locale.T("Available")), locale.T("no"))
}
if len(errors) > 0 {
fmt.Printf("\n%s (%d):\n", blue("Ошибки"), len(errors))
fmt.Printf("\n%s (%d):\n", blue(locale.T("Errors")), len(errors))
for _, e := range errors {
fmt.Printf(" %d: %s\n", e.Line, e.Text)
}
......
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"ximperconf/config"
"ximperconf/locale"
"github.com/urfave/cli/v3"
)
......@@ -12,11 +13,11 @@ func CommandList() *cli.Command {
return &cli.Command{
Name: "hyprland",
Hidden: config.Env.Hyprland == nil,
Usage: "Hyprland Management",
Usage: locale.T("Hyprland Management"),
Before: func(ctx context.Context, command *cli.Command) (context.Context, error) {
manager, err := NewHyprlandManager()
if err != nil {
return ctx, fmt.Errorf("не удалось инициализировать HyprlandManager: %w", err)
return ctx, fmt.Errorf(locale.T("failed to initialize HyprlandManager: %w"), err)
}
ctx = context.WithValue(ctx, config.HyprManagerKey, manager)
......@@ -25,7 +26,7 @@ func CommandList() *cli.Command {
After: func(ctx context.Context, command *cli.Command) error {
manager, err := GetHyprlandManager(ctx)
if err != nil {
return fmt.Errorf("не удалось инициализировать HyprlandManager: %w", err)
return fmt.Errorf(locale.T("failed to initialize HyprlandManager: %w"), err)
}
manager.Save()
return nil
......@@ -33,22 +34,22 @@ func CommandList() *cli.Command {
Commands: []*cli.Command{
{
Name: "check",
Usage: "Check the Hyprland config",
Usage: locale.T("Check the Hyprland config"),
Action: HyprlandCheckCommand,
},
{
Name: "fix",
Usage: "Fix config: sort modules into sections by order",
Usage: locale.T("Fix config: sort modules into sections by order"),
Action: HyprlandFixConfigCommand,
},
{
Name: "sync-xkb-layouts",
Usage: "Sync layouts with xkb",
Usage: locale.T("Sync layouts with xkb"),
Action: HyprlandSyncSystemLayouts,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "force",
Usage: "Forced update",
Usage: locale.T("Forced update"),
Aliases: []string{"f"},
Value: false,
},
......@@ -56,11 +57,11 @@ func CommandList() *cli.Command {
},
{
Name: "module",
Usage: "Hyprland modules",
Usage: locale.T("Hyprland modules"),
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "user",
Usage: "use user modules",
Usage: locale.T("use user modules"),
Aliases: []string{"u"},
Value: false,
},
......@@ -68,28 +69,28 @@ func CommandList() *cli.Command {
Commands: []*cli.Command{
{
Name: "check",
Usage: "Check Hyprland module",
Usage: locale.T("Check Hyprland module"),
ArgsUsage: "module",
Action: HyprlandModuleCheckCommand,
ShellComplete: ShellCompleteModule("all"),
},
{
Name: "edit",
Usage: "Edit module file",
Usage: locale.T("Edit module file"),
ArgsUsage: "module",
Action: HyprlandModuleEditCommand,
ShellComplete: ShellCompleteModule("all"),
},
{
Name: "status",
Usage: "Hyprland module status",
Usage: locale.T("Hyprland module status"),
ArgsUsage: "module",
Action: HyprlandModuleStatusCommand,
ShellComplete: ShellCompleteModule("all"),
},
{
Name: "show",
Usage: "Show detailed module info",
Usage: locale.T("Show detailed module info"),
ArgsUsage: "module",
Flags: []cli.Flag{
config.FormatFlag,
......@@ -99,11 +100,11 @@ func CommandList() *cli.Command {
},
{
Name: "info",
Usage: "Information about modules",
Usage: locale.T("Information about modules"),
Flags: []cli.Flag{
&cli.StringFlag{
Name: "filter",
Usage: "status filter",
Usage: locale.T("status filter"),
Aliases: []string{"f"},
Value: "all",
},
......@@ -113,18 +114,18 @@ func CommandList() *cli.Command {
},
{
Name: "enable",
Usage: "enable module",
Usage: locale.T("enable module"),
ArgsUsage: "module",
Action: HyprlandModuleEnableCommand,
ShellComplete: ShellCompleteModule("disabled"),
},
{
Name: "disable",
Usage: "disable module",
Usage: locale.T("disable module"),
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "remove",
Usage: "delete module line from config",
Usage: locale.T("delete module line from config"),
Aliases: []string{"r"},
Value: false,
},
......@@ -135,7 +136,7 @@ func CommandList() *cli.Command {
},
{
Name: "toggle",
Usage: "toggle module",
Usage: locale.T("toggle module"),
ArgsUsage: "module",
Action: HyprlandToggleModuleCommand,
ShellComplete: ShellCompleteModule("all"),
......@@ -144,11 +145,11 @@ func CommandList() *cli.Command {
},
{
Name: "var",
Usage: "Hyprland vars",
Usage: locale.T("Hyprland vars"),
Commands: []*cli.Command{
{
Name: "list",
Usage: "vars list",
Usage: locale.T("vars list"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -156,7 +157,7 @@ func CommandList() *cli.Command {
},
{
Name: "info",
Usage: "vars info",
Usage: locale.T("vars info"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -164,18 +165,18 @@ func CommandList() *cli.Command {
},
{
Name: "get",
Usage: "get var value",
Usage: locale.T("get var value"),
Action: HyprlandVarGetCommand,
ShellComplete: ShellCompleteVarList,
},
{
Name: "set",
Usage: "set var value",
Usage: locale.T("set var value"),
Action: HyprlandVarSetCommand,
},
{
Name: "unset",
Usage: "unset var",
Usage: locale.T("unset var"),
Action: HyprlandVarUnsetCommand,
ShellComplete: ShellCompleteVarList,
},
......@@ -183,11 +184,11 @@ func CommandList() *cli.Command {
},
{
Name: "plugin",
Usage: "Hyprland plugins",
Usage: locale.T("Hyprland plugins"),
Commands: []*cli.Command{
{
Name: "list",
Usage: "Hyprland plugins list",
Usage: locale.T("Hyprland plugins list"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -195,18 +196,18 @@ func CommandList() *cli.Command {
},
{
Name: "status",
Usage: "Hyprland plugin status",
Usage: locale.T("Hyprland plugin status"),
ArgsUsage: "plugin",
Action: HyprlandPluginStatusCommand,
ShellComplete: ShellCompletePlugin("all"),
},
{
Name: "info",
Usage: "Information about plugins",
Usage: locale.T("Information about plugins"),
Flags: []cli.Flag{
&cli.StringFlag{
Name: "filter",
Usage: "status filter",
Usage: locale.T("status filter"),
Aliases: []string{"f"},
Value: "all",
},
......@@ -216,21 +217,21 @@ func CommandList() *cli.Command {
},
{
Name: "load",
Usage: "load plugin",
Usage: locale.T("load plugin"),
ArgsUsage: "plugin",
Action: HyprlandPluginLoadCommand,
ShellComplete: ShellCompletePlugin("unloaded"),
},
{
Name: "unload",
Usage: "unload plugin",
Usage: locale.T("unload plugin"),
ArgsUsage: "plugin",
Action: HyprlandPluginUnloadCommand,
ShellComplete: ShellCompletePlugin("loaded"),
},
{
Name: "toggle",
Usage: "toggle plugin",
Usage: locale.T("toggle plugin"),
ArgsUsage: "plugin",
Action: HyprlandPluginToggleCommand,
ShellComplete: ShellCompletePlugin("all"),
......
......@@ -2,8 +2,10 @@ package hyprland
import (
"context"
"errors"
"fmt"
"ximperconf/config"
"ximperconf/locale"
"github.com/fatih/color"
"github.com/godbus/dbus/v5"
......@@ -38,18 +40,18 @@ func HyprlandSyncSystemLayouts(ctx context.Context, cmd *cli.Command) error {
sysLayouts, err := HyprlandGetKeyboardLayouts()
if err != nil {
return fmt.Errorf("не удалось получить системные раскладки: %w", err)
return fmt.Errorf(locale.T("failed to get system layouts: %w"), err)
}
hyprLayouts := manager.GetVar("kb_layout")
if force || hyprLayouts == "" {
if _, err := manager.SetVar("kb_layout", sysLayouts); err != nil {
return fmt.Errorf("не удалось обновить kb_layout в Hyprland: %w", err)
return fmt.Errorf(locale.T("failed to update kb_layout in Hyprland: %w"), err)
}
color.Green("Раскладка обновлена!")
color.Green(locale.T("Layout updated!"))
} else {
return fmt.Errorf("раскладка уже установлена, используйте '--force' для принудительного обновления")
return errors.New(locale.T("layout is already set, use '--force' for forced update"))
}
return nil
......
......@@ -3,6 +3,7 @@ package hyprland
import (
"context"
"encoding/json"
"errors"
"fmt"
"os"
"os/exec"
......@@ -11,6 +12,7 @@ import (
"strings"
"time"
"ximperconf/config"
"ximperconf/locale"
"ximperconf/utils"
)
......@@ -105,7 +107,7 @@ func NewHyprlandManager() (*HyprlandManager, error) {
func GetHyprlandManager(ctx context.Context) (*HyprlandManager, error) {
mgr, ok := ctx.Value(config.HyprManagerKey).(*HyprlandManager)
if !ok || mgr == nil {
return nil, fmt.Errorf("HyprlandManager не найден в контексте")
return nil, errors.New(locale.T("HyprlandManager not found in context"))
}
return mgr, nil
}
......@@ -136,7 +138,7 @@ func (m *HyprlandManager) Check(configPath string) ([]HyprConfigError, error) {
output, err := cmd.CombinedOutput()
if err != nil {
if _, ok := err.(*exec.ExitError); !ok {
return nil, fmt.Errorf("проверка не удалась")
return nil, errors.New(locale.T("check failed"))
}
}
......@@ -151,7 +153,7 @@ func (m *HyprlandManager) CheckModule(
info := m.GetModuleInfo(module, user)
if info.Path == "" {
return nil, fmt.Errorf("модуль '%s' не найден", module)
return nil, fmt.Errorf(locale.T("module '%s' not found"), module)
}
tmp, err := os.CreateTemp("", "ximperconf-hypr-check-*.conf")
......@@ -339,11 +341,11 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
info := m.GetModuleInfo(module, user)
if !info.Available {
return "", fmt.Errorf("недопустимое название для модуля")
return "", errors.New(locale.T("invalid module name"))
}
if info.Status.IsEqual(config.ModuleStatus.Unknown) {
return "", fmt.Errorf("модуль '%s' не найден: %s", module, info.Path)
return "", fmt.Errorf(locale.T("module '%s' not found: %s"), module, info.Path)
}
switch action {
......@@ -351,12 +353,12 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
// нет файла
if info.Path == "" || info.Status.IsEqual(config.ModuleStatus.Unknown) {
return "", fmt.Errorf("нельзя включить данный модуль")
return "", errors.New(locale.T("cannot enable this module"))
}
// уже включён
if info.Status.IsEqual(config.ModuleStatus.Enabled) {
return "", fmt.Errorf("модуль '%s' уже включён", module)
return "", fmt.Errorf(locale.T("module '%s' is already enabled"), module)
}
// отключить другие модули той же группы
......@@ -378,7 +380,7 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
// был закомментирован
if info.Status.IsEqual(config.ModuleStatus.Disabled) {
if onlyNew {
return "", fmt.Errorf("модуль '%s' уже присутствует в конфиге (закомментирован) — пропущено", module)
return "", fmt.Errorf(locale.T("module '%s' already present in config (commented) — skipped"), module)
}
m.Lines[info.LineNumber] = strings.TrimPrefix(m.Lines[info.LineNumber], "#")
m.updateSourceCommented(info.LineNumber, false)
......@@ -396,14 +398,14 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
return m.enableMessage(module, disabledGroup), nil
}
return "", fmt.Errorf("модуль '%s' не изменён", module)
return "", fmt.Errorf(locale.T("module '%s' not changed"), module)
case "disable":
// Уже выключен
if info.Status.IsEqual(config.ModuleStatus.Disabled) ||
info.Status.IsEqual(config.ModuleStatus.Unused) {
return "", fmt.Errorf("модуль '%s' уже отключён", module)
return "", fmt.Errorf(locale.T("module '%s' is already disabled"), module)
}
// Включён
......@@ -412,30 +414,30 @@ func (m *HyprlandManager) SetModule(action, module string, user, onlyNew bool) (
m.Lines[info.LineNumber] = "#" + m.Lines[info.LineNumber]
m.updateSourceCommented(info.LineNumber, true)
m.Changed = true
return fmt.Sprintf("Модуль '%s' отключён", module), nil
return fmt.Sprintf(locale.T("Module '%s' disabled"), module), nil
}
case "remove":
if info.LineNumber <= 0 {
return "", fmt.Errorf("модуль '%s' не найден в конфигурации", module)
return "", fmt.Errorf(locale.T("module '%s' not found in config"), module)
}
m.removeSource(info.LineNumber)
m.removeLine(info.LineNumber)
return fmt.Sprintf("Модуль '%s' удалён", module), nil
return fmt.Sprintf(locale.T("Module '%s' removed"), module), nil
}
return "", nil
}
func (m *HyprlandManager) enableMessage(module string, disabledGroup []string) string {
msg := fmt.Sprintf("Модуль '%s' включён", module)
msg := fmt.Sprintf(locale.T("Module '%s' enabled"), module)
for _, name := range disabledGroup {
msg += fmt.Sprintf("\nМодуль '%s' отключён (группа)", name)
msg += fmt.Sprintf("\n"+locale.T("Module '%s' disabled (group)"), name)
}
if m.hasSourcesOutsideSections() {
msg += "\n\nВнимание: обнаружены модули вне секций. Выполните 'ximperconf hyprland fix' для исправления."
msg += "\n\n" + locale.T("Warning: modules found outside sections. Run 'ximperconf hyprland fix' to fix.")
}
return msg
}
......@@ -790,12 +792,12 @@ func (m *HyprlandManager) GetPluginStatus(name string) config.ItemStatus {
func (m *HyprlandManager) GetPluginFile(name string) (string, error) {
if name == "" {
return "", fmt.Errorf("плагин не указан")
return "", errors.New(locale.T("plugin not specified"))
}
path := filepath.Join(m.PluginsDir, name+".so")
if !utils.FileExists(path) {
return "", fmt.Errorf("плагин не найден")
return "", errors.New(locale.T("plugin not found"))
}
return path, nil
......@@ -818,7 +820,7 @@ func (m *HyprlandManager) GetPluginsList(filter string) []string {
func (m *HyprlandManager) SetPlugin(action string, name string) (string, error) {
if name == "" {
return "", fmt.Errorf("плагин не указан")
return "", errors.New(locale.T("plugin not specified"))
}
path, err := m.GetPluginFile(name)
......@@ -831,7 +833,7 @@ func (m *HyprlandManager) SetPlugin(action string, name string) (string, error)
switch action {
case "load":
if status.IsEqual(config.PluginStatus.Loaded) {
return "", fmt.Errorf("плагин уже загружен")
return "", errors.New(locale.T("plugin is already loaded"))
}
time.Sleep(1 * time.Second)
......@@ -839,11 +841,11 @@ func (m *HyprlandManager) SetPlugin(action string, name string) (string, error)
if out, err := cmd.CombinedOutput(); err != nil {
return "", fmt.Errorf("%v (%s)", err, out)
}
return fmt.Sprintf("Плагин '%s' загружен", name), nil
return fmt.Sprintf(locale.T("Plugin '%s' loaded"), name), nil
case "unload":
if status.IsEqual(config.PluginStatus.Unloaded) {
return "", fmt.Errorf("плагин не загружен")
return "", errors.New(locale.T("plugin is not loaded"))
}
time.Sleep(1 * time.Second)
......@@ -851,7 +853,7 @@ func (m *HyprlandManager) SetPlugin(action string, name string) (string, error)
if out, err := cmd.CombinedOutput(); err != nil {
return "", fmt.Errorf("%v (%s)", err, out)
}
return fmt.Sprintf("Плагин '%s' выгружен", name), nil
return fmt.Sprintf(locale.T("Plugin '%s' unloaded"), name), nil
}
return "", nil
......@@ -882,21 +884,21 @@ func (m *HyprlandManager) GetVar(name string) string {
func (m *HyprlandManager) SetVar(name, value string) (string, error) {
if name == "" {
return "", fmt.Errorf("укажите имя переменной")
return "", errors.New(locale.T("specify variable name"))
}
if value == "" {
return "", fmt.Errorf("укажите значение переменной")
return "", errors.New(locale.T("specify variable value"))
}
for i, v := range m.Vars {
if v.Name == name {
if v.Value == value {
return "", fmt.Errorf("переменная '%s' уже '%s'", v.Name, v.Value)
return "", fmt.Errorf(locale.T("variable '%s' is already '%s'"), v.Name, v.Value)
}
m.Lines[v.LineNumber] = fmt.Sprintf("$%s = %s", name, value)
m.Vars[i].Value = value
m.Changed = true
return fmt.Sprintf("Переменная '%s' обновлена: %s", name, value), nil
return fmt.Sprintf(locale.T("Variable '%s' updated: %s"), name, value), nil
}
}
......@@ -909,19 +911,19 @@ func (m *HyprlandManager) SetVar(name, value string) (string, error) {
m.shiftLineNumbers(insertAt-1, 1)
m.Vars = append(m.Vars, HyprVar{Name: name, Value: value, LineNumber: insertAt})
m.Changed = true
return fmt.Sprintf("Переменная '%s' установлена: %s", name, value), nil
return fmt.Sprintf(locale.T("Variable '%s' set: %s"), name, value), nil
}
insertAt := len(m.Lines)
m.Lines = append(m.Lines, "", sectionHeader(sectionVars), newLine)
m.Vars = append(m.Vars, HyprVar{Name: name, Value: value, LineNumber: insertAt + 2})
m.Changed = true
return fmt.Sprintf("Блок VARS создан, переменная '%s' установлена: %s", name, value), nil
return fmt.Sprintf(locale.T("VARS block created, variable '%s' set: %s"), name, value), nil
}
func (m *HyprlandManager) UnsetVar(name string) error {
if name == "" {
return fmt.Errorf("укажите имя переменной")
return errors.New(locale.T("specify variable name"))
}
for i, v := range m.Vars {
......@@ -931,7 +933,7 @@ func (m *HyprlandManager) UnsetVar(name string) error {
return nil
}
}
return fmt.Errorf("переменная %s не найдена", name)
return fmt.Errorf(locale.T("variable '%s' not found"), name)
}
// ====================
......
......@@ -2,9 +2,11 @@ package hyprland
import (
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
"context"
"errors"
"fmt"
"strings"
......@@ -49,7 +51,7 @@ func HyprlandPluginInfoCommand(ctx context.Context, cmd *cli.Command) error {
if config.IsJSON(cmd) {
return ui.PrintJSON([]ui.JSONItem{})
}
return fmt.Errorf("нет доступных плагинов")
return errors.New(locale.T("no available plugins"))
}
items := make([]ui.TreeItem, 0, len(plugins))
......@@ -76,7 +78,7 @@ func HyprlandPluginInfoCommand(ctx context.Context, cmd *cli.Command) error {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Plugins",
Title: locale.T("Plugins"),
Items: items,
Style: ui.DefaultTreeStyle,
Color: true,
......
......@@ -3,6 +3,7 @@ package hyprland
import (
"context"
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
"ximperconf/utils"
......@@ -48,7 +49,7 @@ func HyprlandVarInfoCommand(ctx context.Context, cmd *cli.Command) error {
if config.IsJSON(cmd) {
return ui.PrintJSON([]ui.JSONItem{})
}
color.Yellow("Нет переменных в конфигурации")
color.Yellow(locale.T("No variables in configuration"))
return nil
}
......@@ -73,7 +74,7 @@ func HyprlandVarInfoCommand(ctx context.Context, cmd *cli.Command) error {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Vars",
Title: locale.T("Vars"),
Items: items,
Style: ui.DefaultTreeStyle,
Sort: true,
......@@ -90,7 +91,7 @@ func HyprlandVarGetCommand(ctx context.Context, cmd *cli.Command) error {
}
info := manager.GetVar(v)
if info == "" {
return fmt.Errorf("переменная '%s' не установлена", v)
return fmt.Errorf(locale.T("variable '%s' is not set"), v)
}
fmt.Println(info)
return nil
......@@ -113,15 +114,15 @@ func HyprlandVarSetCommand(ctx context.Context, cmd *cli.Command) error {
func hyprlandVarUnset(name string) error {
if name == "" {
color.Red("Укажите имя переменной")
color.Red(locale.T("specify variable name"))
os.Exit(1)
}
if !regexp.MustCompile(`^[A-Za-z_][A-Za-z0-9_]*$`).MatchString(name) {
color.Red("Недопустимое имя переменной: %s", name)
color.Red(locale.T("Invalid variable name: %s"), name)
os.Exit(1)
}
if !utils.FileExists(config.Env.Hyprland.Config) {
color.Red("Конфигурация не найдена: %s", config.Env.Hyprland.Config)
color.Red(locale.T("Configuration not found: %s"), config.Env.Hyprland.Config)
os.Exit(1)
}
......@@ -141,11 +142,11 @@ func hyprlandVarUnset(name string) error {
}
if !removed {
color.Red("Переменная %s не найдена", name)
color.Red(locale.T("variable '%s' not found"), name)
os.Exit(1)
}
color.Green("Переменная %s удалена", name)
color.Green(locale.T("Variable '%s' removed"), name)
return os.WriteFile(config.Env.Hyprland.Config, []byte(strings.Join(newLines, "\n")), 0644)
}
......
package locale
import (
"os"
"strings"
"github.com/leonelquinteros/gotext"
)
var LocaleDir string
func Init() {
gotext.Configure(LocaleDir, getLocale(), "ximperconf")
}
// getText is a variable to avoid go vet printf wrapper detection.
var getText = gotext.Get
func T(msgid string) string {
return getText(msgid)
}
func TN(msgid, msgidPlural string, n int) string {
return gotext.GetN(msgid, msgidPlural, n)
}
func getLocale() string {
for _, env := range []string{"LC_ALL", "LC_MESSAGES", "LANG"} {
if v := os.Getenv(env); v != "" {
if idx := strings.Index(v, "."); idx != -1 {
return v[:idx]
}
return v
}
}
return "en"
}
......@@ -5,9 +5,11 @@ import (
"os"
"ximperconf/config"
"ximperconf/hyprland"
"ximperconf/locale"
"ximperconf/preset"
"ximperconf/repo"
"ximperconf/system"
"ximperconf/ui"
"github.com/urfave/cli/v3"
)
......@@ -15,12 +17,14 @@ import (
func main() {
config.InitConfig()
locale.Init()
ui.SetupHelpTemplates()
config.InitDBus()
defer config.DBusConn.Close()
rootCommand := &cli.Command{
Name: "ximperconf",
Usage: "Ximper Linux Configuration Tool",
Usage: locale.T("Ximper Linux Configuration Tool"),
EnableShellCompletion: true,
Version: config.Env.Version,
Commands: []*cli.Command{
......@@ -31,7 +35,7 @@ func main() {
{
Name: "help",
Aliases: []string{"h"},
Usage: "show help",
Usage: locale.T("show help"),
ArgsUsage: "[command]",
HideHelp: true,
},
......
......@@ -7,13 +7,21 @@ project('ximperconf',
],
)
i18n = import('i18n')
go_root = run_command('printenv', 'GOROOT', check: false)
go_bin = go_root.returncode() != 0 ? find_program('go') : find_program(join_paths(go_root.stdout().strip(), 'bin', 'go'))
LOCALES_DIR = get_option('prefix') / get_option('localedir')
ldflags = '-X \'ximperconf/locale.LocaleDir=' + LOCALES_DIR + '\''
if get_option('shell_completion').enabled()
subdir('data/completion')
endif
subdir('po')
custom_target(
'go-build',
build_by_default: true,
......@@ -23,7 +31,10 @@ custom_target(
install: true,
install_dir: get_option('bindir'),
command: [
'go', 'build','-o','@OUTPUT@',meson.current_source_dir()
'go', 'build',
'-ldflags', ldflags,
'-o', '@OUTPUT@',
meson.current_source_dir()
],
env: [
'CGO_ENABLED=0'
......
hyprland/actions.go
hyprland/commands.go
hyprland/keyboard-actions.go
hyprland/manager.go
hyprland/plugin-actions.go
hyprland/var-actions.go
main.go
preset/actions.go
preset/commands.go
preset/tools.go
repo/actions.go
repo/commands.go
system/commands.go
system/grub-actions.go
ui/help.go
#!/bin/sh
# Should run from project root dir
po/update_potfiles
cat ./po/POTFILES | xargs xgettext --language=C --keyword=T --keyword=TN:1,2 -o po/ximperconf.pot --from-code=UTF-8 --add-comments --package-name=ximperconf
i18n.gettext(meson.project_name(), preset: 'glib')
# Russian translations for ximperconf package.
# Copyright (C) 2026 THE ximperconf'S COPYRIGHT HOLDER
# This file is distributed under the same license as the ximperconf package.
#
msgid ""
msgstr ""
"Project-Id-Version: ximperconf\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-02-14 18:34+0300\n"
"PO-Revision-Date: 2026-02-14 17:13+0300\n"
"Last-Translator: \n"
"Language-Team: Russian\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\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"
#: hyprland/actions.go:27
msgid "Configuration fixed"
msgstr "Конфигурация исправлена"
#: hyprland/actions.go:43 hyprland/actions.go:93
msgid "No errors"
msgstr "Ошибок нет"
#: hyprland/actions.go:62 hyprland/actions.go:83 hyprland/actions.go:262
#: hyprland/actions.go:298 hyprland/manager.go:343
msgid "invalid module name"
msgstr "недопустимое название для модуля"
#: hyprland/actions.go:72 hyprland/actions.go:287
msgid "specify module name"
msgstr "укажите имя модуля"
#: hyprland/actions.go:186
msgid "no available modules"
msgstr "нет доступных модулей"
#: hyprland/actions.go:226
#, c-format
msgid "(errors: %d)"
msgstr "(ошибки: %d)"
#: hyprland/actions.go:240
msgid "Modules"
msgstr "Модули"
#: hyprland/actions.go:266 hyprland/manager.go:347
#, c-format
msgid "module '%s' not found: %s"
msgstr "модуль '%s' не найден: %s"
#: hyprland/actions.go:278
#, c-format
msgid "failed to start editor: %s"
msgstr "не удалось запустить редактор: %s"
#: hyprland/actions.go:315
msgid "Module"
msgstr "Модуль"
#: hyprland/actions.go:318
msgid "Group"
msgstr "Группа"
#: hyprland/actions.go:321
msgid "Summary"
msgstr "Краткое"
#: hyprland/actions.go:324
msgid "Description"
msgstr "Описание"
#: hyprland/actions.go:327
msgid "Status"
msgstr "Статус"
#: hyprland/actions.go:328
msgid "Path"
msgstr "Путь"
#: hyprland/actions.go:329
msgid "Config path"
msgstr "Путь в конфиге"
#: hyprland/actions.go:330
msgid "Config line"
msgstr "Строка в конфиге"
#: hyprland/actions.go:332 hyprland/actions.go:334
msgid "Available"
msgstr "Доступен"
#: hyprland/actions.go:332
msgid "yes"
msgstr "да"
#: hyprland/actions.go:334
msgid "no"
msgstr "нет"
#: hyprland/actions.go:338
msgid "Errors"
msgstr "Ошибки"
#: hyprland/commands.go:16
msgid "Hyprland Management"
msgstr "Управление Hyprland"
#: hyprland/commands.go:20 hyprland/commands.go:29
msgid "failed to initialize HyprlandManager: %w"
msgstr "не удалось инициализировать HyprlandManager: %w"
#: hyprland/commands.go:37
msgid "Check the Hyprland config"
msgstr "Проверить конфигурацию Hyprland"
#: hyprland/commands.go:42
msgid "Fix config: sort modules into sections by order"
msgstr "Исправить конфиг: отсортировать модули по секциям и порядку"
#: hyprland/commands.go:47
msgid "Sync layouts with xkb"
msgstr "Синхронизировать раскладки с xkb"
#: hyprland/commands.go:52
msgid "Forced update"
msgstr "Принудительное обновление"
#: hyprland/commands.go:60
msgid "Hyprland modules"
msgstr "Модули Hyprland"
#: hyprland/commands.go:64
msgid "use user modules"
msgstr "использовать пользовательские модули"
#: hyprland/commands.go:72
msgid "Check Hyprland module"
msgstr "Проверить модуль Hyprland"
#: hyprland/commands.go:79
msgid "Edit module file"
msgstr "Редактировать файл модуля"
#: hyprland/commands.go:86
msgid "Hyprland module status"
msgstr "Статус модуля Hyprland"
#: hyprland/commands.go:93
msgid "Show detailed module info"
msgstr "Показать подробную информацию о модуле"
#: hyprland/commands.go:103
msgid "Information about modules"
msgstr "Информация о модулях"
#: hyprland/commands.go:107 hyprland/commands.go:210
msgid "status filter"
msgstr "фильтр по статусу"
#: hyprland/commands.go:117
msgid "enable module"
msgstr "включить модуль"
#: hyprland/commands.go:124
msgid "disable module"
msgstr "отключить модуль"
#: hyprland/commands.go:128
msgid "delete module line from config"
msgstr "удалить строку модуля из конфига"
#: hyprland/commands.go:139
msgid "toggle module"
msgstr "переключить модуль"
#: hyprland/commands.go:148
msgid "Hyprland vars"
msgstr "Переменные Hyprland"
#: hyprland/commands.go:152
msgid "vars list"
msgstr "список переменных"
#: hyprland/commands.go:160
msgid "vars info"
msgstr "информация о переменных"
#: hyprland/commands.go:168
msgid "get var value"
msgstr "получить значение переменной"
#: hyprland/commands.go:174
msgid "set var value"
msgstr "установить значение переменной"
#: hyprland/commands.go:179
msgid "unset var"
msgstr "удалить переменную"
#: hyprland/commands.go:187
msgid "Hyprland plugins"
msgstr "Плагины Hyprland"
#: hyprland/commands.go:191
msgid "Hyprland plugins list"
msgstr "Список плагинов Hyprland"
#: hyprland/commands.go:199
msgid "Hyprland plugin status"
msgstr "Статус плагина Hyprland"
#: hyprland/commands.go:206
msgid "Information about plugins"
msgstr "Информация о плагинах"
#: hyprland/commands.go:220
msgid "load plugin"
msgstr "загрузить плагин"
#: hyprland/commands.go:227
msgid "unload plugin"
msgstr "выгрузить плагин"
#: hyprland/commands.go:234
msgid "toggle plugin"
msgstr "переключить плагин"
#: hyprland/keyboard-actions.go:42
msgid "failed to get system layouts: %w"
msgstr "не удалось получить системные раскладки: %w"
#: hyprland/keyboard-actions.go:49
msgid "failed to update kb_layout in Hyprland: %w"
msgstr "не удалось обновить kb_layout в Hyprland: %w"
#: hyprland/keyboard-actions.go:51
msgid "Layout updated!"
msgstr "Раскладка обновлена!"
#: hyprland/keyboard-actions.go:53
msgid "layout is already set, use '--force' for forced update"
msgstr ""
"раскладка уже установлена, используйте '--force' для принудительного "
"обновления"
#: hyprland/manager.go:109
msgid "HyprlandManager not found in context"
msgstr "HyprlandManager не найден в контексте"
#: hyprland/manager.go:140
msgid "check failed"
msgstr "проверка не удалась"
#: hyprland/manager.go:155
#, c-format
msgid "module '%s' not found"
msgstr "модуль '%s' не найден"
#: hyprland/manager.go:355
msgid "cannot enable this module"
msgstr "нельзя включить данный модуль"
#: hyprland/manager.go:360
#, c-format
msgid "module '%s' is already enabled"
msgstr "модуль '%s' уже включён"
#: hyprland/manager.go:382
#, c-format
msgid "module '%s' already present in config (commented) — skipped"
msgstr "модуль '%s' уже присутствует в конфиге (закомментирован) — пропущено"
#: hyprland/manager.go:400
#, c-format
msgid "module '%s' not changed"
msgstr "модуль '%s' не изменён"
#: hyprland/manager.go:407
#, c-format
msgid "module '%s' is already disabled"
msgstr "модуль '%s' уже отключён"
#: hyprland/manager.go:416 preset/actions.go:240 preset/actions.go:267
#, c-format
msgid "Module '%s' disabled"
msgstr "Модуль '%s' отключён"
#: hyprland/manager.go:422
#, c-format
msgid "module '%s' not found in config"
msgstr "модуль '%s' не найден в конфигурации"
#: hyprland/manager.go:428 preset/actions.go:242 preset/actions.go:269
#, c-format
msgid "Module '%s' removed"
msgstr "Модуль '%s' удалён"
#: hyprland/manager.go:434 preset/actions.go:238 preset/actions.go:265
#, c-format
msgid "Module '%s' enabled"
msgstr "Модуль '%s' включён"
#: hyprland/manager.go:436
#, c-format
msgid "Module '%s' disabled (group)"
msgstr "Модуль '%s' отключён (группа)"
#: hyprland/manager.go:439
msgid ""
"Warning: modules found outside sections. Run 'ximperconf hyprland fix' to "
"fix."
msgstr ""
"Внимание: обнаружены модули вне секций. Выполните 'ximperconf hyprland fix' "
"для исправления."
#: hyprland/manager.go:794 hyprland/manager.go:822
msgid "plugin not specified"
msgstr "плагин не указан"
#: hyprland/manager.go:799
msgid "plugin not found"
msgstr "плагин не найден"
#: hyprland/manager.go:835
msgid "plugin is already loaded"
msgstr "плагин уже загружен"
#: hyprland/manager.go:843
#, c-format
msgid "Plugin '%s' loaded"
msgstr "Плагин '%s' загружен"
#: hyprland/manager.go:847
msgid "plugin is not loaded"
msgstr "плагин не загружен"
#: hyprland/manager.go:855
#, c-format
msgid "Plugin '%s' unloaded"
msgstr "Плагин '%s' выгружен"
#: hyprland/manager.go:886 hyprland/manager.go:925 hyprland/var-actions.go:117
msgid "specify variable name"
msgstr "укажите имя переменной"
#: hyprland/manager.go:889
msgid "specify variable value"
msgstr "укажите значение переменной"
#: hyprland/manager.go:895
#, c-format
msgid "variable '%s' is already '%s'"
msgstr "переменная '%s' уже '%s'"
#: hyprland/manager.go:900
#, c-format
msgid "Variable '%s' updated: %s"
msgstr "Переменная '%s' обновлена: %s"
#: hyprland/manager.go:913
#, c-format
msgid "Variable '%s' set: %s"
msgstr "Переменная '%s' установлена: %s"
#: hyprland/manager.go:920
#, c-format
msgid "VARS block created, variable '%s' set: %s"
msgstr "Блок VARS создан, переменная '%s' установлена: %s"
#: hyprland/manager.go:935 hyprland/var-actions.go:145
#, c-format
msgid "variable '%s' not found"
msgstr "переменная '%s' не найдена"
#: hyprland/plugin-actions.go:53
msgid "no available plugins"
msgstr "нет доступных плагинов"
#: hyprland/plugin-actions.go:80
msgid "Plugins"
msgstr "Плагины"
#: hyprland/var-actions.go:52
msgid "No variables in configuration"
msgstr "Нет переменных в конфигурации"
#: hyprland/var-actions.go:77
msgid "Vars"
msgstr "Переменные"
#: hyprland/var-actions.go:94
#, c-format
msgid "variable '%s' is not set"
msgstr "переменная '%s' не установлена"
#: hyprland/var-actions.go:121
#, c-format
msgid "Invalid variable name: %s"
msgstr "Недопустимое имя переменной: %s"
#: hyprland/var-actions.go:125
#, c-format
msgid "Configuration not found: %s"
msgstr "Конфигурация не найдена: %s"
#: hyprland/var-actions.go:149
#, c-format
msgid "Variable '%s' removed"
msgstr "Переменная '%s' удалена"
#: main.go:27
msgid "Ximper Linux Configuration Tool"
msgstr "Инструмент настройки Ximper Linux"
#: main.go:38 ui/help.go:16
msgid "show help"
msgstr "показать справку"
#: preset/actions.go:77
#, c-format
msgid "Not found: '%s'"
msgstr "Не найден: '%s'"
#: preset/actions.go:85
msgid "Failed to read %s: %v"
msgstr "Не удалось прочитать %s: %v"
#: preset/actions.go:93
#, c-format
msgid "Locked: %s"
msgstr "Заблокирован: %s"
#: preset/actions.go:105
#, c-format
msgid "Up to date: '%s'"
msgstr "Актуально: '%s'"
#: preset/actions.go:120
msgid "Replace error %s: %v"
msgstr "Ошибка замены %s: %v"
#: preset/actions.go:136 preset/tools.go:45
#, c-format
msgid "Already exists: %s"
msgstr "Уже существует: %s"
#: preset/actions.go:153
msgid "Error setting %s: %v"
msgstr "Ошибка установки %s: %v"
#: preset/actions.go:170
msgid "Skipped module without name"
msgstr "Пропущен модуль без имени"
#: preset/actions.go:178
#, c-format
msgid "Module '%s': unsupported action"
msgstr "Модуль '%s': неподдерживаемый action"
#: preset/actions.go:190
#, c-format
msgid "Module '%s': command '%s' failed"
msgstr "Модуль '%s': команда '%s' завершилась с ошибкой"
#: preset/actions.go:198
#, c-format
msgid "Module '%s': command '%s' returned no data"
msgstr "Модуль '%s': команда '%s' не вернула данных"
#: preset/actions.go:208
#, c-format
msgid "Module '%s': binary '%s' not found"
msgstr "Модуль '%s': бинарник '%s' не найден"
#: preset/actions.go:220 preset/actions.go:226
#, c-format
msgid "Created empty module: %s"
msgstr "Создан пустой модуль: %s"
#: preset/actions.go:258
msgid "Error (%s): %v"
msgstr "Ошибка (%s): %v"
#: preset/actions.go:286
msgid "Sync Hyprland layouts"
msgstr "Синхронизация раскладок Hyprland"
#: preset/actions.go:295
msgid "Failed to get system layouts"
msgstr "Не удалось получить системные раскладки"
#: preset/actions.go:308
#, c-format
msgid "XCB layout: %s"
msgstr "Раскладка XCB: %s"
#: preset/actions.go:312
#, c-format
msgid "Hyprland layout: %s"
msgstr "Раскладка Hyprland: %s"
#: preset/actions.go:319
msgid "Failed to update kb_layout"
msgstr "Не удалось обновить kb_layout"
#: preset/actions.go:325
#, c-format
msgid "Layout updated: %s"
msgstr "Раскладка обновлена: %s"
#: preset/actions.go:330
#, c-format
msgid "Layout already set: %s"
msgstr "Раскладка уже установлена: %s"
#: preset/actions.go:354
msgid "GRUB error: %v"
msgstr "Ошибка GRUB: %v"
#: preset/actions.go:359 system/grub-actions.go:86
msgid "GRUB_GFXMODE fixed"
msgstr "GRUB_GFXMODE исправлен"
#: preset/actions.go:364 system/grub-actions.go:89
msgid "update-grub completed"
msgstr "update-grub выполнен"
#: preset/actions.go:392
#, c-format
msgid "Creating profile: %s"
msgstr "Создаётся профиль: %s"
#: preset/actions.go:394
#, c-format
msgid "Profile %s unavailable"
msgstr "Профиль %s недоступен"
#: preset/actions.go:408 preset/actions.go:468
msgid "no available profiles"
msgstr "нет доступных профилей"
#: preset/actions.go:430
msgid "Profiles"
msgstr "Профили"
#: preset/actions.go:451
#, c-format
msgid "Profile %s not found"
msgstr "Профиль %s не найден"
#: preset/actions.go:472
msgid "Creating all available profiles..."
msgstr "Создаём все доступные профили..."
#: preset/commands.go:15
msgid "Manage preset configuration profiles"
msgstr "Управление профилями конфигурации"
#: preset/commands.go:19
msgid "Show information about preset profiles"
msgstr "Показать информацию о профилях"
#: preset/commands.go:27
msgid "Apply a profile"
msgstr "Применить профиль"
#: preset/commands.go:31 preset/commands.go:45
msgid "Show what would be created without making changes"
msgstr "Показать что будет создано без внесения изменений"
#: preset/commands.go:41
msgid "Apply all available profiles"
msgstr "Применить все доступные профили"
#: preset/tools.go:51
#, c-format
msgid "Error: %s"
msgstr "Ошибка: %s"
#: preset/tools.go:85
msgid "Copying"
msgstr "Копируем"
#: preset/tools.go:86
msgid "Creating links"
msgstr "Создаём ссылки"
#: preset/tools.go:87
msgid "Updating"
msgstr "Обновляем"
#: preset/tools.go:88
msgid "Configuring system"
msgstr "Настраиваем систему"
#: preset/tools.go:89
msgid "Creating Hyprland variables"
msgstr "Создаём переменные Hyprland"
#: preset/tools.go:90
msgid "Enabling Hyprland modules"
msgstr "Подключаем модули Hyprland"
#: preset/tools.go:91
msgid "Syncing Hyprland layout"
msgstr "Синхронизируем раскладку Hyprland"
#: repo/actions.go:31 repo/actions.go:38
msgid "Error fetching data"
msgstr "Ошибка получения данных"
#: repo/actions.go:90
msgid "Last update"
msgstr "Последнее обновление"
#: repo/actions.go:91
msgid "Archive date"
msgstr "Дата архива"
#: repo/commands.go:13
msgid "Ximper repos"
msgstr "Репозитории Ximper"
#: repo/commands.go:17
msgid "Deferred repo"
msgstr "Репозиторий Deferred"
#: repo/commands.go:21
msgid "Deferred repo info"
msgstr "Информация о Deferred"
#: repo/commands.go:29
msgid "Sisyphus archive date"
msgstr "Дата архива Sisyphus"
#: repo/commands.go:34
msgid "Date of last update"
msgstr "Дата последнего обновления"
#: system/commands.go:17
msgid "System Management"
msgstr "Управление системой"
#: system/commands.go:20
msgid "This command requires root"
msgstr "Эта команда требует root"
#: system/commands.go:28
msgid "Fix GRUB resolution"
msgstr "Исправить разрешение GRUB"
#: system/commands.go:33
msgid "Automatically run update-grub after fixing"
msgstr "Автоматически запустить update-grub после исправления"
#: system/commands.go:39
msgid "Enable verbose output"
msgstr "Включить подробный вывод"
#: system/grub-actions.go:23
msgid "failed to read %s: %w"
msgstr "не удалось прочитать %s: %w"
#: system/grub-actions.go:50
#, c-format
msgid "GRUB_GFXMODE is already set: %s"
msgstr "GRUB_GFXMODE уже установлен: %s"
#: system/grub-actions.go:55
msgid "failed to write %s: %w"
msgstr "не удалось записать %s: %w"
#: system/grub-actions.go:66
msgid "error running update-grub: %v (%s)"
msgstr "ошибка при выполнении update-grub: %v (%s)"
#: system/grub-actions.go:69
msgid "update-grub log:"
msgstr "Лог update-grub:"
#: ui/help.go:24
msgid "print the version"
msgstr "показать версию"
#: ui/help.go:46 ui/help.go:72 ui/help.go:99
msgid "Module:"
msgstr "Модуль:"
#: ui/help.go:47 ui/help.go:73 ui/help.go:100
msgid "Usage:"
msgstr "Использование:"
#: ui/help.go:48 ui/help.go:75 ui/help.go:102
msgid "Description:"
msgstr "Описание:"
#: ui/help.go:49 ui/help.go:103
msgid "Commands:"
msgstr "Команды:"
#: ui/help.go:50 ui/help.go:51 ui/help.go:76 ui/help.go:77 ui/help.go:104
#: ui/help.go:105
msgid "Options:"
msgstr "Параметры:"
#: ui/help.go:74 ui/help.go:101
msgid "Category:"
msgstr "Категория:"
#: ui/help.go:78
msgid "Global options:"
msgstr "Глобальные параметры:"
#: ui/help.go:125
msgid "default"
msgstr "по умолчанию"
#!/bin/bash
# Should run from project root dir
./po/create_pot
update-lang() {
msgmerge -U --backup=off po/$1.po po/ximperconf.pot
}
if [ "$1" = "all" ]; then
for lang in $(cat po/LINGUAS); do
update-lang $lang
done
else
update-lang $1
fi
#!/bin/sh
# Should run from project root dir
touch ./po/unsort-POTFILES
find ./ -iname "*.go" -not -path "./builddir/*" -type f -exec grep -lrE 'locale\.T\(|locale\.TN\(' {} + | while read file; do echo "${file#./}" >> ./po/unsort-POTFILES; done
cat ./po/unsort-POTFILES | sort | uniq > ./po/POTFILES
rm ./po/unsort-POTFILES
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER
# This file is distributed under the same license as the ximperconf package.
# FIRST AUTHOR <EMAIL@ADDRESS>, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: ximperconf\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-02-14 18:34+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"Language: \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
#: hyprland/actions.go:27
msgid "Configuration fixed"
msgstr ""
#: hyprland/actions.go:43 hyprland/actions.go:93
msgid "No errors"
msgstr ""
#: hyprland/actions.go:62 hyprland/actions.go:83 hyprland/actions.go:262
#: hyprland/actions.go:298 hyprland/manager.go:343
msgid "invalid module name"
msgstr ""
#: hyprland/actions.go:72 hyprland/actions.go:287
msgid "specify module name"
msgstr ""
#: hyprland/actions.go:186
msgid "no available modules"
msgstr ""
#: hyprland/actions.go:226
#, c-format
msgid "(errors: %d)"
msgstr ""
#: hyprland/actions.go:240
msgid "Modules"
msgstr ""
#: hyprland/actions.go:266 hyprland/manager.go:347
#, c-format
msgid "module '%s' not found: %s"
msgstr ""
#: hyprland/actions.go:278
#, c-format
msgid "failed to start editor: %s"
msgstr ""
#: hyprland/actions.go:315
msgid "Module"
msgstr ""
#: hyprland/actions.go:318
msgid "Group"
msgstr ""
#: hyprland/actions.go:321
msgid "Summary"
msgstr ""
#: hyprland/actions.go:324
msgid "Description"
msgstr ""
#: hyprland/actions.go:327
msgid "Status"
msgstr ""
#: hyprland/actions.go:328
msgid "Path"
msgstr ""
#: hyprland/actions.go:329
msgid "Config path"
msgstr ""
#: hyprland/actions.go:330
msgid "Config line"
msgstr ""
#: hyprland/actions.go:332 hyprland/actions.go:334
msgid "Available"
msgstr ""
#: hyprland/actions.go:332
msgid "yes"
msgstr ""
#: hyprland/actions.go:334
msgid "no"
msgstr ""
#: hyprland/actions.go:338
msgid "Errors"
msgstr ""
#: hyprland/commands.go:16
msgid "Hyprland Management"
msgstr ""
#: hyprland/commands.go:20 hyprland/commands.go:29
msgid "failed to initialize HyprlandManager: %w"
msgstr ""
#: hyprland/commands.go:37
msgid "Check the Hyprland config"
msgstr ""
#: hyprland/commands.go:42
msgid "Fix config: sort modules into sections by order"
msgstr ""
#: hyprland/commands.go:47
msgid "Sync layouts with xkb"
msgstr ""
#: hyprland/commands.go:52
msgid "Forced update"
msgstr ""
#: hyprland/commands.go:60
msgid "Hyprland modules"
msgstr ""
#: hyprland/commands.go:64
msgid "use user modules"
msgstr ""
#: hyprland/commands.go:72
msgid "Check Hyprland module"
msgstr ""
#: hyprland/commands.go:79
msgid "Edit module file"
msgstr ""
#: hyprland/commands.go:86
msgid "Hyprland module status"
msgstr ""
#: hyprland/commands.go:93
msgid "Show detailed module info"
msgstr ""
#: hyprland/commands.go:103
msgid "Information about modules"
msgstr ""
#: hyprland/commands.go:107 hyprland/commands.go:210
msgid "status filter"
msgstr ""
#: hyprland/commands.go:117
msgid "enable module"
msgstr ""
#: hyprland/commands.go:124
msgid "disable module"
msgstr ""
#: hyprland/commands.go:128
msgid "delete module line from config"
msgstr ""
#: hyprland/commands.go:139
msgid "toggle module"
msgstr ""
#: hyprland/commands.go:148
msgid "Hyprland vars"
msgstr ""
#: hyprland/commands.go:152
msgid "vars list"
msgstr ""
#: hyprland/commands.go:160
msgid "vars info"
msgstr ""
#: hyprland/commands.go:168
msgid "get var value"
msgstr ""
#: hyprland/commands.go:174
msgid "set var value"
msgstr ""
#: hyprland/commands.go:179
msgid "unset var"
msgstr ""
#: hyprland/commands.go:187
msgid "Hyprland plugins"
msgstr ""
#: hyprland/commands.go:191
msgid "Hyprland plugins list"
msgstr ""
#: hyprland/commands.go:199
msgid "Hyprland plugin status"
msgstr ""
#: hyprland/commands.go:206
msgid "Information about plugins"
msgstr ""
#: hyprland/commands.go:220
msgid "load plugin"
msgstr ""
#: hyprland/commands.go:227
msgid "unload plugin"
msgstr ""
#: hyprland/commands.go:234
msgid "toggle plugin"
msgstr ""
#: hyprland/keyboard-actions.go:42
msgid "failed to get system layouts: %w"
msgstr ""
#: hyprland/keyboard-actions.go:49
msgid "failed to update kb_layout in Hyprland: %w"
msgstr ""
#: hyprland/keyboard-actions.go:51
msgid "Layout updated!"
msgstr ""
#: hyprland/keyboard-actions.go:53
msgid "layout is already set, use '--force' for forced update"
msgstr ""
#: hyprland/manager.go:109
msgid "HyprlandManager not found in context"
msgstr ""
#: hyprland/manager.go:140
msgid "check failed"
msgstr ""
#: hyprland/manager.go:155
#, c-format
msgid "module '%s' not found"
msgstr ""
#: hyprland/manager.go:355
msgid "cannot enable this module"
msgstr ""
#: hyprland/manager.go:360
#, c-format
msgid "module '%s' is already enabled"
msgstr ""
#: hyprland/manager.go:382
#, c-format
msgid "module '%s' already present in config (commented) — skipped"
msgstr ""
#: hyprland/manager.go:400
#, c-format
msgid "module '%s' not changed"
msgstr ""
#: hyprland/manager.go:407
#, c-format
msgid "module '%s' is already disabled"
msgstr ""
#: hyprland/manager.go:416 preset/actions.go:240 preset/actions.go:267
#, c-format
msgid "Module '%s' disabled"
msgstr ""
#: hyprland/manager.go:422
#, c-format
msgid "module '%s' not found in config"
msgstr ""
#: hyprland/manager.go:428 preset/actions.go:242 preset/actions.go:269
#, c-format
msgid "Module '%s' removed"
msgstr ""
#: hyprland/manager.go:434 preset/actions.go:238 preset/actions.go:265
#, c-format
msgid "Module '%s' enabled"
msgstr ""
#: hyprland/manager.go:436
#, c-format
msgid "Module '%s' disabled (group)"
msgstr ""
#: hyprland/manager.go:439
msgid ""
"Warning: modules found outside sections. Run 'ximperconf hyprland fix' to "
"fix."
msgstr ""
#: hyprland/manager.go:794 hyprland/manager.go:822
msgid "plugin not specified"
msgstr ""
#: hyprland/manager.go:799
msgid "plugin not found"
msgstr ""
#: hyprland/manager.go:835
msgid "plugin is already loaded"
msgstr ""
#: hyprland/manager.go:843
#, c-format
msgid "Plugin '%s' loaded"
msgstr ""
#: hyprland/manager.go:847
msgid "plugin is not loaded"
msgstr ""
#: hyprland/manager.go:855
#, c-format
msgid "Plugin '%s' unloaded"
msgstr ""
#: hyprland/manager.go:886 hyprland/manager.go:925 hyprland/var-actions.go:117
msgid "specify variable name"
msgstr ""
#: hyprland/manager.go:889
msgid "specify variable value"
msgstr ""
#: hyprland/manager.go:895
#, c-format
msgid "variable '%s' is already '%s'"
msgstr ""
#: hyprland/manager.go:900
#, c-format
msgid "Variable '%s' updated: %s"
msgstr ""
#: hyprland/manager.go:913
#, c-format
msgid "Variable '%s' set: %s"
msgstr ""
#: hyprland/manager.go:920
#, c-format
msgid "VARS block created, variable '%s' set: %s"
msgstr ""
#: hyprland/manager.go:935 hyprland/var-actions.go:145
#, c-format
msgid "variable '%s' not found"
msgstr ""
#: hyprland/plugin-actions.go:53
msgid "no available plugins"
msgstr ""
#: hyprland/plugin-actions.go:80
msgid "Plugins"
msgstr ""
#: hyprland/var-actions.go:52
msgid "No variables in configuration"
msgstr ""
#: hyprland/var-actions.go:77
msgid "Vars"
msgstr ""
#: hyprland/var-actions.go:94
#, c-format
msgid "variable '%s' is not set"
msgstr ""
#: hyprland/var-actions.go:121
#, c-format
msgid "Invalid variable name: %s"
msgstr ""
#: hyprland/var-actions.go:125
#, c-format
msgid "Configuration not found: %s"
msgstr ""
#: hyprland/var-actions.go:149
#, c-format
msgid "Variable '%s' removed"
msgstr ""
#: main.go:27
msgid "Ximper Linux Configuration Tool"
msgstr ""
#: main.go:38 ui/help.go:16
msgid "show help"
msgstr ""
#: preset/actions.go:77
#, c-format
msgid "Not found: '%s'"
msgstr ""
#: preset/actions.go:85
msgid "Failed to read %s: %v"
msgstr ""
#: preset/actions.go:93
#, c-format
msgid "Locked: %s"
msgstr ""
#: preset/actions.go:105
#, c-format
msgid "Up to date: '%s'"
msgstr ""
#: preset/actions.go:120
msgid "Replace error %s: %v"
msgstr ""
#: preset/actions.go:136 preset/tools.go:45
#, c-format
msgid "Already exists: %s"
msgstr ""
#: preset/actions.go:153
msgid "Error setting %s: %v"
msgstr ""
#: preset/actions.go:170
msgid "Skipped module without name"
msgstr ""
#: preset/actions.go:178
#, c-format
msgid "Module '%s': unsupported action"
msgstr ""
#: preset/actions.go:190
#, c-format
msgid "Module '%s': command '%s' failed"
msgstr ""
#: preset/actions.go:198
#, c-format
msgid "Module '%s': command '%s' returned no data"
msgstr ""
#: preset/actions.go:208
#, c-format
msgid "Module '%s': binary '%s' not found"
msgstr ""
#: preset/actions.go:220 preset/actions.go:226
#, c-format
msgid "Created empty module: %s"
msgstr ""
#: preset/actions.go:258
msgid "Error (%s): %v"
msgstr ""
#: preset/actions.go:286
msgid "Sync Hyprland layouts"
msgstr ""
#: preset/actions.go:295
msgid "Failed to get system layouts"
msgstr ""
#: preset/actions.go:308
#, c-format
msgid "XCB layout: %s"
msgstr ""
#: preset/actions.go:312
#, c-format
msgid "Hyprland layout: %s"
msgstr ""
#: preset/actions.go:319
msgid "Failed to update kb_layout"
msgstr ""
#: preset/actions.go:325
#, c-format
msgid "Layout updated: %s"
msgstr ""
#: preset/actions.go:330
#, c-format
msgid "Layout already set: %s"
msgstr ""
#: preset/actions.go:354
msgid "GRUB error: %v"
msgstr ""
#: preset/actions.go:359 system/grub-actions.go:86
msgid "GRUB_GFXMODE fixed"
msgstr ""
#: preset/actions.go:364 system/grub-actions.go:89
msgid "update-grub completed"
msgstr ""
#: preset/actions.go:392
#, c-format
msgid "Creating profile: %s"
msgstr ""
#: preset/actions.go:394
#, c-format
msgid "Profile %s unavailable"
msgstr ""
#: preset/actions.go:408 preset/actions.go:468
msgid "no available profiles"
msgstr ""
#: preset/actions.go:430
msgid "Profiles"
msgstr ""
#: preset/actions.go:451
#, c-format
msgid "Profile %s not found"
msgstr ""
#: preset/actions.go:472
msgid "Creating all available profiles..."
msgstr ""
#: preset/commands.go:15
msgid "Manage preset configuration profiles"
msgstr ""
#: preset/commands.go:19
msgid "Show information about preset profiles"
msgstr ""
#: preset/commands.go:27
msgid "Apply a profile"
msgstr ""
#: preset/commands.go:31 preset/commands.go:45
msgid "Show what would be created without making changes"
msgstr ""
#: preset/commands.go:41
msgid "Apply all available profiles"
msgstr ""
#: preset/tools.go:51
#, c-format
msgid "Error: %s"
msgstr ""
#: preset/tools.go:85
msgid "Copying"
msgstr ""
#: preset/tools.go:86
msgid "Creating links"
msgstr ""
#: preset/tools.go:87
msgid "Updating"
msgstr ""
#: preset/tools.go:88
msgid "Configuring system"
msgstr ""
#: preset/tools.go:89
msgid "Creating Hyprland variables"
msgstr ""
#: preset/tools.go:90
msgid "Enabling Hyprland modules"
msgstr ""
#: preset/tools.go:91
msgid "Syncing Hyprland layout"
msgstr ""
#: repo/actions.go:31 repo/actions.go:38
msgid "Error fetching data"
msgstr ""
#: repo/actions.go:90
msgid "Last update"
msgstr ""
#: repo/actions.go:91
msgid "Archive date"
msgstr ""
#: repo/commands.go:13
msgid "Ximper repos"
msgstr ""
#: repo/commands.go:17
msgid "Deferred repo"
msgstr ""
#: repo/commands.go:21
msgid "Deferred repo info"
msgstr ""
#: repo/commands.go:29
msgid "Sisyphus archive date"
msgstr ""
#: repo/commands.go:34
msgid "Date of last update"
msgstr ""
#: system/commands.go:17
msgid "System Management"
msgstr ""
#: system/commands.go:20
msgid "This command requires root"
msgstr ""
#: system/commands.go:28
msgid "Fix GRUB resolution"
msgstr ""
#: system/commands.go:33
msgid "Automatically run update-grub after fixing"
msgstr ""
#: system/commands.go:39
msgid "Enable verbose output"
msgstr ""
#: system/grub-actions.go:23
msgid "failed to read %s: %w"
msgstr ""
#: system/grub-actions.go:50
#, c-format
msgid "GRUB_GFXMODE is already set: %s"
msgstr ""
#: system/grub-actions.go:55
msgid "failed to write %s: %w"
msgstr ""
#: system/grub-actions.go:66
msgid "error running update-grub: %v (%s)"
msgstr ""
#: system/grub-actions.go:69
msgid "update-grub log:"
msgstr ""
#: ui/help.go:24
msgid "print the version"
msgstr ""
#: ui/help.go:46 ui/help.go:72 ui/help.go:99
msgid "Module:"
msgstr ""
#: ui/help.go:47 ui/help.go:73 ui/help.go:100
msgid "Usage:"
msgstr ""
#: ui/help.go:48 ui/help.go:75 ui/help.go:102
msgid "Description:"
msgstr ""
#: ui/help.go:49 ui/help.go:103
msgid "Commands:"
msgstr ""
#: ui/help.go:50 ui/help.go:51 ui/help.go:76 ui/help.go:77 ui/help.go:104
#: ui/help.go:105
msgid "Options:"
msgstr ""
#: ui/help.go:74 ui/help.go:101
msgid "Category:"
msgstr ""
#: ui/help.go:78
msgid "Global options:"
msgstr ""
#: ui/help.go:125
msgid "default"
msgstr ""
......@@ -5,6 +5,7 @@ import (
"slices"
"ximperconf/config"
"ximperconf/hyprland"
"ximperconf/locale"
"ximperconf/system"
"ximperconf/ui"
......@@ -73,7 +74,7 @@ func processReleaseReplace(prof config.PresetProfile, opts opOptions, res *Resul
func handleReleaseReplace(src, dest, sysVer string, opts opOptions) ui.TreeItem {
if _, err := os.Stat(dest); os.IsNotExist(err) {
return ui.TreeItem{
Name: fmt.Sprintf("Не найден: '%s'", dest),
Name: fmt.Sprintf(locale.T("Not found: '%s'"), dest),
Status: config.OpStatus.Skipped,
}
}
......@@ -81,7 +82,7 @@ func handleReleaseReplace(src, dest, sysVer string, opts opOptions) ui.TreeItem
data, err := os.ReadFile(dest)
if err != nil {
return ui.TreeItem{
Name: fmt.Sprintf("Не удалось прочитать %s: %v", dest, err),
Name: fmt.Sprintf(locale.T("Failed to read %s: %v"), dest, err),
Status: config.OpStatus.Error,
}
}
......@@ -89,7 +90,7 @@ func handleReleaseReplace(src, dest, sysVer string, opts opOptions) ui.TreeItem
content := string(data)
if strings.Contains(content, "XIMPER_LOCK") {
return ui.TreeItem{
Name: fmt.Sprintf("Заблокирован: %s", dest),
Name: fmt.Sprintf(locale.T("Locked: %s"), dest),
Status: config.OpStatus.Skipped,
}
}
......@@ -101,7 +102,7 @@ func handleReleaseReplace(src, dest, sysVer string, opts opOptions) ui.TreeItem
if fileVer == sysVer {
return ui.TreeItem{
Name: fmt.Sprintf("Актуально: '%s'", dest),
Name: fmt.Sprintf(locale.T("Up to date: '%s'"), dest),
Status: config.OpStatus.Skipped,
}
}
......@@ -116,7 +117,7 @@ func handleReleaseReplace(src, dest, sysVer string, opts opOptions) ui.TreeItem
_ = os.Rename(dest, dest+".old")
if err := copyFile(src, dest); err != nil {
return ui.TreeItem{
Name: fmt.Sprintf("Ошибка замены %s: %v", dest, err),
Name: fmt.Sprintf(locale.T("Replace error %s: %v"), dest, err),
Status: config.OpStatus.Error,
}
}
......@@ -132,7 +133,7 @@ func processHyprVars(manager *hyprland.HyprlandManager, prof config.PresetProfil
if !v.Force {
if V := manager.GetVar(v.Var); V != "" {
res.HyprVars = append(res.HyprVars, ui.TreeItem{
Name: fmt.Sprintf("Уже существует: '%s'", v.Var),
Name: fmt.Sprintf(locale.T("Already exists: %s"), v.Var),
Status: config.OpStatus.Skipped,
})
continue
......@@ -149,7 +150,7 @@ func processHyprVars(manager *hyprland.HyprlandManager, prof config.PresetProfil
if _, err := manager.SetVar(v.Var, v.Value); err != nil {
res.HyprVars = append(res.HyprVars, ui.TreeItem{
Name: fmt.Sprintf("Ошибка установки %s: %v", v.Var, err),
Name: fmt.Sprintf(locale.T("Error setting %s: %v"), v.Var, err),
Status: config.OpStatus.Error,
})
} else {
......@@ -166,7 +167,7 @@ func processHyprModules(manager *hyprland.HyprlandManager, prof config.PresetPro
if m.Module == "" {
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: "Пропущен модуль без имени",
Name: locale.T("Skipped module without name"),
Status: config.OpStatus.Skipped,
})
continue
......@@ -174,7 +175,7 @@ func processHyprModules(manager *hyprland.HyprlandManager, prof config.PresetPro
if !slices.Contains(validActions, m.Action) {
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: fmt.Sprintf("Модуль '%s': неподдерживаемый action", m.Module),
Name: fmt.Sprintf(locale.T("Module '%s': unsupported action"), m.Module),
Status: config.OpStatus.Skipped,
})
continue
......@@ -186,7 +187,7 @@ func processHyprModules(manager *hyprland.HyprlandManager, prof config.PresetPro
output, err := cmd.Output()
if err != nil {
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: fmt.Sprintf("Модуль '%s': команда '%s' завершилась с ошибкой", m.Module, m.IfExec),
Name: fmt.Sprintf(locale.T("Module '%s': command '%s' failed"), m.Module, m.IfExec),
Status: config.OpStatus.Skipped,
})
continue
......@@ -194,7 +195,7 @@ func processHyprModules(manager *hyprland.HyprlandManager, prof config.PresetPro
if len(bytes.TrimSpace(output)) == 0 {
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: fmt.Sprintf("Модуль '%s': команда '%s' не вернула данных", m.Module, m.IfExec),
Name: fmt.Sprintf(locale.T("Module '%s': command '%s' returned no data"), m.Module, m.IfExec),
Status: config.OpStatus.Skipped,
})
continue
......@@ -204,7 +205,7 @@ func processHyprModules(manager *hyprland.HyprlandManager, prof config.PresetPro
// if-binary
if m.IfBinary != "" && !commandExists(m.IfBinary) {
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: fmt.Sprintf("Модуль '%s': бинарник '%s' не найден", m.Module, m.IfBinary),
Name: fmt.Sprintf(locale.T("Module '%s': binary '%s' not found"), m.Module, m.IfBinary),
Status: config.OpStatus.Skipped,
})
continue
......@@ -216,13 +217,13 @@ func processHyprModules(manager *hyprland.HyprlandManager, prof config.PresetPro
if _, err := os.Stat(modulefile); os.IsNotExist(err) {
if opts.DryRun {
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: fmt.Sprintf("Создан пустой модуль: %s", m.Module),
Name: fmt.Sprintf(locale.T("Created empty module: %s"), m.Module),
Status: config.OpStatus.DryRun,
})
} else {
_ = os.WriteFile(modulefile, []byte(""), 0o644)
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: fmt.Sprintf("Создан пустой модуль: %s", m.Module),
Name: fmt.Sprintf(locale.T("Created empty module: %s"), m.Module),
Status: config.OpStatus.Done,
})
}
......@@ -234,11 +235,11 @@ func processHyprModules(manager *hyprland.HyprlandManager, prof config.PresetPro
var msg string
switch m.Action {
case "enable":
msg = fmt.Sprintf("Подключён модуль: %s", m.Module)
msg = fmt.Sprintf(locale.T("Module '%s' enabled"), m.Module)
case "disable":
msg = fmt.Sprintf("Отключён модуль: %s", m.Module)
msg = fmt.Sprintf(locale.T("Module '%s' disabled"), m.Module)
case "remove":
msg = fmt.Sprintf("Удалён модуль: %s", m.Module)
msg = fmt.Sprintf(locale.T("Module '%s' removed"), m.Module)
}
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: msg,
......@@ -254,18 +255,18 @@ func processHyprModules(manager *hyprland.HyprlandManager, prof config.PresetPro
m.NewOnly,
); err != nil {
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: fmt.Sprintf("Ошибка (%s): %v", m.Module, err),
Name: fmt.Sprintf(locale.T("Error (%s): %v"), m.Module, err),
Status: config.OpStatus.Error,
})
} else {
var msg string
switch m.Action {
case "enable":
msg = fmt.Sprintf("Подключён модуль: %s", m.Module)
msg = fmt.Sprintf(locale.T("Module '%s' enabled"), m.Module)
case "disable":
msg = fmt.Sprintf("Отключён модуль: %s", m.Module)
msg = fmt.Sprintf(locale.T("Module '%s' disabled"), m.Module)
case "remove":
msg = fmt.Sprintf("Удалён модуль: %s", m.Module)
msg = fmt.Sprintf(locale.T("Module '%s' removed"), m.Module)
}
res.HyprModules = append(res.HyprModules, ui.TreeItem{
Name: msg,
......@@ -282,7 +283,7 @@ func processHyprLayoutSync(manager *hyprland.HyprlandManager, prof config.Preset
if opts.DryRun {
res.SyncSystemLayouts = append(res.SyncSystemLayouts, ui.TreeItem{
Name: "Синхронизация раскладок Hyprland",
Name: locale.T("Sync Hyprland layouts"),
Status: config.OpStatus.DryRun,
})
return
......@@ -291,7 +292,7 @@ func processHyprLayoutSync(manager *hyprland.HyprlandManager, prof config.Preset
sysLayouts, err := hyprland.HyprlandGetKeyboardLayouts()
if err != nil {
res.SyncSystemLayouts = append(res.SyncSystemLayouts, ui.TreeItem{
Name: "Не удалось получить системные раскладки",
Name: locale.T("Failed to get system layouts"),
Status: config.OpStatus.Error,
})
return
......@@ -304,29 +305,29 @@ func processHyprLayoutSync(manager *hyprland.HyprlandManager, prof config.Preset
}
res.SyncSystemLayouts = append(res.SyncSystemLayouts, ui.TreeItem{
Name: fmt.Sprintf("Раскладка XCB: %s", sysLayouts),
Name: fmt.Sprintf(locale.T("XCB layout: %s"), sysLayouts),
Status: config.OpStatus.Done,
})
res.SyncSystemLayouts = append(res.SyncSystemLayouts, ui.TreeItem{
Name: fmt.Sprintf("Раскладка Hyprland: %s", hyprLayouts),
Name: fmt.Sprintf(locale.T("Hyprland layout: %s"), hyprLayouts),
Status: config.OpStatus.Done,
})
if hyprLayouts == "<empty>" {
if _, err := manager.SetVar("kb_layout", sysLayouts); err != nil {
res.SyncSystemLayouts = append(res.SyncSystemLayouts, ui.TreeItem{
Name: "Не удалось обновить kb_layout",
Name: locale.T("Failed to update kb_layout"),
Status: config.OpStatus.Error,
})
return
}
res.SyncSystemLayouts = append(res.SyncSystemLayouts, ui.TreeItem{
Name: fmt.Sprintf("Раскладка обновлена: %s", sysLayouts),
Name: fmt.Sprintf(locale.T("Layout updated: %s"), sysLayouts),
Status: config.OpStatus.Done,
})
} else {
res.SyncSystemLayouts = append(res.SyncSystemLayouts, ui.TreeItem{
Name: fmt.Sprintf("Раскладка уже установлена: %s", hyprLayouts),
Name: fmt.Sprintf(locale.T("Layout already set: %s"), hyprLayouts),
Status: config.OpStatus.Skipped,
})
}
......@@ -350,17 +351,17 @@ func processSystemGrub(prof config.PresetProfile, opts opOptions, res *Result) {
err := system.SystemGrubFixResolution(autoUpdate, false)
if err != nil {
res.System = append(res.System, ui.TreeItem{
Name: fmt.Sprintf("Ошибка GRUB: %v", err),
Name: fmt.Sprintf(locale.T("GRUB error: %v"), err),
Status: config.OpStatus.Error,
})
} else {
res.System = append(res.System, ui.TreeItem{
Name: "GRUB_GFXMODE исправлен",
Name: locale.T("GRUB_GFXMODE fixed"),
Status: config.OpStatus.Done,
})
if autoUpdate {
res.System = append(res.System, ui.TreeItem{
Name: "update-grub выполнен",
Name: locale.T("update-grub completed"),
Status: config.OpStatus.Done,
})
}
......@@ -388,9 +389,9 @@ func processProfile(prof config.PresetProfile, dryRun bool, res *Result) {
}
func createProfile(profileName string, prof config.PresetProfile, dryRun bool, res *Result) {
color.Green("Создаётся профиль: %s", profileName)
color.Green(locale.T("Creating profile: %s"), profileName)
if !profileAvailable(prof) {
color.Red("Профиль %s недоступен", profileName)
color.Red(locale.T("Profile %s unavailable"), profileName)
return
}
processProfile(prof, dryRun, res)
......@@ -404,7 +405,7 @@ func ShowProfilesInfo(jsonFormat bool) {
ui.PrintJSON([]ui.JSONItem{})
return
}
color.Red("Нет доступных профилей")
color.Red(locale.T("no available profiles"))
return
}
......@@ -426,7 +427,7 @@ func ShowProfilesInfo(jsonFormat bool) {
}
ui.RenderTree(ui.RenderTreeOptions{
Title: "Profiles",
Title: locale.T("Profiles"),
Items: items,
Style: ui.DefaultTreeStyle,
Color: true,
......@@ -447,7 +448,7 @@ func presetApplyCommand(ctx context.Context, cmd *cli.Command) error {
mainProf, ok := profiles[profileName]
if !ok {
color.Red("Профиль %s не найден", profileName)
color.Red(locale.T("Profile %s not found"), profileName)
return nil
}
......@@ -464,11 +465,11 @@ func presetApplyAllCommand(ctx context.Context, cmd *cli.Command) error {
profiles := config.Env.Preset.Profiles
if len(profiles) == 0 {
color.Red("Нет доступных профилей")
color.Red(locale.T("no available profiles"))
return nil
}
color.Cyan("Создаём все доступные профили...\n")
color.Cyan(locale.T("Creating all available profiles...") + "\n")
for name, prof := range profiles {
if !profileAvailable(prof) {
......
......@@ -4,6 +4,7 @@ import (
"context"
"fmt"
"ximperconf/config"
"ximperconf/locale"
"github.com/urfave/cli/v3"
)
......@@ -11,11 +12,11 @@ import (
func CommandList() *cli.Command {
return &cli.Command{
Name: "preset",
Usage: "Manage preset configuration profiles",
Usage: locale.T("Manage preset configuration profiles"),
Commands: []*cli.Command{
{
Name: "info",
Usage: "Show information about a preset profiles",
Usage: locale.T("Show information about preset profiles"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -23,11 +24,11 @@ func CommandList() *cli.Command {
},
{
Name: "apply",
Usage: "Apply a profile",
Usage: locale.T("Apply a profile"),
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "dry-run",
Usage: "Show what would be created without making changes.",
Usage: locale.T("Show what would be created without making changes"),
Aliases: []string{"d"},
Value: false,
},
......@@ -37,11 +38,11 @@ func CommandList() *cli.Command {
},
{
Name: "apply-all",
Usage: "Apply all available profiles",
Usage: locale.T("Apply all available profiles"),
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "dry-run",
Usage: "Show what would be created without making changes.",
Usage: locale.T("Show what would be created without making changes"),
Aliases: []string{"d"},
Value: false,
},
......
......@@ -8,6 +8,7 @@ import (
"strings"
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
)
......@@ -41,13 +42,13 @@ func AppendOpResult(res *Result, r opResult) {
switch {
case r.Status.IsEqual(config.OpStatus.Skipped):
item.Name = fmt.Sprintf("Уже существует: %s", r.Target)
item.Name = fmt.Sprintf(locale.T("Already exists: %s"), r.Target)
case r.Status.IsEqual(config.OpStatus.DryRun):
item.Name = fmt.Sprintf("%s → %s", r.Source, r.Target)
case r.Status.IsEqual(config.OpStatus.Done):
item.Name = fmt.Sprintf("%s → %s", r.Source, r.Target)
case r.Status.IsEqual(config.OpStatus.Error):
item.Name = fmt.Sprintf("Ошибка: %s", r.Reason)
item.Name = fmt.Sprintf(locale.T("Error: %s"), r.Reason)
}
switch r.Kind {
......@@ -81,11 +82,11 @@ func expandPath(path, name string) string {
}
func renderPresetResult(res *Result) {
ui.RenderTreeItems("Копируем", res.Copies)
ui.RenderTreeItems("Создаём ссылки", res.Links)
ui.RenderTreeItems("Обновляем", res.Replaced)
ui.RenderTreeItems("Настраиваем систему", res.System)
ui.RenderTreeItems("Создаём переменные Hyprland", res.HyprVars)
ui.RenderTreeItems("Подключаем модули Hyprland", res.HyprModules)
ui.RenderTreeItems("Синхронизируем раскладку Hyprland", res.SyncSystemLayouts)
ui.RenderTreeItems(locale.T("Copying"), res.Copies)
ui.RenderTreeItems(locale.T("Creating links"), res.Links)
ui.RenderTreeItems(locale.T("Updating"), res.Replaced)
ui.RenderTreeItems(locale.T("Configuring system"), res.System)
ui.RenderTreeItems(locale.T("Creating Hyprland variables"), res.HyprVars)
ui.RenderTreeItems(locale.T("Enabling Hyprland modules"), res.HyprModules)
ui.RenderTreeItems(locale.T("Syncing Hyprland layout"), res.SyncSystemLayouts)
}
......@@ -8,6 +8,7 @@ import (
"os"
"regexp"
"ximperconf/config"
"ximperconf/locale"
"ximperconf/ui"
"github.com/fatih/color"
......@@ -27,14 +28,14 @@ var (
func deferredGetHTML() string {
resp, err := http.Get(config.Env.Repo.DeferredInfoURL)
if err != nil {
color.Red("Ошибка получения данных")
color.Red(locale.T("Error fetching data"))
os.Exit(1)
}
defer resp.Body.Close()
data, err := io.ReadAll(resp.Body)
if err != nil {
color.Red("Ошибка получения данных")
color.Red(locale.T("Error fetching data"))
os.Exit(1)
}
return string(data)
......@@ -86,8 +87,8 @@ func DeferredInfoCommand(ctx context.Context, cmd *cli.Command) error {
}
color.Green("Deferred:")
fmt.Printf(" Последнее обновление: %s\n", lastUpdate)
fmt.Printf(" Дата архива: %s\n", archiveDate)
fmt.Printf(" %s: %s\n", locale.T("Last update"), lastUpdate)
fmt.Printf(" %s: %s\n", locale.T("Archive date"), archiveDate)
return nil
}
......@@ -2,6 +2,7 @@ package repo
import (
"ximperconf/config"
"ximperconf/locale"
"github.com/urfave/cli/v3"
)
......@@ -9,15 +10,15 @@ import (
func CommandList() *cli.Command {
return &cli.Command{
Name: "repo",
Usage: "Ximper repos",
Usage: locale.T("Ximper repos"),
Commands: []*cli.Command{
{
Name: "deferred",
Usage: "Deferred repo",
Usage: locale.T("Deferred repo"),
Commands: []*cli.Command{
{
Name: "info",
Usage: "Deferred repo info",
Usage: locale.T("Deferred repo info"),
Flags: []cli.Flag{
config.FormatFlag,
},
......@@ -25,12 +26,12 @@ func CommandList() *cli.Command {
},
{
Name: "date",
Usage: "Sisyphus archive date",
Usage: locale.T("Sisyphus archive date"),
Action: DeferredArchiveDateCommand,
},
{
Name: "last-update",
Usage: "Date of last update",
Usage: locale.T("Date of last update"),
Action: DeferredLastUpdateCommand,
},
},
......
......@@ -3,6 +3,7 @@ package system
import (
"fmt"
"ximperconf/config"
"ximperconf/locale"
"context"
......@@ -13,10 +14,10 @@ func CommandList() *cli.Command {
return &cli.Command{
Name: "system",
Hidden: !config.Env.IsRoot,
Usage: "System Management",
Usage: locale.T("System Management"),
Before: func(ctx context.Context, command *cli.Command) (context.Context, error) {
if !config.Env.IsRoot {
fmt.Printf("Эта команда требует root.\n")
fmt.Println(locale.T("This command requires root"))
return nil, fmt.Errorf("")
}
return ctx, nil
......@@ -24,18 +25,18 @@ func CommandList() *cli.Command {
Commands: []*cli.Command{
{
Name: "fix-grub-resolution",
Usage: "Fix GRUB resolution",
Usage: locale.T("Fix GRUB resolution"),
Action: SystemGrubFixResolutionCommand,
Flags: []cli.Flag{
&cli.BoolFlag{
Name: "update",
Usage: "Automatically run update-grub after fixing",
Usage: locale.T("Automatically run update-grub after fixing"),
Aliases: []string{"u"},
Value: false,
},
&cli.BoolFlag{
Name: "verbose",
Usage: "Enable verbose output",
Usage: locale.T("Enable verbose output"),
Aliases: []string{"V"},
Value: false,
},
......
......@@ -6,6 +6,7 @@ import (
"os"
"os/exec"
"strings"
"ximperconf/locale"
"github.com/urfave/cli/v3"
)
......@@ -19,7 +20,7 @@ func SystemGrubFixResolution(autoUpdate, verbose bool) error {
content, err := os.ReadFile(grubFile)
if err != nil {
return fmt.Errorf("не удалось прочитать %s: %w", grubFile, err)
return fmt.Errorf(locale.T("failed to read %s: %w"), grubFile, err)
}
lines := strings.Split(string(content), "\n")
......@@ -46,12 +47,12 @@ func SystemGrubFixResolution(autoUpdate, verbose bool) error {
}
if !changed {
return fmt.Errorf("GRUB_GFXMODE уже установлен: %s", oldValue)
return fmt.Errorf(locale.T("GRUB_GFXMODE is already set: %s"), oldValue)
}
newContent := strings.Join(lines, "\n")
if err := os.WriteFile(grubFile, []byte(newContent), 0644); err != nil {
return fmt.Errorf("не удалось записать %s: %w", grubFile, err)
return fmt.Errorf(locale.T("failed to write %s: %w"), grubFile, err)
}
if verbose {
......@@ -62,10 +63,10 @@ func SystemGrubFixResolution(autoUpdate, verbose bool) error {
cmd := exec.Command("update-grub")
out, err := cmd.CombinedOutput()
if err != nil {
return fmt.Errorf("ошибка при выполнении update-grub: %v (%s)", err, out)
return fmt.Errorf(locale.T("error running update-grub: %v (%s)"), err, out)
}
if verbose {
fmt.Println("Лог update-grub:\n", string(out))
fmt.Println(locale.T("update-grub log:")+" \n", string(out))
}
}
......@@ -82,10 +83,10 @@ func SystemGrubFixResolutionCommand(ctx context.Context, cmd *cli.Command) error
}
if !verbose {
fmt.Println("GRUB_GFXMODE исправлен успешно.")
fmt.Println(locale.T("GRUB_GFXMODE fixed"))
}
if autoUpdate && !verbose {
fmt.Println("Выполнен update-grub.")
fmt.Println(locale.T("update-grub completed"))
}
return nil
......
package ui
import (
"fmt"
"strings"
"ximperconf/locale"
"github.com/fatih/color"
"github.com/urfave/cli/v3"
)
func SetupHelpTemplates() {
cli.HelpFlag = &cli.BoolFlag{
Name: "help",
Aliases: []string{"h"},
Usage: locale.T("show help"),
HideDefault: true,
Local: true,
}
cli.VersionFlag = &cli.BoolFlag{
Name: "version",
Aliases: []string{"v"},
Usage: locale.T("print the version"),
HideDefault: true,
Local: true,
}
title := color.New(color.Bold, color.FgYellow).SprintFunc()
cli.RootCommandHelpTemplate = fmt.Sprintf(`%s
{{template "helpNameTemplate" .}} {{if .Version}}{{if not .HideVersion}}{{.Version}}{{end}}{{end}}{{if .Description}}
%s
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} [command [command options]]{{end}}
%s
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}}
%s{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
%s{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
%s{{template "visibleFlagTemplate" .}}{{end}}
`,
title(locale.T("Module:")),
title(locale.T("Usage:")),
title(locale.T("Description:")),
title(locale.T("Commands:")),
title(locale.T("Options:")),
title(locale.T("Options:")),
)
cli.CommandHelpTemplate = fmt.Sprintf(`%s
{{template "helpNameTemplate" .}}
%s
{{template "usageTemplate" .}}{{if .Category}}
%s
{{.Category}}{{end}}{{if .Description}}
%s
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
%s{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
%s{{template "visibleFlagTemplate" .}}{{end}}{{if .VisiblePersistentFlags}}
%s{{template "visiblePersistentFlagTemplate" .}}{{end}}
`,
title(locale.T("Module:")),
title(locale.T("Usage:")),
title(locale.T("Category:")),
title(locale.T("Description:")),
title(locale.T("Options:")),
title(locale.T("Options:")),
title(locale.T("Global options:")),
)
cli.SubcommandHelpTemplate = fmt.Sprintf(`%s
{{template "helpNameTemplate" .}}
%s
{{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.FullName}} [command [command options]]{{end}}{{if .Category}}
%s
{{.Category}}{{end}}{{if .Description}}
%s
{{template "descriptionTemplate" .}}{{end}}{{if .VisibleCommands}}
%s{{template "visibleCommandTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
%s{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
%s{{template "visibleFlagTemplate" .}}{{end}}
`,
title(locale.T("Module:")),
title(locale.T("Usage:")),
title(locale.T("Category:")),
title(locale.T("Description:")),
title(locale.T("Commands:")),
title(locale.T("Options:")),
title(locale.T("Options:")),
)
cli.FlagStringer = func(fl cli.Flag) string {
df, ok := fl.(cli.DocGenerationFlag)
if !ok {
return ""
}
placeholder, usage := unquoteUsage(df.GetUsage())
needsPlaceholder := df.TakesValue()
if needsPlaceholder && placeholder == "" {
placeholder = ""
}
defaultValueString := ""
if rf, ok := fl.(cli.RequiredFlag); !ok || !rf.IsRequired() {
isVisible := df.IsDefaultVisible()
if s := df.GetDefaultText(); isVisible && s != "" {
defaultValueString = fmt.Sprintf(" (%s: %s)", locale.T("default"), s)
}
}
usageWithDefault := strings.TrimSpace(usage + defaultValueString)
var prefixed string
names := fl.Names()
for i, name := range names {
if name == "" {
continue
}
if len(name) == 1 {
prefixed += "-" + name
} else {
prefixed += "--" + name
}
if placeholder != "" {
prefixed += " " + placeholder
}
if i < len(names)-1 {
prefixed += ", "
}
}
if sliceFlag, ok := fl.(cli.DocGenerationMultiValueFlag); ok && sliceFlag.IsMultiValueFlag() {
prefixed = prefixed + " [ " + prefixed + " ]"
}
envVars := df.GetEnvVars()
envHint := ""
if len(envVars) > 0 {
envHint = fmt.Sprintf(" [%s]", strings.Join(envVars, ", "))
}
return fmt.Sprintf(" %s\t%s%s", prefixed, usageWithDefault, envHint)
}
}
func unquoteUsage(usage string) (string, string) {
for i := 0; i < len(usage); i++ {
if usage[i] == '`' {
for j := i + 1; j < len(usage); j++ {
if usage[j] == '`' {
name := usage[i+1 : j]
usage = usage[:i] + name + usage[j+1:]
return name, usage
}
}
break
}
}
return "", usage
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment