✨ Localize toolkit
This commit is contained in:
139
pkg/nex/localize/bundle.go
Normal file
139
pkg/nex/localize/bundle.go
Normal file
@ -0,0 +1,139 @@
|
||||
package localize
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/goccy/go-json"
|
||||
"github.com/nicksnyder/go-i18n/v2/i18n"
|
||||
"github.com/rs/zerolog/log"
|
||||
"golang.org/x/text/language"
|
||||
htmpl "html/template"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"text/template"
|
||||
)
|
||||
|
||||
type Bundle struct {
|
||||
Bundle *i18n.Bundle
|
||||
|
||||
LocalesPath string
|
||||
TemplatesPath string
|
||||
}
|
||||
|
||||
const FallbackLanguage = "en-US"
|
||||
|
||||
var L *Bundle
|
||||
|
||||
func LoadLocalization(localesPath string, templatesPath ...string) error {
|
||||
L = &Bundle{
|
||||
LocalesPath: localesPath,
|
||||
}
|
||||
if len(templatesPath) > 0 {
|
||||
L.TemplatesPath = templatesPath[0]
|
||||
}
|
||||
|
||||
L.Bundle = i18n.NewBundle(language.AmericanEnglish)
|
||||
L.Bundle.RegisterUnmarshalFunc("json", json.Unmarshal)
|
||||
|
||||
var count int
|
||||
|
||||
basePath := localesPath
|
||||
if entries, err := os.ReadDir(basePath); err != nil {
|
||||
return fmt.Errorf("unable to read locales directory: %v", err)
|
||||
} else {
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
continue
|
||||
}
|
||||
if _, err := L.Bundle.LoadMessageFile(filepath.Join(basePath, entry.Name())); err != nil {
|
||||
return fmt.Errorf("unable to load localization file %s: %v", entry.Name(), err)
|
||||
} else {
|
||||
count++
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
log.Info().Int("locales", count).Msg("Loaded localization files...")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (v *Bundle) GetLocalizer(lang string) *i18n.Localizer {
|
||||
return i18n.NewLocalizer(v.Bundle, lang)
|
||||
}
|
||||
|
||||
func (v *Bundle) GetLocalizedString(name string, lang string) string {
|
||||
localizer := v.GetLocalizer(lang)
|
||||
msg, err := localizer.LocalizeMessage(&i18n.Message{
|
||||
ID: name,
|
||||
})
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("lang", lang).Str("name", name).Msg("Failed to localize string...")
|
||||
return name
|
||||
}
|
||||
return msg
|
||||
}
|
||||
|
||||
func (v *Bundle) GetLocalizedTemplatePath(name string, lang string) string {
|
||||
basePath := v.TemplatesPath
|
||||
filePath := filepath.Join(basePath, lang, name)
|
||||
|
||||
if _, err := os.Stat(filePath); errors.Is(err, os.ErrNotExist) {
|
||||
// Fallback to English
|
||||
filePath = filepath.Join(basePath, FallbackLanguage, name)
|
||||
return filePath
|
||||
}
|
||||
|
||||
return filePath
|
||||
}
|
||||
|
||||
func (v *Bundle) GetLocalizedTemplate(name string, lang string) *template.Template {
|
||||
path := v.GetLocalizedTemplatePath(name, lang)
|
||||
tmpl, err := template.ParseFiles(path)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("lang", lang).Str("name", name).Msg("Failed to load localized template...")
|
||||
return nil
|
||||
}
|
||||
|
||||
return tmpl
|
||||
}
|
||||
|
||||
func (v *Bundle) GetLocalizedTemplateHTML(name string, lang string) *htmpl.Template {
|
||||
path := v.GetLocalizedTemplatePath(name, lang)
|
||||
tmpl, err := htmpl.ParseFiles(path)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("lang", lang).Str("name", name).Msg("Failed to load localized template...")
|
||||
return nil
|
||||
}
|
||||
|
||||
return tmpl
|
||||
}
|
||||
|
||||
func (v *Bundle) RenderLocalizedTemplateHTML(name string, lang string, data any) string {
|
||||
tmpl := v.GetLocalizedTemplate(name, lang)
|
||||
if tmpl == nil {
|
||||
return ""
|
||||
}
|
||||
buf := new(strings.Builder)
|
||||
err := tmpl.Execute(buf, data)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("lang", lang).Str("name", name).Msg("Failed to render localized template...")
|
||||
return ""
|
||||
}
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
func (v *Bundle) RenderLocalizedTemplate(name string, lang string, data any) string {
|
||||
tmpl := v.GetLocalizedTemplate(name, lang)
|
||||
if tmpl == nil {
|
||||
return ""
|
||||
}
|
||||
buf := new(strings.Builder)
|
||||
err := tmpl.Execute(buf, data)
|
||||
if err != nil {
|
||||
log.Warn().Err(err).Str("lang", lang).Str("name", name).Msg("Failed to render localized template...")
|
||||
return ""
|
||||
}
|
||||
return buf.String()
|
||||
}
|
Reference in New Issue
Block a user