mirror of
https://github.com/Buriburizaem0n/nezha_domains.git
synced 2026-02-04 04:30:05 +00:00
154 lines
2.9 KiB
Go
154 lines
2.9 KiB
Go
package i18n
|
|
|
|
import (
|
|
"embed"
|
|
"fmt"
|
|
"io/fs"
|
|
"path"
|
|
"sync"
|
|
|
|
"github.com/leonelquinteros/gotext"
|
|
)
|
|
|
|
//go:embed translations
|
|
var Translations embed.FS
|
|
|
|
type Localizer struct {
|
|
intlMap map[string]gotext.Translator
|
|
lang string
|
|
domain string
|
|
path string
|
|
fs fs.FS
|
|
|
|
mu sync.RWMutex
|
|
}
|
|
|
|
func NewLocalizer(lang, domain, path string, fs fs.FS) *Localizer {
|
|
loc := &Localizer{
|
|
intlMap: make(map[string]gotext.Translator),
|
|
lang: lang,
|
|
domain: domain,
|
|
path: path,
|
|
fs: fs,
|
|
}
|
|
|
|
file := loc.findExt(lang, "mo")
|
|
if file == "" {
|
|
return loc
|
|
}
|
|
|
|
mo := gotext.NewMoFS(loc.fs)
|
|
mo.ParseFile(file)
|
|
loc.intlMap[lang] = mo
|
|
|
|
return loc
|
|
}
|
|
|
|
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 string) {
|
|
file := l.findExt(lang, "mo")
|
|
if file == "" {
|
|
return
|
|
}
|
|
|
|
mo := gotext.NewMoFS(l.fs)
|
|
mo.ParseFile(file)
|
|
|
|
l.mu.Lock()
|
|
defer l.mu.Unlock()
|
|
|
|
l.intlMap[lang] = mo
|
|
}
|
|
|
|
// 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.Get(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.Get(orig)
|
|
}
|
|
return fmt.Sprintf(intl.GetN(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...)
|
|
}
|
|
|
|
// https://github.com/leonelquinteros/gotext/blob/v1.7.1/locale.go
|
|
func (l *Localizer) findExt(lang, ext string) string {
|
|
filename := path.Join(l.path, lang, "LC_MESSAGES", l.domain+"."+ext)
|
|
if l.fileExists(filename) {
|
|
return filename
|
|
}
|
|
|
|
if len(lang) > 2 {
|
|
filename = path.Join(l.path, lang[:2], "LC_MESSAGES", l.domain+"."+ext)
|
|
if l.fileExists(filename) {
|
|
return filename
|
|
}
|
|
}
|
|
|
|
filename = path.Join(l.path, lang, l.domain+"."+ext)
|
|
if l.fileExists(filename) {
|
|
return filename
|
|
}
|
|
|
|
if len(lang) > 2 {
|
|
filename = path.Join(l.path, lang[:2], l.domain+"."+ext)
|
|
if l.fileExists(filename) {
|
|
return filename
|
|
}
|
|
}
|
|
|
|
return ""
|
|
}
|
|
|
|
func (l *Localizer) fileExists(filename string) bool {
|
|
_, err := fs.Stat(l.fs, filename)
|
|
return err == nil
|
|
}
|