12 "github.com/go-playground/locales"
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"`
25 cardinalType = "Cardinal"
26 ordinalType = "Ordinal"
30 // ImportExportFormat is the format of the file import or export
31 type ImportExportFormat uint8
33 // supported Export Formats
35 FormatJSON ImportExportFormat = iota
38 // Export writes the translations out to a file on disk.
40 // NOTE: this currently only works with string or int translations keys.
41 func (t *UniversalTranslator) Export(format ImportExportFormat, dirname string) error {
43 _, err := os.Stat(dirname)
44 fmt.Println(dirname, err, os.IsNotExist(err))
47 if !os.IsNotExist(err) {
51 if err = os.MkdirAll(dirname, 0744); err != nil {
56 // build up translations
57 var trans []translation
61 for _, locale := range t.translators {
63 for k, v := range locale.(*translator).translations {
64 trans = append(trans, translation{
65 Locale: locale.Locale(),
71 for k, pluralTrans := range locale.(*translator).cardinalTanslations {
73 for i, plural := range pluralTrans {
75 // leave enough for all plural rules
76 // but not all are set for all languages.
81 trans = append(trans, translation{
82 Locale: locale.Locale(),
84 Translation: plural.text,
85 PluralType: cardinalType,
86 PluralRule: locales.PluralRule(i).String(),
91 for k, pluralTrans := range locale.(*translator).ordinalTanslations {
93 for i, plural := range pluralTrans {
95 // leave enough for all plural rules
96 // but not all are set for all languages.
101 trans = append(trans, translation{
102 Locale: locale.Locale(),
104 Translation: plural.text,
105 PluralType: ordinalType,
106 PluralRule: locales.PluralRule(i).String(),
111 for k, pluralTrans := range locale.(*translator).rangeTanslations {
113 for i, plural := range pluralTrans {
115 // leave enough for all plural rules
116 // but not all are set for all languages.
121 trans = append(trans, translation{
122 Locale: locale.Locale(),
124 Translation: plural.text,
125 PluralType: rangeType,
126 PluralRule: locales.PluralRule(i).String(),
133 b, err = json.MarshalIndent(trans, "", " ")
141 err = ioutil.WriteFile(filepath.Join(dirname, fmt.Sprintf("%s%s", locale.Locale(), ext)), b, 0644)
152 // Import reads the translations out of a file or directory on disk.
154 // NOTE: this currently only works with string or int translations keys.
155 func (t *UniversalTranslator) Import(format ImportExportFormat, dirnameOrFilename string) error {
157 fi, err := os.Stat(dirnameOrFilename)
162 processFn := func(filename string) error {
164 f, err := os.Open(filename)
170 return t.ImportByReader(format, f)
174 return processFn(dirnameOrFilename)
177 // recursively go through directory
178 walker := func(path string, info os.FileInfo, err error) error {
186 // skip non JSON files
187 if filepath.Ext(info.Name()) != ".json" {
192 return processFn(path)
195 return filepath.Walk(dirnameOrFilename, walker)
198 // ImportByReader imports the the translations found within the contents read from the supplied reader.
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 {
203 b, err := ioutil.ReadAll(reader)
208 var trans []translation
212 err = json.Unmarshal(b, &trans)
219 for _, tl := range trans {
221 locale, found := t.FindTranslator(tl.Locale)
223 return &ErrMissingLocale{locale: tl.Locale}
226 pr := stringToPR(tl.PluralRule)
228 if pr == locales.PluralRuleUnknown {
230 err = locale.Add(tl.Key, tl.Translation, tl.OverrideExisting)
238 switch tl.PluralType {
240 err = locale.AddCardinal(tl.Key, tl.Translation, pr, tl.OverrideExisting)
242 err = locale.AddOrdinal(tl.Key, tl.Translation, pr, tl.OverrideExisting)
244 err = locale.AddRange(tl.Key, tl.Translation, pr, tl.OverrideExisting)
246 return &ErrBadPluralDefinition{tl: tl}
257 func stringToPR(s string) locales.PluralRule {
261 return locales.PluralRuleOne
263 return locales.PluralRuleTwo
265 return locales.PluralRuleFew
267 return locales.PluralRuleMany
269 return locales.PluralRuleOther
271 return locales.PluralRuleUnknown