From 701d1ab638b23c24877fc41824add66232446676 Mon Sep 17 00:00:00 2001 From: Christopher Speller Date: Thu, 2 Feb 2017 09:32:00 -0500 Subject: Updating server dependancies (#5249) --- .../nicksnyder/go-i18n/i18n/bundle/bundle.go | 52 ++++++++++++++------ .../nicksnyder/go-i18n/i18n/bundle/bundle_test.go | 55 ++++++++++++++++++++++ 2 files changed, 93 insertions(+), 14 deletions(-) (limited to 'vendor/github.com/nicksnyder/go-i18n/i18n') diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle.go b/vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle.go index 8e46fa296..155543bda 100644 --- a/vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle.go +++ b/vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle.go @@ -4,14 +4,14 @@ package bundle import ( "encoding/json" "fmt" - "gopkg.in/yaml.v2" "io/ioutil" - "reflect" - "path/filepath" + "reflect" + "sync" "github.com/nicksnyder/go-i18n/i18n/language" "github.com/nicksnyder/go-i18n/i18n/translation" + "gopkg.in/yaml.v2" ) // TranslateFunc is a copy of i18n.TranslateFunc to avoid a circular dependency. @@ -24,6 +24,8 @@ type Bundle struct { // Translations that can be used when an exact language match is not possible. fallbackTranslations map[string]map[string]translation.Translation + + sync.RWMutex } // New returns an empty bundle. @@ -89,7 +91,7 @@ func parseTranslations(filename string, buf []byte) ([]translation.Translation, var translationsData []map[string]interface{} if len(buf) > 0 { if err := unmarshalFunc(buf, &translationsData); err != nil { - return nil, err + return nil, fmt.Errorf("failed to load %s because %s", filename, err) } } @@ -108,6 +110,8 @@ func parseTranslations(filename string, buf []byte) ([]translation.Translation, // // It is useful if your translations are in a format not supported by LoadTranslationFile. func (b *Bundle) AddTranslation(lang *language.Language, translations ...translation.Translation) { + b.Lock() + defer b.Unlock() if b.translations[lang.Tag] == nil { b.translations[lang.Tag] = make(map[string]translation.Translation, len(translations)) } @@ -128,24 +132,37 @@ func (b *Bundle) AddTranslation(lang *language.Language, translations ...transla // Translations returns all translations in the bundle. func (b *Bundle) Translations() map[string]map[string]translation.Translation { - return b.translations + t := make(map[string]map[string]translation.Translation) + b.RLock() + for tag, translations := range b.translations { + t[tag] = make(map[string]translation.Translation) + for id, translation := range translations { + t[tag][id] = translation + } + } + b.RUnlock() + return t } // LanguageTags returns the tags of all languages that that have been added. func (b *Bundle) LanguageTags() []string { var tags []string + b.RLock() for k := range b.translations { tags = append(tags, k) } + b.RUnlock() return tags } // LanguageTranslationIDs returns the ids of all translations that have been added for a given language. func (b *Bundle) LanguageTranslationIDs(languageTag string) []string { var ids []string + b.RLock() for id := range b.translations[languageTag] { ids = append(ids, id) } + b.RUnlock() return ids } @@ -212,6 +229,8 @@ func (b *Bundle) supportedLanguage(pref string, prefs ...string) *language.Langu func (b *Bundle) translatedLanguage(src string) *language.Language { langs := language.Parse(src) + b.RLock() + defer b.RUnlock() for _, lang := range langs { if len(b.translations[lang.Tag]) > 0 || len(b.fallbackTranslations[lang.Tag]) > 0 { @@ -226,15 +245,7 @@ func (b *Bundle) translate(lang *language.Language, translationID string, args . return translationID } - translations := b.translations[lang.Tag] - if translations == nil { - translations = b.fallbackTranslations[lang.Tag] - if translations == nil { - return translationID - } - } - - translation := translations[translationID] + translation := b.translation(lang, translationID) if translation == nil { return translationID } @@ -280,6 +291,19 @@ func (b *Bundle) translate(lang *language.Language, translationID string, args . return s } +func (b *Bundle) translation(lang *language.Language, translationID string) translation.Translation { + b.RLock() + defer b.RUnlock() + translations := b.translations[lang.Tag] + if translations == nil { + translations = b.fallbackTranslations[lang.Tag] + if translations == nil { + return nil + } + } + return translations[translationID] +} + func isNumber(n interface{}) bool { switch n.(type) { case int, int8, int16, int32, int64, string: diff --git a/vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle_test.go b/vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle_test.go index b241ad1d4..da3830a79 100644 --- a/vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle_test.go +++ b/vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle_test.go @@ -2,6 +2,8 @@ package bundle import ( "fmt" + "strconv" + "sync" "testing" "reflect" @@ -160,6 +162,59 @@ func TestTfuncAndLanguage(t *testing.T) { } } +func TestConcurrent(t *testing.T) { + b := New() + // bootstrap bundle + translationID := "translation_id" // +1 + englishLanguage := languageWithTag("en-US") + addFakeTranslation(t, b, englishLanguage, translationID) + + tf, err := b.Tfunc(englishLanguage.Tag) + if err != nil { + t.Errorf("Tfunc(%v) = error{%q}; expected no error", []string{englishLanguage.Tag}, err) + } + + const iterations = 1000 + var wg sync.WaitGroup + wg.Add(iterations) + + // Using go routines insert 1000 ints into our map. + go func() { + for i := 0; i < iterations/2; i++ { + // Add item to map. + translationID := strconv.FormatInt(int64(i), 10) + addFakeTranslation(t, b, englishLanguage, translationID) + + // Retrieve item from map. + tf(translationID) + + wg.Done() + } // Call go routine with current index. + }() + + go func() { + for i := iterations / 2; i < iterations; i++ { + // Add item to map. + translationID := strconv.FormatInt(int64(i), 10) + addFakeTranslation(t, b, englishLanguage, translationID) + + // Retrieve item from map. + tf(translationID) + + wg.Done() + } // Call go routine with current index. + }() + + // Wait for all go routines to finish. + wg.Wait() + + // Make sure map contains 1000+1 elements. + count := len(b.Translations()[englishLanguage.Tag]) + if count != iterations+1 { + t.Error("Expecting 1001 elements, got", count) + } +} + func addFakeTranslation(t *testing.T, b *Bundle, lang *language.Language, translationID string) string { translation := fakeTranslation(lang, translationID) b.AddTranslation(lang, testNewTranslation(t, map[string]interface{}{ -- cgit v1.2.3-1-g7c22