github.com/mayra-cabrera/buffalo@v0.9.4-0.20170814145312-66d2e7772f11/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  	// SessionName - name of the session to find the desired language.
    30  	// default is "lang"
    31  	SessionName string
    32  	// HelperName - name of the view helper. default is "t"
    33  	HelperName     string
    34  	LanguageFinder LanguageFinder
    35  }
    36  
    37  // Load translations from the t.Box.
    38  func (t *Translator) Load() error {
    39  	return t.Box.Walk(func(path string, f packr.File) error {
    40  		b, err := t.Box.MustBytes(path)
    41  		if err != nil {
    42  			log.Fatal(err)
    43  			return errors.WithStack(err)
    44  		}
    45  		return i18n.ParseTranslationFileBytes(path, b)
    46  	})
    47  }
    48  
    49  // AddTranslation directly, without using a file. This is useful if you wish to load translations
    50  // from a database, instead of disk.
    51  func (t *Translator) AddTranslation(lang *language.Language, translations ...translation.Translation) {
    52  	i18n.AddTranslation(lang, translations...)
    53  }
    54  
    55  // New Translator. Requires a packr.Box that points to the location
    56  // of the translation files, as well as a default language. This will
    57  // also call t.Load() and load the translations from disk.
    58  func New(box packr.Box, language string) (*Translator, error) {
    59  	t := &Translator{
    60  		Box:             box,
    61  		DefaultLanguage: language,
    62  		CookieName:      "lang",
    63  		SessionName:     "lang",
    64  		HelperName:      "t",
    65  		LanguageFinder:  defaultLanguageFinder,
    66  	}
    67  	return t, t.Load()
    68  }
    69  
    70  // Middleware for loading the translations for the language(s)
    71  // selected. By default languages are loaded in the following order:
    72  //
    73  // Cookie - "lang"
    74  // Header - "Accept-Language"
    75  // Default - "en-US"
    76  //
    77  // These values can be changed on the Translator itself. In development
    78  // model the translation files will be reloaded on each request.
    79  func (t *Translator) Middleware() buffalo.MiddlewareFunc {
    80  	return func(next buffalo.Handler) buffalo.Handler {
    81  		return func(c buffalo.Context) error {
    82  
    83  			// in development reload the translations
    84  			if c.Value("env").(string) == "development" {
    85  				err := t.Load()
    86  				if err != nil {
    87  					return err
    88  				}
    89  			}
    90  
    91  			// set up the helper function for the views:
    92  			c.Set(t.HelperName, func(s string) (string, error) {
    93  				return t.Translate(c, s)
    94  			})
    95  			return next(c)
    96  		}
    97  	}
    98  }
    99  
   100  // Translate a string given a Context
   101  func (t *Translator) Translate(c buffalo.Context, s string) (string, error) {
   102  	if langs := c.Value("languages"); langs == nil {
   103  		c.Set("languages", t.LanguageFinder(t, c))
   104  	}
   105  	langs := c.Value("languages").([]string)
   106  	T, err := i18n.Tfunc(langs[0], langs[1:]...)
   107  	if err != nil {
   108  		return "", err
   109  	}
   110  	return T(s, c.Data()), nil
   111  }
   112  
   113  func defaultLanguageFinder(t *Translator, c buffalo.Context) []string {
   114  	langs := []string{}
   115  
   116  	r := c.Request()
   117  
   118  	// try to get the language from a cookie:
   119  	if cookie, err := r.Cookie(t.CookieName); err == nil {
   120  		if cookie.Value != "" {
   121  			langs = append(langs, cookie.Value)
   122  		}
   123  	}
   124  
   125  	// try to get the language from the session
   126  	if s := c.Session().Get(t.SessionName); s != nil {
   127  		langs = append(langs, s.(string))
   128  	}
   129  
   130  	// try to get the language from a header:
   131  	acceptLang := r.Header.Get("Accept-Language")
   132  	if acceptLang != "" {
   133  		langs = append(langs, acceptLang)
   134  	}
   135  
   136  	// try to get the language from the session:
   137  	langs = append(langs, t.DefaultLanguage)
   138  	return langs
   139  }