summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/nicksnyder/go-i18n
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/nicksnyder/go-i18n')
-rw-r--r--vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle.go52
-rw-r--r--vendor/github.com/nicksnyder/go-i18n/i18n/bundle/bundle_test.go55
2 files changed, 93 insertions, 14 deletions
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{}{