Add support for a content dir set per language

A sample config:

```toml
defaultContentLanguage = "en"
defaultContentLanguageInSubdir = true

[Languages]
[Languages.en]
weight = 10
title = "In English"
languageName = "English"
contentDir = "content/english"

[Languages.nn]
weight = 20
title = "På Norsk"
languageName = "Norsk"
contentDir = "content/norwegian"
```

The value of `contentDir` can be any valid path, even absolute path references. The only restriction is that the content dirs cannot overlap.

The content files will be assigned a language by

1. The placement: `content/norwegian/post/my-post.md` will be read as Norwegian content.
2. The filename: `content/english/post/my-post.nn.md` will be read as Norwegian even if it lives in the English content folder.

The content directories will be merged into a big virtual filesystem with one simple rule: The most specific language file will win.
This means that if both `content/norwegian/post/my-post.md` and `content/english/post/my-post.nn.md` exists, they will be considered duplicates and the version inside `content/norwegian` will win.

Note that translations will be automatically assigned by Hugo by the content file's relative placement, so `content/norwegian/post/my-post.md` will be a translation of `content/english/post/my-post.md`.

If this does not work for you, you can connect the translations together by setting a `translationKey` in the content files' front matter.

Fixes #4523
Fixes #4552
Fixes #4553
This commit is contained in:
Bjørn Erik Pedersen
2018-03-21 17:21:46 +01:00
parent f27977809c
commit eb42774e58
66 changed files with 1819 additions and 556 deletions

View File

@@ -14,7 +14,6 @@
package hugolib
import (
"os"
"strings"
"github.com/gohugoio/hugo/helpers"
@@ -25,11 +24,22 @@ import (
var (
_ source.File = (*fileInfo)(nil)
_ source.ReadableFile = (*fileInfo)(nil)
_ pathLangFile = (*fileInfo)(nil)
)
// A partial interface to prevent ambigous compiler error.
type basePather interface {
Filename() string
RealName() string
BaseDir() string
}
type fileInfo struct {
bundleTp bundleDirType
source.ReadableFile
basePather
overriddenLang string
// Set if the content language for this file is disabled.
@@ -43,6 +53,10 @@ func (fi *fileInfo) Lang() string {
return fi.ReadableFile.Lang()
}
func (fi *fileInfo) Filename() string {
return fi.basePather.Filename()
}
func (fi *fileInfo) isOwner() bool {
return fi.bundleTp > bundleNot
}
@@ -55,12 +69,13 @@ func (fi *fileInfo) isContentFile() bool {
return contentFileExtensionsSet[fi.Ext()]
}
func newFileInfo(sp *source.SourceSpec, baseDir, filename string, fi os.FileInfo, tp bundleDirType) *fileInfo {
func newFileInfo(sp *source.SourceSpec, baseDir, filename string, fi pathLangFileFi, tp bundleDirType) *fileInfo {
baseFi := sp.NewFileInfo(baseDir, filename, tp == bundleLeaf, fi)
f := &fileInfo{
bundleTp: tp,
ReadableFile: baseFi,
basePather: fi,
}
lang := f.Lang()