feat: auto-derive i18n keys from command names (Conclave pattern)
commandService.applyI18n() walks registered commands and sets
Short/Long from cmd.{name}.short/long keys automatically. Downstream
packages no longer need to call i18n.T() for command descriptions —
the CLI Conclave handles it via service name derivation.
This is the Conclave pattern: services inside a sealed core.New()
auto-discover each other's capabilities via the lifecycle hooks.
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
91de96994a
commit
0c1b74c637
1 changed files with 25 additions and 1 deletions
|
|
@ -25,7 +25,7 @@ import (
|
|||
// 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) {
|
||||
svc := &commandService{core: c, register: register}
|
||||
svc := &commandService{core: c, name: name, register: register}
|
||||
if len(localeFS) > 0 {
|
||||
svc.localeFS = localeFS[0]
|
||||
}
|
||||
|
|
@ -35,6 +35,7 @@ func WithCommands(name string, register func(root *Command), localeFS ...fs.FS)
|
|||
|
||||
type commandService struct {
|
||||
core *core.Core
|
||||
name string
|
||||
register func(root *Command)
|
||||
localeFS fs.FS
|
||||
}
|
||||
|
|
@ -42,10 +43,33 @@ type commandService struct {
|
|||
func (s *commandService) OnStartup(_ context.Context) error {
|
||||
if root, ok := s.core.App.(*cobra.Command); ok {
|
||||
s.register(root)
|
||||
// Auto-set Short/Long from i18n keys derived from command name.
|
||||
// The Conclave's i18n service has already loaded all translations
|
||||
// from sibling services' LocaleProvider before commands attach.
|
||||
s.applyI18n(root)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// applyI18n walks commands added by this service and sets Short/Long
|
||||
// from derived i18n keys if they're empty or still raw keys.
|
||||
func (s *commandService) applyI18n(root *cobra.Command) {
|
||||
for _, cmd := range root.Commands() {
|
||||
key := "cmd." + cmd.Name()
|
||||
// Only set if Short is empty or looks like a raw key (contains dots)
|
||||
if cmd.Short == "" || cmd.Short == key+".short" {
|
||||
if translated := T(key + ".short"); translated != key+".short" {
|
||||
cmd.Short = translated
|
||||
}
|
||||
}
|
||||
if cmd.Long == "" || cmd.Long == key+".long" {
|
||||
if translated := T(key + ".long"); translated != key+".long" {
|
||||
cmd.Long = translated
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Locales implements core.LocaleProvider.
|
||||
func (s *commandService) Locales() fs.FS {
|
||||
return s.localeFS
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue