mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-21 20:46:30 -05:00
Add proper Language and Languages types
This commit is contained in:
parent
ec33732fbe
commit
06d12ab895
5 changed files with 159 additions and 70 deletions
|
@ -493,9 +493,8 @@ func InitializeConfig(subCmdVs ...*cobra.Command) error {
|
|||
helpers.HugoReleaseVersion(), minVersion)
|
||||
}
|
||||
|
||||
readMultilingualConfiguration()
|
||||
return readMultilingualConfiguration()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func flagChanged(flags *flag.FlagSet, key string) bool {
|
||||
|
@ -715,11 +714,11 @@ func buildSite(watching ...bool) (err error) {
|
|||
|
||||
for _, lang := range langConfigsList {
|
||||
t1 := time.Now()
|
||||
mainSite, present := MainSites[lang]
|
||||
mainSite, present := MainSites[lang.Lang]
|
||||
if !present {
|
||||
mainSite = new(hugolib.Site)
|
||||
MainSites[lang] = mainSite
|
||||
mainSite.SetMultilingualConfig(lang, langConfigsList, langConfigs)
|
||||
MainSites[lang.Lang] = mainSite
|
||||
mainSite.SetMultilingualConfig(lang, langConfigsList)
|
||||
}
|
||||
|
||||
if len(watching) > 0 && watching[0] {
|
||||
|
@ -730,7 +729,7 @@ func buildSite(watching ...bool) (err error) {
|
|||
return err
|
||||
}
|
||||
|
||||
mainSite.Stats(lang, t1)
|
||||
mainSite.Stats(lang.Lang, t1)
|
||||
}
|
||||
|
||||
jww.FEEDBACK.Printf("total in %v ms\n", int(1000*time.Since(t0).Seconds()))
|
||||
|
@ -743,13 +742,13 @@ func rebuildSite(events []fsnotify.Event) error {
|
|||
|
||||
for _, lang := range langConfigsList {
|
||||
t1 := time.Now()
|
||||
mainSite := MainSites[lang]
|
||||
mainSite := MainSites[lang.Lang]
|
||||
|
||||
if err := mainSite.ReBuild(events); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mainSite.Stats(lang, t1)
|
||||
mainSite.Stats(lang.Lang, t1)
|
||||
}
|
||||
|
||||
jww.FEEDBACK.Printf("total in %v ms\n", int(1000*time.Since(t0).Seconds()))
|
||||
|
|
|
@ -1,41 +1,66 @@
|
|||
package commands
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/hugo/hugolib"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var langConfigs map[string]interface{}
|
||||
var langConfigsList langConfigsSortable
|
||||
var langConfigsList hugolib.Languages
|
||||
|
||||
func readMultilingualConfiguration() {
|
||||
func readMultilingualConfiguration() error {
|
||||
multilingual := viper.GetStringMap("Multilingual")
|
||||
if len(multilingual) == 0 {
|
||||
langConfigsList = append(langConfigsList, "")
|
||||
return
|
||||
// TODO(bep) multilingo langConfigsList = append(langConfigsList, hugolib.NewLanguage("en"))
|
||||
return nil
|
||||
}
|
||||
|
||||
langConfigs = make(map[string]interface{})
|
||||
for lang, config := range multilingual {
|
||||
langConfigs[lang] = config
|
||||
langConfigsList = append(langConfigsList, lang)
|
||||
var err error
|
||||
|
||||
langConfigsList, err = toSortedLanguages(multilingual)
|
||||
|
||||
if err != nil {
|
||||
return fmt.Errorf("Failed to parse multilingual config: %s", err)
|
||||
}
|
||||
sort.Sort(langConfigsList)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
type langConfigsSortable []string
|
||||
func toSortedLanguages(l map[string]interface{}) (hugolib.Languages, error) {
|
||||
langs := make(hugolib.Languages, len(l))
|
||||
|
||||
func (p langConfigsSortable) Len() int { return len(p) }
|
||||
func (p langConfigsSortable) Less(i, j int) bool { return weightForLang(p[i]) < weightForLang(p[j]) }
|
||||
func (p langConfigsSortable) Swap(i, j int) { p[i], p[j] = p[j], p[i] }
|
||||
for lang, langConf := range l {
|
||||
langsMap, ok := langConf.(map[string]interface{})
|
||||
|
||||
func weightForLang(lang string) int {
|
||||
conf := langConfigs[lang]
|
||||
if conf == nil {
|
||||
return 0
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("Language config is not a map: %v", langsMap)
|
||||
}
|
||||
|
||||
language := hugolib.NewLanguage(lang)
|
||||
|
||||
for k, v := range langsMap {
|
||||
loki := strings.ToLower(k)
|
||||
switch loki {
|
||||
case "title":
|
||||
language.Title = cast.ToString(v)
|
||||
case "weight":
|
||||
language.Weight = cast.ToInt(v)
|
||||
}
|
||||
|
||||
// Put all into the Params map
|
||||
// TODO(bep) reconsile with the type handling etc. from other params handlers.
|
||||
language.SetParam(loki, v)
|
||||
}
|
||||
|
||||
langs = append(langs, language)
|
||||
}
|
||||
m := cast.ToStringMap(conf)
|
||||
return cast.ToInt(m["weight"])
|
||||
|
||||
sort.Sort(langs)
|
||||
|
||||
return langs, nil
|
||||
}
|
||||
|
|
|
@ -1,43 +1,80 @@
|
|||
package hugolib
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cast"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
type Multilingual struct {
|
||||
enabled bool
|
||||
config *viper.Viper
|
||||
|
||||
Languages []string
|
||||
type Language struct {
|
||||
Lang string
|
||||
Title string
|
||||
Weight int
|
||||
params map[string]interface{}
|
||||
paramsInit sync.Once
|
||||
}
|
||||
|
||||
func (ml *Multilingual) GetString(key string) string { return cast.ToString(ml.Get(key)) }
|
||||
func (ml *Multilingual) GetStringMap(key string) map[string]interface{} {
|
||||
func NewLanguage(lang string) *Language {
|
||||
return &Language{Lang: lang, params: make(map[string]interface{})}
|
||||
}
|
||||
|
||||
type Languages []*Language
|
||||
|
||||
func (l Languages) Len() int { return len(l) }
|
||||
func (l Languages) Less(i, j int) bool { return l[i].Weight < l[j].Weight }
|
||||
func (l Languages) Swap(i, j int) { l[i], l[j] = l[j], l[i] }
|
||||
|
||||
type Multilingual struct {
|
||||
enabled bool
|
||||
|
||||
Languages Languages
|
||||
}
|
||||
|
||||
func (l *Language) Params() map[string]interface{} {
|
||||
l.paramsInit.Do(func() {
|
||||
// Merge with global config.
|
||||
// TODO(bep) consider making this part of a constructor func.
|
||||
globalParams := viper.GetStringMap("Params")
|
||||
for k, v := range globalParams {
|
||||
if _, ok := l.params[k]; !ok {
|
||||
l.params[k] = v
|
||||
}
|
||||
}
|
||||
})
|
||||
return l.params
|
||||
}
|
||||
|
||||
func (l *Language) SetParam(k string, v interface{}) {
|
||||
l.params[k] = v
|
||||
}
|
||||
|
||||
func (l *Language) GetString(key string) string { return cast.ToString(l.Get(key)) }
|
||||
func (ml *Language) GetStringMap(key string) map[string]interface{} {
|
||||
return cast.ToStringMap(ml.Get(key))
|
||||
}
|
||||
|
||||
func (ml *Multilingual) GetStringMapString(key string) map[string]string {
|
||||
return cast.ToStringMapString(ml.Get(key))
|
||||
func (l *Language) GetStringMapString(key string) map[string]string {
|
||||
return cast.ToStringMapString(l.Get(key))
|
||||
}
|
||||
|
||||
func (ml *Multilingual) Get(key string) interface{} {
|
||||
if ml != nil && ml.config != nil && ml.config.IsSet(key) {
|
||||
return ml.config.Get(key)
|
||||
func (l *Language) Get(key string) interface{} {
|
||||
key = strings.ToLower(key)
|
||||
if v, ok := l.params[key]; ok {
|
||||
return v
|
||||
}
|
||||
return viper.Get(key)
|
||||
}
|
||||
|
||||
func (s *Site) SetMultilingualConfig(currentLang string, orderedLanguages []string, langConfigs map[string]interface{}) {
|
||||
conf := viper.New()
|
||||
for k, val := range cast.ToStringMap(langConfigs[currentLang]) {
|
||||
conf.Set(k, val)
|
||||
}
|
||||
conf.Set("CurrentLanguage", currentLang)
|
||||
func (s *Site) SetMultilingualConfig(currentLang *Language, languages Languages) {
|
||||
|
||||
// TODO(bep) multilingo evaluate
|
||||
viper.Set("CurrentLanguage", currentLang)
|
||||
ml := &Multilingual{
|
||||
enabled: len(langConfigs) > 0,
|
||||
config: conf,
|
||||
Languages: orderedLanguages,
|
||||
enabled: len(languages) > 0,
|
||||
Languages: languages,
|
||||
}
|
||||
viper.Set("Multilingual", ml.enabled)
|
||||
s.Multilingual = ml
|
||||
|
@ -46,3 +83,15 @@ func (s *Site) SetMultilingualConfig(currentLang string, orderedLanguages []stri
|
|||
func (s *Site) multilingualEnabled() bool {
|
||||
return s.Multilingual != nil && s.Multilingual.enabled
|
||||
}
|
||||
|
||||
func currentLanguageString() string {
|
||||
return currentLanguage().Lang
|
||||
}
|
||||
|
||||
func currentLanguage() *Language {
|
||||
l := viper.Get("CurrentLanguage")
|
||||
if l == nil {
|
||||
panic("CurrentLanguage not set")
|
||||
}
|
||||
return l.(*Language)
|
||||
}
|
||||
|
|
|
@ -131,7 +131,7 @@ type SiteInfo struct {
|
|||
Multilingual bool
|
||||
CurrentLanguage string
|
||||
LanguagePrefix string
|
||||
Languages []string
|
||||
Languages Languages
|
||||
}
|
||||
|
||||
// SiteSocial is a place to put social details on a site level. These are the
|
||||
|
@ -705,7 +705,7 @@ func (s *Site) Process() (err error) {
|
|||
i18nSources = []source.Input{&source.Filesystem{Base: themeI18nDir}, i18nSources[0]}
|
||||
}
|
||||
|
||||
if err = loadI18n(i18nSources, s.Multilingual.GetString("CurrentLanguage")); err != nil {
|
||||
if err = loadI18n(i18nSources, currentLanguageString()); err != nil {
|
||||
return
|
||||
}
|
||||
s.timerStep("load i18n")
|
||||
|
@ -742,7 +742,7 @@ func (s *Site) setupTranslations() {
|
|||
return
|
||||
}
|
||||
|
||||
currentLang := s.Multilingual.GetString("CurrentLanguage")
|
||||
currentLang := currentLanguageString()
|
||||
|
||||
allTranslations := pagesToTranslationsMap(s.AllPages)
|
||||
assignTranslationsToPages(allTranslations, s.AllPages)
|
||||
|
@ -817,7 +817,27 @@ func (s *Site) initialize() (err error) {
|
|||
}
|
||||
|
||||
func (s *Site) initializeSiteInfo() {
|
||||
params := s.Multilingual.GetStringMap("Params")
|
||||
|
||||
var (
|
||||
lang *Language
|
||||
languages Languages
|
||||
)
|
||||
|
||||
cl := viper.Get("CurrentLanguage")
|
||||
if cl == nil {
|
||||
// Set default to english
|
||||
// TODO(bep) multilingo this looks clumsy
|
||||
lang = NewLanguage("en")
|
||||
viper.Set("CurrentLanguage", lang)
|
||||
} else {
|
||||
lang = cl.(*Language)
|
||||
}
|
||||
|
||||
if s.Multilingual != nil {
|
||||
languages = s.Multilingual.Languages
|
||||
}
|
||||
|
||||
params := lang.Params()
|
||||
|
||||
permalinks := make(PermalinkOverrides)
|
||||
for k, v := range viper.GetStringMapString("Permalinks") {
|
||||
|
@ -826,24 +846,20 @@ func (s *Site) initializeSiteInfo() {
|
|||
|
||||
languagePrefix := ""
|
||||
if s.multilingualEnabled() {
|
||||
languagePrefix = "/" + s.Multilingual.GetString("CurrentLanguage")
|
||||
}
|
||||
|
||||
languages := []string{}
|
||||
if s.Multilingual != nil {
|
||||
languages = s.Multilingual.Languages
|
||||
languagePrefix = "/" + lang.Lang
|
||||
}
|
||||
|
||||
s.Info = SiteInfo{
|
||||
BaseURL: template.URL(helpers.SanitizeURLKeepTrailingSlash(viper.GetString("BaseURL"))),
|
||||
Title: s.Multilingual.GetString("Title"),
|
||||
Author: s.Multilingual.GetStringMap("author"),
|
||||
Social: s.Multilingual.GetStringMapString("social"),
|
||||
LanguageCode: s.Multilingual.GetString("languagecode"),
|
||||
Copyright: s.Multilingual.GetString("copyright"),
|
||||
DisqusShortname: s.Multilingual.GetString("DisqusShortname"),
|
||||
BaseURL: template.URL(helpers.SanitizeURLKeepTrailingSlash(viper.GetString("BaseURL"))),
|
||||
Title: lang.GetString("Title"),
|
||||
Author: lang.GetStringMap("author"),
|
||||
Social: lang.GetStringMapString("social"),
|
||||
LanguageCode: lang.GetString("languagecode"),
|
||||
Copyright: lang.GetString("copyright"),
|
||||
DisqusShortname: lang.GetString("DisqusShortname"),
|
||||
// TODO(bep) multilang, consolidate the below (make into methods etc.)
|
||||
Multilingual: s.multilingualEnabled(),
|
||||
CurrentLanguage: s.Multilingual.GetString("CurrentLanguage"),
|
||||
CurrentLanguage: lang.Lang,
|
||||
LanguagePrefix: languagePrefix,
|
||||
Languages: languages,
|
||||
GoogleAnalytics: viper.GetString("GoogleAnalytics"),
|
||||
|
@ -1594,7 +1610,7 @@ func (s *Site) newTaxonomyNode(t taxRenderInfo) (*Node, string) {
|
|||
func (s *Site) addMultilingualPrefix(basePath string) string {
|
||||
hadPrefix := strings.HasPrefix(basePath, "/")
|
||||
if s.multilingualEnabled() {
|
||||
basePath = path.Join(s.Multilingual.GetString("CurrentLanguage"), basePath)
|
||||
basePath = path.Join(currentLanguageString(), basePath)
|
||||
if hadPrefix {
|
||||
basePath = "/" + basePath
|
||||
}
|
||||
|
|
|
@ -1402,13 +1402,13 @@ NOTE: should use the "permalinks" configuration with :filename
|
|||
s := &Site{
|
||||
Source: &source.InMemorySource{ByteSource: sources},
|
||||
Multilingual: &Multilingual{
|
||||
config: viper.New(),
|
||||
enabled: true,
|
||||
},
|
||||
}
|
||||
// Multilingual settings
|
||||
viper.Set("Multilingual", true)
|
||||
s.Multilingual.config.Set("CurrentLanguage", "en")
|
||||
en := NewLanguage("en")
|
||||
viper.Set("CurrentLanguage", en)
|
||||
viper.Set("DefaultContentLanguage", "fr")
|
||||
viper.Set("paginate", "2")
|
||||
|
||||
|
|
Loading…
Reference in a new issue