feat: add new logger and translation
This commit is contained in:
@ -21,14 +21,16 @@ package config
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync"
|
||||
|
||||
"github.com/pelletier/go-toml/v2"
|
||||
|
||||
"github.com/leonelquinteros/gotext"
|
||||
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/internal/types"
|
||||
"gitea.plemya-x.ru/Plemya-x/ALR/pkg/loggerctx"
|
||||
)
|
||||
|
||||
type ALRConfig struct {
|
||||
@ -56,10 +58,9 @@ func New() *ALRConfig {
|
||||
}
|
||||
|
||||
func (c *ALRConfig) Load(ctx context.Context) {
|
||||
log := loggerctx.From(ctx)
|
||||
cfgFl, err := os.Open(c.GetPaths(ctx).ConfigPath)
|
||||
if err != nil {
|
||||
log.Warn("Error opening config file, using defaults").Err(err).Send()
|
||||
slog.Warn(gotext.Get("Error opening config file, using defaults"), "err", err)
|
||||
c.cfg = defaultConfig
|
||||
return
|
||||
}
|
||||
@ -72,27 +73,28 @@ func (c *ALRConfig) Load(ctx context.Context) {
|
||||
|
||||
err = toml.NewDecoder(cfgFl).Decode(config)
|
||||
if err != nil {
|
||||
log.Warn("Error decoding config file, using defaults").Err(err).Send()
|
||||
slog.Warn(gotext.Get("Error decoding config file, using defaults"), "err", err)
|
||||
c.cfg = defaultConfig
|
||||
return
|
||||
}
|
||||
c.cfg = config
|
||||
}
|
||||
|
||||
func (c *ALRConfig) initPaths(ctx context.Context) {
|
||||
log := loggerctx.From(ctx)
|
||||
func (c *ALRConfig) initPaths() {
|
||||
paths := &Paths{}
|
||||
|
||||
cfgDir, err := os.UserConfigDir()
|
||||
if err != nil {
|
||||
log.Fatal("Unable to detect user config directory").Err(err).Send()
|
||||
slog.Error(gotext.Get("Unable to detect user config directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
paths.ConfigDir = filepath.Join(cfgDir, "alr")
|
||||
|
||||
err = os.MkdirAll(paths.ConfigDir, 0o755)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to create ALR config directory").Err(err).Send()
|
||||
slog.Error(gotext.Get("Unable to create ALR config directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
paths.ConfigPath = filepath.Join(paths.ConfigDir, "alr.toml")
|
||||
@ -100,12 +102,14 @@ func (c *ALRConfig) initPaths(ctx context.Context) {
|
||||
if _, err := os.Stat(paths.ConfigPath); err != nil {
|
||||
cfgFl, err := os.Create(paths.ConfigPath)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to create ALR config file").Err(err).Send()
|
||||
slog.Error(gotext.Get("Unable to create ALR config file"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = toml.NewEncoder(cfgFl).Encode(&defaultConfig)
|
||||
if err != nil {
|
||||
log.Fatal("Error encoding default configuration").Err(err).Send()
|
||||
slog.Error(gotext.Get("Error encoding default configuration"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cfgFl.Close()
|
||||
@ -113,7 +117,8 @@ func (c *ALRConfig) initPaths(ctx context.Context) {
|
||||
|
||||
cacheDir, err := os.UserCacheDir()
|
||||
if err != nil {
|
||||
log.Fatal("Unable to detect cache directory").Err(err).Send()
|
||||
slog.Error(gotext.Get("Unable to detect cache directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
paths.CacheDir = filepath.Join(cacheDir, "alr")
|
||||
@ -122,12 +127,14 @@ func (c *ALRConfig) initPaths(ctx context.Context) {
|
||||
|
||||
err = os.MkdirAll(paths.RepoDir, 0o755)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to create repo cache directory").Err(err).Send()
|
||||
slog.Error(gotext.Get("Unable to create repo cache directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(paths.PkgsDir, 0o755)
|
||||
if err != nil {
|
||||
log.Fatal("Unable to create package cache directory").Err(err).Send()
|
||||
slog.Error(gotext.Get("Unable to create package cache directory"), "err", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
paths.DBPath = filepath.Join(paths.CacheDir, "db")
|
||||
@ -137,7 +144,7 @@ func (c *ALRConfig) initPaths(ctx context.Context) {
|
||||
|
||||
func (c *ALRConfig) GetPaths(ctx context.Context) *Paths {
|
||||
c.pathsOnce.Do(func() {
|
||||
c.initPaths(ctx)
|
||||
c.initPaths()
|
||||
})
|
||||
return c.paths
|
||||
}
|
||||
|
93
internal/logger/log.go
Normal file
93
internal/logger/log.go
Normal file
@ -0,0 +1,93 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
package logger
|
||||
|
||||
import (
|
||||
"context"
|
||||
"log/slog"
|
||||
"os"
|
||||
|
||||
"github.com/charmbracelet/lipgloss"
|
||||
"github.com/charmbracelet/log"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
)
|
||||
|
||||
type Logger struct {
|
||||
lOut slog.Handler
|
||||
lErr slog.Handler
|
||||
}
|
||||
|
||||
func setupOutLogger() *log.Logger {
|
||||
styles := log.DefaultStyles()
|
||||
logger := log.New(os.Stdout)
|
||||
logger.SetStyles(styles)
|
||||
return logger
|
||||
}
|
||||
|
||||
func setupErrorLogger() *log.Logger {
|
||||
styles := log.DefaultStyles()
|
||||
styles.Levels[log.ErrorLevel] = lipgloss.NewStyle().
|
||||
SetString(gotext.Get("ERROR")).
|
||||
Padding(0, 1, 0, 1).
|
||||
Background(lipgloss.Color("204")).
|
||||
Foreground(lipgloss.Color("0"))
|
||||
logger := log.New(os.Stderr)
|
||||
logger.SetStyles(styles)
|
||||
return logger
|
||||
}
|
||||
|
||||
func New() *Logger {
|
||||
standardLogger := setupOutLogger()
|
||||
errLogger := setupErrorLogger()
|
||||
return &Logger{
|
||||
lOut: standardLogger,
|
||||
lErr: errLogger,
|
||||
}
|
||||
}
|
||||
|
||||
func (l *Logger) Enabled(ctx context.Context, level slog.Level) bool {
|
||||
if level <= slog.LevelInfo {
|
||||
return l.lOut.Enabled(ctx, level)
|
||||
}
|
||||
return l.lErr.Enabled(ctx, level)
|
||||
}
|
||||
|
||||
func (l *Logger) Handle(ctx context.Context, rec slog.Record) error {
|
||||
if rec.Level <= slog.LevelInfo {
|
||||
return l.lOut.Handle(ctx, rec)
|
||||
}
|
||||
return l.lErr.Handle(ctx, rec)
|
||||
}
|
||||
|
||||
func (l *Logger) WithAttrs(attrs []slog.Attr) slog.Handler {
|
||||
sl := *l
|
||||
sl.lOut = l.lOut.WithAttrs(attrs)
|
||||
sl.lErr = l.lErr.WithAttrs(attrs)
|
||||
return &sl
|
||||
}
|
||||
|
||||
func (l *Logger) WithGroup(name string) slog.Handler {
|
||||
sl := *l
|
||||
sl.lOut = l.lOut.WithGroup(name)
|
||||
sl.lErr = l.lErr.WithGroup(name)
|
||||
return &sl
|
||||
}
|
||||
|
||||
func SetupDefault() {
|
||||
logger := slog.New(New())
|
||||
slog.SetDefault(logger)
|
||||
}
|
84
internal/translations/default.pot
Normal file
84
internal/translations/default.pot
Normal file
@ -0,0 +1,84 @@
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"Project-Id-Version: \n"
|
||||
"Last-Translator: Automatically generated\n"
|
||||
"Language-Team: none\n"
|
||||
"Language: en\n"
|
||||
"MIME-Version: 1.0\n"
|
||||
"Content-Type: text/plain; charset=UTF-8\n"
|
||||
"Content-Transfer-Encoding: 8bit\n"
|
||||
"Plural-Forms: nplurals=2; plural=(n != 1);\n"
|
||||
|
||||
#: info.go:42
|
||||
msgid "Print information about a package"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:47
|
||||
msgid "Show all information, not just for the current distro"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:59
|
||||
msgid "Command info expected at least 1 argument, got %d"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:65
|
||||
msgid "Error pulling repositories"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:71
|
||||
msgid "Error finding packages"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:87
|
||||
msgid "Error parsing os-release file"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:96
|
||||
msgid "Error resolving overrides"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:105
|
||||
#: info.go:111
|
||||
msgid "Error encoding script variables"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:63
|
||||
msgid "Error opening config file, using defaults"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:76
|
||||
msgid "Error decoding config file, using defaults"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:88
|
||||
msgid "Unable to detect user config directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:96
|
||||
msgid "Unable to create ALR config directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:105
|
||||
msgid "Unable to create ALR config file"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:111
|
||||
msgid "Error encoding default configuration"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:120
|
||||
msgid "Unable to detect cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:130
|
||||
msgid "Unable to create repo cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:136
|
||||
msgid "Unable to create package cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/logger/log.go:44
|
||||
msgid "ERROR"
|
||||
msgstr ""
|
||||
|
88
internal/translations/po/ru/default.po
Normal file
88
internal/translations/po/ru/default.po
Normal file
@ -0,0 +1,88 @@
|
||||
#
|
||||
# Maxim Slipenko <maks1ms@alt-gnome.ru>, 2025.
|
||||
#
|
||||
msgid ""
|
||||
msgstr ""
|
||||
"PO-Revision-Date: 2025-01-22 14:23+0300\n"
|
||||
"Last-Translator: Maxim Slipenko <maks1ms@alt-gnome.ru>\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"
|
||||
"X-Generator: Gtranslator 47.1\n"
|
||||
"Project-Id-Version: \n"
|
||||
"Language-Team: Russian\n"
|
||||
|
||||
#: info.go:42
|
||||
msgid "Print information about a package"
|
||||
msgstr "Напечатать информацию о пакете"
|
||||
|
||||
#: info.go:47
|
||||
msgid "Show all information, not just for the current distro"
|
||||
msgstr "Показывать всю информацию, а не только для текущего дистрибутива"
|
||||
|
||||
#: info.go:59
|
||||
msgid "Command info expected at least 1 argument, got %d"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:65
|
||||
msgid "Error pulling repositories"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:71
|
||||
msgid "Error finding packages"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:87
|
||||
msgid "Error parsing os-release file"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:96
|
||||
msgid "Error resolving overrides"
|
||||
msgstr ""
|
||||
|
||||
#: info.go:105 info.go:111
|
||||
msgid "Error encoding script variables"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:63
|
||||
msgid "Error opening config file, using defaults"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:76
|
||||
msgid "Error decoding config file, using defaults"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:88
|
||||
msgid "Unable to detect user config directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:96
|
||||
msgid "Unable to create ALR config directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:105
|
||||
msgid "Unable to create ALR config file"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:111
|
||||
msgid "Error encoding default configuration"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:120
|
||||
msgid "Unable to detect cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:130
|
||||
msgid "Unable to create repo cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/config/config.go:136
|
||||
msgid "Unable to create package cache directory"
|
||||
msgstr ""
|
||||
|
||||
#: internal/logger/log.go:44
|
||||
msgid "ERROR"
|
||||
msgstr "ОШИБКА"
|
@ -22,8 +22,13 @@ package translations
|
||||
import (
|
||||
"context"
|
||||
"embed"
|
||||
"io/fs"
|
||||
"os"
|
||||
"path"
|
||||
"sync"
|
||||
|
||||
"github.com/jeandeaual/go-locale"
|
||||
"github.com/leonelquinteros/gotext"
|
||||
"go.elara.ws/logger"
|
||||
"go.elara.ws/translate"
|
||||
"golang.org/x/text/language"
|
||||
@ -56,3 +61,25 @@ func Translator(ctx context.Context) *translate.Translator {
|
||||
func NewLogger(ctx context.Context, l logger.Logger, lang language.Tag) *translate.TranslatedLogger {
|
||||
return translate.NewLogger(l, *Translator(ctx), lang)
|
||||
}
|
||||
|
||||
//go:embed po
|
||||
var poFS embed.FS
|
||||
|
||||
func Setup() {
|
||||
userLanguage, err := locale.GetLanguage()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
_, err = fs.Stat(poFS, path.Join("po", userLanguage))
|
||||
if err != nil {
|
||||
if os.IsNotExist(err) {
|
||||
return
|
||||
}
|
||||
panic(err)
|
||||
}
|
||||
|
||||
loc := gotext.NewLocaleFSWithPath(userLanguage, &poFS, "po")
|
||||
loc.SetDomain("default")
|
||||
gotext.SetLocales([]*gotext.Locale{loc})
|
||||
}
|
||||
|
Reference in New Issue
Block a user