forked from gotnospirit/messageformat
-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathformatter.go
More file actions
142 lines (116 loc) · 2.89 KB
/
Copy pathformatter.go
File metadata and controls
142 lines (116 loc) · 2.89 KB
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
139
140
141
142
package messageformat
import (
"bytes"
"fmt"
"github.com/gotnospirit/makeplural/plural"
"golang.org/x/text/language"
)
var (
DefaultLocale = language.English
)
// pluralFunc describes a function used to produce a named key when processing a plural or selectordinal expression.
type pluralFunc func(interface{}, bool) string
type Formatter interface {
Format(*ParseTree) (string, error)
FormatMap(*ParseTree, map[string]any) (string, error)
}
type FormatterOption func(f *formatter)
func WithLocale(locale language.Tag) FormatterOption {
return func(f *formatter) {
f.SetLocale(locale)
}
}
// NewFormatter creates a new formatter with the given options
func NewFormatter(opts ...FormatterOption) (Formatter, error) {
f := formatter{}
for _, opt := range opts {
opt(&f)
}
if f.locale == language.Und {
err := f.SetLocale(DefaultLocale)
if err != nil {
return nil, err
}
}
return &f, nil
}
type formatter struct {
locale language.Tag
plural pluralFunc
date DateTimeFormatter
}
func (x *formatter) SetLocale(tag language.Tag) error {
x.locale = tag
switch tag {
case language.AmericanEnglish:
x.date = createAmericanDateTimeFormatter()
case language.German:
x.date = createGermanDateTimeFormatter()
default:
x.date = createAmericanDateTimeFormatter()
}
if x.plural == nil {
culture := tag
for culture != language.Und {
fn, err := plural.GetFunc(culture.String())
if err == nil {
x.plural = fn
break
}
culture = culture.Parent()
}
}
return nil
}
func (x *formatter) SetPluralFunction(fn pluralFunc) error {
if nil == fn {
return fmt.Errorf("PluralFunctionRequired")
}
x.plural = fn
return nil
}
func (f *formatter) Format(n *ParseTree) (string, error) {
return f.FormatMap(n, nil)
}
func (f *formatter) FormatMap(n *ParseTree, data map[string]any) (string, error) {
var buf bytes.Buffer
err := f.format(n, &buf, data, "")
if err != nil {
return "", err
}
return buf.String(), nil
}
func (f *formatter) format(n *ParseTree, buf *bytes.Buffer, data map[string]any, value string) error {
err := n.ForEach(func(n *Node) error {
switch n.Type {
case "date":
fallthrough
case "time":
return f.formatDateTime(n.Expr, buf, data)
case "literal":
return f.formatLiteral(n.Expr, buf, value)
case "plural":
return f.formatPlural(n.Expr, buf, data)
case "select":
return f.formatSelect(n.Expr, buf, data)
case "selectordinal":
return f.formatOrdinal(n.Expr, buf, data)
case "var":
return f.formatVar(n.Expr, buf, data)
case "number":
return f.formatNumber(n.Expr, buf, data)
default:
return fmt.Errorf("formatter not implemented for expression of type %s", n.Type)
}
})
if nil != err {
return err
}
return nil
}
func (f *formatter) getNamedKey(value interface{}, ordinal bool) (string, error) {
if nil == f.plural {
return "", fmt.Errorf("UndefinedPluralFunc")
}
return f.plural(value, ordinal), nil
}