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 }