local.go 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960
  1. // Package http detect localized from http header
  2. // and set localized info to metadata as key 'locale'
  3. // The locale used following the specification defined at
  4. // http://www.rfc-editor.org/rfc/bcp/bcp47.txt.
  5. // Examples are: "en-US", "fr-CH", "es-MX"
  6. package http
  7. import (
  8. "net/url"
  9. "sort"
  10. "strconv"
  11. "strings"
  12. bm "go-common/library/net/http/blademaster"
  13. )
  14. type language struct {
  15. Name string
  16. Weighting float64
  17. }
  18. // detectLocalizedWeb detect locale from HTTP Accept-Language header
  19. // https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Accept-Language
  20. func detectLocalizedWeb(c *bm.Context) (langs []string) {
  21. parseLang := func(s string) (language, error) {
  22. seps := strings.SplitN(s, ";", 2)
  23. lang := language{Name: seps[0]}
  24. if len(seps) == 1 {
  25. lang.Weighting = 1
  26. return lang, nil
  27. }
  28. params, err := url.ParseQuery(seps[1])
  29. if err != nil {
  30. return lang, err
  31. }
  32. lang.Weighting, err = strconv.ParseFloat(params.Get("q"), 32)
  33. return lang, err
  34. }
  35. items := strings.Split(c.Request.Header.Get("Accept-Language"), ",")
  36. if items[0] == "" {
  37. return
  38. }
  39. // three language is most common accept language send by browser
  40. languages := make([]language, 0, len(items))
  41. for _, s := range items {
  42. l, err := parseLang(s)
  43. if err != nil {
  44. //TODO(weicheng): deal with error
  45. continue
  46. }
  47. languages = append(languages, l)
  48. }
  49. sort.Slice(languages, func(i, j int) bool {
  50. return languages[i].Weighting > languages[j].Weighting
  51. })
  52. for i := range languages {
  53. langs = append(langs, languages[i].Name)
  54. }
  55. return
  56. }