forked from rainycape/gondola
/
error.go
137 lines (121 loc) · 3.83 KB
/
error.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
package i18n
import (
"errors"
"strconv"
)
const (
// These are the possible values for *strconv.NumError
_ String = "value out of range"
_ String = "invalid syntax"
)
// Error represents an error which can be translated to
// another language. Keep in mind that Error also implements
// error, so you can return an Error from any function that
// returns error. You can later use FromError() to get back
// an Error again or TranslatedError, to get an error with
// the translated message.
type Error interface {
// Error returns the untranslated error message.
Error() string
// Err translates the Error and returns it as an error.
Err(languager Languager) error
// TranslatedError returns the translated error message.
TranslatedError(languager Languager) string
}
// translatableError implements the Error interface.
type translatableError struct {
Context string
Format string
PluralFormat string
N int
Args []interface{}
}
func (e *translatableError) sprintf(languager Languager) string {
if e.PluralFormat != "" {
return Sprintfnc(languager, e.Context, e.Format, e.PluralFormat, e.N, e.Args...)
}
return Sprintfc(languager, e.Context, e.Format, e.Args...)
}
func (e *translatableError) Error() string {
return e.sprintf(nil)
}
func (e *translatableError) Err(languager Languager) error {
return errors.New(e.TranslatedError(languager))
}
func (e *translatableError) TranslatedError(languager Languager) string {
return e.sprintf(languager)
}
// Implement TranslatableString too
func (e *translatableError) TranslatedString(languager Languager) string {
return e.TranslatedError(languager)
}
// Errorf returns a error with the given format and arguments. The
// returned Error uses Sprintf internally, which means it will
// translate any argument which supports translation.
func Errorf(format string, args ...interface{}) Error {
return &translatableError{
Format: format,
Args: args,
}
}
// Errorfc returns a error with the given context, format and arguments. The
// returned Error uses Sprintf internally, which means it will
// translate any argument which supports translation.
func Errorfc(ctx string, format string, args ...interface{}) Error {
return &translatableError{
Context: ctx,
Format: format,
Args: args,
}
}
// Errorfn returns a error with the given singular and plural forms as
// well as the given and arguments. The returned Error uses Sprintf
// internally, which means it will translate any argument which supports
// translation.
func Errorfn(singular string, plural string, n int, args ...interface{}) Error {
return &translatableError{
Format: singular,
PluralFormat: plural,
N: n,
Args: args,
}
}
// Errorfnc returns a error with the given conext, singular and plural forms as
// well as the given and arguments. The returned Error uses Sprintf
// internally, which means it will translate any argument which supports
// translation.
func Errorfnc(ctx string, singular string, plural string, n int, args ...interface{}) Error {
return &translatableError{
Context: ctx,
Format: singular,
PluralFormat: plural,
N: n,
Args: args,
}
}
// NewError returns an Error with the given message.
func NewError(message string) Error {
return &translatableError{Format: message}
}
// FromError returns an Error from an error, translating
// it when possible. If e already implements Error, the received
// value is returned.
func FromError(e error) Error {
if e == nil {
return nil
}
if err, ok := e.(Error); ok {
return err
}
if err, ok := e.(*strconv.NumError); ok {
return Errorf("could not parse %q: %s", err.Num, String(err.Err.Error()))
}
return NewError(e.Error())
}
func TranslatedError(err error, languager Languager) error {
terr := FromError(err)
if terr != nil {
return terr.Err(languager)
}
return nil
}