Rework the i18n template func handling
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 26 Jul 2016 12:44:37 +0000 (14:44 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 6 Sep 2016 15:32:16 +0000 (18:32 +0300)
Setting the language to use when loading the language bundles just doesn't work.
The template system is unfortanetely a global, and the last languate processed won ...

hugolib/i18n.go
hugolib/site.go
tpl/template_i18n.go

index cb50615013ff1dca4fde47534d1c963729667d53..8caf30d7c69d93d56439857d40650e2d1ff2ea4d 100644 (file)
@@ -19,18 +19,20 @@ import (
        "github.com/spf13/hugo/tpl"
 )
 
-func loadI18n(sources []source.Input, lang string) (err error) {
+func loadI18n(sources []source.Input) error {
        i18nBundle := bundle.New()
+
        for _, currentSource := range sources {
                for _, r := range currentSource.Files() {
-                       err = i18nBundle.ParseTranslationFileBytes(r.LogicalName(), r.Bytes())
+                       err := i18nBundle.ParseTranslationFileBytes(r.LogicalName(), r.Bytes())
                        if err != nil {
-                               return
+                               return err
                        }
                }
        }
 
-       tpl.SetI18nTfunc(lang, i18nBundle)
+       tpl.SetI18nTfuncs(i18nBundle)
 
        return nil
+
 }
index bbaa1e01933946aa9d2bfe6ed62506411d82d19f..d902f693e55f2429d3307af79c6de4fb1039346b 100644 (file)
@@ -395,11 +395,20 @@ func (s *Site) timerStep(step string) {
        s.timer.Step(step)
 }
 
+func (s *Site) preRender() error {
+       return tpl.SetTranslateLang(s.Lang.Lang)
+}
+
 func (s *Site) Build() (err error) {
+
        if err = s.Process(); err != nil {
                return
        }
 
+       if err = s.preRender(); err != nil {
+               return
+       }
+
        if err = s.Render(); err != nil {
                // Better reporting when the template is missing (commit 2bbecc7b)
                jww.ERROR.Printf("Error rendering site: %s", err)
@@ -423,7 +432,10 @@ func (s *Site) Build() (err error) {
 }
 
 func (s *Site) ReBuild(events []fsnotify.Event) error {
+       // TODO(bep) multilingual this needs some rethinking with multiple sites
+
        s.timerStep("initialize rebuild")
+
        // First we need to determine what changed
 
        sourceChanged := []fsnotify.Event{}
@@ -571,6 +583,10 @@ func (s *Site) ReBuild(events []fsnotify.Event) error {
                s.timerStep("build taxonomies")
        }
 
+       if err := s.preRender(); err != nil {
+               return err
+       }
+
        // Once the appropriate prep step is done we render the entire site
        if err = s.Render(); err != nil {
                // Better reporting when the template is missing (commit 2bbecc7b)
@@ -717,10 +733,11 @@ func (s *Site) Process() (err error) {
 
        themeI18nDir, err := helpers.GetThemeI18nDirPath()
        if err == nil {
+               // TODO(bep) multilingo what is this?
                i18nSources = []source.Input{&source.Filesystem{Base: themeI18nDir}, i18nSources[0]}
        }
 
-       if err = loadI18n(i18nSources, s.currentLanguageString()); err != nil {
+       if err = loadI18n(i18nSources); err != nil {
                return
        }
        s.timerStep("load i18n")
index 3b0f0cb633b03cec5e9a01c4725fccc686c941df..5590fe29aab39d74647d750e49cf36de12c2eb1c 100644 (file)
@@ -20,28 +20,46 @@ import (
        jww "github.com/spf13/jwalterweatherman"
 )
 
-var i18nTfunc bundle.TranslateFunc
+type translate struct {
+       translateFuncs map[string]bundle.TranslateFunc
 
-func SetI18nTfunc(lang string, bndl *bundle.Bundle) {
-       tFunc, err := bndl.Tfunc(lang)
-       if err == nil {
-               i18nTfunc = tFunc
-               return
+       current bundle.TranslateFunc
+}
+
+var translater *translate = &translate{translateFuncs: make(map[string]bundle.TranslateFunc)}
+
+// SetTranslateLang sets the translations language to use during template processing.
+// This construction is unfortunate, but the template system is currently global.
+func SetTranslateLang(lang string) error {
+       if f, ok := translater.translateFuncs[lang]; ok {
+               translater.current = f
+               return nil
+       }
+       return fmt.Errorf("Translation func for language %v not found", lang)
+}
+
+func SetI18nTfuncs(bndl *bundle.Bundle) {
+       for _, lang := range bndl.LanguageTags() {
+               tFunc, err := bndl.Tfunc(lang)
+               if err == nil {
+                       translater.translateFuncs[lang] = tFunc
+                       continue
+               }
+               jww.WARN.Printf("could not load translations for language %q (%s), will not translate!\n", lang, err.Error())
+               translater.translateFuncs[lang] = bundle.TranslateFunc(func(id string, args ...interface{}) string {
+                       // TODO: depending on the site mode, we might want to fall back on the default
+                       // language's translation.
+                       // TODO: eventually, we could add --i18n-warnings and print something when
+                       // such things happen.
+                       return fmt.Sprintf("[i18n: %s]", id)
+               })
        }
 
-       jww.WARN.Printf("could not load translations for language %q (%s), will not translate!\n", lang, err.Error())
-       i18nTfunc = bundle.TranslateFunc(func(id string, args ...interface{}) string {
-               // TODO: depending on the site mode, we might want to fall back on the default
-               // language's translation.
-               // TODO: eventually, we could add --i18n-warnings and print something when
-               // such things happen.
-               return fmt.Sprintf("[i18n: %s]", id)
-       })
 }
 
 func I18nTranslate(id string, args ...interface{}) (string, error) {
-       if i18nTfunc == nil {
+       if translater == nil {
                return "", fmt.Errorf("i18n not initialized, have you configured everything properly?")
        }
-       return i18nTfunc(id, args...), nil
+       return translater.current(id, args...), nil
 }