localization.go 1.7 KB
package webutility

import (
	"encoding/json"
	"errors"
	"io/ioutil"
	"net/http"
	"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) AddLocale(loc, filePath string) error {
	file, err := ioutil.ReadFile(filePath)
	if err != nil {
		return err
	}

	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)

	return nil
}

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) GetBestMatchLocale(req *http.Request) (best string) {
	accepted := d.parseAcceptedLanguageHeader(req)
	best = accepted[0]
	return
}

func (d *Dictionary) parseAcceptedLanguageHeader(req *http.Request) (langs []string) {
	a := req.Header.Get("Accepted-Language")
	if a == "" {
		langs = append(langs, d.GetDefaultLocale())
		return
	}

	parts := strings.Split(a, ",")
	for _, p := range parts {
		langs = append(langs, p)
	}

	return
}