ref: 90de511017f9dcc65cccd7d161c70f326df3ab5b
parent: 36f2a1f676c6e8821d2d1600c696dcb2658d1cc9
author: Bjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
date: Fri Aug 5 09:10:58 EDT 2016
Make taxonomies configurable per language See #2312
--- a/commands/hugo.go
+++ b/commands/hugo.go
@@ -493,12 +493,12 @@
helpers.HugoReleaseVersion(), minVersion)
}
- h, err := readMultilingualConfiguration()
+ h, err := hugolib.NewHugoSitesFromConfiguration()
if err != nil {
return err
}
- //TODO(bep) refactor ...
+ //TODO(bep) ml refactor ...
Hugo = h
return nil
--- a/commands/multilingual.go
+++ /dev/null
@@ -1,75 +1,0 @@
-package commands
-
-import (
- "fmt"
- "sort"
-
- "strings"
-
- "github.com/spf13/cast"
- "github.com/spf13/hugo/hugolib"
- "github.com/spf13/viper"
-)
-
-func readMultilingualConfiguration() (*hugolib.HugoSites, error) {
- sites := make([]*hugolib.Site, 0)
- multilingual := viper.GetStringMap("Languages")
- if len(multilingual) == 0 {
- // TODO(bep) multilingo langConfigsList = append(langConfigsList, hugolib.NewLanguage("en"))
- sites = append(sites, hugolib.NewSite(hugolib.NewLanguage("en")))
- }
-
- if len(multilingual) > 0 {
- var err error
-
- languages, err := toSortedLanguages(multilingual)
-
- if err != nil {
- return nil, fmt.Errorf("Failed to parse multilingual config: %s", err)
- }
-
- for _, lang := range languages {
- sites = append(sites, hugolib.NewSite(lang))
- }
-
- }
-
- return hugolib.NewHugoSites(sites...)
-
-}
-
-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{})
-
- 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[i] = language
- i++
- }
-
- sort.Sort(langs)
-
- return langs, nil
-}
--- a/docs/content/content/multilingual.md
+++ b/docs/content/content/multilingual.md
@@ -38,6 +38,25 @@
Only the obvious non-global options can be overridden per language. Examples of global options are `BaseURL`, `BuildDrafts`, etc.
+Taxonomies configuration can also be set per language, example:
+
+```
+[Taxonomies]
+tag = "tags"
+
+[Languages]
+[Languages.en]
+weight = 1
+title = "English"
+
+[Languages.fr]
+weight = 2
+title = "Français"
+[Languages.fr.Taxonomies]
+plaque = "plaques"
+```
+
+
### Translating your content
Translated articles are identified by the name of the content file.
--- a/hugolib/config_test.go
+++ b/hugolib/config_test.go
@@ -28,9 +28,9 @@
PaginatePath = "side"
`
- writeSource(t, "config.toml", configContent)
+ writeSource(t, "hugo.toml", configContent)
- require.NoError(t, LoadGlobalConfig("", "config.toml"))
+ require.NoError(t, LoadGlobalConfig("", "hugo.toml"))
assert.Equal(t, "side", viper.GetString("PaginatePath"))
// default
assert.Equal(t, "layouts", viper.GetString("LayoutDir"))
--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -15,6 +15,7 @@
import (
"errors"
+ "fmt"
"strings"
"sync"
"time"
@@ -53,6 +54,34 @@
return &HugoSites{Multilingual: langConfig, Sites: sites}, nil
}
+// NewHugoSitesFromConfiguration creates HugoSites from the global Viper config.
+func NewHugoSitesFromConfiguration() (*HugoSites, error) {
+ sites := make([]*Site, 0)
+ multilingual := viper.GetStringMap("Languages")
+ if len(multilingual) == 0 {
+ // TODO(bep) multilingo langConfigsList = append(langConfigsList, NewLanguage("en"))
+ sites = append(sites, NewSite(NewLanguage("en")))
+ }
+
+ if len(multilingual) > 0 {
+ var err error
+
+ languages, err := toSortedLanguages(multilingual)
+
+ if err != nil {
+ return nil, fmt.Errorf("Failed to parse multilingual config: %s", err)
+ }
+
+ for _, lang := range languages {
+ sites = append(sites, NewSite(lang))
+ }
+
+ }
+
+ return NewHugoSites(sites...)
+
+}
+
// Reset resets the sites, making it ready for a full rebuild.
// TODO(bep) multilingo
func (h HugoSites) Reset() {
@@ -61,7 +90,7 @@
}
}
-func (h HugoSites) siteInfos() []*SiteInfo {
+func (h HugoSites) toSiteInfos() []*SiteInfo {
infos := make([]*SiteInfo, len(h.Sites))
for i, s := range h.Sites {
infos[i] = &s.Info
@@ -220,7 +249,7 @@
smLayouts := []string{"sitemapindex.xml", "_default/sitemapindex.xml", "_internal/_default/sitemapindex.xml"}
if err := s.renderAndWriteXML("sitemapindex", sitemapDefault.Filename,
- h.siteInfos(), s.appendThemeTemplates(smLayouts)...); err != nil {
+ h.toSiteInfos(), s.appendThemeTemplates(smLayouts)...); err != nil {
return err
}
--- a/hugolib/hugo_sites_test.go
+++ b/hugolib/hugo_sites_test.go
@@ -22,8 +22,7 @@
func init() {
testCommonResetState()
- jww.SetStdoutThreshold(jww.LevelError)
-
+ jww.SetStdoutThreshold(jww.LevelCritical)
}
func testCommonResetState() {
@@ -38,8 +37,8 @@
}
-func TestMultiSites(t *testing.T) {
-
+func TestMultiSitesBuild(t *testing.T) {
+ testCommonResetState()
sites := createMultiTestSites(t)
err := sites.Build(BuildCfg{})
@@ -128,10 +127,20 @@
sitemapFr := readDestination(t, "public/fr/sitemap.xml")
require.True(t, strings.Contains(sitemapEn, "http://example.com/blog/en/sect/doc2/"), sitemapEn)
require.True(t, strings.Contains(sitemapFr, "http://example.com/blog/fr/sect/doc1/"), sitemapFr)
+
+ // Check taxonomies
+ enTags := enSite.Taxonomies["tags"]
+ frTags := frSite.Taxonomies["plaques"]
+ require.Len(t, enTags, 2, fmt.Sprintf("Tags in en: %=v", enTags))
+ require.Len(t, frTags, 2, fmt.Sprintf("Tags in fr: %=v", frTags))
+ require.NotNil(t, enTags["tag1"])
+ require.NotNil(t, frTags["frtag1"])
+ readDestination(t, "public/fr/plaques/frtag1/index.html")
+ readDestination(t, "public/en/tags/tag1/index.html")
}
func TestMultiSitesRebuild(t *testing.T) {
-
+ testCommonResetState()
sites := createMultiTestSites(t)
cfg := BuildCfg{}
@@ -294,17 +303,7 @@
}
func createMultiTestSites(t *testing.T) *HugoSites {
- // General settings
- hugofs.InitMemFs()
- viper.Set("DefaultExtension", "html")
- viper.Set("baseurl", "http://example.com/blog")
- viper.Set("DisableSitemap", false)
- viper.Set("DisableRSS", false)
- viper.Set("RSSUri", "index.xml")
- viper.Set("Taxonomies", map[string]string{"tag": "tags"})
- viper.Set("Permalinks", map[string]string{"other": "/somewhere/else/:filename"})
-
// Add some layouts
if err := afero.WriteFile(hugofs.Source(),
filepath.Join("layouts", "_default/single.html"),
@@ -362,9 +361,9 @@
`)},
{filepath.FromSlash("sect/doc1.fr.md"), []byte(`---
title: doc1
-tags:
- - tag1
- - tag2
+plaques:
+ - frtag1
+ - frtag2
publishdate: "2000-01-04"
---
# doc1
@@ -393,8 +392,8 @@
`)},
{filepath.FromSlash("sect/doc4.md"), []byte(`---
title: doc4
-tags:
- - tag1
+plaques:
+ - frtag1
publishdate: "2000-01-05"
---
# doc4
@@ -446,14 +445,40 @@
`)},
}
- // Multilingual settings
- viper.Set("Multilingual", true)
- en := NewLanguage("en")
- viper.Set("DefaultContentLanguage", "fr")
- viper.Set("paginate", "2")
+ tomlConfig := `
+DefaultExtension = "html"
+baseurl = "http://example.com/blog"
+DisableSitemap = false
+DisableRSS = false
+RSSUri = "index.xml"
- languages := NewLanguages(en, NewLanguage("fr"))
+paginate = 2
+DefaultContentLanguage = "fr"
+
+[permalinks]
+ other = "/somewhere/else/:filename"
+
+[Taxonomies]
+tag = "tags"
+
+[Languages]
+[Languages.en]
+weight = 1
+title = "English"
+
+[Languages.fr]
+weight = 2
+title = "Français"
+[Languages.fr.Taxonomies]
+plaque = "plaques"
+`
+
+ writeSource(t, "multilangconfig.toml", tomlConfig)
+ if err := LoadGlobalConfig("", "multilangconfig.toml"); err != nil {
+ t.Fatalf("Failed to load config: %s", err)
+ }
+
// Hugo support using ByteSource's directly (for testing),
// but to make it more real, we write them to the mem file system.
for _, s := range sources {
@@ -466,7 +491,8 @@
if err != nil {
t.Fatalf("Unable to locate file")
}
- sites, err := newHugoSitesFromLanguages(languages)
+
+ sites, err := NewHugoSitesFromConfiguration()
if err != nil {
t.Fatalf("Failed to create sites: %s", err)
--- a/hugolib/multilingual.go
+++ b/hugolib/multilingual.go
@@ -6,6 +6,8 @@
"sort"
"strings"
+ "fmt"
+
"github.com/spf13/cast"
"github.com/spf13/viper"
)
@@ -111,4 +113,40 @@
func (s *Site) currentLanguage() *Language {
return s.Language
+}
+
+func toSortedLanguages(l map[string]interface{}) (Languages, error) {
+ langs := make(Languages, len(l))
+ i := 0
+
+ for lang, langConf := range l {
+ langsMap, ok := langConf.(map[string]interface{})
+
+ if !ok {
+ return nil, fmt.Errorf("Language config is not a map: %v", langsMap)
+ }
+
+ language := 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[i] = language
+ i++
+ }
+
+ sort.Sort(langs)
+
+ return langs, nil
}
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -1325,7 +1325,7 @@
func (s *Site) assembleTaxonomies() {
s.Taxonomies = make(TaxonomyList)
- taxonomies := viper.GetStringMapString("Taxonomies")
+ taxonomies := s.Language.GetStringMapString("Taxonomies")
jww.INFO.Printf("found taxonomies: %#v\n", taxonomies)
for _, plural := range taxonomies {
@@ -1563,7 +1563,7 @@
go errorCollator(results, errs)
- taxonomies := viper.GetStringMapString("Taxonomies")
+ taxonomies := s.Language.GetStringMapString("Taxonomies")
for singular, plural := range taxonomies {
for key, pages := range s.Taxonomies[plural] {
taxes <- taxRenderInfo{key, pages, singular, plural}
@@ -1693,7 +1693,7 @@
// renderListsOfTaxonomyTerms renders a page per taxonomy that lists the terms for that taxonomy
func (s *Site) renderListsOfTaxonomyTerms() (err error) {
- taxonomies := viper.GetStringMapString("Taxonomies")
+ taxonomies := s.Language.GetStringMapString("Taxonomies")
for singular, plural := range taxonomies {
n := s.newNode()
n.Title = strings.Title(plural)
@@ -1969,7 +1969,7 @@
jww.FEEDBACK.Printf("%d pages created\n", len(s.Pages))
jww.FEEDBACK.Printf("%d non-page files copied\n", len(s.Files))
jww.FEEDBACK.Printf("%d paginator pages created\n", s.Info.paginationPageCount)
- taxonomies := viper.GetStringMapString("Taxonomies")
+ taxonomies := s.Language.GetStringMapString("Taxonomies")
for _, pl := range taxonomies {
jww.FEEDBACK.Printf("%d %s created\n", len(s.Taxonomies[pl]), pl)
--- a/hugolib/taxonomy_test.go
+++ b/hugolib/taxonomy_test.go
@@ -30,7 +30,7 @@
viper.Set("taxonomies", taxonomies)
- site := new(Site)
+ site := newSiteDefaultLang()
page, _ := NewPageFrom(strings.NewReader(pageYamlWithTaxonomiesA), "path/to/page")
site.Pages = append(site.Pages, page)
site.assembleTaxonomies()
--
⑨