ref: 06d12ab895a83fc8a9f94b23e533b25511bbb6d1
parent: ec33732fbe84f67c1164fb713d6cb738609f2e2e
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
date: Sun Jul 24 09:58:27 EDT 2016
Add proper Language and Languages types
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -493,9 +493,8 @@
helpers.HugoReleaseVersion(), minVersion)
}
- readMultilingualConfiguration()
+ return readMultilingualConfiguration()
- return nil
}
func flagChanged(flags *flag.FlagSet, key string) bool {@@ -715,11 +714,11 @@
for _, lang := range langConfigsList {t1 := time.Now()
- mainSite, present := MainSites[lang]
+ mainSite, present := MainSites[lang.Lang]
if !present {mainSite = new(hugolib.Site)
- MainSites[lang] = mainSite
- mainSite.SetMultilingualConfig(lang, langConfigsList, langConfigs)
+ MainSites[lang.Lang] = mainSite
+ mainSite.SetMultilingualConfig(lang, langConfigsList)
}
if len(watching) > 0 && watching[0] {@@ -730,7 +729,7 @@
return err
}
- mainSite.Stats(lang, t1)
+ mainSite.Stats(lang.Lang, t1)
}
jww.FEEDBACK.Printf("total in %v ms\n", int(1000*time.Since(t0).Seconds()))@@ -743,13 +742,13 @@
for _, lang := range langConfigsList {t1 := time.Now()
- mainSite := MainSites[lang]
+ mainSite := MainSites[lang.Lang]
if err := mainSite.ReBuild(events); err != nil {return err
}
- mainSite.Stats(lang, t1)
+ mainSite.Stats(lang.Lang, t1)
}
jww.FEEDBACK.Printf("total in %v ms\n", int(1000*time.Since(t0).Seconds()))--- a/commands/multilingual.go
+++ b/commands/multilingual.go
@@ -1,41 +1,66 @@
package commands
import (
+ "fmt"
"sort"
+ "strings"
+
"github.com/spf13/cast"
+ "github.com/spf13/hugo/hugolib"
"github.com/spf13/viper"
)
-var langConfigs map[string]interface{}-var langConfigsList langConfigsSortable
+var langConfigsList hugolib.Languages
-func readMultilingualConfiguration() {+func readMultilingualConfiguration() error { multilingual := viper.GetStringMap("Multilingual") if len(multilingual) == 0 {- langConfigsList = append(langConfigsList, "")
- return
+ // TODO(bep) multilingo langConfigsList = append(langConfigsList, hugolib.NewLanguage("en"))+ return nil
}
- langConfigs = make(map[string]interface{})- for lang, config := range multilingual {- langConfigs[lang] = config
- langConfigsList = append(langConfigsList, lang)
+ var err error
+
+ langConfigsList, err = toSortedLanguages(multilingual)
+
+ if err != nil {+ return fmt.Errorf("Failed to parse multilingual config: %s", err)}
- sort.Sort(langConfigsList)
+
+ return nil
}
-type langConfigsSortable []string
+func toSortedLanguages(l map[string]interface{}) (hugolib.Languages, error) {+ langs := make(hugolib.Languages, len(l))
-func (p langConfigsSortable) Len() int { return len(p) }-func (p langConfigsSortable) Less(i, j int) bool { return weightForLang(p[i]) < weightForLang(p[j]) }-func (p langConfigsSortable) Swap(i, j int) { p[i], p[j] = p[j], p[i] }+ for lang, langConf := range l {+ langsMap, ok := langConf.(map[string]interface{})-func weightForLang(lang string) int {- conf := langConfigs[lang]
- if conf == nil {- return 0
+ if !ok {+ return nil, fmt.Errorf("Language config is not a map: %v", langsMap)+ }
+
+ language := hugolib.NewLanguage(lang)
+
+ for k, v := range langsMap {+ loki := strings.ToLower(k)
+ switch loki {+ case "title":
+ language.Title = cast.ToString(v)
+ case "weight":
+ language.Weight = cast.ToInt(v)
+ }
+
+ // Put all into the Params map
+ // TODO(bep) reconsile with the type handling etc. from other params handlers.
+ language.SetParam(loki, v)
+ }
+
+ langs = append(langs, language)
}
- m := cast.ToStringMap(conf)
- return cast.ToInt(m["weight"])
+
+ sort.Sort(langs)
+
+ return langs, nil
}
--- a/hugolib/multilingual.go
+++ b/hugolib/multilingual.go
@@ -1,43 +1,80 @@
package hugolib
import (
+ "sync"
+
+ "strings"
+
"github.com/spf13/cast"
"github.com/spf13/viper"
)
+type Language struct {+ Lang string
+ Title string
+ Weight int
+ params map[string]interface{}+ paramsInit sync.Once
+}
+
+func NewLanguage(lang string) *Language {+ return &Language{Lang: lang, params: make(map[string]interface{})}+}
+
+type Languages []*Language
+
+func (l Languages) Len() int { return len(l) }+func (l Languages) Less(i, j int) bool { return l[i].Weight < l[j].Weight }+func (l Languages) Swap(i, j int) { l[i], l[j] = l[j], l[i] }+
type Multilingual struct {enabled bool
- config *viper.Viper
- Languages []string
+ Languages Languages
}
-func (ml *Multilingual) GetString(key string) string { return cast.ToString(ml.Get(key)) }-func (ml *Multilingual) GetStringMap(key string) map[string]interface{} {+func (l *Language) Params() map[string]interface{} {+ l.paramsInit.Do(func() {+ // Merge with global config.
+ // TODO(bep) consider making this part of a constructor func.
+ globalParams := viper.GetStringMap("Params")+ for k, v := range globalParams {+ if _, ok := l.params[k]; !ok {+ l.params[k] = v
+ }
+ }
+ })
+ return l.params
+}
+
+func (l *Language) SetParam(k string, v interface{}) {+ l.params[k] = v
+}
+
+func (l *Language) GetString(key string) string { return cast.ToString(l.Get(key)) }+func (ml *Language) GetStringMap(key string) map[string]interface{} {return cast.ToStringMap(ml.Get(key))
}
-func (ml *Multilingual) GetStringMapString(key string) map[string]string {- return cast.ToStringMapString(ml.Get(key))
+func (l *Language) GetStringMapString(key string) map[string]string {+ return cast.ToStringMapString(l.Get(key))
}
-func (ml *Multilingual) Get(key string) interface{} {- if ml != nil && ml.config != nil && ml.config.IsSet(key) {- return ml.config.Get(key)
+func (l *Language) Get(key string) interface{} {+ key = strings.ToLower(key)
+ if v, ok := l.params[key]; ok {+ return v
}
return viper.Get(key)
}
-func (s *Site) SetMultilingualConfig(currentLang string, orderedLanguages []string, langConfigs map[string]interface{}) {- conf := viper.New()
- for k, val := range cast.ToStringMap(langConfigs[currentLang]) {- conf.Set(k, val)
- }
- conf.Set("CurrentLanguage", currentLang)+func (s *Site) SetMultilingualConfig(currentLang *Language, languages Languages) {+
+ // TODO(bep) multilingo evaluate
+ viper.Set("CurrentLanguage", currentLang) ml := &Multilingual{- enabled: len(langConfigs) > 0,
- config: conf,
- Languages: orderedLanguages,
+ enabled: len(languages) > 0,
+ Languages: languages,
}
viper.Set("Multilingual", ml.enabled)s.Multilingual = ml
@@ -45,4 +82,16 @@
func (s *Site) multilingualEnabled() bool {return s.Multilingual != nil && s.Multilingual.enabled
+}
+
+func currentLanguageString() string {+ return currentLanguage().Lang
+}
+
+func currentLanguage() *Language {+ l := viper.Get("CurrentLanguage")+ if l == nil {+ panic("CurrentLanguage not set")+ }
+ return l.(*Language)
}
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -131,7 +131,7 @@
Multilingual bool
CurrentLanguage string
LanguagePrefix string
- Languages []string
+ Languages Languages
}
// SiteSocial is a place to put social details on a site level. These are the
@@ -705,7 +705,7 @@
i18nSources = []source.Input{&source.Filesystem{Base: themeI18nDir}, i18nSources[0]}}
- if err = loadI18n(i18nSources, s.Multilingual.GetString("CurrentLanguage")); err != nil {+ if err = loadI18n(i18nSources, currentLanguageString()); err != nil {return
}
s.timerStep("load i18n")@@ -742,7 +742,7 @@
return
}
- currentLang := s.Multilingual.GetString("CurrentLanguage")+ currentLang := currentLanguageString()
allTranslations := pagesToTranslationsMap(s.AllPages)
assignTranslationsToPages(allTranslations, s.AllPages)
@@ -817,8 +817,28 @@
}
func (s *Site) initializeSiteInfo() {- params := s.Multilingual.GetStringMap("Params")+ var (
+ lang *Language
+ languages Languages
+ )
+
+ cl := viper.Get("CurrentLanguage")+ if cl == nil {+ // Set default to english
+ // TODO(bep) multilingo this looks clumsy
+ lang = NewLanguage("en")+ viper.Set("CurrentLanguage", lang)+ } else {+ lang = cl.(*Language)
+ }
+
+ if s.Multilingual != nil {+ languages = s.Multilingual.Languages
+ }
+
+ params := lang.Params()
+
permalinks := make(PermalinkOverrides)
for k, v := range viper.GetStringMapString("Permalinks") {permalinks[k] = pathPattern(v)
@@ -826,24 +846,20 @@
languagePrefix := ""
if s.multilingualEnabled() {- languagePrefix = "/" + s.Multilingual.GetString("CurrentLanguage")+ languagePrefix = "/" + lang.Lang
}
- languages := []string{}- if s.Multilingual != nil {- languages = s.Multilingual.Languages
- }
-
s.Info = SiteInfo{- BaseURL: template.URL(helpers.SanitizeURLKeepTrailingSlash(viper.GetString("BaseURL"))),- Title: s.Multilingual.GetString("Title"),- Author: s.Multilingual.GetStringMap("author"),- Social: s.Multilingual.GetStringMapString("social"),- LanguageCode: s.Multilingual.GetString("languagecode"),- Copyright: s.Multilingual.GetString("copyright"),- DisqusShortname: s.Multilingual.GetString("DisqusShortname"),+ BaseURL: template.URL(helpers.SanitizeURLKeepTrailingSlash(viper.GetString("BaseURL"))),+ Title: lang.GetString("Title"),+ Author: lang.GetStringMap("author"),+ Social: lang.GetStringMapString("social"),+ LanguageCode: lang.GetString("languagecode"),+ Copyright: lang.GetString("copyright"),+ DisqusShortname: lang.GetString("DisqusShortname"),+ // TODO(bep) multilang, consolidate the below (make into methods etc.)
Multilingual: s.multilingualEnabled(),
- CurrentLanguage: s.Multilingual.GetString("CurrentLanguage"),+ CurrentLanguage: lang.Lang,
LanguagePrefix: languagePrefix,
Languages: languages,
GoogleAnalytics: viper.GetString("GoogleAnalytics"),@@ -1594,7 +1610,7 @@
func (s *Site) addMultilingualPrefix(basePath string) string {hadPrefix := strings.HasPrefix(basePath, "/")
if s.multilingualEnabled() {- basePath = path.Join(s.Multilingual.GetString("CurrentLanguage"), basePath)+ basePath = path.Join(currentLanguageString(), basePath)
if hadPrefix {basePath = "/" + basePath
}
--- a/hugolib/site_test.go
+++ b/hugolib/site_test.go
@@ -1402,13 +1402,13 @@
s := &Site{ Source: &source.InMemorySource{ByteSource: sources}, Multilingual: &Multilingual{- config: viper.New(),
enabled: true,
},
}
// Multilingual settings
viper.Set("Multilingual", true)- s.Multilingual.config.Set("CurrentLanguage", "en")+ en := NewLanguage("en")+ viper.Set("CurrentLanguage", en) viper.Set("DefaultContentLanguage", "fr") viper.Set("paginate", "2")--
⑨