/* * SPDX-FileCopyrightText: 2023 jordi fita mas * SPDX-License-Identifier: AGPL-3.0-only */ package locale import ( "context" "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 Endonym string } 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 (m Locales) Get(lang string) (loc *Locale, ok bool) { tag, err := language.Parse(lang) if err != nil { return } loc, ok = m[tag] return } func GetAll(ctx context.Context, db *database.DB) (Locales, error) { availableLanguages, err := getAvailableLanguages(ctx, db) if err != nil { return nil, err } locales := Locales{} for _, lang := range availableLanguages { locale := lang.locale() locale.AddDomain("camper") locales[lang.tag] = locale } return locales, nil } func (l *Locale) Gettext(str string) string { return l.GetD(l.GetDomain(), str) } func (l *Locale) Pgettext(str string, ctx string) string { return l.GetDC(l.GetDomain(), str, ctx) } func (l *Locale) GettextNoop(str string) string { return str } func PgettextNoop(str string, ctx string) string { return str } func Match(acceptLanguage string, locales Locales, matcher language.Matcher) *Locale { t, _, err := language.ParseAcceptLanguage(acceptLanguage) if err != nil { return nil } var locale *Locale tag, _, confidence := matcher.Match(t...) if confidence > language.No { var ok bool locale, ok = locales[tag] for !ok && !tag.IsRoot() { tag = tag.Parent() locale, ok = locales[tag] } } return locale } type availableLanguage struct { tag language.Tag endonym string currencyPattern string } func getAvailableLanguages(ctx context.Context, db *database.DB) ([]*availableLanguage, error) { rows, err := db.Query(ctx, "select lang_tag, endonym, currency_pattern from language where selectable") if err != nil { return nil, err } defer rows.Close() var languages []*availableLanguage for rows.Next() { lang := &availableLanguage{} var langTag string err = rows.Scan(&langTag, &lang.endonym, &lang.currencyPattern) if err != nil { return nil, err } lang.tag = language.MustParse(langTag) languages = append(languages, lang) } if rows.Err() != nil { return nil, rows.Err() } return languages, nil } func (lang *availableLanguage) locale() *Locale { return &Locale{ gotext.NewLocale("locale", lang.tag.String()), lang.currencyPattern, lang.tag, lang.endonym, } }