Will revisit Node later.
func toSortedLanguages(l map[string]interface{}) (hugolib.Languages, error) {
langs := make(hugolib.Languages, len(l))
+ i := 0
for lang, langConf := range l {
langsMap, ok := langConf.(map[string]interface{})
language.SetParam(loki, v)
}
- langs = append(langs, language)
+ langs[i] = language
+ i++
}
sort.Sort(langs)
import (
"sync"
+ "sort"
"strings"
"github.com/spf13/cast"
type Languages []*Language
+func NewLanguages(l ...*Language) Languages {
+ languages := make(Languages, len(l))
+ for i := 0; i < len(l); i++ {
+ languages[i] = l[i]
+ }
+ sort.Sort(languages)
+ return languages
+}
+
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
-
Languages Languages
+
+ langMap map[string]*Language
+ langMapInit sync.Once
+}
+
+func (ml *Multilingual) Language(lang string) *Language {
+ ml.langMapInit.Do(func() {
+ ml.langMap = make(map[string]*Language)
+ for _, l := range ml.Languages {
+ ml.langMap[l.Lang] = l
+ }
+ })
+ return ml.langMap[lang]
+}
+
+func (ml *Multilingual) enabled() bool {
+ return len(ml.Languages) > 0
}
func (l *Language) Params() map[string]interface{} {
// TODO(bep) multilingo evaluate
viper.Set("CurrentLanguage", currentLang)
ml := &Multilingual{
- enabled: len(languages) > 0,
Languages: languages,
}
- viper.Set("Multilingual", ml.enabled)
+ viper.Set("Multilingual", ml.enabled())
s.Multilingual = ml
}
func (s *Site) multilingualEnabled() bool {
- return s.Multilingual != nil && s.Multilingual.enabled
+ return s.Multilingual != nil && s.Multilingual.enabled()
}
func currentLanguageString() string {
package hugolib
import (
- "github.com/spf13/cast"
"html/template"
"sync"
"time"
+
+ "github.com/spf13/cast"
)
type Node struct {
PublishDate time.Time
ExpiryDate time.Time
Markup string
- Translations Translations
+ translations Pages
extension string
contentType string
lang string
+ language *Language
renderable bool
Layout string
layoutsCalculated []string
Source: Source{File: *source.NewFile(filename)},
Node: Node{Keywords: []string{}, Sitemap: Sitemap{Priority: -1}},
Params: make(map[string]interface{}),
- Translations: make(Translations),
+ translations: make(Pages, 0),
}
jww.DEBUG.Println("Reading from", page.File.Path())
return viper.GetString("DefaultExtension")
}
+// TODO(bep) multilingo consolidate
+func (p *Page) Language() *Language {
+ return p.language
+}
func (p *Page) Lang() string {
return p.lang
}
+// AllTranslations returns all translations, including the current Page.
+func (p *Page) AllTranslations() Pages {
+ return p.translations
+}
+
+// Translations returns the translations excluding the current Page.
+func (p *Page) Translations() Pages {
+ translations := make(Pages, 0)
+ for _, t := range p.translations {
+ if t != p {
+ translations = append(translations, t)
+ }
+ }
+ return translations
+}
+
func (p *Page) LinkTitle() string {
if len(p.linkTitle) > 0 {
return p.linkTitle
return p1.Weight < p2.Weight
}
+var languagePageSort = func(p1, p2 *Page) bool {
+ if p1.language.Weight == p2.language.Weight {
+ if p1.Date.Unix() == p2.Date.Unix() {
+ if p1.LinkTitle() == p2.LinkTitle() {
+ return (p1.FullFilePath() < p2.FullFilePath())
+ }
+ return (p1.LinkTitle() < p2.LinkTitle())
+ }
+ return p1.Date.Unix() > p2.Date.Unix()
+ }
+ return p1.language.Weight < p2.language.Weight
+}
+
func (ps *pageSorter) Len() int { return len(ps.pages) }
func (ps *pageSorter) Swap(i, j int) { ps.pages[i], ps.pages[j] = ps.pages[j], ps.pages[i] }
return pages
}
+// ByLanguage sorts the Pages by the language's Weight.
+//
+// Adjacent invocactions on the same receiver will return a cached result.
+//
+// This may safely be executed in parallel.
+func (p Pages) ByLanguage() Pages {
+
+ key := "pageSort.ByLanguage"
+
+ pages, _ := spc.get(key, p, pageBy(languagePageSort).Sort)
+
+ return pages
+}
+
// Reverse reverses the order in Pages and returns a copy.
//
// Adjacent invocactions on the same receiver will return a cached result.
currentLang := currentLanguageString()
- allTranslations := pagesToTranslationsMap(s.AllPages)
+ allTranslations := pagesToTranslationsMap(s.Multilingual, s.AllPages)
assignTranslationsToPages(allTranslations, s.AllPages)
- var currentLangPages []*Page
+ var currentLangPages Pages
for _, p := range s.AllPages {
if p.Lang() == "" || strings.HasPrefix(currentLang, p.lang) {
currentLangPages = append(currentLangPages, p)
err := s.render(name, d, renderBuffer, layouts...)
+ if err != nil {
+ return err
+ }
+
outBuffer := bp.GetBuffer()
defer bp.PutBuffer(outBuffer)
transformer := transform.NewChain(transform.AbsURLInXML)
transformer.Apply(outBuffer, renderBuffer, path)
- if err == nil {
- err = s.writeDestFile(dest, outBuffer)
- }
+ return s.writeDestFile(dest, outBuffer)
- return err
}
func (s *Site) renderAndWritePage(name string, dest string, d interface{}, layouts ...string) error {
err := s.render(name, d, renderBuffer, layouts...)
+ if err != nil {
+ return err
+ }
+
+ if renderBuffer.Len() == 0 {
+ if p, ok := d.(*Page); ok {
+ fmt.Println(">>>>", p.Lang(), len(p.Content))
+ }
+ }
+
outBuffer := bp.GetBuffer()
defer bp.PutBuffer(outBuffer)
}
if err == nil {
+
if err = s.writeDestPage(dest, pageTarget, outBuffer); err != nil {
return err
}
}
if err := s.renderThing(d, layout, w); err != nil {
+
// Behavior here should be dependent on if running in server or watch mode.
distinctErrorLogger.Printf("Error while rendering %s: %v", name, err)
if !s.running() && !testMode {
}
func (s *Site) renderThing(d interface{}, layout string, w io.Writer) error {
+
// If the template doesn't exist, then return, but leave the Writer open
if templ := s.Tmpl.Lookup(layout); templ != nil {
return templ.Execute(w, d)
hugofs.InitMemFs()
- s := &Site{
- Source: &source.InMemorySource{ByteSource: sources},
- Multilingual: &Multilingual{
- enabled: true,
- },
- }
// Multilingual settings
viper.Set("Multilingual", true)
en := NewLanguage("en")
viper.Set("DefaultContentLanguage", "fr")
viper.Set("paginate", "2")
+ languages := NewLanguages(en, NewLanguage("fr"))
+ s := &Site{
+ Source: &source.InMemorySource{ByteSource: sources},
+ Multilingual: &Multilingual{
+ Languages: languages,
+ },
+ }
+
s.prepTemplates()
s.initializeSiteInfo()
permalink, err := doc1en.Permalink()
assert.NoError(t, err, "permalink call failed")
assert.Equal(t, "http://example.com/blog/en/sect/doc1-slug", permalink, "invalid doc1.en permalink")
- assert.Len(t, doc1en.Translations, 1, "doc1-en should have one translation, excluding itself")
+ assert.Len(t, doc1en.Translations(), 1, "doc1-en should have one translation, excluding itself")
doc2 := s.Pages[1]
permalink, err = doc2.Permalink()
assert.Equal(t, doc2.Next, doc3, "doc3 should follow doc2, in .Next")
- doc1fr := doc1en.Translations["fr"]
+ doc1fr := doc1en.Translations()[0]
permalink, err = doc1fr.Permalink()
assert.NoError(t, err, "permalink call failed")
assert.Equal(t, "http://example.com/blog/fr/sect/doc1", permalink, "invalid doc1fr permalink")
- assert.Equal(t, doc1en.Translations["fr"], doc1fr, "doc1-en should have doc1-fr as translation")
- assert.Equal(t, doc1fr.Translations["en"], doc1en, "doc1-fr should have doc1-en as translation")
+ assert.Equal(t, doc1en.Translations()[0], doc1fr, "doc1-en should have doc1-fr as translation")
+ assert.Equal(t, doc1fr.Translations()[0], doc1en, "doc1-fr should have doc1-en as translation")
+ assert.Equal(t, "fr", doc1fr.Language().Lang)
doc4 := s.AllPages[4]
permalink, err = doc4.Permalink()
assert.NoError(t, err, "permalink call failed")
assert.Equal(t, "http://example.com/blog/fr/sect/doc4", permalink, "invalid doc4 permalink")
- assert.Len(t, doc4.Translations, 0, "found translations for doc4")
+ assert.Len(t, doc4.Translations(), 0, "found translations for doc4")
doc5 := s.AllPages[5]
permalink, err = doc5.Permalink()
package hugolib
+import (
+ "fmt"
+)
+
// Translations represent the other translations for a given page. The
// string here is the language code, as affected by the `post.LANG.md`
// filename.
type Translations map[string]*Page
-func pagesToTranslationsMap(pages []*Page) map[string]Translations {
+func pagesToTranslationsMap(ml *Multilingual, pages []*Page) map[string]Translations {
out := make(map[string]Translations)
for _, page := range pages {
continue
}
+ language := ml.Language(pageLang)
+
+ if language == nil {
+ panic(fmt.Sprintf("Page language not found in multilang setup: %s", pageLang))
+ }
+
+ page.language = language
+
pageTranslation[pageLang] = page
out[base] = pageTranslation
}
continue
}
- for lang, translatedPage := range trans {
+ // TODO(bep) multilingo remove lang
+ for _, translatedPage := range trans {
if translatedPage == page {
continue
}
- page.Translations[lang] = translatedPage
+ page.translations = append(page.translations, translatedPage)
}
+
+ pageBy(languagePageSort).Sort(page.translations)
}
}