mirror of
https://github.com/BigJk/end_of_eden.git
synced 2026-02-06 10:48:09 +00:00
145 lines
3.3 KiB
Go
145 lines
3.3 KiB
Go
package localization
|
|
|
|
import (
|
|
"fmt"
|
|
"github.com/BigJk/end_of_eden/internal/fs"
|
|
"gopkg.in/yaml.v3"
|
|
"path/filepath"
|
|
"strings"
|
|
)
|
|
|
|
type Localization struct {
|
|
current string
|
|
locals map[string]map[string]string
|
|
}
|
|
|
|
func New() *Localization {
|
|
loc := &Localization{current: "en", locals: make(map[string]map[string]string)}
|
|
loc.locals["en"] = make(map[string]string)
|
|
return loc
|
|
}
|
|
|
|
// SetCurrent sets the current locale.
|
|
func (l *Localization) SetCurrent(locale string) {
|
|
l.current = locale
|
|
}
|
|
|
|
// GetCurrent returns the current locale.
|
|
func (l *Localization) GetCurrent() string {
|
|
return l.current
|
|
}
|
|
|
|
// Add adds a new locale with the given translations. If the locale
|
|
// already exists, the translations will be added to the existing ones.
|
|
func (l *Localization) Add(locale string, translations map[string]string) {
|
|
if _, ok := l.locals[locale]; !ok {
|
|
l.locals[locale] = make(map[string]string)
|
|
}
|
|
|
|
for k, v := range translations {
|
|
l.locals[locale][k] = v
|
|
}
|
|
}
|
|
|
|
// AddFolder adds all locales from the given folder. Will walk through all
|
|
// sub-folders and add all .yaml and .yml files.
|
|
func (l *Localization) AddFolder(folder string) error {
|
|
return fs.Walk(folder, func(path string, isDir bool) error {
|
|
if isDir {
|
|
return nil
|
|
}
|
|
|
|
if filepath.Ext(path) != ".yaml" && filepath.Ext(path) != ".yml" {
|
|
return nil
|
|
}
|
|
|
|
return l.AddFile(path)
|
|
})
|
|
}
|
|
|
|
// AddFile adds a new locale with the given translations from the given file.
|
|
func (l *Localization) AddFile(file string) error {
|
|
var parsed map[string]map[string]any
|
|
|
|
data, err := fs.ReadFile(file)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
err = yaml.Unmarshal(data, &parsed)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
var walk func(found map[string]string, m map[string]any, prefix string)
|
|
walk = func(found map[string]string, m map[string]any, prefix string) {
|
|
for k, v := range m {
|
|
if m, ok := v.(map[string]any); ok {
|
|
if prefix != "" {
|
|
walk(found, m, prefix+"."+k)
|
|
} else {
|
|
walk(found, m, k)
|
|
}
|
|
} else {
|
|
if prefix != "" {
|
|
found[prefix+"."+k] = fmt.Sprint(v)
|
|
} else {
|
|
found[k] = fmt.Sprint(v)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for local, v := range parsed {
|
|
if len(local) != 2 {
|
|
return fmt.Errorf("invalid locale: %s", local)
|
|
}
|
|
found := make(map[string]string)
|
|
walk(found, v, "")
|
|
l.Add(local, found)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// GetLocales returns a list of all available locales.
|
|
func (l *Localization) GetLocales() []string {
|
|
var locales []string
|
|
for k := range l.locals {
|
|
locales = append(locales, k)
|
|
}
|
|
return locales
|
|
}
|
|
|
|
// Get returns the translation for the given key in the given locale. If the key is not found,
|
|
// it will fall back to the "en" locale and if the key is not found there, it will return the key
|
|
// or the given defaults.
|
|
func (l *Localization) Get(locale, key string, defaults ...string) string {
|
|
if _, ok := l.locals[locale]; !ok {
|
|
if locale != "en" {
|
|
return l.Get("en", key, defaults...)
|
|
}
|
|
if len(defaults) > 0 {
|
|
return strings.Join(defaults, " ")
|
|
}
|
|
return key
|
|
}
|
|
|
|
if _, ok := l.locals[locale][key]; !ok {
|
|
if locale != "en" {
|
|
return l.Get("en", key, defaults...)
|
|
}
|
|
if len(defaults) > 0 {
|
|
return strings.Join(defaults, " ")
|
|
}
|
|
return key
|
|
}
|
|
|
|
return l.locals[locale][key]
|
|
}
|
|
|
|
// G is a shortcut for Get with the current locale.
|
|
func (l *Localization) G(key string, defaults ...string) string {
|
|
return l.Get(l.current, key, defaults...)
|
|
}
|