Files
hanko/backend/mail/render.go
2022-06-09 14:36:00 +02:00

76 lines
2.3 KiB
Go

package mail
import (
"bytes"
"embed"
"fmt"
"github.com/nicksnyder/go-i18n/v2/i18n"
"golang.org/x/text/language"
"gopkg.in/yaml.v3"
"html/template"
"strings"
)
//go:embed templates/* locales/*
var mailFS embed.FS
type Renderer struct {
template *template.Template
bundle *i18n.Bundle
localizer *i18n.Localizer
}
// NewRenderer creates an instance of Renderer, which renders the templates (located in mail/templates) with locales (located in mail/locales)
func NewRenderer() (*Renderer, error) {
r := &Renderer{}
bundle := i18n.NewBundle(language.English)
dir, err := mailFS.ReadDir("locales")
if err != nil {
return nil, fmt.Errorf("failed to read locales directory: %w", err)
}
bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal)
for _, entry := range dir {
_, _ = bundle.LoadMessageFileFS(mailFS, fmt.Sprintf("locales/%s", entry.Name()))
}
r.bundle = bundle
// add the translate function to the template, so it can be used inside
funcMap := template.FuncMap{"t": r.translate}
t := template.New("root").Funcs(funcMap)
_, err = t.ParseFS(mailFS, "templates/*")
if err != nil {
return nil, fmt.Errorf("failed to load templates: %w", err)
}
r.template = t
return r, nil
}
// translate is a helper function to translate texts in a template
func (r *Renderer) translate(messageID string, templateData map[string]interface{}) string {
return r.localizer.MustLocalize(&i18n.LocalizeConfig{
MessageID: messageID,
TemplateData: templateData,
})
}
// Render renders a template with the given data and lang.
// The lang can be the contents of Accept-Language headers as defined in http://www.ietf.org/rfc/rfc2616.txt.
func (r *Renderer) Render(templateName string, lang string, data map[string]interface{}) (string, error) {
r.localizer = i18n.NewLocalizer(r.bundle, lang) // set the localizer, so the test will be translated to the given language
templateBuffer := &bytes.Buffer{}
err := r.template.ExecuteTemplate(templateBuffer, templateName, data)
if err != nil {
return "", fmt.Errorf("failed to fill template with data: %w", err)
}
return strings.TrimSpace(templateBuffer.String()), nil
}
func (r *Renderer) Translate(lang string, messageID string, data map[string]interface{}) string {
loc := i18n.NewLocalizer(r.bundle, lang)
return loc.MustLocalize(&i18n.LocalizeConfig{
MessageID: messageID,
TemplateData: data,
})
}