URI: 
       Add proper Language and Languages types - hugo - [fork] hugo port for 9front
  HTML git clone git@git.drkhsh.at/hugo.git
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
   DIR commit 06d12ab895a83fc8a9f94b23e533b25511bbb6d1
   DIR parent ec33732fbe84f67c1164fb713d6cb738609f2e2e
  HTML Author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
       Date:   Sun, 24 Jul 2016 13:58:27 +0200
       
       Add proper Language and Languages types
       
       Diffstat:
         M commands/hugo.go                    |      15 +++++++--------
         M commands/multilingual.go            |      65 +++++++++++++++++++++----------
         M hugolib/multilingual.go             |      85 ++++++++++++++++++++++++-------
         M hugolib/site.go                     |      54 ++++++++++++++++++++-----------
         M hugolib/site_test.go                |       4 ++--
       
       5 files changed, 156 insertions(+), 67 deletions(-)
       ---
   DIR diff --git a/commands/hugo.go b/commands/hugo.go
       @@ -493,9 +493,8 @@ func InitializeConfig(subCmdVs ...*cobra.Command) error {
                                helpers.HugoReleaseVersion(), minVersion)
                }
        
       -        readMultilingualConfiguration()
       +        return readMultilingualConfiguration()
        
       -        return nil
        }
        
        func flagChanged(flags *flag.FlagSet, key string) bool {
       @@ -715,11 +714,11 @@ func buildSite(watching ...bool) (err error) {
        
                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 @@ func buildSite(watching ...bool) (err error) {
                                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 @@ func rebuildSite(events []fsnotify.Event) error {
        
                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()))
   DIR diff --git 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))
       +
       +        for lang, langConf := range l {
       +                langsMap, ok := langConf.(map[string]interface{})
        
       -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] }
       +                if !ok {
       +                        return nil, fmt.Errorf("Language config is not a map: %v", langsMap)
       +                }
        
       -func weightForLang(lang string) int {
       -        conf := langConfigs[lang]
       -        if conf == nil {
       -                return 0
       +                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
        }
   DIR diff --git 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 (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 (ml *Multilingual) GetString(key string) string { return cast.ToString(ml.Get(key)) }
       -func (ml *Multilingual) GetStringMap(key string) map[string]interface{} {
       +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
       @@ -46,3 +83,15 @@ func (s *Site) SetMultilingualConfig(currentLang string, orderedLanguages []stri
        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)
       +}
   DIR diff --git a/hugolib/site.go b/hugolib/site.go
       @@ -131,7 +131,7 @@ type SiteInfo struct {
                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 @@ func (s *Site) Process() (err error) {
                        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 @@ func (s *Site) setupTranslations() {
                        return
                }
        
       -        currentLang := s.Multilingual.GetString("CurrentLanguage")
       +        currentLang := currentLanguageString()
        
                allTranslations := pagesToTranslationsMap(s.AllPages)
                assignTranslationsToPages(allTranslations, s.AllPages)
       @@ -817,7 +817,27 @@ func (s *Site) initialize() (err error) {
        }
        
        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") {
       @@ -826,24 +846,20 @@ func (s *Site) initializeSiteInfo() {
        
                languagePrefix := ""
                if s.multilingualEnabled() {
       -                languagePrefix = "/" + s.Multilingual.GetString("CurrentLanguage")
       -        }
       -
       -        languages := []string{}
       -        if s.Multilingual != nil {
       -                languages = s.Multilingual.Languages
       +                languagePrefix = "/" + lang.Lang
                }
        
                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) newTaxonomyNode(t taxRenderInfo) (*Node, string) {
        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
                        }
   DIR diff --git a/hugolib/site_test.go b/hugolib/site_test.go
       @@ -1402,13 +1402,13 @@ NOTE: should use the "permalinks" configuration with :filename
                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")