From eb63891aa6d47e396acc3739f3692faac6ba2ea7 Mon Sep 17 00:00:00 2001 From: Nick Snyder Date: Wed, 1 May 2019 21:43:37 -0700 Subject: [PATCH 1/4] add NewBundle and remove init --- v2/i18n/bundle.go | 27 ++++++++++++--------------- v2/i18n/localizer.go | 1 - 2 files changed, 12 insertions(+), 16 deletions(-) diff --git a/v2/i18n/bundle.go b/v2/i18n/bundle.go index a2c4e455..a25eb876 100644 --- a/v2/i18n/bundle.go +++ b/v2/i18n/bundle.go @@ -19,31 +19,29 @@ type UnmarshalFunc = internal.UnmarshalFunc // It is not goroutine safe to modify the bundle while Localizers // are reading from it. type Bundle struct { - // DefaultLanguage is the default language of the bundle. - DefaultLanguage language.Tag - - // UnmarshalFuncs is a map of file extensions to UnmarshalFuncs. - UnmarshalFuncs map[string]UnmarshalFunc - + defaultLanguage language.Tag + unmarshalFuncs map[string]UnmarshalFunc messageTemplates map[language.Tag]map[string]*internal.MessageTemplate pluralRules plural.Rules tags []language.Tag matcher language.Matcher } -func (b *Bundle) init() { - if b.pluralRules == nil { - b.pluralRules = plural.DefaultRules() +func NewBundle(defaultLanguage language.Tag) *Bundle { + b := &Bundle{ + defaultLanguage: defaultLanguage, + pluralRules: plural.DefaultRules(), } - b.addTag(b.DefaultLanguage) + b.addTag(defaultLanguage) + return b } // RegisterUnmarshalFunc registers an UnmarshalFunc for format. func (b *Bundle) RegisterUnmarshalFunc(format string, unmarshalFunc UnmarshalFunc) { - if b.UnmarshalFuncs == nil { - b.UnmarshalFuncs = make(map[string]UnmarshalFunc) + if b.unmarshalFuncs == nil { + b.unmarshalFuncs = make(map[string]UnmarshalFunc) } - b.UnmarshalFuncs[format] = unmarshalFunc + b.unmarshalFuncs[format] = unmarshalFunc } // LoadMessageFile loads the bytes from path @@ -73,7 +71,7 @@ type MessageFile = internal.MessageFile // // The language tag of the file is everything after the second to last "." or after the last path separator, but before the format. func (b *Bundle) ParseMessageFileBytes(buf []byte, path string) (*MessageFile, error) { - messageFile, err := internal.ParseMessageFileBytes(buf, path, b.UnmarshalFuncs) + messageFile, err := internal.ParseMessageFileBytes(buf, path, b.unmarshalFuncs) if err != nil { return nil, err } @@ -94,7 +92,6 @@ func (b *Bundle) MustParseMessageFileBytes(buf []byte, path string) { // AddMessages adds messages for a language. // It is useful if your messages are in a format not supported by ParseMessageFileBytes. func (b *Bundle) AddMessages(tag language.Tag, messages ...*Message) error { - b.init() pluralRule := b.pluralRules.Rule(tag) if pluralRule == nil { return fmt.Errorf("no plural rule registered for %s", tag) diff --git a/v2/i18n/localizer.go b/v2/i18n/localizer.go index 38020fd8..ea723e8d 100644 --- a/v2/i18n/localizer.go +++ b/v2/i18n/localizer.go @@ -24,7 +24,6 @@ type Localizer struct { // in the bundle according to the language preferences in langs. // It can parse Accept-Language headers as defined in http://www.ietf.org/rfc/rfc2616.txt. func NewLocalizer(bundle *Bundle, langs ...string) *Localizer { - bundle.init() return &Localizer{ bundle: bundle, tags: parseTags(langs), From e8a983a95c1b30370df88b43b96f82c634c14283 Mon Sep 17 00:00:00 2001 From: Nick Snyder Date: Wed, 1 May 2019 21:49:04 -0700 Subject: [PATCH 2/4] NewBundle --- v2/example/main.go | 2 +- v2/goi18n/extract_command_test.go | 4 ++-- v2/i18n/bundle_test.go | 4 ++-- v2/i18n/doc.go | 2 +- v2/i18n/example_test.go | 12 ++++++------ 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/v2/example/main.go b/v2/example/main.go index e10ff80f..838e1456 100644 --- a/v2/example/main.go +++ b/v2/example/main.go @@ -27,7 +27,7 @@ var page = template.Must(template.New("").Parse(` `)) func main() { - bundle := &i18n.Bundle{DefaultLanguage: language.English} + bundle := i18n.NewBundle(language.English) bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) // No need to load active.en.toml since we are providing default translations. // bundle.MustLoadMessageFile("active.en.toml") diff --git a/v2/goi18n/extract_command_test.go b/v2/goi18n/extract_command_test.go index e675d304..efee57e7 100644 --- a/v2/goi18n/extract_command_test.go +++ b/v2/goi18n/extract_command_test.go @@ -48,7 +48,7 @@ func TestExtract(t *testing.T) { import "github.com/nicksnyder/go-i18n/v2/i18n" func main() { - bundle := &i18n.Bundle{} + bundle := i18n.NewBundle(language.English) l := i18n.NewLocalizer(bundle, "en") l.Localize(&i18n.LocalizeConfig{MessageID: "Plural ID"}) } @@ -66,7 +66,7 @@ func TestExtract(t *testing.T) { import "github.com/nicksnyder/go-i18n/v2/i18n" func main() { - bundle := &i18n.Bundle{} + bundle := i18n.NewBundle(language.English) l := i18n.NewLocalizer(bundle, "en") l.MustLocalize(&i18n.LocalizeConfig{MessageID: "Plural ID"}) } diff --git a/v2/i18n/bundle_test.go b/v2/i18n/bundle_test.go index c0491c1c..2075d226 100644 --- a/v2/i18n/bundle_test.go +++ b/v2/i18n/bundle_test.go @@ -33,7 +33,7 @@ var everythingMessage = internal.MustNewMessage(map[string]string{ }) func TestPseudoLanguage(t *testing.T) { - bundle := &Bundle{DefaultLanguage: language.English} + bundle := NewBundle(language.English) bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) expected := "simple simple" bundle.MustParseMessageFileBytes([]byte(` @@ -51,7 +51,7 @@ simple = "simple simple" } func TestPseudoLanguagePlural(t *testing.T) { - bundle := &Bundle{DefaultLanguage: language.English} + bundle := NewBundle(language.English) bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) bundle.MustParseMessageFileBytes([]byte(` [everything] diff --git a/v2/i18n/doc.go b/v2/i18n/doc.go index 19030827..73d7a069 100644 --- a/v2/i18n/doc.go +++ b/v2/i18n/doc.go @@ -2,7 +2,7 @@ // according to a set of locale preferences. // // Create a Bundle to use for the lifetime of your application. -// bundle := &i18n.Bundle{DefaultLanguage: language.English} +// bundle := i18n.NewBundle(language.English) // // Load translations into your bundle during initialization. // bundle.LoadMessageFile("en-US.yaml") diff --git a/v2/i18n/example_test.go b/v2/i18n/example_test.go index 13fd6413..2256e636 100644 --- a/v2/i18n/example_test.go +++ b/v2/i18n/example_test.go @@ -9,7 +9,7 @@ import ( ) func ExampleLocalizer_MustLocalize() { - bundle := &i18n.Bundle{DefaultLanguage: language.English} + bundle := i18n.NewBundle(language.English) localizer := i18n.NewLocalizer(bundle, "en") fmt.Println(localizer.MustLocalize(&i18n.LocalizeConfig{ DefaultMessage: &i18n.Message{ @@ -22,7 +22,7 @@ func ExampleLocalizer_MustLocalize() { } func ExampleLocalizer_MustLocalize_noDefaultMessage() { - bundle := &i18n.Bundle{DefaultLanguage: language.English} + bundle := i18n.NewBundle(language.English) bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) bundle.MustParseMessageFileBytes([]byte(` HelloWorld = "Hello World!" @@ -45,7 +45,7 @@ HelloWorld = "Hola Mundo!" } func ExampleLocalizer_MustLocalize_plural() { - bundle := &i18n.Bundle{DefaultLanguage: language.English} + bundle := i18n.NewBundle(language.English) localizer := i18n.NewLocalizer(bundle, "en") catsMessage := &i18n.Message{ ID: "Cats", @@ -71,7 +71,7 @@ func ExampleLocalizer_MustLocalize_plural() { } func ExampleLocalizer_MustLocalize_template() { - bundle := &i18n.Bundle{DefaultLanguage: language.English} + bundle := i18n.NewBundle(language.English) localizer := i18n.NewLocalizer(bundle, "en") helloPersonMessage := &i18n.Message{ ID: "HelloPerson", @@ -86,7 +86,7 @@ func ExampleLocalizer_MustLocalize_template() { } func ExampleLocalizer_MustLocalize_plural_template() { - bundle := &i18n.Bundle{DefaultLanguage: language.English} + bundle := i18n.NewBundle(language.English) localizer := i18n.NewLocalizer(bundle, "en") personCatsMessage := &i18n.Message{ ID: "PersonCats", @@ -124,7 +124,7 @@ func ExampleLocalizer_MustLocalize_plural_template() { } func ExampleLocalizer_MustLocalize_customTemplateDelims() { - bundle := &i18n.Bundle{DefaultLanguage: language.English} + bundle := i18n.NewBundle(language.English) localizer := i18n.NewLocalizer(bundle, "en") helloPersonMessage := &i18n.Message{ ID: "HelloPerson", From f66cb6a2910700c236ed0e16d6ceb7c73a7f78d3 Mon Sep 17 00:00:00 2001 From: Nick Snyder Date: Wed, 1 May 2019 21:51:09 -0700 Subject: [PATCH 3/4] fix usage --- v2/i18n/localizer.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/v2/i18n/localizer.go b/v2/i18n/localizer.go index ea723e8d..e02f66b8 100644 --- a/v2/i18n/localizer.go +++ b/v2/i18n/localizer.go @@ -154,7 +154,7 @@ func (l *Localizer) getTemplate(id string, defaultMessage *Message) (language.Ta } if len(l.bundle.tags) <= 1 { - return l.bundle.DefaultLanguage, nil + return l.bundle.defaultLanguage, nil } // Slow path. @@ -162,7 +162,7 @@ func (l *Localizer) getTemplate(id string, defaultMessage *Message) (language.Ta // so we need to create a new matcher that contains only the tags in the bundle // that have this message. foundTags := make([]language.Tag, 0, len(l.bundle.messageTemplates)+1) - foundTags = append(foundTags, l.bundle.DefaultLanguage) + foundTags = append(foundTags, l.bundle.defaultLanguage) for t, templates := range l.bundle.messageTemplates { template := templates[id] @@ -182,7 +182,7 @@ func (l *Localizer) matchTemplate(id string, defaultMessage *Message, matcher la if templates != nil && templates[id] != nil { return tag, templates[id] } - if tag == l.bundle.DefaultLanguage && defaultMessage != nil { + if tag == l.bundle.defaultLanguage && defaultMessage != nil { return tag, internal.NewMessageTemplate(defaultMessage) } return tag, nil From 6618985679973ec9be0110260e468db4e26c710f Mon Sep 17 00:00:00 2001 From: Nick Snyder Date: Wed, 1 May 2019 21:58:06 -0700 Subject: [PATCH 4/4] fix test --- v2/goi18n/active.en.toml | 0 v2/i18n/bundle_test.go | 12 ++++++------ v2/i18n/localizer_test.go | 6 ++++-- 3 files changed, 10 insertions(+), 8 deletions(-) create mode 100644 v2/goi18n/active.en.toml diff --git a/v2/goi18n/active.en.toml b/v2/goi18n/active.en.toml new file mode 100644 index 00000000..e69de29b diff --git a/v2/i18n/bundle_test.go b/v2/i18n/bundle_test.go index 2075d226..e14c8464 100644 --- a/v2/i18n/bundle_test.go +++ b/v2/i18n/bundle_test.go @@ -86,7 +86,7 @@ zero = "zero translation" } func TestJSON(t *testing.T) { - var bundle Bundle + bundle := NewBundle(language.English) bundle.MustParseMessageFileBytes([]byte(`{ "simple": "simple translation", "detail": { @@ -110,7 +110,7 @@ func TestJSON(t *testing.T) { } func TestYAML(t *testing.T) { - var bundle Bundle + bundle := NewBundle(language.English) bundle.RegisterUnmarshalFunc("yaml", yaml.Unmarshal) bundle.MustParseMessageFileBytes([]byte(` # Comment @@ -138,7 +138,7 @@ everything: } func TestTOML(t *testing.T) { - var bundle Bundle + bundle := NewBundle(language.English) bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal) bundle.MustParseMessageFileBytes([]byte(` # Comment @@ -166,7 +166,7 @@ other = "other translation" } func TestV1Format(t *testing.T) { - var bundle Bundle + bundle := NewBundle(language.English) bundle.MustParseMessageFileBytes([]byte(`[ { "id": "simple", @@ -193,7 +193,7 @@ func TestV1Format(t *testing.T) { } func TestV1FlatFormat(t *testing.T) { - var bundle Bundle + bundle := NewBundle(language.English) bundle.MustParseMessageFileBytes([]byte(`{ "simple": { "other": "simple translation" @@ -215,7 +215,7 @@ func TestV1FlatFormat(t *testing.T) { expectMessage(t, bundle, language.AmericanEnglish, "everything", &e) } -func expectMessage(t *testing.T, bundle Bundle, tag language.Tag, messageID string, message *Message) { +func expectMessage(t *testing.T, bundle *Bundle, tag language.Tag, messageID string, message *Message) { expected := internal.NewMessageTemplate(message) actual := bundle.messageTemplates[tag][messageID] if !reflect.DeepEqual(actual, expected) { diff --git a/v2/i18n/localizer_test.go b/v2/i18n/localizer_test.go index 6c4aa99b..9328a6ae 100644 --- a/v2/i18n/localizer_test.go +++ b/v2/i18n/localizer_test.go @@ -544,9 +544,11 @@ func TestLocalizer_Localize(t *testing.T) { } for _, testCase := range testCases { t.Run(testCase.name, func(t *testing.T) { - bundle := &Bundle{DefaultLanguage: testCase.defaultLanguage} + bundle := NewBundle(testCase.defaultLanguage) for tag, messages := range testCase.messages { - bundle.AddMessages(tag, messages...) + if err := bundle.AddMessages(tag, messages...); err != nil { + t.Fatal(err) + } } localizer := NewLocalizer(bundle, testCase.acceptLangs...) localized, err := localizer.Localize(testCase.conf)