Blame view

localization.go 2.66 KB
9933169c8   Marko Tikvić   localization support
1
2
3
4
5
  package webutility
  
  import (
  	"encoding/json"
  	"io/ioutil"
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
6
  	"net/http"
e97375e4d   Marko Tikvić   strip file extension
7
  	"path"
715bb6ad8   Marko Tikvić   parsing of accept...
8
  	"strconv"
3712c373f   Marko Tikvić   better localizati...
9
  	"strings"
3fffcb954   Marko Tikvić   removed old http API
10
  	"sync"
9933169c8   Marko Tikvić   localization support
11
  )
f84e7607d   Marko Tikvić   added dictionary;...
12
  type Dictionary struct {
3fffcb954   Marko Tikvić   removed old http API
13
  	my            sync.Mutex
a205e8f40   Marko Tikvić   changes
14
15
16
  	locales       map[string]map[string]string
  	supported     []string
  	defaultLocale string
f84e7607d   Marko Tikvić   added dictionary;...
17
  }
715bb6ad8   Marko Tikvić   parsing of accept...
18
19
  func NewDictionary(def string) *Dictionary {
  	d := Dictionary{
f84e7607d   Marko Tikvić   added dictionary;...
20
21
  		locales: map[string]map[string]string{},
  	}
715bb6ad8   Marko Tikvić   parsing of accept...
22
23
  	d.defaultLocale = def
  	return &d
f84e7607d   Marko Tikvić   added dictionary;...
24
  }
9933169c8   Marko Tikvić   localization support
25

0207726c4   Marko Tikvić   improved localiza...
26
27
  func (d *Dictionary) AddTranslations(directory string) error {
  	files, err := ioutil.ReadDir(directory)
9933169c8   Marko Tikvić   localization support
28
29
30
  	if err != nil {
  		return err
  	}
0207726c4   Marko Tikvić   improved localiza...
31
32
  	for _, fileInfo := range files {
  		fName := fileInfo.Name()
5bba6f75f   Marko Tikvić   bug fix
33
  		path := directory + "/" + fName
0207726c4   Marko Tikvić   improved localiza...
34
35
36
37
  		file, err := ioutil.ReadFile(path)
  		if err != nil {
  			return err
  		}
9933169c8   Marko Tikvić   localization support
38

e97375e4d   Marko Tikvić   strip file extension
39
  		loc := stripFileExtension(fName)
0207726c4   Marko Tikvić   improved localiza...
40

0207726c4   Marko Tikvić   improved localiza...
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
  		var data interface{}
  		err = json.Unmarshal(file, &data)
  		if err != nil {
  			return err
  		}
  
  		l := map[string]string{}
  		for k, v := range data.(map[string]interface{}) {
  			l[k] = v.(string)
  		}
  
  		mu.Lock()
  		defer mu.Unlock()
  		d.locales[loc] = l
  		d.supported = append(d.supported, loc)
  	}
9933169c8   Marko Tikvić   localization support
57

715bb6ad8   Marko Tikvić   parsing of accept...
58
59
60
61
62
  	if d.defaultLocale == "" {
  		if len(d.supported) > 0 {
  			d.defaultLocale = d.supported[0]
  		}
  	}
9933169c8   Marko Tikvić   localization support
63
64
  	return nil
  }
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
65
66
  func (d *Dictionary) GetBestMatchLocale(req *http.Request) (best string) {
  	accepted := d.parseAcceptedLanguages(req.Header.Get("Accept-Language"))
715bb6ad8   Marko Tikvić   parsing of accept...
67
68
  
  	for i, _ := range accepted {
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
69
70
71
  		if accepted[i].Code == "*" {
  			return d.defaultLocale
  		}
715bb6ad8   Marko Tikvić   parsing of accept...
72
73
74
75
76
77
78
79
  		for j, _ := range d.supported {
  			if accepted[i].Code == d.supported[j] {
  				return d.supported[j]
  			}
  		}
  	}
  
  	return d.defaultLocale
0207726c4   Marko Tikvić   improved localiza...
80
  }
f84e7607d   Marko Tikvić   added dictionary;...
81
82
83
  func (d *Dictionary) Translate(loc, key string) string {
  	return d.locales[loc][key]
  }
0207726c4   Marko Tikvić   improved localiza...
84
  func (d *Dictionary) hasLocale(loc string) bool {
a205e8f40   Marko Tikvić   changes
85
86
  	for _, v := range d.supported {
  		if v == loc {
f84e7607d   Marko Tikvić   added dictionary;...
87
88
89
90
  			return true
  		}
  	}
  	return false
9933169c8   Marko Tikvić   localization support
91
  }
a205e8f40   Marko Tikvić   changes
92

715bb6ad8   Marko Tikvić   parsing of accept...
93
94
95
  type LangWeight struct {
  	Code   string
  	Weight float64
a205e8f40   Marko Tikvić   changes
96
  }
715bb6ad8   Marko Tikvić   parsing of accept...
97
98
99
100
  func (d *Dictionary) parseAcceptedLanguages(accepted string) (langs []LangWeight) {
  	if accepted == "" {
  		langs = append(langs, LangWeight{Code: d.defaultLocale, Weight: 1.0})
  		return langs
3712c373f   Marko Tikvić   better localizati...
101
  	}
715bb6ad8   Marko Tikvić   parsing of accept...
102
103
  	parts := strings.Split(accepted, ",")
  	for i, _ := range parts {
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
104
  		parts[i] = strings.Trim(parts[i], " ")
715bb6ad8   Marko Tikvić   parsing of accept...
105
106
107
108
109
110
111
112
113
114
115
116
117
118
  
  		var code string = ""
  		var weight float64 = 0.0
  
  		cw := strings.Split(parts[i], ";")
  		paramCount := len(cw)
  
  		if paramCount == 1 {
  			// default weight of 1
  			code = cw[0]
  			weight = 1.0
  		} else if paramCount == 2 {
  			// parse weight
  			code = cw[0]
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
119
  			weight, _ = strconv.ParseFloat(cw[1][2:], 64)
715bb6ad8   Marko Tikvić   parsing of accept...
120
121
  
  		}
715bb6ad8   Marko Tikvić   parsing of accept...
122
  		langs = append(langs, LangWeight{Code: code, Weight: weight})
3712c373f   Marko Tikvić   better localizati...
123
  	}
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
124
  	// TODO(marko): sort langs by weights?
715bb6ad8   Marko Tikvić   parsing of accept...
125
126
  
  	return langs
3712c373f   Marko Tikvić   better localizati...
127
  }
0207726c4   Marko Tikvić   improved localiza...
128
129
  
  func stripFileExtension(full string) (stripped string) {
e97375e4d   Marko Tikvić   strip file extension
130
131
132
  	extension := path.Ext(full)
  	stripped = strings.TrimSuffix(full, extension)
  	return stripped
0207726c4   Marko Tikvić   improved localiza...
133
  }