aboutsummaryrefslogtreecommitdiffhomepage
path: root/langs
diff options
context:
space:
mode:
authorBjørn Erik Pedersen <[email protected]>2023-01-04 18:24:36 +0100
committerBjørn Erik Pedersen <[email protected]>2023-05-16 18:01:29 +0200
commit241b21b0fd34d91fccb2ce69874110dceae6f926 (patch)
treed4e0118eac7e9c42f065815447a70805f8d6ad3e /langs
parent6aededf6b42011c3039f5f66487a89a8dd65e0e7 (diff)
downloadhugo-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.go219
-rw-r--r--langs/i18n/i18n.go10
-rw-r--r--langs/i18n/i18n_test.go66
-rw-r--r--langs/i18n/translationProvider.go18
-rw-r--r--langs/language.go231
-rw-r--r--langs/language_test.go29
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)