summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2016-07-24 13:58:27 +0200
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>2016-09-06 18:32:15 +0300
commit06d12ab895a83fc8a9f94b23e533b25511bbb6d1 (patch)
treee25be5f3afb89ce99af7aaa49561b23fd053a616
parentec33732fbe84f67c1164fb713d6cb738609f2e2e (diff)
Add proper Language and Languages types
-rw-r--r--commands/hugo.go15
-rw-r--r--commands/multilingual.go65
-rw-r--r--hugolib/multilingual.go85
-rw-r--r--hugolib/site.go54
-rw-r--r--hugolib/site_test.go4
5 files changed, 156 insertions, 67 deletions
diff --git a/commands/hugo.go b/commands/hugo.go
index 57a426458..c773ac5c4 100644
--- 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()))
diff --git a/commands/multilingual.go b/commands/multilingual.go
index 68da7c96d..983dc756d 100644
--- 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
}
diff --git a/hugolib/multilingual.go b/hugolib/multilingual.go
index 2552bad4c..eebd43e3d 100644
--- 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)
+}
diff --git a/hugolib/site.go b/hugolib/site.go
index 308e35c90..92ce48535 100644
--- 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
}
diff --git a/hugolib/site_test.go b/hugolib/site_test.go
index 2f03dec97..9f29bf376 100644
--- 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")