Blame view

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

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

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

0207726c4   Marko Tikvić   improved localiza...
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
  		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
59

2b62f61cc   Marko Tikvić   minor changes
60
61
  	if d.defaultLocale == "" && len(d.supported) > 0 {
  		d.defaultLocale = d.supported[0]
715bb6ad8   Marko Tikvić   parsing of accept...
62
  	}
9933169c8   Marko Tikvić   localization support
63
64
  	return nil
  }
707782344   Marko Tikvić   lint; vet
65
  // GetBestMatchLocale ...
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
66
67
  func (d *Dictionary) GetBestMatchLocale(req *http.Request) (best string) {
  	accepted := d.parseAcceptedLanguages(req.Header.Get("Accept-Language"))
715bb6ad8   Marko Tikvić   parsing of accept...
68

707782344   Marko Tikvić   lint; vet
69
  	for i := range accepted {
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
70
71
72
  		if accepted[i].Code == "*" {
  			return d.defaultLocale
  		}
707782344   Marko Tikvić   lint; vet
73
  		for j := range d.supported {
715bb6ad8   Marko Tikvić   parsing of accept...
74
75
76
77
78
79
80
  			if accepted[i].Code == d.supported[j] {
  				return d.supported[j]
  			}
  		}
  	}
  
  	return d.defaultLocale
0207726c4   Marko Tikvić   improved localiza...
81
  }
707782344   Marko Tikvić   lint; vet
82
  // Translate ...
f84e7607d   Marko Tikvić   added dictionary;...
83
84
85
  func (d *Dictionary) Translate(loc, key string) string {
  	return d.locales[loc][key]
  }
707782344   Marko Tikvić   lint; vet
86
  // SetDefaultLocale ...
2b62f61cc   Marko Tikvić   minor changes
87
88
89
90
91
92
93
94
95
96
97
  func (d *Dictionary) SetDefaultLocale(loc string) error {
  	if !d.contains(loc) {
  		return fmt.Errorf("locale file not loaded: %s", loc)
  	}
  
  	d.defaultLocale = loc
  
  	return nil
  }
  
  func (d *Dictionary) contains(loc string) bool {
a205e8f40   Marko Tikvić   changes
98
99
  	for _, v := range d.supported {
  		if v == loc {
f84e7607d   Marko Tikvić   added dictionary;...
100
101
102
103
  			return true
  		}
  	}
  	return false
9933169c8   Marko Tikvić   localization support
104
  }
a205e8f40   Marko Tikvić   changes
105

707782344   Marko Tikvić   lint; vet
106
  // LangWeight ...
715bb6ad8   Marko Tikvić   parsing of accept...
107
108
109
  type LangWeight struct {
  	Code   string
  	Weight float64
a205e8f40   Marko Tikvić   changes
110
  }
715bb6ad8   Marko Tikvić   parsing of accept...
111
112
113
114
  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...
115
  	}
707782344   Marko Tikvić   lint; vet
116
117
  	var code string
  	var weight float64
715bb6ad8   Marko Tikvić   parsing of accept...
118
  	parts := strings.Split(accepted, ",")
707782344   Marko Tikvić   lint; vet
119
  	for i := range parts {
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
120
  		parts[i] = strings.Trim(parts[i], " ")
715bb6ad8   Marko Tikvić   parsing of accept...
121

715bb6ad8   Marko Tikvić   parsing of accept...
122
123
124
125
126
127
128
129
130
131
  		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...
132
  			weight, _ = strconv.ParseFloat(cw[1][2:], 64)
715bb6ad8   Marko Tikvić   parsing of accept...
133
134
  
  		}
715bb6ad8   Marko Tikvić   parsing of accept...
135
  		langs = append(langs, LangWeight{Code: code, Weight: weight})
3712c373f   Marko Tikvić   better localizati...
136
  	}
89f45d7aa   Marko Tikvić   GetBestMatchLocal...
137
  	// TODO(marko): sort langs by weights?
715bb6ad8   Marko Tikvić   parsing of accept...
138
139
  
  	return langs
3712c373f   Marko Tikvić   better localizati...
140
  }
0207726c4   Marko Tikvić   improved localiza...
141
142
  
  func stripFileExtension(full string) (stripped string) {
e97375e4d   Marko Tikvić   strip file extension
143
144
145
  	extension := path.Ext(full)
  	stripped = strings.TrimSuffix(full, extension)
  	return stripped
0207726c4   Marko Tikvić   improved localiza...
146
  }