OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / go-playground / universal-translator / import_export.go
1 package ut
2
3 import (
4         "encoding/json"
5         "fmt"
6         "io/ioutil"
7         "os"
8         "path/filepath"
9
10         "io"
11
12         "github.com/go-playground/locales"
13 )
14
15 type translation struct {
16         Locale           string      `json:"locale"`
17         Key              interface{} `json:"key"` // either string or integer
18         Translation      string      `json:"trans"`
19         PluralType       string      `json:"type,omitempty"`
20         PluralRule       string      `json:"rule,omitempty"`
21         OverrideExisting bool        `json:"override,omitempty"`
22 }
23
24 const (
25         cardinalType = "Cardinal"
26         ordinalType  = "Ordinal"
27         rangeType    = "Range"
28 )
29
30 // ImportExportFormat is the format of the file import or export
31 type ImportExportFormat uint8
32
33 // supported Export Formats
34 const (
35         FormatJSON ImportExportFormat = iota
36 )
37
38 // Export writes the translations out to a file on disk.
39 //
40 // NOTE: this currently only works with string or int translations keys.
41 func (t *UniversalTranslator) Export(format ImportExportFormat, dirname string) error {
42
43         _, err := os.Stat(dirname)
44         fmt.Println(dirname, err, os.IsNotExist(err))
45         if err != nil {
46
47                 if !os.IsNotExist(err) {
48                         return err
49                 }
50
51                 if err = os.MkdirAll(dirname, 0744); err != nil {
52                         return err
53                 }
54         }
55
56         // build up translations
57         var trans []translation
58         var b []byte
59         var ext string
60
61         for _, locale := range t.translators {
62
63                 for k, v := range locale.(*translator).translations {
64                         trans = append(trans, translation{
65                                 Locale:      locale.Locale(),
66                                 Key:         k,
67                                 Translation: v.text,
68                         })
69                 }
70
71                 for k, pluralTrans := range locale.(*translator).cardinalTanslations {
72
73                         for i, plural := range pluralTrans {
74
75                                 // leave enough for all plural rules
76                                 // but not all are set for all languages.
77                                 if plural == nil {
78                                         continue
79                                 }
80
81                                 trans = append(trans, translation{
82                                         Locale:      locale.Locale(),
83                                         Key:         k.(string),
84                                         Translation: plural.text,
85                                         PluralType:  cardinalType,
86                                         PluralRule:  locales.PluralRule(i).String(),
87                                 })
88                         }
89                 }
90
91                 for k, pluralTrans := range locale.(*translator).ordinalTanslations {
92
93                         for i, plural := range pluralTrans {
94
95                                 // leave enough for all plural rules
96                                 // but not all are set for all languages.
97                                 if plural == nil {
98                                         continue
99                                 }
100
101                                 trans = append(trans, translation{
102                                         Locale:      locale.Locale(),
103                                         Key:         k.(string),
104                                         Translation: plural.text,
105                                         PluralType:  ordinalType,
106                                         PluralRule:  locales.PluralRule(i).String(),
107                                 })
108                         }
109                 }
110
111                 for k, pluralTrans := range locale.(*translator).rangeTanslations {
112
113                         for i, plural := range pluralTrans {
114
115                                 // leave enough for all plural rules
116                                 // but not all are set for all languages.
117                                 if plural == nil {
118                                         continue
119                                 }
120
121                                 trans = append(trans, translation{
122                                         Locale:      locale.Locale(),
123                                         Key:         k.(string),
124                                         Translation: plural.text,
125                                         PluralType:  rangeType,
126                                         PluralRule:  locales.PluralRule(i).String(),
127                                 })
128                         }
129                 }
130
131                 switch format {
132                 case FormatJSON:
133                         b, err = json.MarshalIndent(trans, "", "    ")
134                         ext = ".json"
135                 }
136
137                 if err != nil {
138                         return err
139                 }
140
141                 err = ioutil.WriteFile(filepath.Join(dirname, fmt.Sprintf("%s%s", locale.Locale(), ext)), b, 0644)
142                 if err != nil {
143                         return err
144                 }
145
146                 trans = trans[0:0]
147         }
148
149         return nil
150 }
151
152 // Import reads the translations out of a file or directory on disk.
153 //
154 // NOTE: this currently only works with string or int translations keys.
155 func (t *UniversalTranslator) Import(format ImportExportFormat, dirnameOrFilename string) error {
156
157         fi, err := os.Stat(dirnameOrFilename)
158         if err != nil {
159                 return err
160         }
161
162         processFn := func(filename string) error {
163
164                 f, err := os.Open(filename)
165                 if err != nil {
166                         return err
167                 }
168                 defer f.Close()
169
170                 return t.ImportByReader(format, f)
171         }
172
173         if !fi.IsDir() {
174                 return processFn(dirnameOrFilename)
175         }
176
177         // recursively go through directory
178         walker := func(path string, info os.FileInfo, err error) error {
179
180                 if info.IsDir() {
181                         return nil
182                 }
183
184                 switch format {
185                 case FormatJSON:
186                         // skip non JSON files
187                         if filepath.Ext(info.Name()) != ".json" {
188                                 return nil
189                         }
190                 }
191
192                 return processFn(path)
193         }
194
195         return filepath.Walk(dirnameOrFilename, walker)
196 }
197
198 // ImportByReader imports the the translations found within the contents read from the supplied reader.
199 //
200 // NOTE: generally used when assets have been embedded into the binary and are already in memory.
201 func (t *UniversalTranslator) ImportByReader(format ImportExportFormat, reader io.Reader) error {
202
203         b, err := ioutil.ReadAll(reader)
204         if err != nil {
205                 return err
206         }
207
208         var trans []translation
209
210         switch format {
211         case FormatJSON:
212                 err = json.Unmarshal(b, &trans)
213         }
214
215         if err != nil {
216                 return err
217         }
218
219         for _, tl := range trans {
220
221                 locale, found := t.FindTranslator(tl.Locale)
222                 if !found {
223                         return &ErrMissingLocale{locale: tl.Locale}
224                 }
225
226                 pr := stringToPR(tl.PluralRule)
227
228                 if pr == locales.PluralRuleUnknown {
229
230                         err = locale.Add(tl.Key, tl.Translation, tl.OverrideExisting)
231                         if err != nil {
232                                 return err
233                         }
234
235                         continue
236                 }
237
238                 switch tl.PluralType {
239                 case cardinalType:
240                         err = locale.AddCardinal(tl.Key, tl.Translation, pr, tl.OverrideExisting)
241                 case ordinalType:
242                         err = locale.AddOrdinal(tl.Key, tl.Translation, pr, tl.OverrideExisting)
243                 case rangeType:
244                         err = locale.AddRange(tl.Key, tl.Translation, pr, tl.OverrideExisting)
245                 default:
246                         return &ErrBadPluralDefinition{tl: tl}
247                 }
248
249                 if err != nil {
250                         return err
251                 }
252         }
253
254         return nil
255 }
256
257 func stringToPR(s string) locales.PluralRule {
258
259         switch s {
260         case "One":
261                 return locales.PluralRuleOne
262         case "Two":
263                 return locales.PluralRuleTwo
264         case "Few":
265                 return locales.PluralRuleFew
266         case "Many":
267                 return locales.PluralRuleMany
268         case "Other":
269                 return locales.PluralRuleOther
270         default:
271                 return locales.PluralRuleUnknown
272         }
273
274 }