-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathpool.go
138 lines (116 loc) · 3.12 KB
/
pool.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
package l10n
import (
"path/filepath"
"github.com/iafan/Plurr/go/plurr"
"github.com/pkg/errors"
"github.com/ungerik/go-dry"
"github.com/xelaj/errs"
)
type Translator interface {
Tr(key string) string
TrWithError(key string) (string, error)
Trf(key string, params plurr.Params) (string, error)
Strf(key string, params plurr.Params) string
Lang() string
MustAll(items []string) error
Message(key string) MessageCode
MessageWithParams(key string) MessageWithParamsCode
}
// Resources is an array that holds string resources for a particular language
type Resource map[string]string
// Pool object holds all string resources and language-specific contexts.
// Pool can be created either for an entire project, or for each logical
// part of the application that has its own set of strings.
type Pool struct {
Resources map[string]Resource
resourcePath string
appName string
locales []*Locale
}
// NewPool creates a new localization pool object
func NewPool(resourcePath, appName string, preloadAll bool) (*Pool, error) {
lp := &Pool{
resourcePath: resourcePath,
appName: appName,
Resources: make(map[string]Resource),
}
locales, err := lp.availableLocales()
if err != nil {
return nil, errors.Wrap(err, "getting all locales")
}
lp.locales = locales
if preloadAll {
err := lp.PreloadAll()
if err != nil {
return nil, errors.Wrap(err, "preloading all locales")
}
}
return lp, nil
}
// GetContext returns a translation context based on the provided language.
// Contexts are thread-safe.
func (lp *Pool) GetContext(lang string) (*Context, error) {
err := lp.LoadResource(lang)
if err != nil {
return nil, errors.Wrap(err, "loading resource")
}
return &Context{
pool: lp,
lang: lang,
plurr: plurr.New().SetLocale(lang),
}, nil
}
func (lp *Pool) ForceLoadResource(lang string) error {
res, err := walkDir(filepath.Join(lp.resourcePath, lang, lp.appName))
if err == nil {
lp.Resources[lang] = res
}
return err
}
func (lp *Pool) LoadResource(lang string) error {
if _, ok := lp.Resources[lang]; ok {
return nil
}
return lp.ForceLoadResource(lang)
}
func (lp *Pool) PreloadAll() error {
resources := make(map[string]Resource)
errMultiple := &errs.MultipleErrors{}
for _, locale := range lp.locales {
path := filepath.Join(lp.resourcePath, locale.Code, lp.appName)
if !dry.FileExists(path) {
continue
}
res, err := walkDir(path)
if err != nil {
errMultiple.Add(err)
continue
}
resources[locale.Code] = res
}
if err := errMultiple.Normalize(); err != nil {
return errors.Wrap(err, "loading all languages")
}
for code, resource := range resources {
lp.Resources[code] = resource
}
return nil
}
func (lp *Pool) availableLocales() ([]*Locale, error) {
dirs, err := dry.ListDirDirectories(lp.resourcePath)
dry.PanicIfErr(err)
locales := make([]*Locale, 0)
errMultiple := &errs.MultipleErrors{}
for _, dir := range dirs {
locale, err := langInfo(lp.resourcePath, dir)
if err != nil {
errMultiple.Add(err)
continue
}
locales = append(locales, locale)
}
if err := errMultiple.Normalize(); err != nil {
return nil, err
}
return locales, nil
}