106 lines
2.1 KiB
Go
106 lines
2.1 KiB
Go
|
package i18n
|
||
|
|
||
|
import (
|
||
|
"embed"
|
||
|
"fmt"
|
||
|
"sync"
|
||
|
|
||
|
"github.com/chai2010/gettext-go"
|
||
|
)
|
||
|
|
||
|
//go:embed translations
|
||
|
var Translations embed.FS
|
||
|
|
||
|
var Languages = map[string]string{
|
||
|
"zh_CN": "简体中文",
|
||
|
"zh_TW": "繁體中文",
|
||
|
"en_US": "English",
|
||
|
"es_ES": "Español",
|
||
|
}
|
||
|
|
||
|
type Localizer struct {
|
||
|
intlMap map[string]gettext.Gettexter
|
||
|
lang string
|
||
|
|
||
|
mu sync.RWMutex
|
||
|
}
|
||
|
|
||
|
func NewLocalizer(lang, domain, path string, data any) *Localizer {
|
||
|
intl := gettext.New(domain, path, data)
|
||
|
intl.SetLanguage(lang)
|
||
|
|
||
|
intlMap := make(map[string]gettext.Gettexter)
|
||
|
intlMap[lang] = intl
|
||
|
|
||
|
return &Localizer{intlMap: intlMap, lang: lang}
|
||
|
}
|
||
|
|
||
|
func (l *Localizer) SetLanguage(lang string) {
|
||
|
l.mu.Lock()
|
||
|
defer l.mu.Unlock()
|
||
|
|
||
|
l.lang = lang
|
||
|
}
|
||
|
|
||
|
func (l *Localizer) Exists(lang string) bool {
|
||
|
l.mu.RLock()
|
||
|
defer l.mu.RUnlock()
|
||
|
|
||
|
if _, ok := l.intlMap[lang]; ok {
|
||
|
return ok
|
||
|
}
|
||
|
return false
|
||
|
}
|
||
|
|
||
|
func (l *Localizer) AppendIntl(lang, domain, path string, data any) {
|
||
|
intl := gettext.New(domain, path, data)
|
||
|
intl.SetLanguage(lang)
|
||
|
|
||
|
l.mu.Lock()
|
||
|
defer l.mu.Unlock()
|
||
|
|
||
|
l.intlMap[lang] = intl
|
||
|
}
|
||
|
|
||
|
// Modified from k8s.io/kubectl/pkg/util/i18n
|
||
|
|
||
|
func (l *Localizer) T(orig string) string {
|
||
|
l.mu.RLock()
|
||
|
intl, ok := l.intlMap[l.lang]
|
||
|
l.mu.RUnlock()
|
||
|
if !ok {
|
||
|
return orig
|
||
|
}
|
||
|
|
||
|
return intl.PGettext("", orig)
|
||
|
}
|
||
|
|
||
|
// N translates a string, possibly substituting arguments into it along
|
||
|
// the way. If len(args) is > 0, args1 is assumed to be the plural value
|
||
|
// and plural translation is used.
|
||
|
func (l *Localizer) N(orig string, args ...int) string {
|
||
|
l.mu.RLock()
|
||
|
intl, ok := l.intlMap[l.lang]
|
||
|
l.mu.RUnlock()
|
||
|
if !ok {
|
||
|
return orig
|
||
|
}
|
||
|
|
||
|
if len(args) == 0 {
|
||
|
return intl.PGettext("", orig)
|
||
|
}
|
||
|
return fmt.Sprintf(intl.PNGettext("", orig, orig+".plural", args[0]),
|
||
|
args[0])
|
||
|
}
|
||
|
|
||
|
// ErrorT produces an error with a translated error string.
|
||
|
// Substitution is performed via the `T` function above, following
|
||
|
// the same rules.
|
||
|
func (l *Localizer) ErrorT(defaultValue string, args ...any) error {
|
||
|
return fmt.Errorf(l.T(defaultValue), args...)
|
||
|
}
|
||
|
|
||
|
func (l *Localizer) Tf(defaultValue string, args ...any) string {
|
||
|
return fmt.Sprintf(l.T(defaultValue), args...)
|
||
|
}
|