diff options
author | Bjørn Erik Pedersen <[email protected]> | 2023-01-04 18:24:36 +0100 |
---|---|---|
committer | Bjørn Erik Pedersen <[email protected]> | 2023-05-16 18:01:29 +0200 |
commit | 241b21b0fd34d91fccb2ce69874110dceae6f926 (patch) | |
tree | d4e0118eac7e9c42f065815447a70805f8d6ad3e /langs | |
parent | 6aededf6b42011c3039f5f66487a89a8dd65e0e7 (diff) | |
download | hugo-241b21b0fd34d91fccb2ce69874110dceae6f926.tar.gz hugo-241b21b0fd34d91fccb2ce69874110dceae6f926.zip |
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
Diffstat (limited to 'langs')
-rw-r--r-- | langs/config.go | 219 | ||||
-rw-r--r-- | langs/i18n/i18n.go | 10 | ||||
-rw-r--r-- | langs/i18n/i18n_test.go | 66 | ||||
-rw-r--r-- | langs/i18n/translationProvider.go | 18 | ||||
-rw-r--r-- | langs/language.go | 231 | ||||
-rw-r--r-- | langs/language_test.go | 29 |
6 files changed, 75 insertions, 498 deletions
diff --git a/langs/config.go b/langs/config.go index 81e6fc2ab..3c7278388 100644 --- a/langs/config.go +++ b/langs/config.go @@ -14,213 +14,34 @@ package langs import ( - "fmt" - "path/filepath" - "sort" - "strings" - "github.com/gohugoio/hugo/common/maps" - - "github.com/spf13/cast" - - "errors" - - "github.com/gohugoio/hugo/config" + "github.com/mitchellh/mapstructure" ) -type LanguagesConfig struct { - Languages Languages - Multihost bool - DefaultContentLanguageInSubdir bool -} +// LanguageConfig holds the configuration for a single language. +// This is what is read from the config file. +type LanguageConfig struct { + // The language name, e.g. "English". + LanguageName string -func LoadLanguageSettings(cfg config.Provider, oldLangs Languages) (c LanguagesConfig, err error) { - defaultLang := strings.ToLower(cfg.GetString("defaultContentLanguage")) - if defaultLang == "" { - defaultLang = "en" - cfg.Set("defaultContentLanguage", defaultLang) - } - - var languages map[string]any - - languagesFromConfig := cfg.GetParams("languages") - disableLanguages := cfg.GetStringSlice("disableLanguages") - - if len(disableLanguages) == 0 { - languages = languagesFromConfig - } else { - languages = make(maps.Params) - for k, v := range languagesFromConfig { - for _, disabled := range disableLanguages { - if disabled == defaultLang { - return c, fmt.Errorf("cannot disable default language %q", defaultLang) - } - - if strings.EqualFold(k, disabled) { - v.(maps.Params)["disabled"] = true - break - } - } - languages[k] = v - } - } + // The language title. When set, this will + // override site.Title for this language. + Title string - var languages2 Languages - - if len(languages) == 0 { - languages2 = append(languages2, NewDefaultLanguage(cfg)) - } else { - languages2, err = toSortedLanguages(cfg, languages) - if err != nil { - return c, fmt.Errorf("Failed to parse multilingual config: %w", err) - } - } - - if oldLangs != nil { - // When in multihost mode, the languages are mapped to a server, so - // some structural language changes will need a restart of the dev server. - // The validation below isn't complete, but should cover the most - // important cases. - var invalid bool - if languages2.IsMultihost() != oldLangs.IsMultihost() { - invalid = true - } else { - if languages2.IsMultihost() && len(languages2) != len(oldLangs) { - invalid = true - } - } - - if invalid { - return c, errors.New("language change needing a server restart detected") - } - - if languages2.IsMultihost() { - // We need to transfer any server baseURL to the new language - for i, ol := range oldLangs { - nl := languages2[i] - nl.Set("baseURL", ol.GetString("baseURL")) - } - } - } - - // The defaultContentLanguage is something the user has to decide, but it needs - // to match a language in the language definition list. - langExists := false - for _, lang := range languages2 { - if lang.Lang == defaultLang { - langExists = true - break - } - } - - if !langExists { - return c, fmt.Errorf("site config value %q for defaultContentLanguage does not match any language definition", defaultLang) - } + // The language direction, e.g. "ltr" or "rtl". + LanguageDirection string - c.Languages = languages2 - c.Multihost = languages2.IsMultihost() - c.DefaultContentLanguageInSubdir = c.Multihost - - sortedDefaultFirst := make(Languages, len(c.Languages)) - for i, v := range c.Languages { - sortedDefaultFirst[i] = v - } - sort.Slice(sortedDefaultFirst, func(i, j int) bool { - li, lj := sortedDefaultFirst[i], sortedDefaultFirst[j] - if li.Lang == defaultLang { - return true - } - - if lj.Lang == defaultLang { - return false - } - - return i < j - }) - - cfg.Set("languagesSorted", c.Languages) - cfg.Set("languagesSortedDefaultFirst", sortedDefaultFirst) - cfg.Set("multilingual", len(languages2) > 1) - - multihost := c.Multihost - - if multihost { - cfg.Set("defaultContentLanguageInSubdir", true) - cfg.Set("multihost", true) - } - - if multihost { - // The baseURL may be provided at the language level. If that is true, - // then every language must have a baseURL. In this case we always render - // to a language sub folder, which is then stripped from all the Permalink URLs etc. - for _, l := range languages2 { - burl := l.GetLocal("baseURL") - if burl == nil { - return c, errors.New("baseURL must be set on all or none of the languages") - } - } - } - - for _, language := range c.Languages { - if language.initErr != nil { - return c, language.initErr - } - } - - return c, nil + // The language weight. When set to a non-zero value, this will + // be the main sort criteria for the language. + Weight int } -func toSortedLanguages(cfg config.Provider, l map[string]any) (Languages, error) { - languages := make(Languages, len(l)) - i := 0 - - for lang, langConf := range l { - langsMap, err := maps.ToStringMapE(langConf) - if err != nil { - return nil, fmt.Errorf("Language config is not a map: %T", langConf) - } - - language := NewLanguage(lang, cfg) +func DecodeConfig(m map[string]any) (map[string]LanguageConfig, error) { + m = maps.CleanConfigStringMap(m) + var langs map[string]LanguageConfig - for loki, v := range langsMap { - switch loki { - case "title": - language.Title = cast.ToString(v) - case "languagename": - language.LanguageName = cast.ToString(v) - case "languagedirection": - language.LanguageDirection = cast.ToString(v) - case "weight": - language.Weight = cast.ToInt(v) - case "contentdir": - language.ContentDir = filepath.Clean(cast.ToString(v)) - case "disabled": - language.Disabled = cast.ToBool(v) - case "params": - m := maps.ToStringMap(v) - // Needed for case insensitive fetching of params values - maps.PrepareParams(m) - for k, vv := range m { - language.SetParam(k, vv) - } - case "timezone": - if err := language.loadLocation(cast.ToString(v)); err != nil { - return nil, err - } - } - - // Put all into the Params map - language.SetParam(loki, v) - - // Also set it in the configuration map (for baseURL etc.) - language.Set(loki, v) - } - - languages[i] = language - i++ + if err := mapstructure.WeakDecode(m, &langs); err != nil { + return nil, err } - - sort.Sort(languages) - - return languages, nil + return langs, nil } diff --git a/langs/i18n/i18n.go b/langs/i18n/i18n.go index b7fdc1060..a9b7b4c97 100644 --- a/langs/i18n/i18n.go +++ b/langs/i18n/i18n.go @@ -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) } diff --git a/langs/i18n/i18n_test.go b/langs/i18n/i18n_test.go index cddfaf5a2..491ae3373 100644 --- a/langs/i18n/i18n_test.go +++ b/langs/i18n/i18n_test.go @@ -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) diff --git a/langs/i18n/translationProvider.go b/langs/i18n/translationProvider.go index 782bbf719..6d7b3ecfd 100644 --- a/langs/i18n/translationProvider.go +++ b/langs/i18n/translationProvider.go @@ -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 } diff --git a/langs/language.go b/langs/language.go index 9b96ec0a0..c904b0c6b 100644 --- a/langs/language.go +++ b/langs/language.go @@ -1,4 +1,4 @@ -// Copyright 2018 The Hugo Authors. All rights reserved. +// Copyright 2023 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. @@ -16,8 +16,6 @@ package langs import ( "fmt" - "sort" - "strings" "sync" "time" @@ -25,97 +23,32 @@ import ( "golang.org/x/text/language" "github.com/gohugoio/hugo/common/htime" - "github.com/gohugoio/hugo/common/maps" - "github.com/gohugoio/hugo/config" "github.com/gohugoio/locales" translators "github.com/gohugoio/localescompressed" ) -// These are the settings that should only be looked up in the global Viper -// config and not per language. -// This list may not be complete, but contains only settings that we know -// will be looked up in both. -// This isn't perfect, but it is ultimately the user who shoots him/herself in -// the foot. -// See the pathSpec. -var globalOnlySettings = map[string]bool{ - strings.ToLower("defaultContentLanguageInSubdir"): true, - strings.ToLower("defaultContentLanguage"): true, - strings.ToLower("multilingual"): true, - strings.ToLower("assetDir"): true, - strings.ToLower("resourceDir"): true, - strings.ToLower("build"): true, -} - -// Language manages specific-language configuration. type Language struct { - Lang string - LanguageName string - LanguageDirection string - Title string - Weight int - - // For internal use. - Disabled bool - - // If set per language, this tells Hugo that all content files without any - // language indicator (e.g. my-page.en.md) is in this language. - // This is usually a path relative to the working dir, but it can be an - // absolute directory reference. It is what we get. - // For internal use. - ContentDir string - - // Global config. - // For internal use. - Cfg config.Provider + // The language code, e.g. "en" or "no". + // This is currently only settable as the key in the language map in the config. + Lang string - // Language specific config. - // For internal use. - LocalCfg config.Provider - - // Composite config. - // For internal use. - config.Provider - - // These are params declared in the [params] section of the language merged with the - // site's params, the most specific (language) wins on duplicate keys. - params map[string]any - paramsMu sync.Mutex - paramsSet bool + // Fields from the language config. + LanguageConfig // Used for date formatting etc. We don't want these exported to the // templates. - // TODO(bep) do the same for some of the others. translator locales.Translator timeFormatter htime.TimeFormatter tag language.Tag collator *Collator location *time.Location - - // Error during initialization. Will fail the build. - initErr error -} - -// For internal use. -func (l *Language) String() string { - return l.Lang } // NewLanguage creates a new language. -func NewLanguage(lang string, cfg config.Provider) *Language { - // Note that language specific params will be overridden later. - // We should improve that, but we need to make a copy: - params := make(map[string]any) - for k, v := range cfg.GetStringMap("params") { - params[k] = v - } - maps.PrepareParams(params) - - localCfg := config.New() - compositeConfig := config.NewCompositeConfig(cfg, localCfg) +func NewLanguage(lang, defaultContentLanguage, timeZone string, languageConfig LanguageConfig) (*Language, error) { translator := translators.GetTranslator(lang) if translator == nil { - translator = translators.GetTranslator(cfg.GetString("defaultContentLanguage")) + translator = translators.GetTranslator(defaultContentLanguage) if translator == nil { translator = translators.GetTranslator("en") } @@ -134,76 +67,31 @@ func NewLanguage(lang string, cfg config.Provider) *Language { } l := &Language{ - Lang: lang, - ContentDir: cfg.GetString("contentDir"), - Cfg: cfg, LocalCfg: localCfg, - Provider: compositeConfig, - params: params, - translator: translator, - timeFormatter: htime.NewTimeFormatter(translator), - tag: tag, - collator: coll, + Lang: lang, + LanguageConfig: languageConfig, + translator: translator, + timeFormatter: htime.NewTimeFormatter(translator), + tag: tag, + collator: coll, } - if err := l.loadLocation(cfg.GetString("timeZone")); err != nil { - l.initErr = err - } + return l, l.loadLocation(timeZone) - return l } -// NewDefaultLanguage creates the default language for a config.Provider. -// If not otherwise specified the default is "en". -func NewDefaultLanguage(cfg config.Provider) *Language { - defaultLang := cfg.GetString("defaultContentLanguage") - - if defaultLang == "" { - defaultLang = "en" +func (l *Language) loadLocation(tzStr string) error { + location, err := time.LoadLocation(tzStr) + if err != nil { + return fmt.Errorf("invalid timeZone for language %q: %w", l.Lang, err) } + l.location = location - return NewLanguage(defaultLang, cfg) + return nil } // Languages is a sortable list of languages. type Languages []*Language -// NewLanguages creates a sorted list of languages. -// NOTE: function is currently unused. -func NewLanguages(l ...*Language) Languages { - languages := make(Languages, len(l)) - for i := 0; i < len(l); i++ { - languages[i] = l[i] - } - sort.Sort(languages) - return languages -} - -func (l Languages) Len() int { return len(l) } -func (l Languages) Less(i, j int) bool { - wi, wj := l[i].Weight, l[j].Weight - - if wi == wj { - return l[i].Lang < l[j].Lang - } - - return wj == 0 || wi < wj -} - -func (l Languages) Swap(i, j int) { l[i], l[j] = l[j], l[i] } - -// Params returns language-specific params merged with the global params. -func (l *Language) Params() maps.Params { - // TODO(bep) this construct should not be needed. Create the - // language params in one go. - l.paramsMu.Lock() - defer l.paramsMu.Unlock() - if !l.paramsSet { - maps.PrepareParams(l.params) - l.paramsSet = true - } - return l.params -} - func (l Languages) AsSet() map[string]bool { m := make(map[string]bool) for _, lang := range l { @@ -222,73 +110,6 @@ func (l Languages) AsOrdinalSet() map[string]int { return m } -// IsMultihost returns whether there are more than one language and at least one of -// the languages has baseURL specified on the language level. -func (l Languages) IsMultihost() bool { - if len(l) <= 1 { - return false - } - - for _, lang := range l { - if lang.GetLocal("baseURL") != nil { - return true - } - } - return false -} - -// SetParam sets a param with the given key and value. -// SetParam is case-insensitive. -// For internal use. -func (l *Language) SetParam(k string, v any) { - l.paramsMu.Lock() - defer l.paramsMu.Unlock() - if l.paramsSet { - panic("params cannot be changed once set") - } - l.params[k] = v -} - -// GetLocal gets a configuration value set on language level. It will -// not fall back to any global value. -// It will return nil if a value with the given key cannot be found. -// For internal use. -func (l *Language) GetLocal(key string) any { - if l == nil { - panic("language not set") - } - key = strings.ToLower(key) - if !globalOnlySettings[key] { - return l.LocalCfg.Get(key) - } - return nil -} - -// For internal use. -func (l *Language) Set(k string, v any) { - k = strings.ToLower(k) - if globalOnlySettings[k] { - return - } - l.Provider.Set(k, v) -} - -// Merge is currently not supported for Language. -// For internal use. -func (l *Language) Merge(key string, value any) { - panic("Not supported") -} - -// IsSet checks whether the key is set in the language or the related config store. -// For internal use. -func (l *Language) IsSet(key string) bool { - key = strings.ToLower(key) - if !globalOnlySettings[key] { - return l.Provider.IsSet(key) - } - return l.Cfg.IsSet(key) -} - // Internal access to unexported Language fields. // This construct is to prevent them from leaking to the templates. @@ -308,16 +129,6 @@ func GetCollator(l *Language) *Collator { return l.collator } -func (l *Language) loadLocation(tzStr string) error { - location, err := time.LoadLocation(tzStr) - if err != nil { - return fmt.Errorf("invalid timeZone for language %q: %w", l.Lang, err) - } - l.location = location - - return nil -} - type Collator struct { sync.Mutex c *collate.Collator diff --git a/langs/language_test.go b/langs/language_test.go index 264e813a0..e2c734567 100644 --- a/langs/language_test.go +++ b/langs/language_test.go @@ -18,39 +18,10 @@ import ( "testing" qt "github.com/frankban/quicktest" - "github.com/gohugoio/hugo/config" "golang.org/x/text/collate" "golang.org/x/text/language" ) -func TestGetGlobalOnlySetting(t *testing.T) { - c := qt.New(t) - v := config.NewWithTestDefaults() - v.Set("defaultContentLanguageInSubdir", true) - v.Set("contentDir", "content") - v.Set("paginatePath", "page") - lang := NewDefaultLanguage(v) - lang.Set("defaultContentLanguageInSubdir", false) - lang.Set("paginatePath", "side") - - c.Assert(lang.GetBool("defaultContentLanguageInSubdir"), qt.Equals, true) - c.Assert(lang.GetString("paginatePath"), qt.Equals, "side") -} - -func TestLanguageParams(t *testing.T) { - c := qt.New(t) - - v := config.NewWithTestDefaults() - v.Set("p1", "p1cfg") - v.Set("contentDir", "content") - - lang := NewDefaultLanguage(v) - lang.SetParam("p1", "p1p") - - c.Assert(lang.Params()["p1"], qt.Equals, "p1p") - c.Assert(lang.Get("p1"), qt.Equals, "p1cfg") -} - func TestCollator(t *testing.T) { c := qt.New(t) |