Commit 89f45d7aa83a4bb8347c80404b5856e648e14731

Authored by Marko Tikvić
1 parent e1e658e7fe
Exists in master

GetBestMatchLocale takes in *http.Request for simplicity

Showing 1 changed file with 9 additions and 8 deletions   Show diff stats
1 package webutility 1 package webutility
2 2
3 import ( 3 import (
4 "encoding/json" 4 "encoding/json"
5 "fmt"
6 "io/ioutil" 5 "io/ioutil"
6 "net/http"
7 "path" 7 "path"
8 "strconv" 8 "strconv"
9 "strings" 9 "strings"
10 "sync" 10 "sync"
11 ) 11 )
12 12
13 type Dictionary struct { 13 type Dictionary struct {
14 my sync.Mutex 14 my sync.Mutex
15 locales map[string]map[string]string 15 locales map[string]map[string]string
16 supported []string 16 supported []string
17 defaultLocale string 17 defaultLocale string
18 } 18 }
19 19
20 func NewDictionary(def string) *Dictionary { 20 func NewDictionary(def string) *Dictionary {
21 d := Dictionary{ 21 d := Dictionary{
22 locales: map[string]map[string]string{}, 22 locales: map[string]map[string]string{},
23 } 23 }
24 d.defaultLocale = def 24 d.defaultLocale = def
25 return &d 25 return &d
26 } 26 }
27 27
28 func (d *Dictionary) AddTranslations(directory string) error { 28 func (d *Dictionary) AddTranslations(directory string) error {
29 files, err := ioutil.ReadDir(directory) 29 files, err := ioutil.ReadDir(directory)
30 if err != nil { 30 if err != nil {
31 return err 31 return err
32 } 32 }
33 33
34 for _, fileInfo := range files { 34 for _, fileInfo := range files {
35 fName := fileInfo.Name() 35 fName := fileInfo.Name()
36 path := directory + "/" + fName 36 path := directory + "/" + fName
37 file, err := ioutil.ReadFile(path) 37 file, err := ioutil.ReadFile(path)
38 if err != nil { 38 if err != nil {
39 return err 39 return err
40 } 40 }
41 41
42 loc := stripFileExtension(fName) 42 loc := stripFileExtension(fName)
43 43
44 var data interface{} 44 var data interface{}
45 err = json.Unmarshal(file, &data) 45 err = json.Unmarshal(file, &data)
46 if err != nil { 46 if err != nil {
47 return err 47 return err
48 } 48 }
49 49
50 l := map[string]string{} 50 l := map[string]string{}
51 for k, v := range data.(map[string]interface{}) { 51 for k, v := range data.(map[string]interface{}) {
52 l[k] = v.(string) 52 l[k] = v.(string)
53 } 53 }
54 54
55 mu.Lock() 55 mu.Lock()
56 defer mu.Unlock() 56 defer mu.Unlock()
57 d.locales[loc] = l 57 d.locales[loc] = l
58 d.supported = append(d.supported, loc) 58 d.supported = append(d.supported, loc)
59 } 59 }
60 60
61 if d.defaultLocale == "" { 61 if d.defaultLocale == "" {
62 if len(d.supported) > 0 { 62 if len(d.supported) > 0 {
63 d.defaultLocale = d.supported[0] 63 d.defaultLocale = d.supported[0]
64 } 64 }
65 } 65 }
66 66
67 return nil 67 return nil
68 } 68 }
69 69
70 func (d *Dictionary) GetBestMatchLocale(langs string) (best string) { 70 func (d *Dictionary) GetBestMatchLocale(req *http.Request) (best string) {
71 accepted := d.parseAcceptedLanguages(langs) 71 accepted := d.parseAcceptedLanguages(req.Header.Get("Accept-Language"))
72 72
73 for i, _ := range accepted { 73 for i, _ := range accepted {
74 if accepted[i].Code == "*" {
75 return d.defaultLocale
76 }
74 for j, _ := range d.supported { 77 for j, _ := range d.supported {
75 if accepted[i].Code == d.supported[j] { 78 if accepted[i].Code == d.supported[j] {
76 return d.supported[j] 79 return d.supported[j]
77 } 80 }
78 } 81 }
79 } 82 }
80 83
81 return d.defaultLocale 84 return d.defaultLocale
82 } 85 }
83 86
84 func (d *Dictionary) Translate(loc, key string) string { 87 func (d *Dictionary) Translate(loc, key string) string {
85 return d.locales[loc][key] 88 return d.locales[loc][key]
86 } 89 }
87 90
88 func (d *Dictionary) hasLocale(loc string) bool { 91 func (d *Dictionary) hasLocale(loc string) bool {
89 for _, v := range d.supported { 92 for _, v := range d.supported {
90 if v == loc { 93 if v == loc {
91 return true 94 return true
92 } 95 }
93 } 96 }
94 return false 97 return false
95 } 98 }
96 99
97 type LangWeight struct { 100 type LangWeight struct {
98 Code string 101 Code string
99 Weight float64 102 Weight float64
100 } 103 }
101 104
102 func (d *Dictionary) parseAcceptedLanguages(accepted string) (langs []LangWeight) { 105 func (d *Dictionary) parseAcceptedLanguages(accepted string) (langs []LangWeight) {
103 if accepted == "" { 106 if accepted == "" {
104 langs = append(langs, LangWeight{Code: d.defaultLocale, Weight: 1.0}) 107 langs = append(langs, LangWeight{Code: d.defaultLocale, Weight: 1.0})
105 return langs 108 return langs
106 } 109 }
107 110
108 parts := strings.Split(accepted, ",") 111 parts := strings.Split(accepted, ",")
109 for i, _ := range parts { 112 for i, _ := range parts {
110 parts[i] = strings.Trim(parts[i], "") 113 parts[i] = strings.Trim(parts[i], " ")
111 114
112 var code string = "" 115 var code string = ""
113 var weight float64 = 0.0 116 var weight float64 = 0.0
114 117
115 cw := strings.Split(parts[i], ";") 118 cw := strings.Split(parts[i], ";")
116 paramCount := len(cw) 119 paramCount := len(cw)
117 120
118 if paramCount == 1 { 121 if paramCount == 1 {
119 // default weight of 1 122 // default weight of 1
120 code = cw[0] 123 code = cw[0]
121 weight = 1.0 124 weight = 1.0
122 } else if paramCount == 2 { 125 } else if paramCount == 2 {
123 // parse weight 126 // parse weight
124 code = cw[0] 127 code = cw[0]
125 weight, _ = strconv.ParseFloat(cw[1], 64) 128 weight, _ = strconv.ParseFloat(cw[1][2:], 64)
126 129
127 } 130 }
128 131
129 fmt.Println(parts[i], code, weight)
130
131 langs = append(langs, LangWeight{Code: code, Weight: weight}) 132 langs = append(langs, LangWeight{Code: code, Weight: weight})
132 } 133 }
133 134
134 // TODO(marko): sort langs by weights 135 // TODO(marko): sort langs by weights?
135 136
136 return langs 137 return langs
137 } 138 }
138 139
139 func stripFileExtension(full string) (stripped string) { 140 func stripFileExtension(full string) (stripped string) {
140 extension := path.Ext(full) 141 extension := path.Ext(full)
141 stripped = strings.TrimSuffix(full, extension) 142 stripped = strings.TrimSuffix(full, extension)