package middleware import ( "app/commons/constant" "app/commons/services" "bufio" "bytes" "fmt" "github.com/gin-gonic/gin" "github.com/tidwall/gjson" "github.com/tidwall/sjson" "net" "net/http" ) func I18n() gin.HandlerFunc { return func(ctx *gin.Context) { lang := constant.LangeEn // 默认英文 // postman会覆盖掉language if val := ctx.GetHeader(constant.HeaderKeyLang); len(val) > 0 { lang = val } if val := ctx.GetHeader(constant.HeaderKeyLanguage); len(val) > 0 { lang = val } ctx.Set(constant.HeaderKeyLang, lang) // 开始处理返回结果 w := NewResWriter(ctx.Writer) ctx.Writer = w // 调用下一个中间件 ctx.Next() // 最终输出内容 defer func() { w.Flush() }() var err error // 获取返回结果 if bodyString := w.Body.String(); len(bodyString) > 0 { msg := gjson.Get(bodyString, "msg").String() if len(msg) == 0 { return } // 翻译返回码 key := fmt.Sprintf("%s", msg) i18nText := services.GetI18nService().Translate(lang, key) bodyString, err = sjson.Set(bodyString, "msg", i18nText) if err != nil { return } // 重新写入响应 w.Body.Reset() w.Body.Write([]byte(bodyString)) } } } type ResWriter struct { Writer gin.ResponseWriter // the actual ResponseWriter to flush to status int // the HTTP response code from WriteHeader Body *bytes.Buffer // the response content body Flushed bool } func NewResWriter(w gin.ResponseWriter) *ResWriter { return &ResWriter{ Writer: w, status: w.Status(), Body: &bytes.Buffer{}, } } func (w *ResWriter) Header() http.Header { return w.Writer.Header() // use the actual response header } func (w *ResWriter) Write(buf []byte) (int, error) { w.Body.Write(buf) return len(buf), nil } func (w *ResWriter) WriteString(s string) (n int, err error) { n, err = w.Write([]byte(s)) return } const ( noWritten = -1 ) func (w *ResWriter) Written() bool { return w.Body.Len() != noWritten } func (w *ResWriter) WriteHeader(status int) { w.status = status } func (w *ResWriter) WriteHeaderNow() { } func (w *ResWriter) Status() int { return w.status } func (w *ResWriter) Size() int { return w.Body.Len() } func (w *ResWriter) Hijack() (net.Conn, *bufio.ReadWriter, error) { return w.Writer.(http.Hijacker).Hijack() } func (w *ResWriter) CloseNotify() <-chan bool { return w.Writer.(http.CloseNotifier).CloseNotify() } func (w *ResWriter) Pusher() http.Pusher { return w.Pusher() } func (w *ResWriter) Flush() { w.realFlush() } func (w *ResWriter) realFlush() { if w.Flushed { return } w.Writer.WriteHeader(w.status) if w.Body.Len() > 0 { _, err := w.Writer.Write(w.Body.Bytes()) if err != nil { panic(err) } w.Body.Reset() } w.Flushed = true }