github.com/jasonish/buffalo@v0.8.2-0.20170413145823-bacbdd415f1b/middleware/i18n/i18n.go (about) 1 package i18n 2 3 import ( 4 "log" 5 6 "github.com/gobuffalo/buffalo" 7 "github.com/gobuffalo/packr" 8 "github.com/nicksnyder/go-i18n/i18n" 9 "github.com/nicksnyder/go-i18n/i18n/language" 10 "github.com/nicksnyder/go-i18n/i18n/translation" 11 "github.com/pkg/errors" 12 ) 13 14 // LanguageFinder can be implemented for custom finding of search 15 // languages. This can be useful if you want to load a user's langugage 16 // from something like a database. See Middleware() for more information 17 // on how the default implementation searches for languages. 18 type LanguageFinder func(*Translator, buffalo.Context) []string 19 20 // Translator for handling all your i18n needs. 21 type Translator struct { 22 // Box - where are the files? 23 Box packr.Box 24 // DefaultLanguage - default is "en-US" 25 DefaultLanguage string 26 // CookieName - name of the cookie to find the desired language. 27 // default is "lang" 28 CookieName string 29 // HelperName - name of the view helper. default is "t" 30 HelperName string 31 LanguageFinder LanguageFinder 32 } 33 34 // Load translations from the t.Box. 35 func (t *Translator) Load() error { 36 return t.Box.Walk(func(path string, f packr.File) error { 37 b, err := t.Box.MustBytes(path) 38 if err != nil { 39 log.Fatal(err) 40 return errors.WithStack(err) 41 } 42 return i18n.ParseTranslationFileBytes(path, b) 43 }) 44 } 45 46 // AddTranslation directly, without using a file. This is useful if you wish to load translations 47 // from a database, instead of disk. 48 func (t *Translator) AddTranslation(lang *language.Language, translations ...translation.Translation) { 49 i18n.AddTranslation(lang, translations...) 50 } 51 52 // New Translator. Requires a packr.Box that points to the location 53 // of the translation files, as well as a default language. This will 54 // also call t.Load() and load the translations from disk. 55 func New(box packr.Box, language string) (*Translator, error) { 56 t := &Translator{ 57 Box: box, 58 DefaultLanguage: language, 59 CookieName: "lang", 60 HelperName: "t", 61 LanguageFinder: defaultLanguageFinder, 62 } 63 return t, t.Load() 64 } 65 66 // Middleware for loading the translations for the language(s) 67 // selected. By default languages are loaded in the following order: 68 // 69 // Cookie - "lang" 70 // Header - "Accept-Language" 71 // Default - "en-US" 72 // 73 // These values can be changed on the Translator itself. In development 74 // model the translation files will be reloaded on each request. 75 func (t *Translator) Middleware() buffalo.MiddlewareFunc { 76 return func(next buffalo.Handler) buffalo.Handler { 77 return func(c buffalo.Context) error { 78 79 // in development reload the translations 80 if c.Value("env").(string) == "development" { 81 err := t.Load() 82 if err != nil { 83 return err 84 } 85 } 86 87 // set up the helper function for the views: 88 c.Set(t.HelperName, func(s string) (string, error) { 89 return t.Translate(c, s) 90 }) 91 return next(c) 92 } 93 } 94 } 95 96 // Translate a string given a Context 97 func (t *Translator) Translate(c buffalo.Context, s string) (string, error) { 98 if langs := c.Value("languages"); langs == nil { 99 c.Set("languages", t.LanguageFinder(t, c)) 100 } 101 langs := c.Value("languages").([]string) 102 T, err := i18n.Tfunc(langs[0], langs[1:]...) 103 if err != nil { 104 return "", err 105 } 106 return T(s, c.Data()), nil 107 } 108 109 func defaultLanguageFinder(t *Translator, c buffalo.Context) []string { 110 langs := []string{} 111 112 r := c.Request() 113 114 // try to get the language from a cookie: 115 if cookie, err := r.Cookie(t.CookieName); err == nil { 116 if cookie.Value != "" { 117 langs = append(langs, cookie.Value) 118 } 119 } 120 121 // try to get the language from a header: 122 acceptLang := r.Header.Get("Accept-Language") 123 if acceptLang != "" { 124 langs = append(langs, acceptLang) 125 } 126 127 // try to get the language from the session: 128 langs = append(langs, t.DefaultLanguage) 129 return langs 130 }