package pkg import ( "context" "net/http" "github.com/leonelquinteros/gotext" "golang.org/x/text/language" ) const contextLocaleKey = "numerus-locale" type Locale struct { *gotext.Locale CurrencyPattern string Language language.Tag } func NewLocale(lang availableLanguage) *Locale { return &Locale{ gotext.NewLocale("locales", lang.tag.String()), lang.currencyPattern, lang.tag, } } func LocaleSetter(db *Db, next http.Handler) http.Handler { availableLanguages := mustGetAvailableLanguages(db) locales := map[language.Tag]*Locale{} var tags []language.Tag for _, lang := range availableLanguages { locale := NewLocale(lang) locale.AddDomain("numerus") locales[lang.tag] = locale tags = append(tags, lang.tag) } defaultLocale := locales[language.Catalan] var matcher = language.NewMatcher(tags) return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { var locale *Locale user := getUser(r) locale = locales[user.Language] if locale == nil { t, _, err := language.ParseAcceptLanguage(r.Header.Get("Accept-Language")) if err == nil { tag, _, _ := matcher.Match(t...) var ok bool locale, ok = locales[tag] for !ok && !tag.IsRoot() { tag = tag.Parent() locale, ok = locales[tag] } } } if locale == nil { locale = defaultLocale } ctx := context.WithValue(r.Context(), contextLocaleKey, locale) next.ServeHTTP(w, r.WithContext(ctx)) }) } func getLocale(r *http.Request) *Locale { return r.Context().Value(contextLocaleKey).(*Locale) } func pgettext(context string, str string, locale *Locale) string { return locale.GetC(str, context) } func gettext(str string, locale *Locale) string { return locale.Get(str) } type availableLanguage struct { tag language.Tag currencyPattern string } func mustGetAvailableLanguages(db *Db) []availableLanguage { rows, err := db.Query(context.Background(), "select lang_tag, currency_pattern from language where selectable") if err != nil { panic(err) } defer rows.Close() var langs []availableLanguage for rows.Next() { var langTag string var currencyPattern string err = rows.Scan(&langTag, ¤cyPattern) if err != nil { panic(err) } langs = append(langs, availableLanguage{language.MustParse(langTag), currencyPattern}) } if rows.Err() != nil { panic(rows.Err()) } return langs }