universal_translator.go (2911B)
1 package ut 2 3 import ( 4 "strings" 5 6 "github.com/go-playground/locales" 7 ) 8 9 // UniversalTranslator holds all locale & translation data 10 type UniversalTranslator struct { 11 translators map[string]Translator 12 fallback Translator 13 } 14 15 // New returns a new UniversalTranslator instance set with 16 // the fallback locale and locales it should support 17 func New(fallback locales.Translator, supportedLocales ...locales.Translator) *UniversalTranslator { 18 19 t := &UniversalTranslator{ 20 translators: make(map[string]Translator), 21 } 22 23 for _, v := range supportedLocales { 24 25 trans := newTranslator(v) 26 t.translators[strings.ToLower(trans.Locale())] = trans 27 28 if fallback.Locale() == v.Locale() { 29 t.fallback = trans 30 } 31 } 32 33 if t.fallback == nil && fallback != nil { 34 t.fallback = newTranslator(fallback) 35 } 36 37 return t 38 } 39 40 // FindTranslator trys to find a Translator based on an array of locales 41 // and returns the first one it can find, otherwise returns the 42 // fallback translator. 43 func (t *UniversalTranslator) FindTranslator(locales ...string) (trans Translator, found bool) { 44 45 for _, locale := range locales { 46 47 if trans, found = t.translators[strings.ToLower(locale)]; found { 48 return 49 } 50 } 51 52 return t.fallback, false 53 } 54 55 // GetTranslator returns the specified translator for the given locale, 56 // or fallback if not found 57 func (t *UniversalTranslator) GetTranslator(locale string) (trans Translator, found bool) { 58 59 if trans, found = t.translators[strings.ToLower(locale)]; found { 60 return 61 } 62 63 return t.fallback, false 64 } 65 66 // GetFallback returns the fallback locale 67 func (t *UniversalTranslator) GetFallback() Translator { 68 return t.fallback 69 } 70 71 // AddTranslator adds the supplied translator, if it already exists the override param 72 // will be checked and if false an error will be returned, otherwise the translator will be 73 // overridden; if the fallback matches the supplied translator it will be overridden as well 74 // NOTE: this is normally only used when translator is embedded within a library 75 func (t *UniversalTranslator) AddTranslator(translator locales.Translator, override bool) error { 76 77 lc := strings.ToLower(translator.Locale()) 78 _, ok := t.translators[lc] 79 if ok && !override { 80 return &ErrExistingTranslator{locale: translator.Locale()} 81 } 82 83 trans := newTranslator(translator) 84 85 if t.fallback.Locale() == translator.Locale() { 86 87 // because it's optional to have a fallback, I don't impose that limitation 88 // don't know why you wouldn't but... 89 if !override { 90 return &ErrExistingTranslator{locale: translator.Locale()} 91 } 92 93 t.fallback = trans 94 } 95 96 t.translators[lc] = trans 97 98 return nil 99 } 100 101 // VerifyTranslations runs through all locales and identifies any issues 102 // eg. missing plural rules for a locale 103 func (t *UniversalTranslator) VerifyTranslations() (err error) { 104 105 for _, trans := range t.translators { 106 err = trans.VerifyTranslations() 107 if err != nil { 108 return 109 } 110 } 111 112 return 113 }