package webutility import ( "encoding/json" "errors" "io/ioutil" "path" "strings" "sync" ) type Dictionary struct { my sync.Mutex locales map[string]map[string]string supported []string defaultLocale string } func NewDictionary() *Dictionary { return &Dictionary{ locales: map[string]map[string]string{}, } } func (d *Dictionary) AddTranslations(directory string) error { files, err := ioutil.ReadDir(directory) if err != nil { return err } for _, fileInfo := range files { fName := fileInfo.Name() path := directory + "/" + fName file, err := ioutil.ReadFile(path) if err != nil { return err } loc := stripFileExtension(fName) 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) } if len(d.supported) > 0 { d.setDefaultLocale(d.supported[0]) } return nil } func (d *Dictionary) GetBestMatchLocale(acceptedLanguages string) (best string) { accepted := d.parseAcceptedLanguageHeader(acceptedLanguages) best = accepted[0] return } func (d *Dictionary) Translate(loc, key string) string { return d.locales[loc][key] } func (d *Dictionary) hasLocale(loc string) bool { for _, v := range d.supported { if v == loc { return true } } return false } func (d *Dictionary) setDefaultLocale(loc string) error { if !d.hasLocale(loc) { return errors.New("dictionary does not contain translations for " + loc) } d.defaultLocale = loc return nil } func (d *Dictionary) getDefaultLocale() string { return d.defaultLocale } func (d *Dictionary) parseAcceptedLanguageHeader(acceptedLanguages string) (langs []string) { if acceptedLanguages == "" { langs = append(langs, d.getDefaultLocale()) return } parts := strings.Split(acceptedLanguages, ",") for _, p := range parts { langs = append(langs, p) } return } func stripFileExtension(full string) (stripped string) { extension := path.Ext(full) stripped = strings.TrimSuffix(full, extension) return stripped }