hugo/tpl/transform/remarshal_test.go
Bjørn Erik Pedersen eb42774e58
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
2018-04-02 08:06:21 +02:00

203 lines
4.1 KiB
Go

// Copyright 2018 The Hugo Authors. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package transform
import (
"fmt"
"testing"
"github.com/gohugoio/hugo/helpers"
"github.com/spf13/viper"
"github.com/stretchr/testify/require"
)
func TestRemarshal(t *testing.T) {
t.Parallel()
v := viper.New()
v.Set("contentDir", "content")
ns := New(newDeps(v))
assert := require.New(t)
tomlExample := `title = "Test Metadata"
[[resources]]
src = "**image-4.png"
title = "The Fourth Image!"
[resources.params]
byline = "picasso"
[[resources]]
name = "my-cool-image-:counter"
src = "**.png"
title = "TOML: The Image #:counter"
[resources.params]
byline = "bep"
`
yamlExample := `resources:
- params:
byline: picasso
src: '**image-4.png'
title: The Fourth Image!
- name: my-cool-image-:counter
params:
byline: bep
src: '**.png'
title: 'TOML: The Image #:counter'
title: Test Metadata
`
jsonExample := `{
"resources": [
{
"params": {
"byline": "picasso"
},
"src": "**image-4.png",
"title": "The Fourth Image!"
},
{
"name": "my-cool-image-:counter",
"params": {
"byline": "bep"
},
"src": "**.png",
"title": "TOML: The Image #:counter"
}
],
"title": "Test Metadata"
}
`
variants := []struct {
format string
data string
}{
{"yaml", yamlExample},
{"json", jsonExample},
{"toml", tomlExample},
{"TOML", tomlExample},
{"Toml", tomlExample},
{" TOML ", tomlExample},
}
for _, v1 := range variants {
for _, v2 := range variants {
// Both from and to may be the same here, but that is fine.
fromTo := fmt.Sprintf("%s => %s", v2.format, v1.format)
converted, err := ns.Remarshal(v1.format, v2.data)
assert.NoError(err, fromTo)
diff := helpers.DiffStrings(v1.data, converted)
if len(diff) > 0 {
t.Errorf("[%s] Expected \n%v\ngot\n%v\ndiff:\n%v", fromTo, v1.data, converted, diff)
}
}
}
}
func TestRemarshalComments(t *testing.T) {
t.Parallel()
v := viper.New()
v.Set("contentDir", "content")
ns := New(newDeps(v))
assert := require.New(t)
input := `
Hugo = "Rules"
# It really does!
[m]
# A comment
a = "b"
`
expected := `
Hugo = "Rules"
[m]
a = "b"
`
for _, format := range []string{"json", "yaml", "toml"} {
fromTo := fmt.Sprintf("%s => %s", "toml", format)
converted := input
var err error
// Do a round-trip conversion
for _, toFormat := range []string{format, "toml"} {
converted, err = ns.Remarshal(toFormat, converted)
assert.NoError(err, fromTo)
}
diff := helpers.DiffStrings(expected, converted)
if len(diff) > 0 {
t.Fatalf("[%s] Expected \n%v\ngot\n%v\ndiff:\n%v\n", fromTo, expected, converted, diff)
}
}
}
func TestTestRemarshalError(t *testing.T) {
t.Parallel()
v := viper.New()
v.Set("contentDir", "content")
ns := New(newDeps(v))
assert := require.New(t)
_, err := ns.Remarshal("asdf", "asdf")
assert.Error(err)
_, err = ns.Remarshal("json", "asdf")
assert.Error(err)
}
func TestRemarshalDetectFormat(t *testing.T) {
t.Parallel()
assert := require.New(t)
for i, test := range []struct {
data string
expect interface{}
}{
{`foo = "bar"`, "toml"},
{` foo = "bar"`, "toml"},
{`foo="bar"`, "toml"},
{`foo: "bar"`, "yaml"},
{`foo:"bar"`, "yaml"},
{`{ "foo": "bar"`, "json"},
{`asdfasdf`, false},
{``, false},
} {
errMsg := fmt.Sprintf("[%d] %s", i, test.data)
result, err := detectFormat(test.data)
if b, ok := test.expect.(bool); ok && !b {
assert.Error(err, errMsg)
continue
}
assert.NoError(err, errMsg)
assert.Equal(test.expect, result, errMsg)
}
}