pkg/i18n/i18n.go (90 lines of code) (raw):

// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. package i18n import ( "fmt" "os" "strings" "path" "github.com/leonelquinteros/gotext" "github.com/pkg/errors" ) func loadSystemLanguage() string { language := os.Getenv("LANG") if language == "" { return defaultLanguage } // Posix locale name usually has the ll_CC.encoding syntax. parts := strings.Split(language, ".") if len(parts) == 0 { return defaultLanguage } if _, ok := supportedTranslations[parts[0]]; ok { return parts[0] } return defaultLanguage } // LoadTranslations loads translation files and sets the locale to // the system locale. It should be called by the main program. func LoadTranslations() (*gotext.Locale, error) { lang := loadSystemLanguage() SetLanguage(lang) dir := path.Join(defaultLocalDir, lang, defaultMessageDir) translationFiles := []string{ path.Join(dir, fmt.Sprintf("%s.mo", defaultDomain)), path.Join(dir, fmt.Sprintf("%s.po", defaultDomain)), } if _, err := os.Stat(dir); os.IsNotExist(err) { if err := os.MkdirAll(dir, 0700); err != nil { return nil, err } } for _, file := range translationFiles { if _, err := os.Stat(file); os.IsNotExist(err) { data, err := Asset(file) if err != nil { return nil, err } err = os.WriteFile(file, data, 0600) if err != nil { return nil, err } } } locale := gotext.NewLocale(defaultLocalDir, lang) Initialize(locale) return locale, nil } // Initialize is the translation initialization function shared by the main program and package. func Initialize(locale *gotext.Locale) error { if locale == nil { return errors.New("Initialize expected locale but got nil") } locale.AddDomain(defaultDomain) return nil } // SetLanguage sets the program's current locale. If the language is not // supported, then the default locale is used. func SetLanguage(language string) { if _, ok := supportedTranslations[language]; ok { gotext.SetLanguage(language) return } gotext.SetLanguage(defaultLanguage) } // GetLanguage queries the program's current locale. func GetLanguage() string { return gotext.GetLanguage() } // Translator is a wrapper over gotext's Locale and provides interface to // translate text string and produce translated error type Translator struct { Locale *gotext.Locale } // T translates a text string, based on GNU's gettext library. func (t *Translator) T(msgid string, vars ...interface{}) string { if t.Locale == nil { return fmt.Sprintf(msgid, vars...) } return t.Locale.GetD(defaultDomain, msgid, vars...) } // NT translates a text string into the appropriate plural form, based on GNU's gettext library. func (t *Translator) NT(msgid, msgidPlural string, n int, vars ...interface{}) string { if t.Locale == nil { return fmt.Sprintf(msgidPlural, vars...) } return t.Locale.GetND(defaultDomain, msgid, msgidPlural, n, vars...) } // Errorf produces an error with a translated error string. func (t *Translator) Errorf(msgid string, vars ...interface{}) error { return errors.New(t.T(msgid, vars...)) } // NErrorf produces an error with a translated error string in the appropriate plural form. func (t *Translator) NErrorf(msgid, msgidPlural string, n int, vars ...interface{}) error { return errors.New(t.NT(msgid, msgidPlural, n, vars...)) }