OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / go-playground / universal-translator / examples / full-with-files / main.go
1 package main
2
3 import (
4         "context"
5         "html/template"
6         "log"
7         "net/http"
8         "time"
9
10         "github.com/go-playground/locales"
11         "github.com/go-playground/locales/currency"
12         "github.com/go-playground/locales/en"
13         "github.com/go-playground/locales/fr"
14         "github.com/go-playground/pure"
15         "github.com/go-playground/pure/examples/middleware/logging-recovery"
16         "github.com/go-playground/universal-translator"
17 )
18
19 var (
20         tmpls    *template.Template
21         utrans   *ut.UniversalTranslator
22         transKey = struct {
23                 name string
24         }{
25                 name: "transKey",
26         }
27 )
28
29 // Translator wraps ut.Translator in order to handle errors transparently
30 // it is totally optional but recommended as it can now be used directly in
31 // templates and nobody can add translations where they're not supposed to.
32 type Translator interface {
33         locales.Translator
34
35         // creates the translation for the locale given the 'key' and params passed in.
36         // wraps ut.Translator.T to handle errors
37         T(key interface{}, params ...string) string
38
39         // creates the cardinal translation for the locale given the 'key', 'num' and 'digit' arguments
40         //  and param passed in.
41         // wraps ut.Translator.C to handle errors
42         C(key interface{}, num float64, digits uint64, param string) string
43
44         // creates the ordinal translation for the locale given the 'key', 'num' and 'digit' arguments
45         // and param passed in.
46         // wraps ut.Translator.O to handle errors
47         O(key interface{}, num float64, digits uint64, param string) string
48
49         //  creates the range translation for the locale given the 'key', 'num1', 'digit1', 'num2' and
50         //  'digit2' arguments and 'param1' and 'param2' passed in
51         // wraps ut.Translator.R to handle errors
52         R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) string
53
54         // Currency returns the type used by the given locale.
55         Currency() currency.Type
56 }
57
58 // implements Translator interface definition above.
59 type translator struct {
60         locales.Translator
61         trans ut.Translator
62 }
63
64 var _ Translator = (*translator)(nil)
65
66 func (t *translator) T(key interface{}, params ...string) string {
67
68         s, err := t.trans.T(key, params...)
69         if err != nil {
70                 log.Printf("issue translating key: '%v' error: '%s'", key, err)
71         }
72
73         return s
74 }
75
76 func (t *translator) C(key interface{}, num float64, digits uint64, param string) string {
77
78         s, err := t.trans.C(key, num, digits, param)
79         if err != nil {
80                 log.Printf("issue translating cardinal key: '%v' error: '%s'", key, err)
81         }
82
83         return s
84 }
85
86 func (t *translator) O(key interface{}, num float64, digits uint64, param string) string {
87
88         s, err := t.trans.C(key, num, digits, param)
89         if err != nil {
90                 log.Printf("issue translating ordinal key: '%v' error: '%s'", key, err)
91         }
92
93         return s
94 }
95
96 func (t *translator) R(key interface{}, num1 float64, digits1 uint64, num2 float64, digits2 uint64, param1, param2 string) string {
97
98         s, err := t.trans.R(key, num1, digits1, num2, digits2, param1, param2)
99         if err != nil {
100                 log.Printf("issue translating range key: '%v' error: '%s'", key, err)
101         }
102
103         return s
104 }
105
106 func (t *translator) Currency() currency.Type {
107
108         // choose your own locale. The reason it isn't mapped for you is because many
109         // countries have multiple currencies; it's up to you and you're application how
110         // and which currencies to use. I recommend adding a function it to to your custon translator
111         // interface like defined above.
112         switch t.Locale() {
113         case "en":
114                 return currency.USD
115         case "fr":
116                 return currency.EUR
117         default:
118                 return currency.USD
119         }
120 }
121
122 func main() {
123
124         en := en.New()
125         utrans = ut.New(en, en, fr.New())
126         setup()
127
128         tmpls, _ = template.ParseFiles("home.tmpl")
129
130         r := pure.New()
131         r.Use(middleware.LoggingAndRecovery(true), translatorMiddleware)
132         r.Get("/", home)
133
134         log.Println("Running on Port :8080")
135         log.Println("Try me with URL http://localhost:8080/?locale=en")
136         log.Println("and then http://localhost:8080/?locale=fr")
137         http.ListenAndServe(":8080", r.Serve())
138 }
139
140 func home(w http.ResponseWriter, r *http.Request) {
141
142         // get locale translator ( could be wrapped into a helper function )
143         t := r.Context().Value(transKey).(Translator)
144
145         s := struct {
146                 Trans       Translator
147                 Now         time.Time
148                 PositiveNum float64
149                 NegativeNum float64
150                 Percent     float64
151         }{
152                 Trans:       t,
153                 Now:         time.Now(),
154                 PositiveNum: 1234576.45,
155                 NegativeNum: -35900394.34,
156                 Percent:     96.76,
157         }
158
159         if err := tmpls.ExecuteTemplate(w, "home", s); err != nil {
160                 log.Fatal(err)
161         }
162 }
163
164 func translatorMiddleware(next http.HandlerFunc) http.HandlerFunc {
165
166         return func(w http.ResponseWriter, r *http.Request) {
167
168                 // there are many ways to check, this is just checking for query param &
169                 // Accept-Language header but can be expanded to Cookie's etc....
170
171                 params := r.URL.Query()
172
173                 locale := params.Get("locale")
174                 var t ut.Translator
175
176                 if len(locale) > 0 {
177
178                         var found bool
179
180                         if t, found = utrans.GetTranslator(locale); found {
181                                 goto END
182                         }
183                 }
184
185                 // get and parse the "Accept-Language" http header and return an array
186                 t, _ = utrans.FindTranslator(pure.AcceptedLanguages(r)...)
187         END:
188                 // I would normally wrap ut.Translator with one with my own functions in order
189                 // to handle errors and be able to use all functions from translator within the templates.
190                 r = r.WithContext(context.WithValue(r.Context(), transKey, &translator{trans: t, Translator: t.(locales.Translator)}))
191
192                 next(w, r)
193         }
194 }
195
196 func setup() {
197
198         err := utrans.Import(ut.FormatJSON, "translations")
199         if err != nil {
200                 log.Fatal(err)
201         }
202
203         err = utrans.VerifyTranslations()
204         if err != nil {
205                 log.Fatal(err)
206         }
207 }