summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2018-01-25 17:03:29 +0100
committerBjørn Erik Pedersen <[email protected]>2018-01-26 14:04:14 +0100
commit6413559f7575e2653d76227a8037a7edbaae82aa (patch)
tree4b2d2be2943e1f7c37d6aa09937bec4391c1e678
parent322c567220aa4123a5d707629c1bebd375599912 (diff)
downloadhugo-6413559f7575e2653d76227a8037a7edbaae82aa.tar.gz
hugo-6413559f7575e2653d76227a8037a7edbaae82aa.zip
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
-rw-r--r--commands/server.go23
-rw-r--r--config/configProvider.go1
-rw-r--r--helpers/language.go5
-rw-r--r--hugolib/config.go38
-rw-r--r--hugolib/fileInfo.go6
-rw-r--r--hugolib/page_bundler_capture.go36
-rw-r--r--hugolib/page_bundler_capture_test.go1
-rw-r--r--hugolib/page_bundler_test.go49
-rw-r--r--hugolib/site.go34
-rw-r--r--source/sourceSpec.go9
10 files changed, 160 insertions, 42 deletions
diff --git a/commands/server.go b/commands/server.go
index 0ae58c991..f2522aaf7 100644
--- a/commands/server.go
+++ b/commands/server.go
@@ -173,20 +173,23 @@ func server(cmd *cobra.Command, args []string) error {
c.Set("liveReloadPort", serverPorts[0])
}
- if c.languages.IsMultihost() {
- for i, language := range c.languages {
- baseURL, err := fixURL(language, baseURL, serverPorts[i])
- if err != nil {
- return err
- }
- language.Set("baseURL", baseURL)
+ isMultiHost := c.languages.IsMultihost()
+ for i, language := range c.languages {
+ var serverPort int
+ if isMultiHost {
+ serverPort = serverPorts[i]
+ } else {
+ serverPort = serverPorts[0]
}
- } else {
- baseURL, err := fixURL(c.Cfg, baseURL, serverPorts[0])
+
+ baseURL, err := fixURL(language, baseURL, serverPort)
if err != nil {
return err
}
- c.Set("baseURL", baseURL)
+ language.Set("baseURL", baseURL)
+ if i == 0 {
+ c.Set("baseURL", baseURL)
+ }
}
return nil
diff --git a/config/configProvider.go b/config/configProvider.go
index 870341f7f..471ce9a1d 100644
--- a/config/configProvider.go
+++ b/config/configProvider.go
@@ -20,6 +20,7 @@ type Provider interface {
GetBool(key string) bool
GetStringMap(key string) map[string]interface{}
GetStringMapString(key string) map[string]string
+ GetStringSlice(key string) []string
Get(key string) interface{}
Set(key string, value interface{})
IsSet(key string) bool
diff --git a/helpers/language.go b/helpers/language.go
index fa933fddd..934c82de0 100644
--- a/helpers/language.go
+++ b/helpers/language.go
@@ -140,6 +140,11 @@ func (l *Language) GetStringMapString(key string) map[string]string {
return cast.ToStringMapString(l.Get(key))
}
+// returns the value associated with the key as a slice of strings.
+func (l *Language) GetStringSlice(key string) []string {
+ return cast.ToStringSlice(l.Get(key))
+}
+
// Get returns a value associated with the key relying on specified language.
// Get is case-insensitive for a key.
//
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.
diff --git a/source/sourceSpec.go b/source/sourceSpec.go
index 74a754a26..e40010162 100644
--- a/source/sourceSpec.go
+++ b/source/sourceSpec.go
@@ -35,6 +35,7 @@ type SourceSpec struct {
Languages map[string]interface{}
DefaultContentLanguage string
+ DisabledLanguages map[string]bool
}
// NewSourceSpec initializes SourceSpec using languages from a given configuration.
@@ -42,6 +43,12 @@ func NewSourceSpec(cfg config.Provider, fs *hugofs.Fs) *SourceSpec {
defaultLang := cfg.GetString("defaultContentLanguage")
languages := cfg.GetStringMap("languages")
+ disabledLangsSet := make(map[string]bool)
+
+ for _, disabledLang := range cfg.GetStringSlice("disableLanguages") {
+ disabledLangsSet[disabledLang] = true
+ }
+
if len(languages) == 0 {
l := helpers.NewDefaultLanguage(cfg)
languages[l.Lang] = l
@@ -62,7 +69,7 @@ func NewSourceSpec(cfg config.Provider, fs *hugofs.Fs) *SourceSpec {
}
}
- return &SourceSpec{ignoreFilesRe: regexps, Cfg: cfg, Fs: fs, Languages: languages, DefaultContentLanguage: defaultLang}
+ return &SourceSpec{ignoreFilesRe: regexps, Cfg: cfg, Fs: fs, Languages: languages, DefaultContentLanguage: defaultLang, DisabledLanguages: disabledLangsSet}
}
func (s *SourceSpec) IgnoreFile(filename string) bool {