inou/lib/translate.go

107 lines
2.8 KiB
Go

package lib
import (
"bufio"
"bytes"
"fmt"
"html/template"
"os"
"path/filepath"
"strings"
)
var translations = make(map[string]map[string]string)
// TranslateInit loads translation files from the given directory
func TranslateInit(langDir string) {
files, _ := filepath.Glob(filepath.Join(langDir, "*.yaml"))
for _, f := range files {
lang := strings.TrimSuffix(filepath.Base(f), ".yaml")
translations[lang] = make(map[string]string)
file, _ := os.Open(f)
if file == nil {
continue
}
scanner := bufio.NewScanner(file)
for scanner.Scan() {
line := scanner.Text()
if idx := strings.Index(line, ": "); idx > 0 {
translations[lang][line[:idx]] = strings.Trim(line[idx+2:], "\"'")
}
}
file.Close()
}
}
// T translates a key to the given language, falling back to English
func T(lang, key string) string {
if t, ok := translations[lang]; ok {
if s, ok := t[key]; ok {
return s
}
}
if t, ok := translations["en"]; ok {
if s, ok := t[key]; ok {
return s
}
}
return "[" + key + "]"
}
// CategoryTranslate returns the translated category name
func CategoryTranslate(cat int, lang string) string {
return T(lang, CategoryKey(cat))
}
// SexTranslate returns the translated sex string (ISO 5218)
func SexTranslate(sex int, lang string) string {
key := fmt.Sprintf("sex_%d", sex)
return T(lang, key)
}
var htmlTemplates *template.Template
// TemplateInit loads HTML templates from the given directory
func TemplateInit(tmplDir string) {
htmlTemplates = template.Must(template.New("").Funcs(template.FuncMap{
"T": func(key string) string { return key }, // placeholder, overridden per-render
}).ParseGlob(filepath.Join(tmplDir, "*.tmpl")))
}
// RenderHTML renders a named template with translated strings and variables.
// Tries name_lang first (e.g. "email_invite_de"), falls back to name.
// Vars are accessible as {{index . "Key"}}, translations as {{T "key"}}.
func RenderHTML(name, lang string, vars map[string]string) (string, error) {
if htmlTemplates == nil {
return "", fmt.Errorf("templates not initialized")
}
t, err := htmlTemplates.Clone()
if err != nil {
return "", err
}
t = t.Funcs(template.FuncMap{
"T": func(key string) template.HTML { return template.HTML(T(lang, key)) },
})
tmplName := name + "_" + lang
if t.Lookup(tmplName) == nil {
tmplName = name
}
var buf bytes.Buffer
if err := t.ExecuteTemplate(&buf, tmplName, vars); err != nil {
return "", err
}
return buf.String(), nil
}
// DossierLanguage returns the language for a dossier, defaulting to "en"
func DossierLanguage(dossierID string) string {
if dossierID == "" {
return "en"
}
d, err := DossierGet("", dossierID) // nil ctx = internal operation
if err != nil || d.Preferences.Language == "" {
return "en"
}
return d.Preferences.Language
}