[agent/codex:gpt-5.4-mini] Read ~/spec/code/core/go/i18n/RFC.md fully. Find features de... #189
3 changed files with 114 additions and 0 deletions
60
i18n.go
60
i18n.go
|
|
@ -10,6 +10,9 @@ import (
|
|||
)
|
||||
|
||||
// T translates a message using the default service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.T("greeting")
|
||||
func T(messageID string, args ...any) string {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.T(messageID, args...)
|
||||
|
|
@ -18,6 +21,9 @@ func T(messageID string, args ...any) string {
|
|||
}
|
||||
|
||||
// Translate translates a message using the default service and returns a Core result.
|
||||
//
|
||||
// Example:
|
||||
// result := i18n.Translate("greeting")
|
||||
func Translate(messageID string, args ...any) core.Result {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Translate(messageID, args...)
|
||||
|
|
@ -26,6 +32,9 @@ func Translate(messageID string, args ...any) core.Result {
|
|||
}
|
||||
|
||||
// Raw translates without i18n.* namespace magic.
|
||||
//
|
||||
// Example:
|
||||
// i18n.Raw("prompt.yes")
|
||||
func Raw(messageID string, args ...any) string {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Raw(messageID, args...)
|
||||
|
|
@ -40,6 +49,9 @@ var ErrServiceNotInitialised = core.NewError("i18n: service not initialised")
|
|||
var ErrServiceNotInitialized = ErrServiceNotInitialised
|
||||
|
||||
// SetLanguage sets the language for the default service.
|
||||
//
|
||||
// Example:
|
||||
// _ = i18n.SetLanguage("fr")
|
||||
func SetLanguage(lang string) error {
|
||||
svc := Default()
|
||||
if svc == nil {
|
||||
|
|
@ -49,6 +61,9 @@ func SetLanguage(lang string) error {
|
|||
}
|
||||
|
||||
// CurrentLanguage returns the current language code.
|
||||
//
|
||||
// Example:
|
||||
// lang := i18n.CurrentLanguage()
|
||||
func CurrentLanguage() string {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Language()
|
||||
|
|
@ -57,6 +72,9 @@ func CurrentLanguage() string {
|
|||
}
|
||||
|
||||
// AvailableLanguages returns the loaded language tags on the default service.
|
||||
//
|
||||
// Example:
|
||||
// langs := i18n.AvailableLanguages()
|
||||
func AvailableLanguages() []string {
|
||||
if svc := Default(); svc != nil {
|
||||
langs := svc.AvailableLanguages()
|
||||
|
|
@ -69,6 +87,9 @@ func AvailableLanguages() []string {
|
|||
}
|
||||
|
||||
// SetMode sets the translation mode for the default service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.SetMode(i18n.ModeCollect)
|
||||
func SetMode(m Mode) {
|
||||
if svc := Default(); svc != nil {
|
||||
svc.SetMode(m)
|
||||
|
|
@ -76,6 +97,9 @@ func SetMode(m Mode) {
|
|||
}
|
||||
|
||||
// SetFallback sets the fallback language for the default service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.SetFallback("en")
|
||||
func SetFallback(lang string) {
|
||||
if svc := Default(); svc != nil {
|
||||
svc.SetFallback(lang)
|
||||
|
|
@ -83,6 +107,9 @@ func SetFallback(lang string) {
|
|||
}
|
||||
|
||||
// CurrentMode returns the current translation mode.
|
||||
//
|
||||
// Example:
|
||||
// mode := i18n.CurrentMode()
|
||||
func CurrentMode() Mode {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Mode()
|
||||
|
|
@ -91,6 +118,9 @@ func CurrentMode() Mode {
|
|||
}
|
||||
|
||||
// CurrentFallback returns the current fallback language.
|
||||
//
|
||||
// Example:
|
||||
// fallback := i18n.CurrentFallback()
|
||||
func CurrentFallback() string {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Fallback()
|
||||
|
|
@ -99,6 +129,9 @@ func CurrentFallback() string {
|
|||
}
|
||||
|
||||
// CurrentFormality returns the current default formality.
|
||||
//
|
||||
// Example:
|
||||
// formality := i18n.CurrentFormality()
|
||||
func CurrentFormality() Formality {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Formality()
|
||||
|
|
@ -107,6 +140,9 @@ func CurrentFormality() Formality {
|
|||
}
|
||||
|
||||
// CurrentDebug reports whether debug mode is enabled on the default service.
|
||||
//
|
||||
// Example:
|
||||
// debug := i18n.CurrentDebug()
|
||||
func CurrentDebug() bool {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Debug()
|
||||
|
|
@ -130,6 +166,9 @@ 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?"
|
||||
func Prompt(key string) string {
|
||||
|
|
@ -142,6 +181,9 @@ func Prompt(key string) string {
|
|||
|
||||
// Lang translates a language label from the lang namespace.
|
||||
//
|
||||
// Example:
|
||||
// i18n.Lang("de")
|
||||
//
|
||||
// Lang("de") // "German"
|
||||
func Lang(key string) string {
|
||||
key = normalizeLookupKey(key)
|
||||
|
|
@ -166,6 +208,9 @@ func normalizeLookupKey(key string) string {
|
|||
}
|
||||
|
||||
// AddHandler appends one or more handlers to the default service's handler chain.
|
||||
//
|
||||
// Example:
|
||||
// i18n.AddHandler(MyHandler{})
|
||||
func AddHandler(handlers ...KeyHandler) {
|
||||
if svc := Default(); svc != nil {
|
||||
svc.AddHandler(handlers...)
|
||||
|
|
@ -173,6 +218,9 @@ func AddHandler(handlers ...KeyHandler) {
|
|||
}
|
||||
|
||||
// SetHandlers replaces the default service's handler chain.
|
||||
//
|
||||
// Example:
|
||||
// i18n.SetHandlers(i18n.LabelHandler{}, i18n.ProgressHandler{})
|
||||
func SetHandlers(handlers ...KeyHandler) {
|
||||
if svc := Default(); svc != nil {
|
||||
svc.SetHandlers(handlers...)
|
||||
|
|
@ -181,6 +229,9 @@ func SetHandlers(handlers ...KeyHandler) {
|
|||
|
||||
// LoadFS loads additional translations from an fs.FS into the default service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.LoadFS(os.DirFS("."), "locales")
|
||||
//
|
||||
// Call this from init() in packages that ship their own locale files:
|
||||
//
|
||||
// //go:embed locales/*.json
|
||||
|
|
@ -196,6 +247,9 @@ func LoadFS(fsys fs.FS, dir string) {
|
|||
}
|
||||
|
||||
// PrependHandler inserts one or more handlers at the start of the default service's handler chain.
|
||||
//
|
||||
// Example:
|
||||
// i18n.PrependHandler(MyHandler{})
|
||||
func PrependHandler(handlers ...KeyHandler) {
|
||||
if svc := Default(); svc != nil {
|
||||
svc.PrependHandler(handlers...)
|
||||
|
|
@ -203,6 +257,9 @@ func PrependHandler(handlers ...KeyHandler) {
|
|||
}
|
||||
|
||||
// CurrentHandlers returns a copy of the default service's handler chain.
|
||||
//
|
||||
// Example:
|
||||
// handlers := i18n.CurrentHandlers()
|
||||
func CurrentHandlers() []KeyHandler {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Handlers()
|
||||
|
|
@ -211,6 +268,9 @@ func CurrentHandlers() []KeyHandler {
|
|||
}
|
||||
|
||||
// ClearHandlers removes all handlers from the default service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.ClearHandlers()
|
||||
func ClearHandlers() {
|
||||
if svc := Default(); svc != nil {
|
||||
svc.ClearHandlers()
|
||||
|
|
|
|||
21
localise.go
21
localise.go
|
|
@ -68,6 +68,9 @@ func IsRTLLanguage(lang string) bool {
|
|||
}
|
||||
|
||||
// SetFormality sets the default formality level on the default service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.SetFormality(i18n.FormalityFormal)
|
||||
func SetFormality(f Formality) {
|
||||
if svc := Default(); svc != nil {
|
||||
svc.SetFormality(f)
|
||||
|
|
@ -75,6 +78,9 @@ func SetFormality(f Formality) {
|
|||
}
|
||||
|
||||
// SetLocation sets the default location context on the default service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.SetLocation("workspace")
|
||||
func SetLocation(location string) {
|
||||
if svc := Default(); svc != nil {
|
||||
svc.SetLocation(location)
|
||||
|
|
@ -82,6 +88,9 @@ func SetLocation(location string) {
|
|||
}
|
||||
|
||||
// CurrentLocation returns the current default location context.
|
||||
//
|
||||
// Example:
|
||||
// location := i18n.CurrentLocation()
|
||||
func CurrentLocation() string {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Location()
|
||||
|
|
@ -90,6 +99,9 @@ func CurrentLocation() string {
|
|||
}
|
||||
|
||||
// Direction returns the text direction for the current language.
|
||||
//
|
||||
// Example:
|
||||
// dir := i18n.Direction()
|
||||
func Direction() TextDirection {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.Direction()
|
||||
|
|
@ -98,14 +110,23 @@ func Direction() TextDirection {
|
|||
}
|
||||
|
||||
// CurrentDirection returns the current default text direction.
|
||||
//
|
||||
// Example:
|
||||
// dir := i18n.CurrentDirection()
|
||||
func CurrentDirection() TextDirection {
|
||||
return Direction()
|
||||
}
|
||||
|
||||
// IsRTL returns true if the current language uses right-to-left text.
|
||||
//
|
||||
// Example:
|
||||
// rtl := i18n.IsRTL()
|
||||
func IsRTL() bool { return Direction() == DirRTL }
|
||||
|
||||
// CurrentPluralCategory returns the plural category for the current default language.
|
||||
//
|
||||
// Example:
|
||||
// cat := i18n.CurrentPluralCategory(2)
|
||||
func CurrentPluralCategory(n int) PluralCategory {
|
||||
if svc := Default(); svc != nil {
|
||||
return svc.PluralCategory(n)
|
||||
|
|
|
|||
33
service.go
33
service.go
|
|
@ -103,12 +103,18 @@ var _ Translator = (*Service)(nil)
|
|||
var _ core.Translator = (*Service)(nil)
|
||||
|
||||
// New creates a new i18n service with embedded locales.
|
||||
//
|
||||
// Example:
|
||||
// svc, err := i18n.New(i18n.WithLanguage("en"))
|
||||
func New(opts ...Option) (*Service, error) {
|
||||
return NewWithLoader(NewFSLoader(localeFS, "locales"), opts...)
|
||||
}
|
||||
|
||||
// NewService creates a new i18n service with embedded locales.
|
||||
//
|
||||
// Example:
|
||||
// svc, err := i18n.NewService(i18n.WithFallback("en"))
|
||||
//
|
||||
// This is a named alias for New that keeps the constructor intent explicit
|
||||
// for callers that prefer service-oriented naming.
|
||||
func NewService(opts ...Option) (*Service, error) {
|
||||
|
|
@ -116,16 +122,25 @@ func NewService(opts ...Option) (*Service, error) {
|
|||
}
|
||||
|
||||
// NewWithFS creates a new i18n service loading locales from the given filesystem.
|
||||
//
|
||||
// Example:
|
||||
// svc, err := i18n.NewWithFS(os.DirFS("."), "locales")
|
||||
func NewWithFS(fsys fs.FS, dir string, opts ...Option) (*Service, error) {
|
||||
return NewWithLoader(NewFSLoader(fsys, dir), opts...)
|
||||
}
|
||||
|
||||
// NewServiceWithFS creates a new i18n service loading locales from the given filesystem.
|
||||
//
|
||||
// Example:
|
||||
// svc, err := i18n.NewServiceWithFS(os.DirFS("."), "locales")
|
||||
func NewServiceWithFS(fsys fs.FS, dir string, opts ...Option) (*Service, error) {
|
||||
return NewWithFS(fsys, dir, opts...)
|
||||
}
|
||||
|
||||
// NewWithLoader creates a new i18n service with a custom loader.
|
||||
//
|
||||
// Example:
|
||||
// svc, err := i18n.NewWithLoader(loader)
|
||||
func NewWithLoader(loader Loader, opts ...Option) (*Service, error) {
|
||||
if loader == nil {
|
||||
return nil, log.E("NewWithLoader", "nil loader", nil)
|
||||
|
|
@ -199,11 +214,17 @@ func NewWithLoader(loader Loader, opts ...Option) (*Service, error) {
|
|||
}
|
||||
|
||||
// NewServiceWithLoader creates a new i18n service with a custom loader.
|
||||
//
|
||||
// Example:
|
||||
// svc, err := i18n.NewServiceWithLoader(loader)
|
||||
func NewServiceWithLoader(loader Loader, opts ...Option) (*Service, error) {
|
||||
return NewWithLoader(loader, opts...)
|
||||
}
|
||||
|
||||
// Init initialises the default global service if none has been set via SetDefault.
|
||||
//
|
||||
// Example:
|
||||
// if err := i18n.Init(); err != nil { return err }
|
||||
func Init() error {
|
||||
if defaultService.Load() != nil {
|
||||
return nil
|
||||
|
|
@ -232,6 +253,9 @@ func Init() error {
|
|||
}
|
||||
|
||||
// Default returns the global i18n service, initialising if needed.
|
||||
//
|
||||
// Example:
|
||||
// svc := i18n.Default()
|
||||
// Returns nil if initialisation fails (error is logged).
|
||||
func Default() *Service {
|
||||
if svc := defaultService.Load(); svc != nil {
|
||||
|
|
@ -244,6 +268,9 @@ func Default() *Service {
|
|||
}
|
||||
|
||||
// SetDefault sets the global i18n service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.SetDefault(svc)
|
||||
// Passing nil clears the default service.
|
||||
func SetDefault(s *Service) {
|
||||
defaultService.Store(s)
|
||||
|
|
@ -259,6 +286,9 @@ func SetDefault(s *Service) {
|
|||
}
|
||||
|
||||
// AddLoader loads translations from a Loader into the default service.
|
||||
//
|
||||
// Example:
|
||||
// i18n.AddLoader(loader)
|
||||
// Call this from init() in packages that ship their own locale files:
|
||||
//
|
||||
// //go:embed *.json
|
||||
|
|
@ -1008,6 +1038,9 @@ func translateOK(messageID, value string) bool {
|
|||
}
|
||||
|
||||
// LoadFS loads additional locale files from a filesystem.
|
||||
//
|
||||
// Example:
|
||||
// _ = svc.LoadFS(os.DirFS("."), "locales")
|
||||
// Deprecated: Use AddLoader(NewFSLoader(fsys, dir)) instead for proper grammar handling.
|
||||
func (s *Service) LoadFS(fsys fs.FS, dir string) error {
|
||||
loader := NewFSLoader(fsys, dir)
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue