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 @@

-[![Go Report Card](https://goreportcard.com/badge/gitea.plemya-x.ru/Plemya-x/ALR)](https://goreportcard.com/report/gitea.plemya-x.ru/Plemya-x/ALR) ![Test coverage](./coverage-badge.svg) +[![Go Report Card](https://goreportcard.com/badge/gitea.plemya-x.ru/Plemya-x/ALR)](https://goreportcard.com/report/gitea.plemya-x.ru/Plemya-x/ALR) ![Test coverage](./assets/coverage-badge.svg) ![ru translate](./assets/i18n-ru-badge.svg) # 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 @@ + + + + + + + + + + + + + ru translate + ru translate + 79.00% + 79.00% + + 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 diff --git a/scripts/i18n-badge.sh b/scripts/i18n-badge.sh new file mode 100755 index 0000000..7282281 --- /dev/null +++ b/scripts/i18n-badge.sh @@ -0,0 +1,74 @@ +#!/bin/bash +# 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 . + + +TRANSLATIONS_DIR="internal/translations/po" + +if [ ! -d "$TRANSLATIONS_DIR" ]; then + echo "Ошибка: директория '$TRANSLATIONS_DIR' не найдена" + exit 1 +fi + +declare -A TOTAL_STRINGS_MAP +declare -A TRANSLATED_STRINGS_MAP + +for PO_FILE in $(find "$TRANSLATIONS_DIR" -type f -name "*.po"); do + LANG_DIR=$(dirname "$PO_FILE") + LANG=$(basename "$LANG_DIR") + + TOTAL_STRINGS=$(grep -c "^msgid " "$PO_FILE") + TRANSLATED_STRINGS=$(grep -c "^msgstr \"[^\"]\+\"" "$PO_FILE") + + TOTAL_STRINGS_MAP[$LANG]=$((TOTAL_STRINGS_MAP[$LANG] + TOTAL_STRINGS)) + TRANSLATED_STRINGS_MAP[$LANG]=$((TRANSLATED_STRINGS_MAP[$LANG] + TRANSLATED_STRINGS)) +done + +for LANG in "${!TOTAL_STRINGS_MAP[@]}"; do + TOTAL=${TOTAL_STRINGS_MAP[$LANG]} + TRANSLATED=${TRANSLATED_STRINGS_MAP[$LANG]} + if [ "$TOTAL" -eq 0 ]; then + PERCENTAGE="0.00" + else + PERCENTAGE=$(echo "scale=2; ($TRANSLATED / $TOTAL) * 100" | bc) + fi + COLOR="#4c1" + if (( $(echo "$PERCENTAGE < 50" | bc -l) )); then + COLOR="#e05d44" + elif (( $(echo "$PERCENTAGE < 80" | bc -l) )); then + COLOR="#dfb317" + fi +cat < assets/i18n-$LANG-badge.svg + + + + + + + + + + + + + $LANG translate + $LANG translate + ${PERCENTAGE}% + ${PERCENTAGE}% + + +EOF +done