feat: RegisterCommands accepts locale FS for automatic translation loading
Both WithCommands() and RegisterCommands() now accept an optional fs.FS for translations. The CLI collects them via RegisteredLocales() and the i18n service loads them on startup. Packages just pass their embed.FS — no i18n import needed: cli.RegisterCommands(AddDevCommands, locales.FS) Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
bf994fab17
commit
ee7e9d1abf
1 changed files with 33 additions and 9 deletions
|
|
@ -3,6 +3,7 @@ package cli
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"io/fs"
|
||||||
"iter"
|
"iter"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
|
@ -18,15 +19,24 @@ import (
|
||||||
// cli.WithCommands("config", config.AddConfigCommands),
|
// cli.WithCommands("config", config.AddConfigCommands),
|
||||||
// cli.WithCommands("doctor", doctor.AddDoctorCommands),
|
// cli.WithCommands("doctor", doctor.AddDoctorCommands),
|
||||||
// )
|
// )
|
||||||
func WithCommands(name string, register func(root *Command)) core.Option {
|
// WithCommands creates a framework Option that registers a command group.
|
||||||
|
// Optionally pass a locale fs.FS as the third argument to provide translations.
|
||||||
|
//
|
||||||
|
// cli.WithCommands("dev", dev.AddDevCommands, locales.FS)
|
||||||
|
func WithCommands(name string, register func(root *Command), localeFS ...fs.FS) core.Option {
|
||||||
return core.WithName("cmd."+name, func(c *core.Core) (any, error) {
|
return core.WithName("cmd."+name, func(c *core.Core) (any, error) {
|
||||||
return &commandService{core: c, register: register}, nil
|
svc := &commandService{core: c, register: register}
|
||||||
|
if len(localeFS) > 0 {
|
||||||
|
svc.localeFS = localeFS[0]
|
||||||
|
}
|
||||||
|
return svc, nil
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
type commandService struct {
|
type commandService struct {
|
||||||
core *core.Core
|
core *core.Core
|
||||||
register func(root *Command)
|
register func(root *Command)
|
||||||
|
localeFS fs.FS
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *commandService) OnStartup(_ context.Context) error {
|
func (s *commandService) OnStartup(_ context.Context) error {
|
||||||
|
|
@ -36,6 +46,11 @@ func (s *commandService) OnStartup(_ context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Locales implements core.LocaleProvider.
|
||||||
|
func (s *commandService) Locales() fs.FS {
|
||||||
|
return s.localeFS
|
||||||
|
}
|
||||||
|
|
||||||
// CommandRegistration is a function that adds commands to the root.
|
// CommandRegistration is a function that adds commands to the root.
|
||||||
type CommandRegistration func(root *cobra.Command)
|
type CommandRegistration func(root *cobra.Command)
|
||||||
|
|
||||||
|
|
@ -43,22 +58,24 @@ var (
|
||||||
registeredCommands []CommandRegistration
|
registeredCommands []CommandRegistration
|
||||||
registeredCommandsMu sync.Mutex
|
registeredCommandsMu sync.Mutex
|
||||||
commandsAttached bool
|
commandsAttached bool
|
||||||
|
registeredLocales []fs.FS
|
||||||
)
|
)
|
||||||
|
|
||||||
// RegisterCommands registers a function that adds commands to the CLI.
|
// RegisterCommands registers a function that adds commands to the CLI.
|
||||||
// Call this in your package's init() to register commands.
|
// Optionally pass a locale fs.FS to provide translations for the commands.
|
||||||
//
|
//
|
||||||
// func init() {
|
// func init() {
|
||||||
// cli.RegisterCommands(AddCommands)
|
// cli.RegisterCommands(AddCommands, locales.FS)
|
||||||
// }
|
// }
|
||||||
//
|
func RegisterCommands(fn CommandRegistration, localeFS ...fs.FS) {
|
||||||
// func AddCommands(root *cobra.Command) {
|
|
||||||
// root.AddCommand(myCmd)
|
|
||||||
// }
|
|
||||||
func RegisterCommands(fn CommandRegistration) {
|
|
||||||
registeredCommandsMu.Lock()
|
registeredCommandsMu.Lock()
|
||||||
defer registeredCommandsMu.Unlock()
|
defer registeredCommandsMu.Unlock()
|
||||||
registeredCommands = append(registeredCommands, fn)
|
registeredCommands = append(registeredCommands, fn)
|
||||||
|
for _, lfs := range localeFS {
|
||||||
|
if lfs != nil {
|
||||||
|
registeredLocales = append(registeredLocales, lfs)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If commands already attached (CLI already running), attach immediately
|
// If commands already attached (CLI already running), attach immediately
|
||||||
if commandsAttached && instance != nil && instance.root != nil {
|
if commandsAttached && instance != nil && instance.root != nil {
|
||||||
|
|
@ -66,6 +83,13 @@ func RegisterCommands(fn CommandRegistration) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// RegisteredLocales returns all locale filesystems registered by command packages.
|
||||||
|
func RegisteredLocales() []fs.FS {
|
||||||
|
registeredCommandsMu.Lock()
|
||||||
|
defer registeredCommandsMu.Unlock()
|
||||||
|
return registeredLocales
|
||||||
|
}
|
||||||
|
|
||||||
// RegisteredCommands returns an iterator over the registered command functions.
|
// RegisteredCommands returns an iterator over the registered command functions.
|
||||||
func RegisteredCommands() iter.Seq[CommandRegistration] {
|
func RegisteredCommands() iter.Seq[CommandRegistration] {
|
||||||
return func(yield func(CommandRegistration) bool) {
|
return func(yield func(CommandRegistration) bool) {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue