1
0

parser.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. /*
  2. * @Author: lwnmengjing
  3. * @Date: 2021/6/9 10:59 上午
  4. * @Last Modified by: lwnmengjing
  5. * @Last Modified time: 2021/6/9 10:59 上午
  6. */
  7. package language
  8. import (
  9. "sort"
  10. "strconv"
  11. "strings"
  12. )
  13. type language struct {
  14. name string
  15. quality float64
  16. }
  17. type languageSlice []language
  18. func (e languageSlice) SortByQuality() {
  19. sort.Sort(e)
  20. }
  21. func (e languageSlice) Len() int {
  22. return len(e)
  23. }
  24. func (e languageSlice) Swap(i, j int) {
  25. e[i], e[j] = e[j], e[i]
  26. }
  27. func (e languageSlice) Less(i, j int) bool {
  28. return e[i].quality > e[j].quality
  29. }
  30. // ParseAcceptLanguage returns RFC1766 language codes parsed and sorted from
  31. // languages.
  32. //
  33. // If supportedLanguages is not empty, the returned codes will be filtered
  34. // by its contents.
  35. func ParseAcceptLanguage(languages string, supportedLanguages []string) []string {
  36. preferredLanguages := strings.Split(languages, ",")
  37. preferredLanguagesLen := len(preferredLanguages)
  38. // Preallocate processed languages, as we know the maximum possible.
  39. langCap := preferredLanguagesLen
  40. if len(supportedLanguages) > 0 {
  41. langCap = len(supportedLanguages)
  42. }
  43. langs := make(languageSlice, 0, langCap)
  44. for i, rawPreferredLanguage := range preferredLanguages {
  45. // Format strings.
  46. preferredLanguage := strings.Replace(strings.ToLower(strings.TrimSpace(rawPreferredLanguage)), "_", "-", 0)
  47. if preferredLanguage == "" {
  48. continue
  49. }
  50. // Split out quality factor.
  51. parts := strings.SplitN(preferredLanguage, ";", 2)
  52. // If supported languages are given, return only the langs that fit.
  53. supported := len(supportedLanguages) == 0
  54. for _, supportedLanguage := range supportedLanguages {
  55. if supported = supportedLanguage == parts[0]; supported {
  56. break
  57. }
  58. }
  59. if !supported {
  60. continue
  61. }
  62. lang := language{parts[0], 0}
  63. if len(parts) == 2 {
  64. q := parts[1]
  65. if strings.HasPrefix(q, "q=") {
  66. q = strings.SplitN(q, "=", 2)[1]
  67. var err error
  68. if lang.quality, err = strconv.ParseFloat(q, 64); err != nil {
  69. // Default value (1) if quality is empty.
  70. lang.quality = 1
  71. }
  72. }
  73. }
  74. // Use order of items if no quality is given.
  75. if lang.quality == 0 {
  76. lang.quality = float64(preferredLanguagesLen - i)
  77. }
  78. langs = append(langs, lang)
  79. }
  80. langs.SortByQuality()
  81. // Filter quality string.
  82. langString := make([]string, 0, len(langs))
  83. for _, lang := range langs {
  84. langString = append(langString, lang.name)
  85. }
  86. return langString
  87. }