From 6413559f7575e2653d76227a8037a7edbaae82aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Pedersen?= Date: Thu, 25 Jan 2018 17:03:29 +0100 Subject: Add a way to disable one or more languages This commit adds a new config setting: ```toml disableLanguages = ["fr"] ``` If this is a multilingual site: * No site for the French language will be created * French content pages will be ignored/not read * The French language configuration (menus etc.) will also be ignored This makes it possible to start translating new languages and turn it on when you're happy etc. Fixes #4297 Fixed #4329 --- hugolib/config.go | 38 ++++++++++++++++++++++++---- hugolib/fileInfo.go | 6 +++++ hugolib/page_bundler_capture.go | 36 ++++++++++++++++++-------- hugolib/page_bundler_capture_test.go | 1 + hugolib/page_bundler_test.go | 49 ++++++++++++++++++++++++++++++++++++ hugolib/site.go | 34 +++++++++++++------------ 6 files changed, 133 insertions(+), 31 deletions(-) (limited to 'hugolib') diff --git a/hugolib/config.go b/hugolib/config.go index fe3a64f2a..c30e93f15 100644 --- a/hugolib/config.go +++ b/hugolib/config.go @@ -72,16 +72,46 @@ func LoadConfig(fs afero.Fs, relativeSourcePath, configFilename string) (*viper. } func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error { - multilingual := cfg.GetStringMap("languages") + + defaultLang := cfg.GetString("defaultContentLanguage") + + var languages map[string]interface{} + + languagesFromConfig := cfg.GetStringMap("languages") + disableLanguages := cfg.GetStringSlice("disableLanguages") + + if len(disableLanguages) == 0 { + languages = languagesFromConfig + } else { + languages = make(map[string]interface{}) + for k, v := range languagesFromConfig { + isDisabled := false + for _, disabled := range disableLanguages { + if disabled == defaultLang { + return fmt.Errorf("cannot disable default language %q", defaultLang) + } + + if strings.EqualFold(k, disabled) { + isDisabled = true + break + } + } + if !isDisabled { + languages[k] = v + } + + } + } + var ( langs helpers.Languages err error ) - if len(multilingual) == 0 { + if len(languages) == 0 { langs = append(langs, helpers.NewDefaultLanguage(cfg)) } else { - langs, err = toSortedLanguages(cfg, multilingual) + langs, err = toSortedLanguages(cfg, languages) if err != nil { return fmt.Errorf("Failed to parse multilingual config: %s", err) } @@ -114,8 +144,6 @@ func loadLanguageSettings(cfg config.Provider, oldLangs helpers.Languages) error } } - defaultLang := cfg.GetString("defaultContentLanguage") - // The defaultContentLanguage is something the user has to decide, but it needs // to match a language in the language definition list. langExists := false diff --git a/hugolib/fileInfo.go b/hugolib/fileInfo.go index 582d2be8c..b146aede9 100644 --- a/hugolib/fileInfo.go +++ b/hugolib/fileInfo.go @@ -31,6 +31,9 @@ type fileInfo struct { bundleTp bundleDirType source.ReadableFile overriddenLang string + + // Set if the content language for this file is disabled. + disabled bool } func (fi *fileInfo) Lang() string { @@ -60,6 +63,9 @@ func newFileInfo(sp *source.SourceSpec, baseDir, filename string, fi os.FileInfo ReadableFile: baseFi, } + lang := f.Lang() + f.disabled = lang != "" && sp.DisabledLanguages[lang] + return f } diff --git a/hugolib/page_bundler_capture.go b/hugolib/page_bundler_capture.go index 34a1be5fb..4d8f39fb7 100644 --- a/hugolib/page_bundler_capture.go +++ b/hugolib/page_bundler_capture.go @@ -149,8 +149,10 @@ func (c *capturer) capturePartial(filenames ...string) error { // create the proper mapping for it. c.getRealFileInfo(dir) - f := c.newFileInfo(resolvedFilename, fi, tp) - c.copyOrHandleSingle(f) + f, active := c.newFileInfo(resolvedFilename, fi, tp) + if active { + c.copyOrHandleSingle(f) + } } } @@ -228,7 +230,10 @@ func (c *capturer) handleBranchDir(dirname string) error { tp, isContent := classifyBundledFile(fi.Name()) - f := c.newFileInfo(fi.filename, fi.FileInfo, tp) + f, active := c.newFileInfo(fi.filename, fi.FileInfo, tp) + if !active { + continue + } if f.isOwner() { dirs.addBundleHeader(f) } else if !isContent { @@ -309,7 +314,7 @@ func (c *capturer) handleDir(dirname string) error { return c.handleNonBundle(dirname, files, state == dirStateSinglesOnly) } - var fileInfos = make([]*fileInfo, len(files)) + var fileInfos = make([]*fileInfo, 0, len(files)) for i, fi := range files { currentType := bundleNot @@ -324,8 +329,12 @@ func (c *capturer) handleDir(dirname string) error { if bundleType == bundleNot && currentType != bundleNot { bundleType = currentType } + f, active := c.newFileInfo(fi.filename, fi.FileInfo, currentType) + if !active { + continue + } - fileInfos[i] = c.newFileInfo(fi.filename, fi.FileInfo, currentType) + fileInfos = append(fileInfos, f) } var todo []*fileInfo @@ -377,8 +386,11 @@ func (c *capturer) handleNonBundle( } } else { if singlesOnly { - file := c.newFileInfo(fi.filename, fi, bundleNot) - c.handler.handleSingles(file) + f, active := c.newFileInfo(fi.filename, fi, bundleNot) + if !active { + continue + } + c.handler.handleSingles(f) } else { c.handler.handleCopyFiles(fi.filename) } @@ -462,7 +474,10 @@ func (c *capturer) collectFiles(dirname string, handleFiles func(fis ...*fileInf return err } } else { - handleFiles(c.newFileInfo(fi.filename, fi.FileInfo, bundleNot)) + f, active := c.newFileInfo(fi.filename, fi.FileInfo, bundleNot) + if active { + handleFiles(f) + } } } @@ -506,8 +521,9 @@ func (c *capturer) readDir(dirname string) ([]fileInfoName, error) { return fis, nil } -func (c *capturer) newFileInfo(filename string, fi os.FileInfo, tp bundleDirType) *fileInfo { - return newFileInfo(c.sourceSpec, c.baseDir, filename, fi, tp) +func (c *capturer) newFileInfo(filename string, fi os.FileInfo, tp bundleDirType) (*fileInfo, bool) { + f := newFileInfo(c.sourceSpec, c.baseDir, filename, fi, tp) + return f, !f.disabled } type fileInfoName struct { diff --git a/hugolib/page_bundler_capture_test.go b/hugolib/page_bundler_capture_test.go index 176f752e0..a7a7054b4 100644 --- a/hugolib/page_bundler_capture_test.go +++ b/hugolib/page_bundler_capture_test.go @@ -174,6 +174,7 @@ func TestPageBundlerCaptureMultilingual(t *testing.T) { expected := ` F: /work/base/1s/mypage.md +/work/base/1s/mypage.nn.md /work/base/bb/_1.md /work/base/bb/_1.nn.md /work/base/bb/en.md diff --git a/hugolib/page_bundler_test.go b/hugolib/page_bundler_test.go index 474f6676d..cef1e0239 100644 --- a/hugolib/page_bundler_test.go +++ b/hugolib/page_bundler_test.go @@ -192,6 +192,10 @@ func TestPageBundlerSiteMultilingual(t *testing.T) { s := sites.Sites[0] + assert.Equal(8, len(s.RegularPages)) + assert.Equal(18, len(s.Pages)) + assert.Equal(35, len(s.AllPages)) + bundleWithSubPath := s.getPage(KindPage, "lb/index") assert.NotNil(bundleWithSubPath) @@ -214,6 +218,8 @@ func TestPageBundlerSiteMultilingual(t *testing.T) { assert.Equal(bfBundle, s.getPage(KindPage, "my-bf-bundle")) nnSite := sites.Sites[1] + assert.Equal(7, len(nnSite.RegularPages)) + bfBundleNN := nnSite.getPage(KindPage, "bf/my-bf-bundle/index") assert.NotNil(bfBundleNN) assert.Equal("nn", bfBundleNN.Lang()) @@ -233,6 +239,48 @@ func TestPageBundlerSiteMultilingual(t *testing.T) { } } +func TestMultilingualDisableDefaultLanguage(t *testing.T) { + t.Parallel() + + assert := require.New(t) + cfg, _ := newTestBundleSourcesMultilingual(t) + + cfg.Set("disableLanguages", []string{"en"}) + + err := loadDefaultSettingsFor(cfg) + assert.Error(err) + assert.Contains(err.Error(), "cannot disable default language") +} + +func TestMultilingualDisableLanguage(t *testing.T) { + t.Parallel() + + assert := require.New(t) + cfg, fs := newTestBundleSourcesMultilingual(t) + cfg.Set("disableLanguages", []string{"nn"}) + + assert.NoError(loadDefaultSettingsFor(cfg)) + sites, err := NewHugoSites(deps.DepsCfg{Fs: fs, Cfg: cfg}) + assert.NoError(err) + assert.Equal(1, len(sites.Sites)) + + assert.NoError(sites.Build(BuildCfg{})) + + s := sites.Sites[0] + + assert.Equal(8, len(s.RegularPages)) + assert.Equal(18, len(s.Pages)) + // No nn pages + assert.Equal(18, len(s.AllPages)) + for _, p := range s.rawAllPages { + assert.True(p.Lang() != "nn") + } + for _, p := range s.AllPages { + assert.True(p.Lang() != "nn") + } + +} + func TestPageBundlerSiteWitSymbolicLinksInContent(t *testing.T) { assert := require.New(t) cfg, fs, workDir := newTestBundleSymbolicSources(t) @@ -509,6 +557,7 @@ TheContent. writeSource(t, fs, filepath.Join(workDir, "layouts", "_default", "list.html"), layout) writeSource(t, fs, filepath.Join(workDir, "base", "1s", "mypage.md"), pageContent) + writeSource(t, fs, filepath.Join(workDir, "base", "1s", "mypage.nn.md"), pageContent) writeSource(t, fs, filepath.Join(workDir, "base", "1s", "mylogo.png"), "content") writeSource(t, fs, filepath.Join(workDir, "base", "bb", "_index.md"), pageContent) diff --git a/hugolib/site.go b/hugolib/site.go index 0dbf84a07..55eb6ae72 100644 --- a/hugolib/site.go +++ b/hugolib/site.go @@ -1207,30 +1207,28 @@ func (s *Site) checkDirectories() (err error) { } type contentCaptureResultHandler struct { - contentProcessors map[string]*siteContentProcessor + defaultContentProcessor *siteContentProcessor + contentProcessors map[string]*siteContentProcessor +} + +func (c *contentCaptureResultHandler) getContentProcessor(lang string) *siteContentProcessor { + proc, found := c.contentProcessors[lang] + if found { + return proc + } + return c.defaultContentProcessor } func (c *contentCaptureResultHandler) handleSingles(fis ...*fileInfo) { for _, fi := range fis { - // May be connected to a language (content files) - proc, found := c.contentProcessors[fi.Lang()] - if !found { - panic("proc not found") - } + proc := c.getContentProcessor(fi.Lang()) proc.fileSinglesChan <- fi - } } func (c *contentCaptureResultHandler) handleBundles(d *bundleDirs) { for _, b := range d.bundles { - lang := b.fi.Lang() - - proc, found := c.contentProcessors[lang] - if !found { - panic("proc not found") - } + proc := c.getContentProcessor(b.fi.Lang()) proc.fileBundlesChan <- b - } } @@ -1247,13 +1245,17 @@ func (s *Site) readAndProcessContent(filenames ...string) error { sourceSpec := source.NewSourceSpec(s.owner.Cfg, s.Fs) baseDir := s.absContentDir() + defaultContentLanguage := s.SourceSpec.DefaultContentLanguage contentProcessors := make(map[string]*siteContentProcessor) + var defaultContentProcessor *siteContentProcessor sites := s.owner.langSite() for k, v := range sites { proc := newSiteContentProcessor(baseDir, len(filenames) > 0, v) contentProcessors[k] = proc - + if k == defaultContentLanguage { + defaultContentProcessor = proc + } g.Go(func() error { return proc.process(ctx) }) @@ -1264,7 +1266,7 @@ func (s *Site) readAndProcessContent(filenames ...string) error { bundleMap *contentChangeMap ) - mainHandler := &contentCaptureResultHandler{contentProcessors: contentProcessors} + mainHandler := &contentCaptureResultHandler{contentProcessors: contentProcessors, defaultContentProcessor: defaultContentProcessor} if s.running() { // Need to track changes. -- cgit v1.2.3