diff --git a/Makefile b/Makefile
index 157b882..6af9352 100644
--- a/Makefile
+++ b/Makefile
@@ -66,6 +66,7 @@ i18n:
$(XGOTEXT_BIN) --output ./internal/translations/default.pot
msguniq --use-first -o ./internal/translations/default.pot ./internal/translations/default.pot
msgmerge --backup=off -U ./internal/translations/po/ru/default.po ./internal/translations/default.pot
+ bash scripts/i18n-badge.sh
test-coverage:
go test ./... -v -coverpkg=./... -coverprofile=coverage.out
diff --git a/README.md b/README.md
index 6ae4871..1378b28 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
-[](https://goreportcard.com/report/gitea.plemya-x.ru/Plemya-x/ALR) 
+[](https://goreportcard.com/report/gitea.plemya-x.ru/Plemya-x/ALR)  
# ALR (Any Linux Repository)
diff --git a/coverage-badge.svg b/assets/coverage-badge.svg
similarity index 100%
rename from coverage-badge.svg
rename to assets/coverage-badge.svg
diff --git a/assets/i18n-ru-badge.svg b/assets/i18n-ru-badge.svg
new file mode 100644
index 0000000..6deb013
--- /dev/null
+++ b/assets/i18n-ru-badge.svg
@@ -0,0 +1,18 @@
+
diff --git a/internal/cliutils/template.go b/internal/cliutils/template.go
new file mode 100644
index 0000000..101a461
--- /dev/null
+++ b/internal/cliutils/template.go
@@ -0,0 +1,102 @@
+// ALR - Any Linux Repository
+// Copyright (C) 2025 Евгений Храмов
+//
+// This program is free software: you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program. If not, see .
+
+package cliutils
+
+import (
+ "fmt"
+
+ "github.com/leonelquinteros/gotext"
+)
+
+// Templates are based on https://github.com/urfave/cli/blob/3b17080d70a630feadadd23dd036cad121dd9a50/template.go
+
+//nolint:unused
+var (
+ helpNameTemplate = `{{$v := offset .HelpName 6}}{{wrap .HelpName 3}}{{if .Usage}} - {{wrap .Usage $v}}{{end}}`
+ descriptionTemplate = `{{wrap .Description 3}}`
+ authorsTemplate = `{{with $length := len .Authors}}{{if ne 1 $length}}S{{end}}{{end}}:
+ {{range $index, $author := .Authors}}{{if $index}}
+ {{end}}{{$author}}{{end}}`
+ visibleCommandTemplate = `{{ $cv := offsetCommands .VisibleCommands 5}}{{range .VisibleCommands}}
+ {{$s := join .Names ", "}}{{$s}}{{ $sp := subtract $cv (offset $s 3) }}{{ indent $sp ""}}{{wrap .Usage $cv}}{{end}}`
+ visibleCommandCategoryTemplate = `{{range .VisibleCategories}}{{if .Name}}
+ {{.Name}}:{{range .VisibleCommands}}
+ {{join .Names ", "}}{{"\t"}}{{.Usage}}{{end}}{{else}}{{template "visibleCommandTemplate" .}}{{end}}{{end}}`
+ visibleFlagCategoryTemplate = `{{range .VisibleFlagCategories}}
+ {{if .Name}}{{.Name}}
+
+ {{end}}{{$flglen := len .Flags}}{{range $i, $e := .Flags}}{{if eq (subtract $flglen $i) 1}}{{$e}}
+{{else}}{{$e}}
+ {{end}}{{end}}{{end}}`
+ visibleFlagTemplate = `{{range $i, $e := .VisibleFlags}}
+ {{wrap $e.String 6}}{{end}}`
+ copyrightTemplate = `{{wrap .Copyright 3}}`
+)
+
+func GetAppCliTemplate() string {
+ return fmt.Sprintf(`%s:
+ {{template "helpNameTemplate" .}}
+
+%s:
+ {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}} {{if .VisibleFlags}}[global options]{{end}}{{if .Commands}} command [command options]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[arguments...]{{end}}{{end}}{{if .Version}}{{if not .HideVersion}}
+
+%s:
+ {{.Version}}{{end}}{{end}}{{if .Description}}
+
+%s:
+ {{template "descriptionTemplate" .}}{{end}}
+{{- if len .Authors}}
+
+%s{{template "authorsTemplate" .}}{{end}}{{if .VisibleCommands}}
+
+%s:{{template "visibleCommandCategoryTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
+
+%s:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
+
+%s:{{template "visibleFlagTemplate" .}}{{end}}{{if .Copyright}}
+
+%s:
+ {{template "copyrightTemplate" .}}{{end}}
+`, gotext.Get("NAME"), gotext.Get("USAGE"), gotext.Get("VERSION"), gotext.Get("DESCRIPTION"), gotext.Get("AUTHOR"), gotext.Get("COMMANDS"), gotext.Get("GLOBAL OPTIONS"), gotext.Get("GLOBAL OPTIONS"), gotext.Get("COPYRIGHT"))
+}
+
+func GetCommandHelpTemplate() string {
+ return fmt.Sprintf(`%s:
+ {{template "helpNameTemplate" .}}
+
+%s:
+ {{if .UsageText}}{{wrap .UsageText 3}}{{else}}{{.HelpName}}{{if .VisibleFlags}} [%s]{{end}} {{if .ArgsUsage}}{{.ArgsUsage}}{{else}}[%s]{{end}}{{end}}{{if .Category}}
+
+%s:
+ {{.Category}}{{end}}{{if .Description}}
+
+%s:
+ {{template "descriptionTemplate" .}}{{end}}{{if .VisibleFlagCategories}}
+
+%s:{{template "visibleFlagCategoryTemplate" .}}{{else if .VisibleFlags}}
+
+%s:{{template "visibleFlagTemplate" .}}{{end}}
+`, gotext.Get("NAME"),
+ gotext.Get("USAGE"),
+ gotext.Get("command options"),
+ gotext.Get("arguments..."),
+ gotext.Get("CATEGORY"),
+ gotext.Get("DESCRIPTION"),
+ gotext.Get("OPTIONS"),
+ gotext.Get("OPTIONS"),
+ )
+}
diff --git a/internal/translations/default.pot b/internal/translations/default.pot
index 6739f13..c132ac0 100644
--- a/internal/translations/default.pot
+++ b/internal/translations/default.pot
@@ -194,6 +194,54 @@ msgstr ""
msgid "Choose which optional package(s) to install"
msgstr ""
+#: internal/cliutils/template.go:74 internal/cliutils/template.go:93
+msgid "NAME"
+msgstr ""
+
+#: internal/cliutils/template.go:74 internal/cliutils/template.go:94
+msgid "USAGE"
+msgstr ""
+
+#: internal/cliutils/template.go:74
+msgid "VERSION"
+msgstr ""
+
+#: internal/cliutils/template.go:74 internal/cliutils/template.go:98
+msgid "DESCRIPTION"
+msgstr ""
+
+#: internal/cliutils/template.go:74
+msgid "AUTHOR"
+msgstr ""
+
+#: internal/cliutils/template.go:74
+msgid "COMMANDS"
+msgstr ""
+
+#: internal/cliutils/template.go:74
+msgid "GLOBAL OPTIONS"
+msgstr ""
+
+#: internal/cliutils/template.go:74
+msgid "COPYRIGHT"
+msgstr ""
+
+#: internal/cliutils/template.go:95
+msgid "command options"
+msgstr ""
+
+#: internal/cliutils/template.go:96
+msgid "arguments..."
+msgstr ""
+
+#: internal/cliutils/template.go:97
+msgid "CATEGORY"
+msgstr ""
+
+#: internal/cliutils/template.go:99 internal/cliutils/template.go:100
+msgid "OPTIONS"
+msgstr ""
+
#: internal/config/config.go:59
msgid "Error opening config file, using defaults"
msgstr ""
@@ -275,25 +323,29 @@ msgstr ""
msgid "Error listing installed packages"
msgstr ""
-#: main.go:44
+#: main.go:45
msgid "Print the current ALR version and exit"
msgstr ""
-#: main.go:60
+#: main.go:61
msgid "Arguments to be passed on to the package manager"
msgstr ""
-#: main.go:66
+#: main.go:67
msgid "Enable interactive questions and prompts"
msgstr ""
-#: main.go:91
+#: main.go:92
msgid ""
"Running ALR as root is forbidden as it may cause catastrophic damage to your "
"system"
msgstr ""
-#: main.go:123
+#: main.go:125
+msgid "Show help"
+msgstr ""
+
+#: main.go:129
msgid "Error while running app"
msgstr ""
diff --git a/internal/translations/po/ru/default.po b/internal/translations/po/ru/default.po
index cb9e07a..0c95890 100644
--- a/internal/translations/po/ru/default.po
+++ b/internal/translations/po/ru/default.po
@@ -1,12 +1,12 @@
#
-# Maxim Slipenko , 2025.
# x1z53 , 2025.
+# Maxim Slipenko , 2025.
#
msgid ""
msgstr ""
"Project-Id-Version: unnamed project\n"
-"PO-Revision-Date: 2025-01-24 21:20+0300\n"
-"Last-Translator: x1z53 \n"
+"PO-Revision-Date: 2025-02-27 10:10+0300\n"
+"Last-Translator: Maxim Slipenko \n"
"Language-Team: Russian\n"
"Language: ru\n"
"MIME-Version: 1.0\n"
@@ -202,6 +202,54 @@ msgstr "Выберите, какой пакет использовать для
msgid "Choose which optional package(s) to install"
msgstr "Выберите, какой дополнительный пакет(ы) следует установить"
+#: internal/cliutils/template.go:74 internal/cliutils/template.go:93
+msgid "NAME"
+msgstr "НАЗВАНИЕ"
+
+#: internal/cliutils/template.go:74 internal/cliutils/template.go:94
+msgid "USAGE"
+msgstr "ИСПОЛЬЗОВАНИЕ"
+
+#: internal/cliutils/template.go:74
+msgid "VERSION"
+msgstr "ВЕРСИЯ"
+
+#: internal/cliutils/template.go:74 internal/cliutils/template.go:98
+msgid "DESCRIPTION"
+msgstr "ОПИСАНИЕ"
+
+#: internal/cliutils/template.go:74
+msgid "AUTHOR"
+msgstr ""
+
+#: internal/cliutils/template.go:74
+msgid "COMMANDS"
+msgstr ""
+
+#: internal/cliutils/template.go:74
+msgid "GLOBAL OPTIONS"
+msgstr ""
+
+#: internal/cliutils/template.go:74
+msgid "COPYRIGHT"
+msgstr ""
+
+#: internal/cliutils/template.go:95
+msgid "command options"
+msgstr ""
+
+#: internal/cliutils/template.go:96
+msgid "arguments..."
+msgstr ""
+
+#: internal/cliutils/template.go:97
+msgid "CATEGORY"
+msgstr ""
+
+#: internal/cliutils/template.go:99 internal/cliutils/template.go:100
+msgid "OPTIONS"
+msgstr ""
+
#: internal/config/config.go:59
msgid "Error opening config file, using defaults"
msgstr ""
@@ -288,19 +336,19 @@ msgstr "Список пакетов репозитория ALR"
msgid "Error listing installed packages"
msgstr "Ошибка при составлении списка установленных пакетов"
-#: main.go:44
+#: main.go:45
msgid "Print the current ALR version and exit"
msgstr "Показать текущую версию ALR и выйти"
-#: main.go:60
+#: main.go:61
msgid "Arguments to be passed on to the package manager"
msgstr "Аргументы, которые будут переданы менеджеру пакетов"
-#: main.go:66
+#: main.go:67
msgid "Enable interactive questions and prompts"
msgstr "Включение интерактивных вопросов и запросов"
-#: main.go:91
+#: main.go:92
msgid ""
"Running ALR as root is forbidden as it may cause catastrophic damage to your "
"system"
@@ -308,7 +356,11 @@ msgstr ""
"Запуск ALR от имени root запрещён, так как это может привести к "
"катастрофическому повреждению вашей системы"
-#: main.go:123
+#: main.go:125
+msgid "Show help"
+msgstr ""
+
+#: main.go:129
msgid "Error while running app"
msgstr "Ошибка при запуске приложения"
diff --git a/main.go b/main.go
index 2bb286a..1d4ce30 100644
--- a/main.go
+++ b/main.go
@@ -31,6 +31,7 @@ import (
"github.com/mattn/go-isatty"
"github.com/urfave/cli/v2"
+ "gitea.plemya-x.ru/Plemya-x/ALR/internal/cliutils"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/config"
"gitea.plemya-x.ru/Plemya-x/ALR/internal/translations"
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/manager"
@@ -118,6 +119,11 @@ func main() {
ctx, cancel := signal.NotifyContext(ctx, syscall.SIGINT, syscall.SIGTERM)
defer cancel()
+ // Make the application more internationalized
+ cli.AppHelpTemplate = cliutils.GetAppCliTemplate()
+ cli.CommandHelpTemplate = cliutils.GetCommandHelpTemplate()
+ cli.HelpFlag.(*cli.BoolFlag).Usage = gotext.Get("Show help")
+
err := app.RunContext(ctx, os.Args)
if err != nil {
slog.Error(gotext.Get("Error while running app"), "err", err)
diff --git a/scripts/coverage-badge.sh b/scripts/coverage-badge.sh
index 935aa0c..b6c575d 100755
--- a/scripts/coverage-badge.sh
+++ b/scripts/coverage-badge.sh
@@ -25,7 +25,7 @@ elif (( $(echo "$COVERAGE < 80" | bc -l) )); then
COLOR="#dfb317"
fi
-cat < coverage-badge.svg
+cat < assets/coverage-badge.svg