aboutsummaryrefslogtreecommitdiff
path: root/misc/i18n/locale.go
blob: 6b4a7932faf24dc3787d7a527f3e14d4cc3bae48 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package i18n

import (
	"errors"
	"net/http"
	"strconv"
	"strings"
)

// Locale is locale value from the Accept-Language header in request
type Locale struct {
	Lang, Country string
	Qual          float64
}

// Name returns the locale value in 'lang' or 'lang_country' format
// eg: de_DE, en_US, gb
func (l *Locale) Name() string {
	if len(l.Country) > 0 {
		return l.Lang + "_" + l.Country
	}
	return l.Lang
}

// ParseLocale creates a Locale from a locale string
func ParseLocale(locale string) Locale {
	locsplt := strings.Split(locale, "_")
	resp := Locale{}
	resp.Lang = locsplt[0]
	if len(locsplt) > 1 {
		resp.Country = locsplt[1]
	}
	return resp
}

const (
	acceptLanguage = "Accept-Language"
)

func supportedLocales(alstr string) []Locale {
	locales := make([]Locale, 0)
	alstr = strings.Replace(alstr, " ", "", -1)
	if alstr == "" {
		return locales
	}
	al := strings.Split(alstr, ",")
	for _, lstr := range al {
		locales = append(locales, Locale{
			Lang:    parseLang(lstr),
			Country: parseCountry(lstr),
			Qual:    parseQual(lstr),
		})
	}
	return locales
}

// GetLocales returns supported locales for the given requet
func GetLocales(r *http.Request) []Locale {
	return supportedLocales(r.Header.Get(acceptLanguage))
}

// GetPreferredLocale return preferred locale for the given reuqest
// returns error if there is no preferred locale
func GetPreferredLocale(r *http.Request) (*Locale, error) {
	locales := GetLocales(r)
	if len(locales) == 0 {
		return &Locale{}, errors.New("No locale found")
	}
	return &locales[0], nil
}

func parseLang(val string) string {
	locale := strings.Split(val, ";")[0]
	lang := strings.Split(locale, "-")[0]
	return lang
}

func parseCountry(val string) string {
	locale := strings.Split(val, ";")[0]
	spl := strings.Split(locale, "-")
	if len(spl) > 1 {
		return spl[1]
	}
	return ""
}

func parseQual(val string) float64 {
	spl := strings.Split(val, ";")
	if len(spl) > 1 {
		qualSpl := strings.Split(spl[1], "=")
		if len(qualSpl) > 1 {
			qual, err := strconv.ParseFloat(qualSpl[1], 64)
			if err != nil {
				return 1
			}
			return qual
		}
	}
	return 1
}