@@ -4,14 +4,14 @@ package bundle
44import (
55 "encoding/json"
66 "fmt"
7- "gopkg.in/yaml.v2"
87 "io/ioutil"
9- "reflect"
10-
118 "path/filepath"
9+ "reflect"
10+ "sync"
1211
1312 "github.com/nicksnyder/go-i18n/i18n/language"
1413 "github.com/nicksnyder/go-i18n/i18n/translation"
14+ "gopkg.in/yaml.v2"
1515)
1616
1717// TranslateFunc is a copy of i18n.TranslateFunc to avoid a circular dependency.
@@ -24,6 +24,8 @@ type Bundle struct {
2424
2525 // Translations that can be used when an exact language match is not possible.
2626 fallbackTranslations map [string ]map [string ]translation.Translation
27+
28+ sync.RWMutex
2729}
2830
2931// New returns an empty bundle.
@@ -108,6 +110,8 @@ func parseTranslations(filename string, buf []byte) ([]translation.Translation,
108110//
109111// It is useful if your translations are in a format not supported by LoadTranslationFile.
110112func (b * Bundle ) AddTranslation (lang * language.Language , translations ... translation.Translation ) {
113+ b .Lock ()
114+ defer b .Unlock ()
111115 if b .translations [lang .Tag ] == nil {
112116 b .translations [lang .Tag ] = make (map [string ]translation.Translation , len (translations ))
113117 }
@@ -128,24 +132,37 @@ func (b *Bundle) AddTranslation(lang *language.Language, translations ...transla
128132
129133// Translations returns all translations in the bundle.
130134func (b * Bundle ) Translations () map [string ]map [string ]translation.Translation {
131- return b .translations
135+ t := make (map [string ]map [string ]translation.Translation )
136+ b .RLock ()
137+ for tag , translations := range b .translations {
138+ t [tag ] = make (map [string ]translation.Translation )
139+ for id , translation := range translations {
140+ t [tag ][id ] = translation
141+ }
142+ }
143+ b .RUnlock ()
144+ return t
132145}
133146
134147// LanguageTags returns the tags of all languages that that have been added.
135148func (b * Bundle ) LanguageTags () []string {
136149 var tags []string
150+ b .RLock ()
137151 for k := range b .translations {
138152 tags = append (tags , k )
139153 }
154+ b .RUnlock ()
140155 return tags
141156}
142157
143158// LanguageTranslationIDs returns the ids of all translations that have been added for a given language.
144159func (b * Bundle ) LanguageTranslationIDs (languageTag string ) []string {
145160 var ids []string
161+ b .RLock ()
146162 for id := range b .translations [languageTag ] {
147163 ids = append (ids , id )
148164 }
165+ b .RUnlock ()
149166 return ids
150167}
151168
@@ -212,6 +229,8 @@ func (b *Bundle) supportedLanguage(pref string, prefs ...string) *language.Langu
212229
213230func (b * Bundle ) translatedLanguage (src string ) * language.Language {
214231 langs := language .Parse (src )
232+ b .RLock ()
233+ defer b .RUnlock ()
215234 for _ , lang := range langs {
216235 if len (b .translations [lang .Tag ]) > 0 ||
217236 len (b .fallbackTranslations [lang .Tag ]) > 0 {
@@ -226,15 +245,7 @@ func (b *Bundle) translate(lang *language.Language, translationID string, args .
226245 return translationID
227246 }
228247
229- translations := b .translations [lang .Tag ]
230- if translations == nil {
231- translations = b .fallbackTranslations [lang .Tag ]
232- if translations == nil {
233- return translationID
234- }
235- }
236-
237- translation := translations [translationID ]
248+ translation := b .translation (lang , translationID )
238249 if translation == nil {
239250 return translationID
240251 }
@@ -280,6 +291,19 @@ func (b *Bundle) translate(lang *language.Language, translationID string, args .
280291 return s
281292}
282293
294+ func (b * Bundle ) translation (lang * language.Language , translationID string ) translation.Translation {
295+ b .RLock ()
296+ defer b .RUnlock ()
297+ translations := b .translations [lang .Tag ]
298+ if translations == nil {
299+ translations = b .fallbackTranslations [lang .Tag ]
300+ if translations == nil {
301+ return nil
302+ }
303+ }
304+ return translations [translationID ]
305+ }
306+
283307func isNumber (n interface {}) bool {
284308 switch n .(type ) {
285309 case int , int8 , int16 , int32 , int64 , string :
0 commit comments