Skip to content

Commit

Permalink
i18n: Upgrade to go-i18n v2
Browse files Browse the repository at this point in the history
  • Loading branch information
bep committed Sep 21, 2018
1 parent f1a00b2 commit 890ca5f
Show file tree
Hide file tree
Showing 6 changed files with 63 additions and 65 deletions.
2 changes: 1 addition & 1 deletion deps/deps.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ type Deps struct {
Cfg config.Provider `json:"-"`

// The translation func to use
Translate func(translationID string, args ...interface{}) string `json:"-"`
Translate func(translationID string, templateData interface{}) string `json:"-"`

Language *langs.Language

Expand Down
3 changes: 2 additions & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module github.com/gohugoio/hugo

require (
github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69
github.com/BurntSushi/toml v0.0.0-20170626110600-a368813c5e64
github.com/BurntSushi/toml v0.3.0

This comment has been minimized.

Copy link
@kaushalmodi

kaushalmodi Sep 21, 2018

@bep This would revert back the toml package to a March 2017 release. At the moment, we are using the June 2017 commit which has this fix that I rely on: BurntSushi/toml@8fb9fdc

Update: OK, a moment after I pinged on that toml repo issue, a new tag was added. Please update the toml reference to 0.3.1.

github.com/PuerkitoBio/purell v1.1.0
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 // indirect
github.com/alecthomas/assert v0.0.0-20170929043011-405dbfeb8e38
Expand Down Expand Up @@ -37,6 +37,7 @@ require (
github.com/muesli/smartcrop v0.0.0-20180228075044-f6ebaa786a12
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 // indirect
github.com/nicksnyder/go-i18n v1.10.0
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5.0.20180809142456-e786c8873251
github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/russross/blackfriday v0.0.0-20180804101149-46c73eb196ba
Expand Down
7 changes: 7 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69 h1:+tu3HOoMXB7RX
github.com/BurntSushi/locker v0.0.0-20171006230638-a6e239ea1c69/go.mod h1:L1AbZdiDllfyYH5l5OkAaZtk7VkWe89bPJFmnDBNHxg=
github.com/BurntSushi/toml v0.0.0-20170626110600-a368813c5e64 h1:BuYewlQyh/jroxY8qx41SrzD8Go17GkyCyAeVmprvQI=
github.com/BurntSushi/toml v0.0.0-20170626110600-a368813c5e64/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/toml v0.3.0 h1:e1/Ivsx3Z0FVTV0NSOv/aVgbUWyQuzj7DDnFblkRvsY=
github.com/BurntSushi/toml v0.3.0/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/PuerkitoBio/purell v1.1.0 h1:rmGxhojJlM0tuKtfdvliR84CFHljx9ag64t2xmVkjK4=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
Expand Down Expand Up @@ -83,6 +85,10 @@ github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646 h1:zYyBkD/k9seD2A7fsi6
github.com/nfnt/resize v0.0.0-20180221191011-83c6a9932646/go.mod h1:jpp1/29i3P1S/RLdc7JQKbRpFeM1dOBd8T9ki5s+AY8=
github.com/nicksnyder/go-i18n v1.10.0 h1:5AzlPKvXBH4qBzmZ09Ua9Gipyruv6uApMcrNZdo96+Q=
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5 h1:/TjjTS4kg7vC+05gD0LE4+97f/+PRFICnK/7wJPk7kE=
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5/go.mod h1:4Opqa6/HIv0lhG3WRAkqzO0afezkRhxXI0P8EJkqeRU=
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5.0.20180809142456-e786c8873251 h1:t+H3wc9GR6DQNaSNfYnfAQnQSf7EM9CwxsOpYuEyXCM=
github.com/nicksnyder/go-i18n/v2 v2.0.0-beta.5.0.20180809142456-e786c8873251/go.mod h1:4Opqa6/HIv0lhG3WRAkqzO0afezkRhxXI0P8EJkqeRU=
github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84 h1:fiKJgB4JDUd43CApkmCeTSQlWjtTtABrU2qsgbuP0BI=
github.com/olekukonko/tablewriter v0.0.0-20180506121414-d4647c9c7a84/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo=
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
Expand Down Expand Up @@ -133,6 +139,7 @@ golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f h1:wMNYb4v58l5UBM7MYRLPG6Zh
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992 h1:BH3eQWeGbwRU2+wxxuuPOdFBmaiBH81O8BugSjHeTFg=
golang.org/x/sys v0.0.0-20180906133057-8cf3aee42992/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/text v0.0.0-20171214130843-f21a4dfb5e38/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
Expand Down
75 changes: 41 additions & 34 deletions i18n/i18n.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,33 +14,37 @@
package i18n

import (
"fmt"

"github.com/gohugoio/hugo/config"
"github.com/gohugoio/hugo/helpers"
"github.com/nicksnyder/go-i18n/i18n/bundle"
"github.com/nicksnyder/go-i18n/v2/i18n"
jww "github.com/spf13/jwalterweatherman"
)

type translateFunc func(translationID string, templateData interface{}) string

var (
i18nWarningLogger = helpers.NewDistinctFeedbackLogger()
)

// Translator handles i18n translations.
type Translator struct {
translateFuncs map[string]bundle.TranslateFunc
translateFuncs map[string]translateFunc
cfg config.Provider
logger *jww.Notepad
}

// NewTranslator creates a new Translator for the given language bundle and configuration.
func NewTranslator(b *bundle.Bundle, cfg config.Provider, logger *jww.Notepad) Translator {
t := Translator{cfg: cfg, logger: logger, translateFuncs: make(map[string]bundle.TranslateFunc)}
func NewTranslator(b *i18n.Bundle, cfg config.Provider, logger *jww.Notepad) Translator {
t := Translator{cfg: cfg, logger: logger, translateFuncs: make(map[string]translateFunc)}
t.initFuncs(b)
return t
}

// Func gets the translate func for the given language, or for the default
// configured language if not found.
func (t Translator) Func(lang string) bundle.TranslateFunc {
func (t Translator) Func(lang string) translateFunc {
if f, ok := t.translateFuncs[lang]; ok {
return f
}
Expand All @@ -49,34 +53,35 @@ func (t Translator) Func(lang string) bundle.TranslateFunc {
return f
}
t.logger.WARN.Println("i18n not initialized, check that you have language file (in i18n) that matches the site language or the default language.")
return func(translationID string, args ...interface{}) string {
return func(translationID string, args interface{}) string {
return ""
}

}

func (t Translator) initFuncs(bndl *bundle.Bundle) {
defaultContentLanguage := t.cfg.GetString("defaultContentLanguage")
var defaultMessage = &i18n.Message{
ID: "___I18N_DEFAULT",
Other: "I18N_MISSING",
}

defaultT, err := bndl.Tfunc(defaultContentLanguage)
if err != nil {
jww.WARN.Printf("No translation bundle found for default language %q", defaultContentLanguage)
}
func (t Translator) initFuncs(bndl *i18n.Bundle) {
// TODO(bep) i18n defaultContentLanguage := t.cfg.GetString("defaultContentLanguage")

enableMissingTranslationPlaceholders := t.cfg.GetBool("enableMissingTranslationPlaceholders")
for _, lang := range bndl.LanguageTags() {
currentLang := lang
currentLang := lang.String()

t.translateFuncs[currentLang] = func(translationID string, args ...interface{}) string {
tFunc, err := bndl.Tfunc(currentLang)
if err != nil {
jww.WARN.Printf("could not load translations for language %q (%s), will use default content language.\n", lang, err)
}
t.translateFuncs[currentLang] = func(translationID string, templateData interface{}) string {
localizer := i18n.NewLocalizer(bndl, currentLang)

translated, err := localizer.Localize(&i18n.LocalizeConfig{
//DefaultMessage: defaultMessage,
MessageID: translationID,
TemplateData: templateData,
})

fmt.Printf(">>>%v %T %s %s %s\n", err, err, currentLang, translationID, translated)

translated := tFunc(translationID, args...)
if translated != translationID {
return translated
}
// If there is no translation for translationID,
// then Tfunc returns translationID itself.
// But if user set same translationID and translation, we should check
Expand All @@ -91,23 +96,25 @@ func (t Translator) initFuncs(bndl *bundle.Bundle) {
if enableMissingTranslationPlaceholders {
return "[i18n] " + translationID
}
if defaultT != nil {
translated := defaultT(translationID, args...)
if translated != translationID {
return translated
}
if isIDTranslated(defaultContentLanguage, translationID, bndl) {
return translated
}
}
/*
TODO(bep) i18n
if defaultT != nil {
translated := defaultT(translationID, args...)
if translated != translationID {
return translated
}
if isIDTranslated(defaultContentLanguage, translationID, bndl) {
return translated
}
}*/
return ""
}
}
}

// If bndl contains the translationID for specified currentLang,
// then the translationID is actually translated.
func isIDTranslated(lang, id string, b *bundle.Bundle) bool {
_, contains := b.Translations()[lang][id]
return contains
func isIDTranslated(lang, id string, b *i18n.Bundle) bool {
// _, contains := b.Translations()[lang][id]
return true // TODO(bep) i18n
}
37 changes: 10 additions & 27 deletions i18n/translationProvider.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,15 @@
package i18n

import (
"errors"
"fmt"

"github.com/BurntSushi/toml"
"github.com/gohugoio/hugo/helpers"
"github.com/nicksnyder/go-i18n/v2/i18n"

"github.com/gohugoio/hugo/deps"
"github.com/gohugoio/hugo/source"
"github.com/nicksnyder/go-i18n/i18n/bundle"
"github.com/nicksnyder/go-i18n/i18n/language"
"golang.org/x/text/language"
)

// TranslationProvider provides translation handling, i.e. loading
Expand All @@ -41,51 +41,34 @@ func (tp *TranslationProvider) Update(d *deps.Deps) error {
sp := source.NewSourceSpec(d.PathSpec, d.BaseFs.SourceFilesystems.I18n.Fs)
src := sp.NewFilesystem("")

i18nBundle := bundle.New()

en := language.GetPluralSpec("en")
if en == nil {
return errors.New("the English language has vanished like an old oak table")
}
var newLangs []string

for _, r := range src.Files() {
currentSpec := language.GetPluralSpec(r.BaseFileName())
if currentSpec == nil {
// This may is a language code not supported by go-i18n, it may be
// Klingon or ... not even a fake language. Make sure it works.
newLangs = append(newLangs, r.BaseFileName())
}
}

if len(newLangs) > 0 {
language.RegisterPluralSpec(newLangs, en)
}
bundle := &i18n.Bundle{DefaultLanguage: language.English}
bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)

//localizer := i18n.NewLocalizer(bundle, "en")
// The source files are ordered so the most important comes first. Since this is a
// last key win situation, we have to reverse the iteration order.
files := src.Files()
for i := len(files) - 1; i >= 0; i-- {
if err := addTranslationFile(i18nBundle, files[i]); err != nil {
if err := addTranslationFile(bundle, files[i]); err != nil {
return err
}
}

tp.t = NewTranslator(i18nBundle, d.Cfg, d.Log)
tp.t = NewTranslator(bundle, d.Cfg, d.Log)

d.Translate = tp.t.Func(d.Language.Lang)

return nil

}

func addTranslationFile(bundle *bundle.Bundle, r source.ReadableFile) error {
func addTranslationFile(bundle *i18n.Bundle, r source.ReadableFile) error {
f, err := r.Open()
if err != nil {
return fmt.Errorf("Failed to open translations file %q: %s", r.LogicalName(), err)
}
defer f.Close()
err = bundle.ParseTranslationFileBytes(r.LogicalName(), helpers.ReaderToBytes(f))
_, err = bundle.ParseMessageFileBytes(helpers.ReaderToBytes(f), r.LogicalName())
if err != nil {
return fmt.Errorf("Failed to load translations in file %q: %s", r.LogicalName(), err)
}
Expand Down
4 changes: 2 additions & 2 deletions tpl/lang/lang.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,13 @@ type Namespace struct {
}

// Translate returns a translated string for id.
func (ns *Namespace) Translate(id interface{}, args ...interface{}) (string, error) {
func (ns *Namespace) Translate(id interface{}, templateData interface{}) (string, error) {
sid, err := cast.ToStringE(id)
if err != nil {
return "", nil
}

return ns.deps.Translate(sid, args...), nil
return ns.deps.Translate(sid, templateData), nil
}

// NumFmt formats a number with the given precision using the
Expand Down

0 comments on commit 890ca5f

Please sign in to comment.