shithub: hugo

Download patch

ref: b6fcb3d0bbf8e7632206104cb14ce9e708fdbcd3
parent: d572071784f54f083ab7918c5029d2f88bc64016
author: Bjørn Erik Pedersen <[email protected]>
date: Thu Aug 4 18:12:19 EDT 2016

Add sitemap index for multilingual sites

See #2309

--- a/hugolib/hugo_sites.go
+++ b/hugolib/hugo_sites.go
@@ -61,6 +61,14 @@
 	}
 }
 
+func (h HugoSites) siteInfos() []*SiteInfo {
+	infos := make([]*SiteInfo, len(h.Sites))
+	for i, s := range h.Sites {
+		infos[i] = &s.Info
+	}
+	return infos
+}
+
 type BuildCfg struct {
 	// Whether we are in watch (server) mode
 	Watching bool
@@ -118,9 +126,9 @@
 		return err
 	}
 
-	for _, s := range h.Sites {
+	if !config.skipRender {
+		for _, s := range h.Sites {
 
-		if !config.skipRender {
 			if err := s.Render(); err != nil {
 				return err
 			}
@@ -129,7 +137,10 @@
 				s.Stats()
 			}
 		}
-		// TODO(bep) ml lang in site.Info?
+
+		if err := h.render(); err != nil {
+			return err
+		}
 	}
 
 	if config.PrintStats {
@@ -180,6 +191,10 @@
 				s.Stats()
 			}
 		}
+
+		if err := h.render(); err != nil {
+			return err
+		}
 	}
 
 	if config.PrintStats {
@@ -188,6 +203,28 @@
 
 	return nil
 
+}
+
+// Render the cross-site artifacts.
+func (h *HugoSites) render() error {
+
+	if !h.Multilingual.enabled() {
+		return nil
+	}
+
+	// TODO(bep) DRY
+	sitemapDefault := parseSitemap(viper.GetStringMap("Sitemap"))
+
+	s := h.Sites[0]
+
+	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 {
+		return err
+	}
+
+	return nil
 }
 
 func (s *HugoSites) setupTranslations(master *Site) {
--- a/hugolib/hugo_sites_test.go
+++ b/hugolib/hugo_sites_test.go
@@ -126,11 +126,18 @@
 		assert.Equal(t, "fr", frenchPage.Lang())
 	}
 
+	// Check redirect to main language, French
 	languageRedirect := readDestination(t, "public/index.html")
-
-	// French is the main content language
 	require.True(t, strings.Contains(languageRedirect, "0; url=http://example.com/blog/fr"), languageRedirect)
 
+	// Check sitemap(s)
+	sitemapIndex := readDestination(t, "public/sitemap.xml")
+	require.True(t, strings.Contains(sitemapIndex, "<loc>http:/example.com/blog/en/sitemap.xml</loc>"), sitemapIndex)
+	require.True(t, strings.Contains(sitemapIndex, "<loc>http:/example.com/blog/fr/sitemap.xml</loc>"), sitemapIndex)
+	sitemapEn := readDestination(t, "public/en/sitemap.xml")
+	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)
 }
 
 func TestMultiSitesRebuild(t *testing.T) {
--- a/hugolib/public/rss
+++ /dev/null
@@ -1,11 +1,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
-  <channel>
-    <title></title>
-    <link>/rss/</link>
-    <description>Recent content on </description>
-    <generator>Hugo -- gohugo.io</generator>
-    <atom:link href="/rss/" rel="self" type="application/rss+xml" />
-    
-  </channel>
-</rss>
\ No newline at end of file
--- a/hugolib/public/sitemap.xml
+++ /dev/null
@@ -1,8 +1,0 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
-  
-  <url>
-    <loc>/</loc>
-  </url>
-  
-</urlset>
\ No newline at end of file
--- a/hugolib/site.go
+++ b/hugolib/site.go
@@ -170,10 +170,10 @@
 	paginationPageCount   uint64
 	Data                  *map[string]interface{}
 
-	Multilingual    bool
-	CurrentLanguage string
-	LanguagePrefix  string
-	Languages       Languages
+	Multilingual   bool
+	Language       *Language
+	LanguagePrefix string
+	Languages      Languages
 }
 
 // SiteSocial is a place to put social details on a site level. These are the
@@ -831,6 +831,21 @@
 	return
 }
 
+// HomeURL is a convenience method giving the absolute URL to the home page.
+func (s *SiteInfo) HomeAbsURL() string {
+	base := "/"
+	if s.Multilingual {
+		base = s.Language.Lang
+	}
+	return helpers.AbsURL(base)
+}
+
+// SitemapAbsURL is a convenience method giving the absolute URL to the sitemap.
+func (s *SiteInfo) SitemapAbsURL() string {
+	sitemapDefault := parseSitemap(viper.GetStringMap("Sitemap"))
+	return path.Join(s.HomeAbsURL(), sitemapDefault.Filename)
+}
+
 func (s *Site) initializeSiteInfo() {
 
 	var (
@@ -864,7 +879,7 @@
 		DisqusShortname: lang.GetString("DisqusShortname"),
 		// TODO(bep) multilang, consolidate the below (make into methods etc.)
 		Multilingual:          s.multilingualEnabled(),
-		CurrentLanguage:       lang.Lang,
+		Language:              lang,
 		LanguagePrefix:        languagePrefix,
 		Languages:             languages,
 		GoogleAnalytics:       lang.GetString("GoogleAnalytics"),
--- a/tpl/template_embedded.go
+++ b/tpl/template_embedded.go
@@ -100,6 +100,19 @@
   {{ end }}
 </urlset>`)
 
+	// For multilanguage sites
+	t.AddInternalTemplate("_default", "sitemapindex.xml", `<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
+	{{ range . }}
+	<sitemap>
+	   	<loc>{{ .SitemapAbsURL }}</loc>
+		{{ if not .LastChange.IsZero }}
+	   	<lastmod>{{ .LastChange.Format "2006-01-02T15:04:05-07:00" | safeHTML }}</lastmod>
+		{{ end }}
+	</sitemap>
+	{{ end }}
+</sitemapindex>
+`)
+
 	t.AddInternalTemplate("", "pagination.html", `{{ $pag := $.Paginator }}
     {{ if gt $pag.TotalPages 1 }}
     <ul class="pagination">