Redirect to main language from root
authorBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Thu, 4 Aug 2016 18:41:30 +0000 (20:41 +0200)
committerBjørn Erik Pedersen <bjorn.erik.pedersen@gmail.com>
Tue, 6 Sep 2016 15:32:17 +0000 (18:32 +0300)
See #2312
See #2309

hugolib/hugo_sites_test.go
hugolib/site.go
target/htmlredirect.go

index aa857507566c24f5da1001075d36cba3cd83187b..cbd6bd627c38bbade2de66baa577783611744a62 100644 (file)
@@ -14,10 +14,10 @@ import (
        "github.com/spf13/hugo/helpers"
        "github.com/spf13/hugo/hugofs"
        "github.com/spf13/hugo/source"
+       jww "github.com/spf13/jwalterweatherman"
        "github.com/spf13/viper"
        "github.com/stretchr/testify/assert"
-
-       jww "github.com/spf13/jwalterweatherman"
+       "github.com/stretchr/testify/require"
 )
 
 func init() {
@@ -52,7 +52,7 @@ func TestMultiSites(t *testing.T) {
 
        sites := createMultiTestSites(t)
 
-       err := sites.Build(BuildCfg{skipRender: true})
+       err := sites.Build(BuildCfg{})
 
        if err != nil {
                t.Fatalf("Failed to build sites: %s", err)
@@ -126,6 +126,11 @@ func TestMultiSites(t *testing.T) {
                assert.Equal(t, "fr", frenchPage.Lang())
        }
 
+       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)
+
 }
 
 func TestMultiSitesRebuild(t *testing.T) {
@@ -498,7 +503,7 @@ func readFileFromFs(t *testing.T, fs afero.Fs, filename string) string {
                // Print some debug info
                root := strings.Split(filename, helpers.FilePathSeparator)[0]
                afero.Walk(fs, root, func(path string, info os.FileInfo, err error) error {
-                       if !info.IsDir() {
+                       if info != nil && !info.IsDir() {
                                fmt.Println("    ", path)
                        }
 
index cce78f14d55ab01efab0e84c3a8b4603616e435f..776876980f1a58a6b6871e39ae9cfc9e950737e9 100644 (file)
@@ -134,10 +134,11 @@ func newSiteFromSources(pathContentPairs ...string) *Site {
 }
 
 type targetList struct {
-       page     target.Output
-       pageUgly target.Output
-       file     target.Output
-       alias    target.AliasPublisher
+       page          target.Output
+       pageUgly      target.Output
+       file          target.Output
+       alias         target.AliasPublisher
+       languageAlias target.AliasPublisher
 }
 
 type SiteInfo struct {
@@ -1398,6 +1399,16 @@ func (s *Site) renderAliases() error {
                        }
                }
        }
+
+       if s.Multilingual.enabled() {
+               mainLang := s.Multilingual.DefaultLang.Lang
+               mainLangURL := helpers.AbsURL(mainLang)
+               jww.DEBUG.Printf("Write redirect to main language %s: %s", mainLang, mainLangURL)
+               if err := s.publishDestAlias(s.languageAliasTarget(), "/", mainLangURL); err != nil {
+                       return err
+               }
+       }
+
        return nil
 }
 
@@ -2161,6 +2172,11 @@ func (s *Site) aliasTarget() target.AliasPublisher {
        return s.targets.alias
 }
 
+func (s *Site) languageAliasTarget() target.AliasPublisher {
+       s.initTargetList()
+       return s.targets.languageAlias
+}
+
 func (s *Site) initTargetList() {
        s.targetListInit.Do(func() {
                if s.targets.page == nil {
@@ -2185,6 +2201,12 @@ func (s *Site) initTargetList() {
                                PublishDir: s.absPublishDir(),
                        }
                }
+               if s.targets.languageAlias == nil {
+                       s.targets.languageAlias = &target.HTMLRedirectAlias{
+                               PublishDir: s.absPublishDir(),
+                               AllowRoot:  true,
+                       }
+               }
        })
 }
 
@@ -2198,7 +2220,12 @@ func (s *Site) writeDestPage(path string, publisher target.Publisher, reader io.
        return publisher.Publish(path, reader)
 }
 
+// AliasPublisher
 func (s *Site) writeDestAlias(path string, permalink string) (err error) {
+       return s.publishDestAlias(s.aliasTarget(), path, permalink)
+}
+
+func (s *Site) publishDestAlias(aliasPublisher target.AliasPublisher, path string, permalink string) (err error) {
        if viper.GetBool("RelativeURLs") {
                // convert `permalink` into URI relative to location of `path`
                baseURL := helpers.SanitizeURLKeepTrailingSlash(viper.GetString("BaseURL"))
@@ -2212,7 +2239,7 @@ func (s *Site) writeDestAlias(path string, permalink string) (err error) {
                permalink = filepath.ToSlash(permalink)
        }
        jww.DEBUG.Println("creating alias:", path, "redirecting to", permalink)
-       return s.aliasTarget().Publish(path, permalink)
+       return aliasPublisher.Publish(path, permalink)
 }
 
 func (s *Site) draftStats() string {
index d8eac943ca407567588495580fbded210e6285ff..81051589a54b0aef8e6144ca86150dd67b5804e6 100644 (file)
@@ -45,6 +45,7 @@ type AliasPublisher interface {
 type HTMLRedirectAlias struct {
        PublishDir string
        Templates  *template.Template
+       AllowRoot  bool // for the language redirects
 }
 
 func (h *HTMLRedirectAlias) Translate(alias string) (aliasPath string, err error) {
@@ -56,7 +57,7 @@ func (h *HTMLRedirectAlias) Translate(alias string) (aliasPath string, err error
        alias = filepath.Clean(alias)
        components := strings.Split(alias, helpers.FilePathSeparator)
 
-       if alias == helpers.FilePathSeparator {
+       if !h.AllowRoot && alias == helpers.FilePathSeparator {
                return "", fmt.Errorf("Alias \"%s\" resolves to website root directory", originalAlias)
        }