feat(i18n): add service state snapshot aliases
Co-Authored-By: Virgil <virgil@lethean.io>
This commit is contained in:
parent
158f71443c
commit
9d4af96d3d
6 changed files with 147 additions and 0 deletions
|
|
@ -268,6 +268,19 @@ func (s *CoreService) CurrentDebug() bool {
|
|||
return s.Debug()
|
||||
}
|
||||
|
||||
// State returns a copy-safe snapshot of the wrapped service configuration.
|
||||
func (s *CoreService) State() ServiceState {
|
||||
if s == nil || s.svc == nil {
|
||||
return State()
|
||||
}
|
||||
return s.svc.State()
|
||||
}
|
||||
|
||||
// CurrentState is a more explicit alias for State.
|
||||
func (s *CoreService) CurrentState() ServiceState {
|
||||
return s.State()
|
||||
}
|
||||
|
||||
// AddHandler appends handlers to the wrapped service's chain.
|
||||
func (s *CoreService) AddHandler(handlers ...KeyHandler) {
|
||||
s.svc.AddHandler(handlers...)
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ The API exposes `Current*` aliases for the most common service getters so call s
|
|||
- `CurrentDebug()`
|
||||
- `CurrentHandlers()`
|
||||
- `CurrentPrompt()`
|
||||
- `State()` / `CurrentState()` snapshot of the full service configuration
|
||||
|
||||
### Options
|
||||
|
||||
|
|
|
|||
22
i18n.go
22
i18n.go
|
|
@ -178,6 +178,28 @@ func CurrentDebug() bool {
|
|||
return Debug()
|
||||
}
|
||||
|
||||
// State returns a copy-safe snapshot of the default service configuration.
|
||||
func State() ServiceState {
|
||||
return defaultServiceValue(ServiceState{
|
||||
Language: "en",
|
||||
AvailableLanguages: []string{},
|
||||
Mode: ModeNormal,
|
||||
Fallback: "en",
|
||||
Formality: FormalityNeutral,
|
||||
Direction: DirLTR,
|
||||
IsRTL: false,
|
||||
Debug: false,
|
||||
Handlers: []KeyHandler{},
|
||||
}, func(svc *Service) ServiceState {
|
||||
return svc.State()
|
||||
})
|
||||
}
|
||||
|
||||
// CurrentState is a more explicit alias for State.
|
||||
func CurrentState() ServiceState {
|
||||
return State()
|
||||
}
|
||||
|
||||
// Debug reports whether debug mode is enabled on the default service.
|
||||
//
|
||||
// Example:
|
||||
|
|
|
|||
27
i18n_test.go
27
i18n_test.go
|
|
@ -234,6 +234,33 @@ func TestDebug_Good(t *testing.T) {
|
|||
assert.True(t, Debug())
|
||||
}
|
||||
|
||||
func TestCurrentState_Good(t *testing.T) {
|
||||
svc, err := NewWithLoader(messageBaseFallbackLoader{})
|
||||
require.NoError(t, err)
|
||||
prev := Default()
|
||||
SetDefault(svc)
|
||||
t.Cleanup(func() {
|
||||
SetDefault(prev)
|
||||
})
|
||||
|
||||
state := CurrentState()
|
||||
assert.Equal(t, svc.Language(), state.Language)
|
||||
assert.Equal(t, svc.AvailableLanguages(), state.AvailableLanguages)
|
||||
assert.Equal(t, svc.Mode(), state.Mode)
|
||||
assert.Equal(t, svc.Fallback(), state.Fallback)
|
||||
assert.Equal(t, svc.Formality(), state.Formality)
|
||||
assert.Equal(t, svc.Location(), state.Location)
|
||||
assert.Equal(t, svc.Direction(), state.Direction)
|
||||
assert.Equal(t, svc.IsRTL(), state.IsRTL)
|
||||
assert.Equal(t, svc.Debug(), state.Debug)
|
||||
assert.Len(t, state.Handlers, len(svc.Handlers()))
|
||||
|
||||
state.AvailableLanguages[0] = "zz"
|
||||
assert.NotEqual(t, "zz", CurrentState().AvailableLanguages[0])
|
||||
state.Handlers[0] = nil
|
||||
assert.NotNil(t, CurrentState().Handlers[0])
|
||||
}
|
||||
|
||||
// --- SetMode / CurrentMode ---
|
||||
|
||||
func TestSetMode_Good(t *testing.T) {
|
||||
|
|
|
|||
|
|
@ -190,6 +190,9 @@ func TestServiceCurrentStateAliases(t *testing.T) {
|
|||
if got, want := svc.CurrentHandlers(), svc.Handlers(); len(got) != len(want) {
|
||||
t.Fatalf("CurrentHandlers() len = %d, want %d", len(got), len(want))
|
||||
}
|
||||
if got, want := svc.CurrentState(), svc.State(); len(got.AvailableLanguages) != len(want.AvailableLanguages) || len(got.Handlers) != len(want.Handlers) {
|
||||
t.Fatalf("CurrentState() = %+v, want %+v", got, want)
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceCurrentStateAliasesReturnCopies(t *testing.T) {
|
||||
|
|
@ -215,6 +218,22 @@ func TestServiceCurrentStateAliasesReturnCopies(t *testing.T) {
|
|||
if svc.CurrentHandlers()[0] == nil {
|
||||
t.Fatal("CurrentHandlers() returned a shared slice; first handler mutated to nil")
|
||||
}
|
||||
|
||||
state := svc.CurrentState()
|
||||
if len(state.AvailableLanguages) == 0 {
|
||||
t.Fatal("CurrentState() returned no available languages")
|
||||
}
|
||||
if len(state.Handlers) == 0 {
|
||||
t.Fatal("CurrentState() returned no handlers")
|
||||
}
|
||||
state.AvailableLanguages[0] = "zz"
|
||||
if got := svc.CurrentState().AvailableLanguages[0]; got == "zz" {
|
||||
t.Fatalf("CurrentState() returned a shared available languages slice; first element mutated to %q", got)
|
||||
}
|
||||
state.Handlers[0] = nil
|
||||
if svc.CurrentState().Handlers[0] == nil {
|
||||
t.Fatal("CurrentState() returned a shared handlers slice; first handler mutated to nil")
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceAvailableLanguagesSorted(t *testing.T) {
|
||||
|
|
|
|||
65
state.go
Normal file
65
state.go
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
package i18n
|
||||
|
||||
// ServiceState captures the current configuration of a service in one
|
||||
// copy-safe snapshot.
|
||||
type ServiceState struct {
|
||||
Language string
|
||||
AvailableLanguages []string
|
||||
Mode Mode
|
||||
Fallback string
|
||||
Formality Formality
|
||||
Location string
|
||||
Direction TextDirection
|
||||
IsRTL bool
|
||||
Debug bool
|
||||
Handlers []KeyHandler
|
||||
}
|
||||
|
||||
func (s *Service) State() ServiceState {
|
||||
if s == nil {
|
||||
return ServiceState{
|
||||
Language: "en",
|
||||
AvailableLanguages: []string{},
|
||||
Mode: ModeNormal,
|
||||
Fallback: "en",
|
||||
Formality: FormalityNeutral,
|
||||
Direction: DirLTR,
|
||||
IsRTL: false,
|
||||
Debug: false,
|
||||
Handlers: []KeyHandler{},
|
||||
}
|
||||
}
|
||||
s.mu.RLock()
|
||||
defer s.mu.RUnlock()
|
||||
|
||||
langs := make([]string, len(s.availableLangs))
|
||||
for i, tag := range s.availableLangs {
|
||||
langs[i] = tag.String()
|
||||
}
|
||||
|
||||
handlers := make([]KeyHandler, len(s.handlers))
|
||||
copy(handlers, s.handlers)
|
||||
|
||||
dir := DirLTR
|
||||
if IsRTLLanguage(s.currentLang) {
|
||||
dir = DirRTL
|
||||
}
|
||||
|
||||
return ServiceState{
|
||||
Language: s.currentLang,
|
||||
AvailableLanguages: langs,
|
||||
Mode: s.mode,
|
||||
Fallback: s.fallbackLang,
|
||||
Formality: s.formality,
|
||||
Location: s.location,
|
||||
Direction: dir,
|
||||
IsRTL: dir == DirRTL,
|
||||
Debug: s.debug,
|
||||
Handlers: handlers,
|
||||
}
|
||||
}
|
||||
|
||||
// CurrentState is a more explicit alias for State.
|
||||
func (s *Service) CurrentState() ServiceState {
|
||||
return s.State()
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue