package i18n import ( "embed" "fmt" "strings" "github.com/nicksnyder/go-i18n/v2/i18n" "golang.org/x/text/language" "gopkg.in/yaml.v3" "git.wxccs.org/iceking2nd/winauth-go/internal/global" ) //go:embed locales/*.toml var localeFS embed.FS var ( bundle *i18n.Bundle localizer *i18n.Localizer ) // Init loads bundled locales and selects a localizer based on the requested // language tag. Pass an empty string to use the system default (currently // English). func Init(lang string) error { const fn = "internal.i18n.Init" bundle = i18n.NewBundle(language.English) bundle.RegisterUnmarshalFunc("toml", tomlUnmarshal) bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal) entries, err := localeFS.ReadDir("locales") if err != nil { return fmt.Errorf("read locales: %w", err) } for _, e := range entries { if e.IsDir() { continue } path := "locales/" + e.Name() if _, err := bundle.LoadMessageFileFS(localeFS, path); err != nil { global.Log.WithField("func", fn).WithError(err). WithField("file", path).Warn("failed to load locale") } } if strings.TrimSpace(lang) == "" { lang = "en" } localizer = i18n.NewLocalizer(bundle, lang, "en") global.Log.WithField("func", fn).WithField("lang", lang).Debug("i18n initialized") return nil } // T translates the given message id using the active localizer. If // translation fails (missing key or i18n not initialized), it returns the // id unchanged so the UI still renders something readable. func T(id string, args ...any) string { if localizer == nil { return id } cfg := &i18n.LocalizeConfig{MessageID: id} if len(args) > 0 { // args are formatted directly via fmt.Sprintf if the message // id contains %s/%d-style verbs. out, err := localizer.Localize(cfg) if err != nil { return fmt.Sprintf(id, args...) } return fmt.Sprintf(out, args...) } out, err := localizer.Localize(cfg) if err != nil { return id } return out } // SetLanguage switches the active language at runtime. func SetLanguage(lang string) { const fn = "internal.i18n.SetLanguage" localizer = i18n.NewLocalizer(bundle, lang, "en") global.Log.WithField("func", fn).WithField("lang", lang).Debug("language changed") }