From 6feb95eb68e895eeb4d49bc695ad347fed0ed304 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Sat, 1 Dec 2018 18:19:32 -0800 Subject: [PATCH] try 2 --- cmd/site/html.go | 28 +++++- cmd/site/locale.go | 97 +++++++++++++++++++ cmd/site/main.go | 5 + {locale => conf/locale}/locale_en-US.ini | 0 .../locale}/locale_jbo-latn-us.ini | 0 {locale => conf/locale}/locale_toki.ini | 0 go.mod | 2 + go.sum | 4 + 8 files changed, 135 insertions(+), 1 deletion(-) create mode 100644 cmd/site/locale.go rename {locale => conf/locale}/locale_en-US.ini (100%) rename {locale => conf/locale}/locale_jbo-latn-us.ini (100%) rename {locale => conf/locale}/locale_toki.ini (100%) diff --git a/cmd/site/html.go b/cmd/site/html.go index ba304c5..d85e817 100644 --- a/cmd/site/html.go +++ b/cmd/site/html.go @@ -7,6 +7,7 @@ import ( "net/http" "time" + "github.com/Unknwon/i18n" "github.com/Xe/ln" ) @@ -21,7 +22,32 @@ func (s *Site) renderTemplatePage(templateFname string, data interface{}) http.H s.tlock.RLock() defer s.tlock.RUnlock() - var t *template.Template + const fallbackLang = `en-US` + + getTranslation := func(group, key string, vals ...interface{}) string { + var lang string + locale, err := GetPreferredLocale(r) + if err != nil { + ln.Error(r.Context(), err) + lang = fallbackLang + goto skip + } + + if !i18n.IsExist(locale.Lang) { + lang = fallbackLang + goto skip + } + + lang = locale.Lang + skip: + return i18n.Tr(lang, group+"."+key, vals...) + } + + funcMap := template.FuncMap{ + "trans": getTranslation, + } + + var t = template.New(templateFname).Funcs(funcMap) var err error if s.templates[templateFname] == nil { diff --git a/cmd/site/locale.go b/cmd/site/locale.go new file mode 100644 index 0000000..a65034a --- /dev/null +++ b/cmd/site/locale.go @@ -0,0 +1,97 @@ +package main + +import ( + "errors" + "net/http" + "strconv" + "strings" +) + +// Locale is locale value from the Accept-Language header in request +type Locale struct { + Lang, Country string + Qual float64 +} + +// Name returns the locale value in 'lang' or 'lang_country' format +// eg: de_DE, en_US, gb +func (l *Locale) Name() string { + if len(l.Country) > 0 { + return l.Lang + "_" + l.Country + } + return l.Lang +} + +// ParseLocale creates a Locale from a locale string +func ParseLocale(locale string) Locale { + locsplt := strings.Split(locale, "_") + resp := Locale{} + resp.Lang = locsplt[0] + if len(locsplt) > 1 { + resp.Country = locsplt[1] + } + return resp +} + +const ( + acceptLanguage = "Accept-Language" +) + +func supportedLocales(alstr string) []Locale { + locales := make([]Locale, 0) + alstr = strings.Replace(alstr, " ", "", -1) + if alstr == "" { + return locales + } + al := strings.Split(alstr, ",") + for _, lstr := range al { + locales = append(locales, Locale{ + Lang: parseLang(lstr), + Country: parseCountry(lstr), + Qual: parseQual(lstr), + }) + } + return locales +} + +// GetLocales returns supported locales for the given requet +func GetLocales(r *http.Request) []Locale { + return supportedLocales(r.Header.Get(acceptLanguage)) +} + +// GetPreferredLocale return preferred locale for the given reuqest +// returns error if there is no preferred locale +func GetPreferredLocale(r *http.Request) (*Locale, error) { + locales := GetLocales(r) + if len(locales) == 0 { + return &Locale{}, errors.New("No locale found") + } + return &locales[0], nil +} + +func parseLang(val string) string { + locale := strings.Split(val, ";")[0] + lang := strings.Split(locale, "-")[0] + return lang +} + +func parseCountry(val string) string { + locale := strings.Split(val, ";")[0] + spl := strings.Split(locale, "-") + if len(spl) > 1 { + return spl[1] + } + return "" +} + +func parseQual(val string) float64 { + spl := strings.Split(val, ";") + if len(spl) > 1 { + qual, err := strconv.ParseFloat(strings.Split(spl[1], "=")[1], 64) + if err != nil { + return 1 + } + return qual + } + return 1 +} diff --git a/cmd/site/main.go b/cmd/site/main.go index fa4b9b8..1bc5f71 100644 --- a/cmd/site/main.go +++ b/cmd/site/main.go @@ -12,6 +12,7 @@ import ( "sync" "time" + "github.com/Unknwon/i18n" "github.com/Xe/jsonfeed" "github.com/Xe/ln" "github.com/gorilla/feeds" @@ -62,6 +63,10 @@ func Build() (*Site, error) { Date string } + i18n.SetMessage("en-US", "conf/locale/locale_en-US.ini") + i18n.SetMessage("toki", "conf/locale/locale_toki.ini") + i18n.SetDefaultLang("en-US") + s := &Site{ rssFeed: &feeds.Feed{ Title: "Christine Dodrill's Blog", diff --git a/locale/locale_en-US.ini b/conf/locale/locale_en-US.ini similarity index 100% rename from locale/locale_en-US.ini rename to conf/locale/locale_en-US.ini diff --git a/locale/locale_jbo-latn-us.ini b/conf/locale/locale_jbo-latn-us.ini similarity index 100% rename from locale/locale_jbo-latn-us.ini rename to conf/locale/locale_jbo-latn-us.ini diff --git a/locale/locale_toki.ini b/conf/locale/locale_toki.ini similarity index 100% rename from locale/locale_toki.ini rename to conf/locale/locale_toki.ini diff --git a/go.mod b/go.mod index e6cd435..ab2a4af 100644 --- a/go.mod +++ b/go.mod @@ -1,6 +1,7 @@ module github.com/Xe/site require ( + github.com/Unknwon/i18n v0.0.0-20171114194641-b64d33658966 // indirect github.com/Xe/gopreload v0.0.0-20170326043426-a00a8beb369c github.com/Xe/jsonfeed v0.0.0-20170520170432-e21591505612 github.com/Xe/ln v0.0.0-20170921000907-466e05b2ef3e @@ -17,5 +18,6 @@ require ( github.com/stretchr/testify v1.2.2 // indirect github.com/tj/front v0.0.0-20170212063142-739be213b0a1 gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 // indirect + gopkg.in/ini.v1 v1.39.0 // indirect gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 // indirect ) diff --git a/go.sum b/go.sum index 5b12dc9..5d0bf3d 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,5 @@ +github.com/Unknwon/i18n v0.0.0-20171114194641-b64d33658966 h1:Mp8GNJ/tdTZIEdLdZfykEJaL3mTyEYrSzYNcdoQKpJk= +github.com/Unknwon/i18n v0.0.0-20171114194641-b64d33658966/go.mod h1:SFtfq0zFPsENI7DpE87QM2hcYu5QQ0fRdCgP+P1Hrqo= github.com/Xe/gopreload v0.0.0-20170326043426-a00a8beb369c h1:lqTJqaoonxgJMvvfl1ukr/3qCEGWC0nQxzPezbJrhHs= github.com/Xe/gopreload v0.0.0-20170326043426-a00a8beb369c/go.mod h1:0aSWHJguPNHo6zlU7A4Ktua1A/VUr5Jdr1QZ2amOkAQ= github.com/Xe/jsonfeed v0.0.0-20170520170432-e21591505612 h1:5cPld6YTMozzm3lK9VCnOErgoFbADM2hZc4KDu0YNKs= @@ -33,5 +35,7 @@ github.com/tj/front v0.0.0-20170212063142-739be213b0a1 h1:lA+aPRvltlx2fwv/BnxyYS github.com/tj/front v0.0.0-20170212063142-739be213b0a1/go.mod h1:deJrtusCTptAW4EUn5vBLpl3dhNqPqUwEjWJz5UNxpQ= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/ini.v1 v1.39.0 h1:Jf2sFGT+sAd7i+4ftUN1Jz90uw8XNH8NXbbOY16taA8= +gopkg.in/ini.v1 v1.39.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0 h1:POO/ycCATvegFmVuPpQzZFJ+pGZeX22Ufu6fibxDVjU= gopkg.in/yaml.v1 v1.0.0-20140924161607-9f9df34309c0/go.mod h1:WDnlLJ4WF5VGsH/HVa3CI79GS0ol3YnhVnKP89i0kNg=