| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273 |
- package detect
- import (
- "net/http"
- "strings"
- )
- /* NewHttpDetector initializes new language detector */
- func NewHttpDetector(languages []string, path string, maxAge int) func(http.ResponseWriter, *http.Request) string {
- const cookieName = "lang"
- if len(languages) == 0 {
- panic("empty languages list")
- }
- /* initialize state */
- defaultLang := strings.ToLower(languages[0])
- langSet := make(map[string]struct{}, len(languages))
- for _, lang := range languages {
- langSet[strings.ToLower(lang)] = struct{}{}
- }
- /* detectLanguage returns a language string */
- return func(w http.ResponseWriter, r *http.Request) string {
- /* check for query language override */
- if lang := strings.ToLower(r.URL.Query().Get(cookieName)); lang != "" {
- if _, ok := langSet[lang]; ok {
- /* language provided by query string, enforce it and send cookie */
- http.SetCookie(w, &http.Cookie{
- Name: cookieName,
- Value: lang,
- Path: path,
- HttpOnly: true,
- SameSite: http.SameSiteLaxMode,
- Secure: r.TLS != nil,
- MaxAge: maxAge,
- })
- return lang
- }
- }
- /* check for cookie preferences */
- cookie, err := r.Cookie(cookieName)
- if err == nil {
- cookieLang := strings.ToLower(cookie.Value)
- if _, ok := langSet[cookieLang]; ok {
- return cookieLang
- }
- }
- /* fall back to browser preferences */
- acceptLanguage := strings.ToLower(r.Header.Get("Accept-Language"))
- parts := strings.Split(acceptLanguage, ",")
- for _, part := range parts {
- part = strings.TrimSpace(part)
- if part == "" {
- continue
- }
- /* cut off ";q=..." */
- if idx := strings.IndexByte(part, ';'); idx >= 0 {
- part = part[:idx]
- }
- /* try exact match first */
- if _, ok := langSet[part]; ok {
- return part
- }
- /* try base language */
- if i := strings.IndexByte(part, '-'); i >= 0 {
- base := part[:i]
- if _, ok := langSet[base]; ok {
- return base
- }
- }
- }
- return defaultLang
- }
- }
|