diff --git a/consts.go b/consts.go new file mode 100644 index 0000000..db79ec3 --- /dev/null +++ b/consts.go @@ -0,0 +1,62 @@ +package errorx + +import ( + "context" + + "github.com/yuninks/langx" +) + +// 定义错误常量 + +type ErrorLanguage struct { + langx.LangError +} + +// 生成错误常量 +func NewLanguage(uniKey string, code int, defaultValue string) ErrorLanguage { + langx.AppendCode(map[string]int{uniKey: code}) + langx.AppendTrans(langx.GetDefaultLang(), map[string]string{uniKey: defaultValue}) + + l := langx.NewStruct(context.Background(), uniKey, nil) + + return ErrorLanguage{l} +} + +// Key生成错误信息 +func (l ErrorLanguage) Err() error { + return l +} + +// Key生成错误信息 +func (l ErrorLanguage) Errf(format map[string]string) error { + newLang := l.Copy() + newLang.SetFormat(format) + return newLang +} + +func (l ErrorLanguage) ErrfKV(key, value string) error { + newLang := l.Copy() + newLang.SetFormatKV(key, value) + return newLang +} + +// 获取翻译后的错误信息 +func (l ErrorLanguage) Msg(ctx context.Context) string { + newLang := l.Copy() + newLang.SetCtx(ctx) + return newLang.Error() +} + +// 获取翻译后的错误信息 +func (l ErrorLanguage) Msgf(ctx context.Context, format map[string]string) string { + newLang := l.Copy() + newLang.SetCtx(ctx) + newLang.SetFormat(format) + return newLang.Error() +} + +var ( + Success ErrorLanguage = NewLanguage("success", 200, "操作成功") + Error ErrorLanguage = NewLanguage("error", 400, "操作失败") + ErrWithMsg ErrorLanguage = NewLanguage("error_with_msg", 400, "操作失败: #msg#") +) diff --git a/error_test.go b/error_test.go new file mode 100644 index 0000000..f10e081 --- /dev/null +++ b/error_test.go @@ -0,0 +1,57 @@ +package errorx_test + +import ( + "context" + "testing" + "github.com/yuninks/langx" +) + +func TestError(t *testing.T) { + var err error + + ctx := context.Background() + + langx.InitLangx( + langx.SetDefaultCode(0), + langx.SetDefaultLanguage("zh"), + ) + langx.RegisterCode(map[string]int{ + "login_success": 200, + "error": 400, + "username": 201, + }) + langx.RegisterTrans("zh", map[string]string{ + "login_success": "成功", + "error": "错误", + "username": "你好 #name#", // 有占位符 + }) + langx.RegisterTrans("en", map[string]string{ + "login_success": "success", + "error": "error", + "username": "Hello #name#", // 有占位符 + }) + + err = langx.NewError(ctx, "error") + // fmt.Printf("err: %v\n", err) + t.Log(err.Error()) + val, ok := err.(langx.LangError) + if ok { + t.Log(val.GetCode()) + } + + err = langx.NewErrorf(ctx, "username", map[string]string{ + "name": "yuninks", + }) + t.Log(err.Error()) + val, ok = err.(langx.LangError) + if ok { + t.Log(val.GetCode()) + + // 设置输出语言 + val.SetLang("en") + + } + + t.Log(val.Error()) + +} diff --git a/errorx.go b/errorx.go index 86b14e6..bf2ebdb 100644 --- a/errorx.go +++ b/errorx.go @@ -1,135 +1,97 @@ package errorx import ( - "encoding/json" - "errors" + "context" - "google.golang.org/grpc/codes" - status "google.golang.org/grpc/status" + "github.com/yuninks/langx" ) -const defaultCode = 400 +// Key生成错误信息 -type Errorx struct { - list []CodeError +type LangError interface { + Copy() LangError // 复制一个新的错误信息 + Error() string // 实现error接口&获取翻译后的错误信息 + GetCode() int // 获取翻译后的Code + GetKey() string // 获取原Key值 + GetFormat() map[string]string // 获取附加数据 + SetFormat(format map[string]string) // 设置附加数据 + SetCtx(ctxHttp context.Context) // 设置上下文 + SetLang(lang string) // 设置语言 + SetFormatKV(key, value string) // 设置附加数据键值对 } -type CodeError struct { - *status.Status - // Code int `json:"code"` - // Message string `json:"message"` +type langError struct { + ctx context.Context + key string + format map[string]string } -func NewCodeError(code int, msg string) error { - return &Errorx{ - list: []CodeError{ - { - status.New(codes.Code(code), msg), - // Code: code, - // Message: msg, - }, - }, +func (l *langError) Copy() LangError { + return &langError{ + ctx: l.ctx, + key: l.key, + format: l.format, } } -func New(msg string) error { - return NewCodeError(defaultCode, msg) +func (e *langError) SetFormat(format map[string]string) { + e.format = format } -func WithError(err error, msg string) error { - if err == nil { - return NewCodeError(defaultCode, msg) +func (l *langError) SetFormatKV(key, value string) { + if l.format == nil { + l.format = make(map[string]string) } - e, ok := err.(*Errorx) - if ok { - e.list = append(e.list, CodeError{ - status.New(codes.Code(defaultCode), msg), - // Code: defaultCode, - // Message: msg, - }) - return e - } else { - return &Errorx{ - list: []CodeError{ - { - status.New(codes.Code(defaultCode), msg), - // Code: defaultCode, - // Message: err.Error(), - }, - { - status.New(codes.Code(defaultCode), msg), - // Code: defaultCode, - // Message: msg, - }, - }, - } + l.format[key] = value +} + +func (e *langError) SetCtx(ctxHttp context.Context) { + e.ctx = ctxHttp +} + +func (l *langError) Error() string { + errLang := langx.GetCtxLang(l.ctx) + return langx.GetFormat(errLang, l.key, l.format) +} + +func (e *langError) GetCode() int { + return langx.GetCode(e.key) +} + +func (e *langError) GetKey() string { + return e.key +} + +func (e *langError) GetFormat() map[string]string { + if e.format == nil { + e.format = make(map[string]string) + } + return e.format +} + +func (e *langError) SetLang(lang string) { + e.ctx = langx.SetCtxLang(e.ctx, lang) +} + +func NewErrorf(ctx context.Context, key string, format map[string]string) error { + return &langError{ + ctx: ctx, + key: key, + format: format, } } -func (e *Errorx) Error() string { - c := len(e.list) - if c == 0 { - return "" +func NewError(ctx context.Context, key string) error { + return &langError{ + ctx: ctx, + key: key, } - - return e.list[c-1].Message() } -func (e *Errorx) Code() int { - c := len(e.list) - if c == 0 { - return 200 +func NewStruct(ctx context.Context, key string, format map[string]string) LangError { + return &langError{ + ctx: ctx, + key: key, + format: format, } - return int(e.list[c-1].Code()) -} - -func FromError(err error) (s *status.Status, ok bool) { - if err == nil { - return nil, true - } - type grpcstatus interface{ GRPCStatus() *status.Status } - if gs, ok := err.(grpcstatus); ok { - if gs.GRPCStatus() == nil { - // Error has status nil, which maps to codes.OK. There - // is no sensible behavior for this, so we turn it into - // an error with codes.Unknown and discard the existing - // status. - return status.New(codes.Unknown, err.Error()), false - } - return gs.GRPCStatus(), true - } - var gs grpcstatus - if errors.As(err, &gs) { - if gs.GRPCStatus() == nil { - // Error wraps an error that has status nil, which maps - // to codes.OK. There is no sensible behavior for this, - // so we turn it into an error with codes.Unknown and - // discard the existing status. - return status.New(codes.Unknown, err.Error()), false - } - p := gs.GRPCStatus().Proto() - p.Message = err.Error() - return status.FromProto(p), true - } - return status.New(codes.Unknown, err.Error()), false -} - -func (e *Errorx) GRPCStatus() *status.Status { - c := len(e.list) - if c == 0 { - return nil - } - return e.list[c-1].Status -} -func (e *Errorx) Is(target error) bool { - return true -} - -func (e *Errorx) Data() []CodeError { - return e.list -} - -func (e *Errorx) String() string { - b, _ := json.Marshal(e.list) - return string(b) } diff --git a/example/enample2.go b/example/enample2.go new file mode 100644 index 0000000..3cd8004 --- /dev/null +++ b/example/enample2.go @@ -0,0 +1,48 @@ +package main + +import ( + "context" + + "github.com/yuninks/langx" +) + +func main() { + + err := ErrorWithMsg.Error() + + // 输出:错误 + println(err.Error()) + + err = ErrorWithMsg.Errorf(map[string]string{"msg": "错误"}) + // 输出:错误 + println(err.Error()) + +} + +type Language string + +// 添加key+默认语言 +func newLanguage(uniKey string, code int, defaultValue string) Language { + langx.AppendCode(map[string]int{uniKey: code}) + langx.AppendTrans("zh_hans", map[string]string{uniKey: defaultValue}) + return Language(uniKey) +} + +func (l Language) String() string { + return string(l) +} + +func (l Language) Error() error { + return langx.NewError(context.Background(), l.String()) +} + +func (l Language) Errorf(format map[string]string) error { + return langx.NewErrorf(context.Background(), l.String(), format) +} + +var ( + Success Language = newLanguage("success", 200, "成功") + + Error Language = newLanguage("error", 400, "错误") + ErrorWithMsg Language = newLanguage("error_with_msg", 400, "错误 #msg#") +) diff --git a/example/imports/lang/code.json b/example/imports/lang/code.json new file mode 100644 index 0000000..abcf999 --- /dev/null +++ b/example/imports/lang/code.json @@ -0,0 +1,4 @@ +{ + "success":200, + "error":400 +} \ No newline at end of file diff --git a/example/imports/lang/en.json b/example/imports/lang/en.json new file mode 100644 index 0000000..f671b9a --- /dev/null +++ b/example/imports/lang/en.json @@ -0,0 +1,4 @@ +{ + "success":"Success", + "error":"Error #msg#" +} \ No newline at end of file diff --git a/example/imports/lang/zh.json b/example/imports/lang/zh.json new file mode 100644 index 0000000..b38c68a --- /dev/null +++ b/example/imports/lang/zh.json @@ -0,0 +1,4 @@ +{ + "success":"成功", + "error":"失败 #msg#" +} \ No newline at end of file diff --git a/example/imports/main.go b/example/imports/main.go new file mode 100644 index 0000000..baf5893 --- /dev/null +++ b/example/imports/main.go @@ -0,0 +1,54 @@ +package main + +import ( + "embed" + "fmt" + + "github.com/yuninks/langx" +) + +//go:embed lang +var assetsFs embed.FS + +func main() { + regByAppend() +} + +// 导入语言包 基于Append +func regByAppend() { + langx.AppendCode(map[string]int{ + "success": 200, + }) + langx.AppendTrans("zh-CN", map[string]string{ + "success": "成功", + }) + + code, msg := langx.GetTransFormat("zh-CN", "success", map[string]string{}) + fmt.Println(code, msg) + +} + +// 导入语言包 基于Embed +func regByEmbed() { + err := langx.RegisterEmbed(assetsFs) + fmt.Println(err) + + code, msg := langx.GetTransFormat("zh", "success", map[string]string{}) + fmt.Println(code, msg) + code, msg = langx.GetTransFormat("en", "error", map[string]string{ + "msg": "这是失败的原因", + }) + fmt.Println(code, msg) +} + +// 导入语言包 基于文件 +func regByDir() { + langx.RegisterDir("./lang") + + code, msg := langx.GetTransFormat("zh", "success", map[string]string{}) + fmt.Println(code, msg) + code, msg = langx.GetTransFormat("en", "error", map[string]string{ + "msg": "这是失败的原因", + }) + fmt.Println(code, msg) +} diff --git a/example/imports/readme.md b/example/imports/readme.md new file mode 100644 index 0000000..d1093cf --- /dev/null +++ b/example/imports/readme.md @@ -0,0 +1,7 @@ +# 导入资源 + +# 通过embed导入 + +# 通过文件导入 + +# 追加导入 diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..d365961 --- /dev/null +++ b/go.mod @@ -0,0 +1,5 @@ +module github.com/yuninks/errorx + +go 1.22.4 + +require github.com/yuninks/langx v0.0.6 diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..746c1c5 --- /dev/null +++ b/go.sum @@ -0,0 +1,2 @@ +github.com/yuninks/langx v0.0.6 h1:+gUttpogalaUaKlqm2AsY5sNnSpoVj58jqEM1oFKWTk= +github.com/yuninks/langx v0.0.6/go.mod h1:nAylzjNIjCThhEQSJsIKP8Vhja0aJlcyig+NsNPZLSk=