/* * SPDX-FileCopyrightText: 2023 jordi fita mas * SPDX-License-Identifier: AGPL-3.0-only */ package locale import ( "context" "net/http" "github.com/leonelquinteros/gotext" "golang.org/x/text/language" "dev.tandem.ws/tandem/camper/pkg/database" ) type Locale struct { *gotext.Locale CurrencyPattern string Language language.Tag } type Locales map[language.Tag]*Locale func (m Locales) Tags() []language.Tag { keys := make([]language.Tag, len(m)) i := 0 for k := range m { keys[i] = k i++ } return keys } func MustGetAll(db *database.DB) Locales { availableLanguages := mustGetAvailableLanguages(db) locales := map[language.Tag]*Locale{} for _, lang := range availableLanguages { locale := newLocale(lang) locale.AddDomain("camper") locales[lang.tag] = locale } return locales } func newLocale(lang availableLanguage) *Locale { return &Locale{ gotext.NewLocale("locale", lang.tag.String()), lang.currencyPattern, lang.tag, } } func Match(r *http.Request, locales Locales, defaultLocale *Locale, matcher language.Matcher) *Locale { var locale *Locale // TODO: find user locale 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 } return locale } type availableLanguage struct { tag language.Tag currencyPattern string } func mustGetAvailableLanguages(db *database.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 languages []availableLanguage for rows.Next() { var langTag string var currencyPattern string err = rows.Scan(&langTag, ¤cyPattern) if err != nil { panic(err) } languages = append(languages, availableLanguage{language.MustParse(langTag), currencyPattern}) } if rows.Err() != nil { panic(rows.Err()) } return languages }