Create a struct with all of Hugo's config options

Primary motivation is documentation, but it will also hopefully simplify the code.

Also,

* Lower case the default output format names; this is in line with the custom ones (map keys) and how
it's treated all the places. This avoids doing `stringds.EqualFold` everywhere.

Closes #10896
Closes #10620
This commit is contained in:
Bjørn Erik Pedersen
2023-01-04 18:24:36 +01:00
parent 6aededf6b4
commit 241b21b0fd
337 changed files with 13377 additions and 14898 deletions

View File

@@ -37,12 +37,12 @@ var i18nWarningLogger = helpers.NewDistinctErrorLogger()
// Translator handles i18n translations.
type Translator struct {
translateFuncs map[string]translateFunc
cfg config.Provider
cfg config.AllProvider
logger loggers.Logger
}
// NewTranslator creates a new Translator for the given language bundle and configuration.
func NewTranslator(b *i18n.Bundle, cfg config.Provider, logger loggers.Logger) Translator {
func NewTranslator(b *i18n.Bundle, cfg config.AllProvider, logger loggers.Logger) Translator {
t := Translator{cfg: cfg, logger: logger, translateFuncs: make(map[string]translateFunc)}
t.initFuncs(b)
return t
@@ -55,7 +55,7 @@ func (t Translator) Func(lang string) translateFunc {
return f
}
t.logger.Infof("Translation func for language %v not found, use default.", lang)
if f, ok := t.translateFuncs[t.cfg.GetString("defaultContentLanguage")]; ok {
if f, ok := t.translateFuncs[t.cfg.DefaultContentLanguage()]; ok {
return f
}
@@ -66,7 +66,7 @@ func (t Translator) Func(lang string) translateFunc {
}
func (t Translator) initFuncs(bndl *i18n.Bundle) {
enableMissingTranslationPlaceholders := t.cfg.GetBool("enableMissingTranslationPlaceholders")
enableMissingTranslationPlaceholders := t.cfg.EnableMissingTranslationPlaceholders()
for _, lang := range bndl.LanguageTags() {
currentLang := lang
currentLangStr := currentLang.String()
@@ -122,7 +122,7 @@ func (t Translator) initFuncs(bndl *i18n.Bundle) {
t.logger.Warnf("Failed to get translated string for language %q and ID %q: %s", currentLangStr, translationID, err)
}
if t.cfg.GetBool("logI18nWarnings") {
if t.cfg.LogI18nWarnings() {
i18nWarningLogger.Printf("i18n|MISSING_TRANSLATION|%s|%s", currentLangStr, translationID)
}

View File

@@ -20,13 +20,11 @@ import (
"testing"
"github.com/gohugoio/hugo/common/types"
"github.com/gohugoio/hugo/modules"
"github.com/gohugoio/hugo/config/testconfig"
"github.com/gohugoio/hugo/tpl/tplimpl"
"github.com/gohugoio/hugo/common/loggers"
"github.com/gohugoio/hugo/langs"
"github.com/gohugoio/hugo/resources/page"
"github.com/spf13/afero"
@@ -34,7 +32,6 @@ import (
qt "github.com/frankban/quicktest"
"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/hugofs"
)
var logger = loggers.NewErrorLogger()
@@ -394,26 +391,22 @@ other = "{{ . }} miesiąca"
} {
c.Run(test.name, func(c *qt.C) {
cfg := getConfig()
cfg := config.New()
cfg.Set("enableMissingTranslationPlaceholders", true)
fs := hugofs.NewMem(cfg)
cfg.Set("publishDir", "public")
afs := afero.NewMemMapFs()
err := afero.WriteFile(fs.Source, filepath.Join("i18n", test.lang+".toml"), []byte(test.templ), 0755)
err := afero.WriteFile(afs, filepath.Join("i18n", test.lang+".toml"), []byte(test.templ), 0755)
c.Assert(err, qt.IsNil)
tp := NewTranslationProvider()
depsCfg := newDepsConfig(tp, cfg, fs)
depsCfg.Logger = loggers.NewWarningLogger()
d, err := deps.New(depsCfg)
c.Assert(err, qt.IsNil)
c.Assert(d.LoadResources(), qt.IsNil)
d, tp := prepareDeps(afs, cfg)
f := tp.t.Func(test.lang)
ctx := context.Background()
for _, variant := range test.variants {
c.Assert(f(ctx, test.id, variant.Key), qt.Equals, variant.Value, qt.Commentf("input: %v", variant.Key))
c.Assert(int(depsCfg.Logger.LogCounters().WarnCounter.Count()), qt.Equals, 0)
c.Assert(int(d.Log.LogCounters().WarnCounter.Count()), qt.Equals, 0)
}
})
@@ -471,52 +464,33 @@ func TestGetPluralCount(t *testing.T) {
func prepareTranslationProvider(t testing.TB, test i18nTest, cfg config.Provider) *TranslationProvider {
c := qt.New(t)
fs := hugofs.NewMem(cfg)
afs := afero.NewMemMapFs()
for file, content := range test.data {
err := afero.WriteFile(fs.Source, filepath.Join("i18n", file), []byte(content), 0755)
err := afero.WriteFile(afs, filepath.Join("i18n", file), []byte(content), 0755)
c.Assert(err, qt.IsNil)
}
tp := NewTranslationProvider()
depsCfg := newDepsConfig(tp, cfg, fs)
d, err := deps.New(depsCfg)
c.Assert(err, qt.IsNil)
c.Assert(d.LoadResources(), qt.IsNil)
_, tp := prepareDeps(afs, cfg)
return tp
}
func newDepsConfig(tp *TranslationProvider, cfg config.Provider, fs *hugofs.Fs) deps.DepsCfg {
l := langs.NewLanguage("en", cfg)
l.Set("i18nDir", "i18n")
return deps.DepsCfg{
Language: l,
Site: page.NewDummyHugoSite(cfg),
Cfg: cfg,
Fs: fs,
Logger: logger,
TemplateProvider: tplimpl.DefaultTemplateProvider,
TranslationProvider: tp,
}
}
func getConfig() config.Provider {
v := config.NewWithTestDefaults()
langs.LoadLanguageSettings(v, nil)
mod, err := modules.CreateProjectModule(v)
if err != nil {
func prepareDeps(afs afero.Fs, cfg config.Provider) (*deps.Deps, *TranslationProvider) {
d := testconfig.GetTestDeps(afs, cfg)
translationProvider := NewTranslationProvider()
d.TemplateProvider = tplimpl.DefaultTemplateProvider
d.TranslationProvider = translationProvider
d.Site = page.NewDummyHugoSite(cfg)
if err := d.Compile(nil); err != nil {
panic(err)
}
v.Set("allModules", modules.Modules{mod})
return v
return d, translationProvider
}
func TestI18nTranslate(t *testing.T) {
c := qt.New(t)
var actual, expected string
v := getConfig()
v := config.New()
// Test without and with placeholders
for _, enablePlaceholders := range []bool{false, true} {
@@ -537,7 +511,7 @@ func TestI18nTranslate(t *testing.T) {
}
func BenchmarkI18nTranslate(b *testing.B) {
v := getConfig()
v := config.New()
for _, test := range i18nTests {
b.Run(test.name, func(b *testing.B) {
tp := prepareTranslationProvider(b, test, v)

View File

@@ -45,10 +45,10 @@ func NewTranslationProvider() *TranslationProvider {
}
// Update updates the i18n func in the provided Deps.
func (tp *TranslationProvider) Update(d *deps.Deps) error {
spec := source.NewSourceSpec(d.PathSpec, nil, nil)
func (tp *TranslationProvider) NewResource(dst *deps.Deps) error {
spec := source.NewSourceSpec(dst.PathSpec, nil, nil)
var defaultLangTag, err = language.Parse(d.Cfg.GetString("defaultContentLanguage"))
var defaultLangTag, err = language.Parse(dst.Conf.DefaultContentLanguage())
if err != nil {
defaultLangTag = language.English
}
@@ -61,7 +61,7 @@ func (tp *TranslationProvider) Update(d *deps.Deps) error {
// The source dirs are ordered so the most important comes first. Since this is a
// last key win situation, we have to reverse the iteration order.
dirs := d.BaseFs.I18n.Dirs
dirs := dst.BaseFs.I18n.Dirs
for i := len(dirs) - 1; i >= 0; i-- {
dir := dirs[i]
src := spec.NewFilesystemFromFileMetaInfo(dir)
@@ -76,11 +76,12 @@ func (tp *TranslationProvider) Update(d *deps.Deps) error {
}
}
tp.t = NewTranslator(bundle, d.Cfg, d.Log)
tp.t = NewTranslator(bundle, dst.Conf, dst.Log)
d.Translate = tp.t.Func(d.Language.Lang)
dst.Translate = tp.t.Func(dst.Conf.Language().Lang)
return nil
}
const artificialLangTagPrefix = "art-x-"
@@ -123,9 +124,8 @@ func addTranslationFile(bundle *i18n.Bundle, r source.File) error {
}
// Clone sets the language func for the new language.
func (tp *TranslationProvider) Clone(d *deps.Deps) error {
d.Translate = tp.t.Func(d.Language.Lang)
func (tp *TranslationProvider) CloneResource(dst, src *deps.Deps) error {
dst.Translate = tp.t.Func(dst.Conf.Language().Lang)
return nil
}