[agent/codex:gpt-5.4-mini] Read ~/spec/code/core/go/i18n/RFC.md fully. Find features de... #191

Merged
Virgil merged 1 commit from agent/read---spec-code-core-go-i18n-rfc-md-ful into dev 2026-04-02 09:53:03 +00:00
4 changed files with 114 additions and 103 deletions

View file

@ -2,9 +2,7 @@ package i18n
// SetDebug enables or disables debug mode on the default service.
func SetDebug(enabled bool) {
if svc := Default(); svc != nil {
svc.SetDebug(enabled)
}
withDefaultService(func(svc *Service) { svc.SetDebug(enabled) })
}
func (s *Service) SetDebug(enabled bool) {

17
default_service.go Normal file
View file

@ -0,0 +1,17 @@
package i18n
// withDefaultService runs fn when the default service is available.
func withDefaultService(fn func(*Service)) {
if svc := Default(); svc != nil {
fn(svc)
}
}
// defaultServiceValue returns the value produced by fn when the default
// service exists, or fallback otherwise.
func defaultServiceValue[T any](fallback T, fn func(*Service) T) T {
if svc := Default(); svc != nil {
return fn(svc)
}
return fallback
}

152
i18n.go
View file

@ -12,34 +12,34 @@ import (
// T translates a message using the default service.
//
// Example:
// i18n.T("greeting")
//
// i18n.T("greeting")
func T(messageID string, args ...any) string {
if svc := Default(); svc != nil {
return defaultServiceValue(messageID, func(svc *Service) string {
return svc.T(messageID, args...)
}
return messageID
})
}
// Translate translates a message using the default service and returns a Core result.
//
// Example:
// result := i18n.Translate("greeting")
//
// result := i18n.Translate("greeting")
func Translate(messageID string, args ...any) core.Result {
if svc := Default(); svc != nil {
return defaultServiceValue(core.Result{Value: messageID, OK: false}, func(svc *Service) core.Result {
return svc.Translate(messageID, args...)
}
return core.Result{Value: messageID, OK: false}
})
}
// Raw translates without i18n.* namespace magic.
//
// Example:
// i18n.Raw("prompt.yes")
//
// i18n.Raw("prompt.yes")
func Raw(messageID string, args ...any) string {
if svc := Default(); svc != nil {
return defaultServiceValue(messageID, func(svc *Service) string {
return svc.Raw(messageID, args...)
}
return messageID
})
}
// ErrServiceNotInitialised is returned when the service is not initialised.
@ -51,103 +51,100 @@ var ErrServiceNotInitialized = ErrServiceNotInitialised
// SetLanguage sets the language for the default service.
//
// Example:
// _ = i18n.SetLanguage("fr")
//
// _ = i18n.SetLanguage("fr")
func SetLanguage(lang string) error {
svc := Default()
if svc == nil {
return ErrServiceNotInitialised
}
return svc.SetLanguage(lang)
return defaultServiceValue(ErrServiceNotInitialised, func(svc *Service) error {
return svc.SetLanguage(lang)
})
}
// CurrentLanguage returns the current language code.
//
// Example:
// lang := i18n.CurrentLanguage()
//
// lang := i18n.CurrentLanguage()
func CurrentLanguage() string {
if svc := Default(); svc != nil {
return defaultServiceValue("en", func(svc *Service) string {
return svc.Language()
}
return "en"
})
}
// AvailableLanguages returns the loaded language tags on the default service.
//
// Example:
// langs := i18n.AvailableLanguages()
//
// langs := i18n.AvailableLanguages()
func AvailableLanguages() []string {
if svc := Default(); svc != nil {
return defaultServiceValue([]string(nil), func(svc *Service) []string {
langs := svc.AvailableLanguages()
if len(langs) == 0 {
return nil
}
return append([]string(nil), langs...)
}
return nil
})
}
// SetMode sets the translation mode for the default service.
//
// Example:
// i18n.SetMode(i18n.ModeCollect)
//
// i18n.SetMode(i18n.ModeCollect)
func SetMode(m Mode) {
if svc := Default(); svc != nil {
svc.SetMode(m)
}
withDefaultService(func(svc *Service) { svc.SetMode(m) })
}
// SetFallback sets the fallback language for the default service.
//
// Example:
// i18n.SetFallback("en")
//
// i18n.SetFallback("en")
func SetFallback(lang string) {
if svc := Default(); svc != nil {
svc.SetFallback(lang)
}
withDefaultService(func(svc *Service) { svc.SetFallback(lang) })
}
// CurrentMode returns the current translation mode.
//
// Example:
// mode := i18n.CurrentMode()
//
// mode := i18n.CurrentMode()
func CurrentMode() Mode {
if svc := Default(); svc != nil {
return defaultServiceValue(ModeNormal, func(svc *Service) Mode {
return svc.Mode()
}
return ModeNormal
})
}
// CurrentFallback returns the current fallback language.
//
// Example:
// fallback := i18n.CurrentFallback()
//
// fallback := i18n.CurrentFallback()
func CurrentFallback() string {
if svc := Default(); svc != nil {
return defaultServiceValue("en", func(svc *Service) string {
return svc.Fallback()
}
return "en"
})
}
// CurrentFormality returns the current default formality.
//
// Example:
// formality := i18n.CurrentFormality()
//
// formality := i18n.CurrentFormality()
func CurrentFormality() Formality {
if svc := Default(); svc != nil {
return defaultServiceValue(FormalityNeutral, func(svc *Service) Formality {
return svc.Formality()
}
return FormalityNeutral
})
}
// CurrentDebug reports whether debug mode is enabled on the default service.
//
// Example:
// debug := i18n.CurrentDebug()
//
// debug := i18n.CurrentDebug()
func CurrentDebug() bool {
if svc := Default(); svc != nil {
return defaultServiceValue(false, func(svc *Service) bool {
return svc.Debug()
}
return false
})
}
// N formats a value using the i18n.numeric.* namespace.
@ -167,10 +164,11 @@ func N(format string, value any, args ...any) string {
// Prompt translates a prompt key from the prompt namespace.
//
// Example:
// i18n.Prompt("confirm")
//
// Prompt("yes") // "y"
// Prompt("confirm") // "Are you sure?"
// i18n.Prompt("confirm")
//
// Prompt("yes") // "y"
// Prompt("confirm") // "Are you sure?"
func Prompt(key string) string {
key = normalizeLookupKey(key)
if key == "" {
@ -182,9 +180,10 @@ func Prompt(key string) string {
// Lang translates a language label from the lang namespace.
//
// Example:
// i18n.Lang("de")
//
// Lang("de") // "German"
// i18n.Lang("de")
//
// Lang("de") // "German"
func Lang(key string) string {
key = normalizeLookupKey(key)
if key == "" {
@ -210,27 +209,26 @@ func normalizeLookupKey(key string) string {
// AddHandler appends one or more handlers to the default service's handler chain.
//
// Example:
// i18n.AddHandler(MyHandler{})
//
// i18n.AddHandler(MyHandler{})
func AddHandler(handlers ...KeyHandler) {
if svc := Default(); svc != nil {
svc.AddHandler(handlers...)
}
withDefaultService(func(svc *Service) { svc.AddHandler(handlers...) })
}
// SetHandlers replaces the default service's handler chain.
//
// Example:
// i18n.SetHandlers(i18n.LabelHandler{}, i18n.ProgressHandler{})
//
// i18n.SetHandlers(i18n.LabelHandler{}, i18n.ProgressHandler{})
func SetHandlers(handlers ...KeyHandler) {
if svc := Default(); svc != nil {
svc.SetHandlers(handlers...)
}
withDefaultService(func(svc *Service) { svc.SetHandlers(handlers...) })
}
// LoadFS loads additional translations from an fs.FS into the default service.
//
// Example:
// i18n.LoadFS(os.DirFS("."), "locales")
//
// i18n.LoadFS(os.DirFS("."), "locales")
//
// Call this from init() in packages that ship their own locale files:
//
@ -239,42 +237,40 @@ func SetHandlers(handlers ...KeyHandler) {
//
// func init() { i18n.LoadFS(localeFS, "locales") }
func LoadFS(fsys fs.FS, dir string) {
if svc := Default(); svc != nil {
withDefaultService(func(svc *Service) {
if err := svc.LoadFS(fsys, dir); err != nil {
log.Error("i18n: LoadFS failed", "dir", dir, "err", err)
}
}
})
}
// PrependHandler inserts one or more handlers at the start of the default service's handler chain.
//
// Example:
// i18n.PrependHandler(MyHandler{})
//
// i18n.PrependHandler(MyHandler{})
func PrependHandler(handlers ...KeyHandler) {
if svc := Default(); svc != nil {
svc.PrependHandler(handlers...)
}
withDefaultService(func(svc *Service) { svc.PrependHandler(handlers...) })
}
// CurrentHandlers returns a copy of the default service's handler chain.
//
// Example:
// handlers := i18n.CurrentHandlers()
//
// handlers := i18n.CurrentHandlers()
func CurrentHandlers() []KeyHandler {
if svc := Default(); svc != nil {
return defaultServiceValue([]KeyHandler(nil), func(svc *Service) []KeyHandler {
return svc.Handlers()
}
return nil
})
}
// ClearHandlers removes all handlers from the default service.
//
// Example:
// i18n.ClearHandlers()
//
// i18n.ClearHandlers()
func ClearHandlers() {
if svc := Default(); svc != nil {
svc.ClearHandlers()
}
withDefaultService(func(svc *Service) { svc.ClearHandlers() })
}
func executeIntentTemplate(tmplStr string, data templateData) string {

View file

@ -70,49 +70,48 @@ func IsRTLLanguage(lang string) bool {
// SetFormality sets the default formality level on the default service.
//
// Example:
// i18n.SetFormality(i18n.FormalityFormal)
//
// i18n.SetFormality(i18n.FormalityFormal)
func SetFormality(f Formality) {
if svc := Default(); svc != nil {
svc.SetFormality(f)
}
withDefaultService(func(svc *Service) { svc.SetFormality(f) })
}
// SetLocation sets the default location context on the default service.
//
// Example:
// i18n.SetLocation("workspace")
//
// i18n.SetLocation("workspace")
func SetLocation(location string) {
if svc := Default(); svc != nil {
svc.SetLocation(location)
}
withDefaultService(func(svc *Service) { svc.SetLocation(location) })
}
// CurrentLocation returns the current default location context.
//
// Example:
// location := i18n.CurrentLocation()
//
// location := i18n.CurrentLocation()
func CurrentLocation() string {
if svc := Default(); svc != nil {
return defaultServiceValue("", func(svc *Service) string {
return svc.Location()
}
return ""
})
}
// Direction returns the text direction for the current language.
//
// Example:
// dir := i18n.Direction()
//
// dir := i18n.Direction()
func Direction() TextDirection {
if svc := Default(); svc != nil {
return defaultServiceValue(DirLTR, func(svc *Service) TextDirection {
return svc.Direction()
}
return DirLTR
})
}
// CurrentDirection returns the current default text direction.
//
// Example:
// dir := i18n.CurrentDirection()
//
// dir := i18n.CurrentDirection()
func CurrentDirection() TextDirection {
return Direction()
}
@ -120,18 +119,19 @@ func CurrentDirection() TextDirection {
// IsRTL returns true if the current language uses right-to-left text.
//
// Example:
// rtl := i18n.IsRTL()
//
// rtl := i18n.IsRTL()
func IsRTL() bool { return Direction() == DirRTL }
// CurrentPluralCategory returns the plural category for the current default language.
//
// Example:
// cat := i18n.CurrentPluralCategory(2)
//
// cat := i18n.CurrentPluralCategory(2)
func CurrentPluralCategory(n int) PluralCategory {
if svc := Default(); svc != nil {
return defaultServiceValue(GetPluralCategory("en", n), func(svc *Service) PluralCategory {
return svc.PluralCategory(n)
}
return GetPluralCategory("en", n)
})
}
func detectLanguage(supported []language.Tag) string {