diff --git a/commands/hugobuilder.go b/commands/hugobuilder.go index b5cd0c2bb..d2b43cc77 100644 --- a/commands/hugobuilder.go +++ b/commands/hugobuilder.go @@ -1042,8 +1042,8 @@ func (c *hugoBuilder) rebuildSites(events []fsnotify.Event) error { if c.fastRenderMode { c.withConf(func(conf *commonConfig) { // Make sure we always render the home pages - for _, l := range conf.configs.Languages { - langPath := h.GetLangSubDir(l.Lang) + for _, l := range conf.configs.ConfigLangs() { + langPath := l.LanguagePrefix() if langPath != "" { langPath = langPath + "/" } diff --git a/config/allconfig/configlanguage.go b/config/allconfig/configlanguage.go index be549126b..534276c25 100644 --- a/config/allconfig/configlanguage.go +++ b/config/allconfig/configlanguage.go @@ -41,6 +41,16 @@ func (c ConfigLanguage) LanguagesDefaultFirst() langs.Languages { return c.m.LanguagesDefaultFirst } +func (c ConfigLanguage) LanguagePrefix() string { + if c.DefaultContentLanguageInSubdir() && c.DefaultContentLanguage() == c.Language().Lang { + return c.Language().Lang + } + if !c.IsMultiLingual() || c.DefaultContentLanguage() == c.Language().Lang { + return "" + } + return c.Language().Lang +} + func (c ConfigLanguage) BaseURL() urls.BaseURL { return c.config.C.BaseURL } diff --git a/config/configProvider.go b/config/configProvider.go index 5d6acce9f..946830056 100644 --- a/config/configProvider.go +++ b/config/configProvider.go @@ -27,6 +27,7 @@ type AllProvider interface { Language() *langs.Language Languages() langs.Languages LanguagesDefaultFirst() langs.Languages + LanguagePrefix() string BaseURL() urls.BaseURL BaseURLLiveReload() urls.BaseURL Environment() string diff --git a/helpers/url_test.go b/helpers/url_test.go index b51625a30..448756b5b 100644 --- a/helpers/url_test.go +++ b/helpers/url_test.go @@ -109,8 +109,16 @@ func doTestAbsURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool, "weight": 10, }, }) + v.Set("defaultContentLanguage", "en") + } else { + v.Set("defaultContentLanguage", lang) + v.Set("languages", map[string]any{ + lang: map[string]interface{}{ + "weight": 10, + }, + }) } - v.Set("defaultContentLanguage", "en") + v.Set("defaultContentLanguageInSubdir", defaultInSubDir) v.Set("baseURL", test.baseURL) @@ -118,16 +126,21 @@ func doTestAbsURL(t *testing.T, defaultInSubDir, addLanguage, multilingual bool, if multilingual { configLang = lang } + defaultContentLanguage := lang + if multilingual { + defaultContentLanguage = "en" + } + p := newTestPathSpecFromCfgAndLang(v, configLang) output := p.AbsURL(test.input, addLanguage) expected := test.expected - if multilingual && addLanguage { - if !defaultInSubDir && lang == "en" { - expected = strings.Replace(expected, "MULTI", "", 1) - } else { - expected = strings.Replace(expected, "MULTI", lang+"/", 1) - } + if addLanguage { + addLanguage = defaultInSubDir && lang == defaultContentLanguage + addLanguage = addLanguage || (lang != defaultContentLanguage && multilingual) + } + if addLanguage { + expected = strings.Replace(expected, "MULTI", lang+"/", 1) } else { expected = strings.Replace(expected, "MULTI", "", 1) } @@ -162,8 +175,16 @@ func doTestRelURL(t testing.TB, defaultInSubDir, addLanguage, multilingual bool, "weight": 10, }, }) + v.Set("defaultContentLanguage", "en") + } else { + v.Set("defaultContentLanguage", lang) + v.Set("languages", map[string]any{ + lang: map[string]interface{}{ + "weight": 10, + }, + }) } - v.Set("defaultContentLanguage", "en") + v.Set("defaultContentLanguageInSubdir", defaultInSubDir) tests := []struct { @@ -209,25 +230,25 @@ func doTestRelURL(t testing.TB, defaultInSubDir, addLanguage, multilingual bool, } for i, test := range tests { - c.Run(fmt.Sprintf("%v/%t%t%t/%s", test, defaultInSubDir, addLanguage, multilingual, lang), func(c *qt.C) { + c.Run(fmt.Sprintf("%v/defaultInSubDir=%t;addLanguage=%t;multilingual=%t/%s", test, defaultInSubDir, addLanguage, multilingual, lang), func(c *qt.C) { v.Set("baseURL", test.baseURL) v.Set("canonifyURLs", test.canonify) - var configLang string + defaultContentLanguage := lang if multilingual { - configLang = lang + defaultContentLanguage = "en" } - p := newTestPathSpecFromCfgAndLang(v, configLang) + p := newTestPathSpecFromCfgAndLang(v, lang) output := p.RelURL(test.input, addLanguage) expected := test.expected - if multilingual && addLanguage { - if !defaultInSubDir && lang == "en" { - expected = strings.Replace(expected, "MULTI", "", 1) - } else { - expected = strings.Replace(expected, "MULTI", "/"+lang, 1) - } + if addLanguage { + addLanguage = defaultInSubDir && lang == defaultContentLanguage + addLanguage = addLanguage || (lang != defaultContentLanguage && multilingual) + } + if addLanguage { + expected = strings.Replace(expected, "MULTI", "/"+lang, 1) } else { expected = strings.Replace(expected, "MULTI", "", 1) } diff --git a/hugolib/config_test.go b/hugolib/config_test.go index f87d8b936..c4a373232 100644 --- a/hugolib/config_test.go +++ b/hugolib/config_test.go @@ -1295,3 +1295,94 @@ Home. b.Assert(b.H.Configs.LanguageConfigSlice[0].Module.Mounts, qt.HasLen, 7) } + +func TestDefaultContentLanguageInSubdirOnlyOneLanguage(t *testing.T) { + + t.Run("One language, default in sub dir", func(t *testing.T) { + t.Skip() + t.Parallel() + + files := ` +-- hugo.toml -- +baseURL = "https://example.com" +defaultContentLanguage = "en" +defaultContentLanguageInSubdir = true +disableKinds = ["taxonomy", "term", "page", "section"] +-- content/foo/bar.txt -- +Foo. +-- layouts/index.html -- +Home. +` + b := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + }, + ).Build() + + b.AssertFileContent("public/en/index.html", "Home.") + b.AssertFileContent("public/en/foo/bar.txt", "Foo.") + }) + + t.Run("Two languages, default in sub dir", func(t *testing.T) { + t.Skip() + t.Parallel() + + files := ` +-- hugo.toml -- +baseURL = "https://example.com" +defaultContentLanguage = "en" +defaultContentLanguageInSubdir = true +disableKinds = ["taxonomy", "term", "page", "section"] +[languages] +[languages.en] +title = "English Title" +[languages.sv] +title = "Swedish Title" +-- content/foo/bar.txt -- +Foo. +-- layouts/index.html -- +Home. +` + b := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + }, + ).Build() + + b.AssertFileContent("public/en/index.html", "Home.") + b.AssertFileContent("public/en/foo/bar.txt", "Foo.") + }) + + t.Run("Two languages, default in root", func(t *testing.T) { + t.Parallel() + + files := ` +-- hugo.toml -- +baseURL = "https://example.com" +defaultContentLanguage = "en" +defaultContentLanguageInSubdir = false +disableKinds = ["taxonomy", "term", "page", "section"] +[languages] +[languages.en] +title = "English Title" +[languages.sv] +title = "Swedish Title" +-- content/foo/bar.txt -- +Foo. +-- layouts/index.html -- +Home. +` + b := NewIntegrationTestBuilder( + IntegrationTestConfig{ + T: t, + TxtarString: files, + }, + ).Build() + + b.AssertFileContent("public/index.html", "Home.") + b.AssertFileContent("public/foo/bar.txt", "Foo.") + }) + +} diff --git a/hugolib/pagebundler_test.go b/hugolib/pagebundler_test.go index 51ce82526..ebf5d628b 100644 --- a/hugolib/pagebundler_test.go +++ b/hugolib/pagebundler_test.go @@ -67,6 +67,7 @@ func TestPageBundlerSiteRegular(t *testing.T) { fs, cfg := newTestBundleSources(c) cfg.Set("baseURL", baseURL) cfg.Set("canonifyURLs", canonify) + cfg.Set("defaultContentLanguageInSubdir", false) cfg.Set("permalinks", map[string]string{ "a": ":sections/:filename", diff --git a/hugolib/paths/paths.go b/hugolib/paths/paths.go index 9e15d3ab4..b0d9e3c1b 100644 --- a/hugolib/paths/paths.go +++ b/hugolib/paths/paths.go @@ -102,6 +102,7 @@ func (p *Paths) Lang() string { return p.Cfg.Language().Lang } +// TODO1 check this. func (p *Paths) GetTargetLanguageBasePath() string { if len(p.Cfg.Languages()) > 1 { // In a multihost configuration all assets will be published below the language code. @@ -110,41 +111,8 @@ func (p *Paths) GetTargetLanguageBasePath() string { return p.GetLanguagePrefix() } -func (p *Paths) GetURLLanguageBasePath() string { - if len(p.Cfg.Languages()) > 1 { - return "" - } - return p.GetLanguagePrefix() -} - func (p *Paths) GetLanguagePrefix() string { - if len(p.Cfg.Languages()) < 2 { - return "" - } - defaultLang := p.Cfg.DefaultContentLanguage() - defaultInSubDir := p.Cfg.DefaultContentLanguageInSubdir() - currentLang := p.Cfg.Language().Lang - if currentLang == "" || (currentLang == defaultLang && !defaultInSubDir) { - return "" - } - return currentLang -} - -// GetLangSubDir returns the given language's subdir if needed. -func (p *Paths) GetLangSubDir(lang string) string { - if len(p.Cfg.Languages()) < 2 { - return "" - } - - if p.Cfg.IsMultihost() { - return "" - } - - if lang == "" || (lang == p.Cfg.DefaultContentLanguage() && !p.Cfg.DefaultContentLanguageInSubdir()) { - return "" - } - - return lang + return p.Cfg.LanguagePrefix() } // AbsPathify creates an absolute path if given a relative path. If already diff --git a/hugolib/site.go b/hugolib/site.go index 7a3528929..eb6a4e344 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -887,21 +887,16 @@ func (s *Site) getLanguageTargetPathLang(alwaysInSubDir bool) string { // get any language code to prefix the relative permalink with. func (s *Site) getLanguagePermalinkLang(alwaysInSubDir bool) string { - if !s.h.isMultiLingual() || s.h.Conf.IsMultihost() { + if s.h.Conf.IsMultihost() { return "" } - if alwaysInSubDir { + if s.h.Conf.IsMultiLingual() && alwaysInSubDir { return s.Language().Lang } - isDefault := s.Language().Lang == s.conf.DefaultContentLanguage + return s.GetLanguagePrefix() - if !isDefault || s.conf.DefaultContentLanguageInSubdir { - return s.Language().Lang - } - - return "" } func (s *Site) getTaxonomyKey(key string) string { diff --git a/hugolib/site_new.go b/hugolib/site_new.go index c6c5cd2a3..61273d3c8 100644 --- a/hugolib/site_new.go +++ b/hugolib/site_new.go @@ -470,16 +470,11 @@ func (s *Site) IsMultiLingual() bool { } func (s *Site) LanguagePrefix() string { - conf := s.s.Conf - if !conf.IsMultiLingual() { + prefix := s.GetLanguagePrefix() + if prefix == "" { return "" } - - if !conf.DefaultContentLanguageInSubdir() && s.language.Lang == conf.DefaultContentLanguage() { - return "" - } - - return "/" + s.language.Lang + return "/" + prefix } // Returns the identity of this site. diff --git a/hugolib/site_url_test.go b/hugolib/site_url_test.go index cb69be4ca..821c84c95 100644 --- a/hugolib/site_url_test.go +++ b/hugolib/site_url_test.go @@ -38,35 +38,6 @@ var urlFakeSource = [][2]string{ {filepath.FromSlash("content/blue/doc2.md"), slugDoc2}, } -func TestPageCount(t *testing.T) { - t.Parallel() - c := qt.New(t) - cfg, fs := newTestCfg() - cfg.Set("uglyURLs", false) - cfg.Set("paginate", 10) - configs, err := loadTestConfigFromProvider(cfg) - c.Assert(err, qt.IsNil) - - writeSourcesToSource(t, "", fs, urlFakeSource...) - s := buildSingleSite(t, deps.DepsCfg{Fs: fs, Configs: configs}, BuildCfg{}) - - _, err = s.Fs.WorkingDirReadOnly.Open("public/blue") - if err != nil { - t.Errorf("No indexed rendered.") - } - - for _, pth := range []string{ - "public/sd1/foo/index.html", - "public/sd2/index.html", - "public/sd3/index.html", - "public/sd4.html", - } { - if _, err := s.Fs.WorkingDirReadOnly.Open(filepath.FromSlash(pth)); err != nil { - t.Errorf("No alias rendered: %s", pth) - } - } -} - func TestUglyURLsPerSection(t *testing.T) { t.Parallel() diff --git a/hugolib/sitemap_test.go b/hugolib/sitemap_test.go index 984943c6f..aae874d50 100644 --- a/hugolib/sitemap_test.go +++ b/hugolib/sitemap_test.go @@ -46,6 +46,7 @@ func doTestSitemapOutput(t *testing.T, internal bool) { c := qt.New(t) cfg, fs := newTestCfg() cfg.Set("baseURL", "http://auth/bub/") + cfg.Set("defaultContentLanguageInSubdir", false) configs, err := loadTestConfigFromProvider(cfg) c.Assert(err, qt.IsNil) writeSource(t, fs, "layouts/sitemap.xml", sitemapTemplate) diff --git a/hugolib/testhelpers_test.go b/hugolib/testhelpers_test.go index 73920bd49..700aa8c3d 100644 --- a/hugolib/testhelpers_test.go +++ b/hugolib/testhelpers_test.go @@ -937,8 +937,7 @@ func newTestCfgBasic() (config.Provider, *hugofs.Fs) { func newTestCfg(withConfig ...func(cfg config.Provider) error) (config.Provider, *hugofs.Fs) { mm := afero.NewMemMapFs() cfg := config.New() - // Default is false, but true is easier to use as default in tests - cfg.Set("defaultContentLanguageInSubdir", true) + cfg.Set("defaultContentLanguageInSubdir", false) cfg.Set("publishDir", "public") fs := hugofs.NewFromOld(hugofs.NewBaseFileDecorator(mm), cfg)