mirror of
https://github.com/gohugoio/hugo.git
synced 2025-08-24 21:56:05 +02:00
Add multilingual support in Hugo
Implements: * support to render: * content/post/whatever.en.md to /en/2015/12/22/whatever/index.html * content/post/whatever.fr.md to /fr/2015/12/22/whatever/index.html * gets enabled when `Multilingual:` is specified in config. * support having language switchers in templates, that know where the translated page is (with .Page.Translations) (when you're on /en/about/, you can have a "Francais" link pointing to /fr/a-propos/) * all translations are in the `.Page.Translations` map, including the current one. * easily tweak themes to support Multilingual mode * renders in a single swift, no need for two config files. Adds a couple of variables useful for multilingual sites Adds documentation (content/multilingual.md) Added language prefixing for all URL generation/permalinking see in the code base. Implements i18n. Leverages the great github.com/nicksnyder/go-i18n lib.. thanks Nick. * Adds "i18n" and "T" template functions..
This commit is contained in:
committed by
Bjørn Erik Pedersen
parent
faa3472fa2
commit
ec33732fbe
@@ -46,10 +46,10 @@ import (
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
// MainSite represents the Hugo site to build. This variable is exported as it
|
||||
// MainSites represents the Hugo sites to build. This variable is exported as it
|
||||
// is used by at least one external library (the Hugo caddy plugin). We should
|
||||
// provide a cleaner external API, but until then, this is it.
|
||||
var MainSite *hugolib.Site
|
||||
var MainSites map[string]*hugolib.Site
|
||||
|
||||
// Reset resets Hugo ready for a new full build. This is mainly only useful
|
||||
// for benchmark testing etc. via the CLI commands.
|
||||
@@ -287,6 +287,7 @@ func loadDefaultSettings() {
|
||||
viper.SetDefault("ArchetypeDir", "archetypes")
|
||||
viper.SetDefault("PublishDir", "public")
|
||||
viper.SetDefault("DataDir", "data")
|
||||
viper.SetDefault("I18nDir", "i18n")
|
||||
viper.SetDefault("ThemesDir", "themes")
|
||||
viper.SetDefault("DefaultLayout", "post")
|
||||
viper.SetDefault("BuildDrafts", false)
|
||||
@@ -323,6 +324,8 @@ func loadDefaultSettings() {
|
||||
viper.SetDefault("EnableEmoji", false)
|
||||
viper.SetDefault("PygmentsCodeFencesGuessSyntax", false)
|
||||
viper.SetDefault("UseModTimeAsFallback", false)
|
||||
viper.SetDefault("Multilingual", false)
|
||||
viper.SetDefault("DefaultContentLanguage", "en")
|
||||
}
|
||||
|
||||
// InitializeConfig initializes a config file with sensible default configuration flags.
|
||||
@@ -490,6 +493,8 @@ func InitializeConfig(subCmdVs ...*cobra.Command) error {
|
||||
helpers.HugoReleaseVersion(), minVersion)
|
||||
}
|
||||
|
||||
readMultilingualConfiguration()
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -506,7 +511,7 @@ func watchConfig() {
|
||||
viper.OnConfigChange(func(e fsnotify.Event) {
|
||||
fmt.Println("Config file changed:", e.Name)
|
||||
// Force a full rebuild
|
||||
MainSite = nil
|
||||
MainSites = nil
|
||||
utils.CheckErr(buildSite(true))
|
||||
if !viper.GetBool("DisableLiveReload") {
|
||||
// Will block forever trying to write to a channel that nobody is reading if livereload isn't initialized
|
||||
@@ -632,6 +637,7 @@ func copyStatic() error {
|
||||
func getDirList() []string {
|
||||
var a []string
|
||||
dataDir := helpers.AbsPathify(viper.GetString("DataDir"))
|
||||
i18nDir := helpers.AbsPathify(viper.GetString("I18nDir"))
|
||||
layoutDir := helpers.AbsPathify(viper.GetString("LayoutDir"))
|
||||
staticDir := helpers.AbsPathify(viper.GetString("StaticDir"))
|
||||
walker := func(path string, fi os.FileInfo, err error) error {
|
||||
@@ -639,8 +645,13 @@ func getDirList() []string {
|
||||
if path == dataDir && os.IsNotExist(err) {
|
||||
jww.WARN.Println("Skip DataDir:", err)
|
||||
return nil
|
||||
|
||||
}
|
||||
|
||||
if path == i18nDir && os.IsNotExist(err) {
|
||||
jww.WARN.Println("Skip I18nDir:", err)
|
||||
return nil
|
||||
}
|
||||
|
||||
if path == layoutDir && os.IsNotExist(err) {
|
||||
jww.WARN.Println("Skip LayoutDir:", err)
|
||||
return nil
|
||||
@@ -684,6 +695,7 @@ func getDirList() []string {
|
||||
|
||||
helpers.SymbolicWalk(hugofs.Source(), dataDir, walker)
|
||||
helpers.SymbolicWalk(hugofs.Source(), helpers.AbsPathify(viper.GetString("ContentDir")), walker)
|
||||
helpers.SymbolicWalk(hugofs.Source(), i18nDir, walker)
|
||||
helpers.SymbolicWalk(hugofs.Source(), helpers.AbsPathify(viper.GetString("LayoutDir")), walker)
|
||||
helpers.SymbolicWalk(hugofs.Source(), staticDir, walker)
|
||||
if helpers.ThemeSet() {
|
||||
@@ -695,31 +707,52 @@ func getDirList() []string {
|
||||
|
||||
func buildSite(watching ...bool) (err error) {
|
||||
fmt.Println("Started building site")
|
||||
startTime := time.Now()
|
||||
if MainSite == nil {
|
||||
MainSite = new(hugolib.Site)
|
||||
t0 := time.Now()
|
||||
|
||||
if MainSites == nil {
|
||||
MainSites = make(map[string]*hugolib.Site)
|
||||
}
|
||||
if len(watching) > 0 && watching[0] {
|
||||
MainSite.RunMode.Watching = true
|
||||
|
||||
for _, lang := range langConfigsList {
|
||||
t1 := time.Now()
|
||||
mainSite, present := MainSites[lang]
|
||||
if !present {
|
||||
mainSite = new(hugolib.Site)
|
||||
MainSites[lang] = mainSite
|
||||
mainSite.SetMultilingualConfig(lang, langConfigsList, langConfigs)
|
||||
}
|
||||
|
||||
if len(watching) > 0 && watching[0] {
|
||||
mainSite.RunMode.Watching = true
|
||||
}
|
||||
|
||||
if err := mainSite.Build(); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mainSite.Stats(lang, t1)
|
||||
}
|
||||
err = MainSite.Build()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
MainSite.Stats()
|
||||
jww.FEEDBACK.Printf("in %v ms\n", int(1000*time.Since(startTime).Seconds()))
|
||||
|
||||
jww.FEEDBACK.Printf("total in %v ms\n", int(1000*time.Since(t0).Seconds()))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func rebuildSite(events []fsnotify.Event) error {
|
||||
startTime := time.Now()
|
||||
err := MainSite.ReBuild(events)
|
||||
if err != nil {
|
||||
return err
|
||||
t0 := time.Now()
|
||||
|
||||
for _, lang := range langConfigsList {
|
||||
t1 := time.Now()
|
||||
mainSite := MainSites[lang]
|
||||
|
||||
if err := mainSite.ReBuild(events); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
mainSite.Stats(lang, t1)
|
||||
}
|
||||
MainSite.Stats()
|
||||
jww.FEEDBACK.Printf("in %v ms\n", int(1000*time.Since(startTime).Seconds()))
|
||||
|
||||
jww.FEEDBACK.Printf("total in %v ms\n", int(1000*time.Since(t0).Seconds()))
|
||||
|
||||
return nil
|
||||
}
|
||||
|
Reference in New Issue
Block a user