完成部分翻译功能

This commit is contained in:
474420502 2024-04-12 17:17:10 +08:00
parent 6e8a6eb7d1
commit 353b3f0f4f
15 changed files with 1630 additions and 60 deletions

4
.gitignore vendored
View File

@ -21,4 +21,6 @@ vendor/
go.work
__debug_bin*
.vscode
.vscode
*.php

1
go.mod
View File

@ -31,6 +31,7 @@ require (
github.com/mattn/go-isatty v0.0.19 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/nicksnyder/go-i18n/v2 v2.4.0
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect

6
go.sum
View File

@ -59,8 +59,13 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/nicksnyder/go-i18n v1.10.3 h1:0U60fnLBNrLBVt8vb8Q67yKNs+gykbQuLsIkiesJL+w=
github.com/nicksnyder/go-i18n v1.10.3/go.mod h1:hvLG5HTlZ4UfSuVLSRuX7JRUomIaoKQM19hm6f+no7o=
github.com/nicksnyder/go-i18n/v2 v2.4.0 h1:3IcvPOAvnCKwNm0TB0dLDTuawWEj+ax/RERNC+diLMM=
github.com/nicksnyder/go-i18n/v2 v2.4.0/go.mod h1:nxYSZE9M0bf3Y70gPQjN9ha7XNHX7gMc814+6wVyEI4=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -104,6 +109,7 @@ google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -10,4 +10,5 @@
6. 电话号码和邮件不是唯一, 帐号表数据可能混乱
7. 表绝大部分没建索引, 数量上去, 性能立马下降
8. 表的部分字段不对应, 如 parent_id 和 customer_id 是同一事物, 但是类型不一样. 可能会产生不可预料的错误
9. 数据库里递归查询, 一个查询n个query请求.出问题数据库死锁,整个项目崩溃. 例如 getFullParents
9. 数据库里递归查询, 一个查询n个query请求.出问题数据库死锁,整个项目崩溃. 例如 getFullParents
10. 部分翻译了, 部分不翻译, 导致国际语言经常会返回中文. 多语言只实现了小部分, 错误非常多.

View File

@ -4,8 +4,8 @@ import (
"strings"
"time"
"github.com/gin-gonic/gin"
"github.com/iapologizewhenimwrong/Vestmore_GO/model"
"github.com/iapologizewhenimwrong/Vestmore_GO/translator"
"github.com/iapologizewhenimwrong/Vestmore_GO/utils/auth"
"github.com/iapologizewhenimwrong/Vestmore_GO/utils/basic"
"github.com/iapologizewhenimwrong/Vestmore_GO/utils/email"
@ -21,8 +21,8 @@ var CompanyKey = "vestmore-bjwl"
// app_market: string;
// lang: string;
// token: string;
func BaseGetToken(ctx *gin.Context, param *BaseGetTokenParam) (resp *basic.Response) {
ctx.ShouldBind(param)
func BaseGetToken(ctx *ActionContext[BaseGetTokenParam]) (resp *basic.Response) {
// model.Models.KillaraCustomerModel.Find()
log.Println()
@ -43,28 +43,28 @@ func BaseGetToken(ctx *gin.Context, param *BaseGetTokenParam) (resp *basic.Respo
// app_market: uint64;
// email: string;
// timestamp: int64;
func AccountLoginWithTelephonePassword(ctx *gin.Context, param *AccountLoginWithTelephonePasswordParam) (resp *basic.Response) {
func AccountLoginWithTelephonePassword(ctx *ActionContext[AccountLoginWithTelephonePasswordParam]) (resp *basic.Response) {
// ctx.ShouldBind()
// model.Models.KillaraCustomerModel.Find()
if param.CountryCode == "" {
if ctx.Param.CountryCode == "" {
resp.ErrorMsg(1, "country_code 参数缺失")
return
}
if param.Telephone == "" {
if ctx.Param.Telephone == "" {
resp.ErrorMsg(1, "telephone 参数缺失")
return
}
if param.Password == "" {
if ctx.Param.Password == "" {
resp.ErrorMsg(1, "password 参数缺失")
return
}
telephone := strings.TrimSpace(param.Telephone)
password := strings.TrimSpace(param.Password)
countryCode := strings.TrimSpace(param.CountryCode)
telephone := strings.TrimSpace(ctx.Param.Telephone)
password := strings.TrimSpace(ctx.Param.Password)
countryCode := strings.TrimSpace(ctx.Param.CountryCode)
// 假设 modelCustomer 和 modelCustomerToken 是对应的服务接口
@ -85,52 +85,50 @@ func AccountLoginWithTelephonePassword(ctx *gin.Context, param *AccountLoginWith
}
if customer == nil {
return resp.ErrorMsg(1, "账号未注册")
return resp.ErrorTrCode(ctx, translator.AccountNotRegistered)
}
if *customer.CountryCode != countryCode {
return resp.ErrorMsg(1, "电话号码国家不正确")
return resp.ErrorTrCode(ctx, translator.PhoneNumberCountryIncorrect)
}
if *customer.Status != 1 {
return resp.ErrorMsg(1, "账号已禁用,无法登录")
return resp.ErrorTrCode(ctx, translator.AccountDisabledNotLogin)
}
if !auth.CheckPassword(*customer.Password, *customer.Salt, *customer.RandomPassword, password) {
return resp.ErrorMsg(1, "账号或密码错误")
return resp.ErrorTrCode(ctx, translator.AccountOrPasswordLoginFailed)
}
customerID := *customer.CustomerId
err = model.Models.KillaraCustomerTokenModel.UpdateTokenCustomerID(param.Token, customerID)
err = model.Models.KillaraCustomerTokenModel.UpdateTokenCustomerID(ctx.Param.Token, customerID)
if err != nil {
return resp.ErrorMsg(1, err.Error())
}
var deviceCode string
if param.Device != "" {
deviceCode = param.Device
if ctx.Param.Device != "" {
deviceCode = ctx.Param.Device
}
var version string
if param.Version != "" {
version = param.Version
if ctx.Param.Version != "" {
version = ctx.Param.Version
}
var ip string
addr := strings.Split(ctx.Request.RemoteAddr, ":")
addr := strings.Split(ctx.GinCtx.Request.RemoteAddr, ":")
if len(addr) > 0 {
ip = addr[0]
}
log.Println(deviceCode, version, ip)
data := &model.KillaraCustomerDevice{
CustomerId: &customerID,
Device: &deviceCode,
Version: &version,
Ip: &ip,
AppMarket: &param.AppMarket,
AppMarket: &ctx.Param.AppMarket,
Date: basic.TimePtr(time.Now()),
}
@ -143,14 +141,7 @@ func AccountLoginWithTelephonePassword(ctx *gin.Context, param *AccountLoginWith
// // 假设 clearDuplicateToken 是对应的服务接口
// clearDuplicateToken(customerID, param.Token)
model.Models.KillaraCustomerTokenModel.ClearDuplicateToken(customerID, param.Token, 1)
// return map[string]interface{}{
// "success": true,
// "error_code": 0,
// "error_text": "",
// "data": make(map[string]interface{}),
// }, nil
model.Models.KillaraCustomerTokenModel.ClearDuplicateToken(customerID, ctx.Param.Token, 1)
// log.Println(param)
return resp.Success()
@ -162,7 +153,7 @@ func AccountLoginWithTelephonePassword(ctx *gin.Context, param *AccountLoginWith
// country_code?: string;
// telephone?: string;
// token: string;
func AccountRegisterSmsCode(ctx *gin.Context, param *AccountRegisterSmsCodeParam) (resp *basic.Response) {
func AccountRegisterSmsCode(ctx *ActionContext[AccountRegisterSmsCodeParam]) (resp *basic.Response) {
// ctx.ShouldBind()
log.Println()
return resp.Success()
@ -174,8 +165,9 @@ func AccountRegisterSmsCode(ctx *gin.Context, param *AccountRegisterSmsCodeParam
// country_code?: string;
// telephone?: string;
// token: string;
func AccountForgetSmsCode(ctx *gin.Context, param *AccountForgetSmsCodeParam) (resp *basic.Response) {
func AccountForgetSmsCode(ctx *ActionContext[AccountForgetSmsCodeParam]) (resp *basic.Response) {
// ctx.ShouldBind()
// ctx *gin.Context, param *AccountForgetSmsCodeParam
log.Println()
return resp.Success()
}
@ -195,10 +187,9 @@ type RegisterValidEmailCode struct {
// email: string;
// timestamp: int64;
// token: string;
func AccountRegisterEmailCode(ctx *gin.Context, param *AccountRegisterEmailCodeParam) (resp *basic.Response) {
log.Println(param)
func AccountRegisterEmailCode(ctx *ActionContext[AccountRegisterEmailCodeParam]) (resp *basic.Response) {
if !email.IsEmailValid(param.Email) {
if !email.IsEmailValid(ctx.Param.Email) {
return resp.Error(basic.ErrEmailFormat)
}
@ -207,8 +198,8 @@ func AccountRegisterEmailCode(ctx *gin.Context, param *AccountRegisterEmailCodeP
code := auth.GenerateVerificationCode()
codetoken := &RegisterValidEmailCode{
Code: code,
Email: param.Email,
AppMarket: param.AppMarket,
Email: ctx.Param.Email,
AppMarket: ctx.Param.AppMarket,
}
tokenstr, err := gcm.Encrypt(codetoken)
if err != nil {
@ -228,7 +219,7 @@ func AccountRegisterEmailCode(ctx *gin.Context, param *AccountRegisterEmailCodeP
// new_password: string;
// old_password: string;
// token?: string;
func MemberAlterPassword(ctx *gin.Context, param *MemberAlterPasswordParam) (resp *basic.Response) {
func MemberAlterPassword(ctx *ActionContext[MemberAlterPasswordParam]) (resp *basic.Response) {
// ctx.ShouldBind()
log.Println()
return resp.Success()
@ -242,12 +233,82 @@ func MemberAlterPassword(ctx *gin.Context, param *MemberAlterPasswordParam) (res
// action: string;
// device: string;
// version: string;
// app_market: int;
// app_market: uint64;
// email: string;
// timestamp: int64;
// token: string;
func AccountLoginWithEmailPassword(ctx *gin.Context, param *AccountLoginWithEmailPasswordParam) (resp *basic.Response) {
func AccountLoginWithEmailPassword(ctx *ActionContext[AccountLoginWithEmailPasswordParam]) (resp *basic.Response) {
if ctx.Param.Email == "" {
return resp.ErrorMsg(1, "email 参数缺失")
}
if ctx.Param.Password == "" {
return resp.ErrorMsg(1, "password 参数缺失")
}
email := strings.TrimSpace(ctx.Param.Email)
password := strings.TrimSpace(ctx.Param.Password)
var customer *model.KillaraCustomer
var err error
customer, err = model.Models.KillaraCustomerModel.GetCustomerByEmailForBackEnd(email)
if err != nil {
return resp.ErrorErr(1, err)
}
ctx.Localize(translator.AccountNotRegistered)
if customer == nil {
return resp.ErrorTrCode(ctx, translator.AccountNotRegistered)
}
if *customer.Status != 1 {
return resp.ErrorTrCode(ctx, translator.AccountDisabledNotLogin)
}
if !auth.CheckPassword(*customer.Password, *customer.Salt, *customer.RandomPassword, password) {
return resp.ErrorTrCode(ctx, translator.AccountOrPasswordLoginFailed)
}
customerID := *customer.CustomerId
err = model.Models.KillaraCustomerTokenModel.UpdateTokenCustomerID(ctx.Param.Token, customerID)
if err != nil {
return resp.ErrorMsg(1, err.Error())
}
var deviceCode string
if ctx.Param.Device != "" {
deviceCode = ctx.Param.Device
}
var version string
if ctx.Param.Version != "" {
version = ctx.Param.Version
}
var ip string
addr := strings.Split(ctx.GinCtx.Request.RemoteAddr, ":")
if len(addr) > 0 {
ip = addr[0]
}
data := &model.KillaraCustomerDevice{
CustomerId: &customerID,
Device: &deviceCode,
Version: &version,
Ip: &ip,
AppMarket: &ctx.Param.AppMarket,
Date: basic.TimePtr(time.Now()),
}
err = model.Models.KillaraCustomerModel.InsertCustomerDevice(data)
if err != nil {
return resp.ErrorErr(1, err)
}
model.Models.KillaraCustomerTokenModel.ClearDuplicateToken(customerID, ctx.Param.Token, 1)
log.Println(param)
return resp.Success()
}

View File

@ -2,10 +2,40 @@ package actions
import (
"github.com/gin-gonic/gin"
"github.com/iapologizewhenimwrong/Vestmore_GO/translator"
"github.com/iapologizewhenimwrong/Vestmore_GO/utils/basic"
"github.com/iapologizewhenimwrong/Vestmore_GO/utils/log"
)
type ActionContext[PARAM any] struct {
Lang string
GinCtx *gin.Context
Param *PARAM
}
func (ctx *ActionContext[PARAM]) Localize(MessageID translator.TrCode) (string, error) {
return translator.Localize(MessageID, ctx.Lang, nil)
}
func (ctx *ActionContext[PARAM]) LocalizeWithData(MessageID translator.TrCode, MessageTemplateParam any) (string, error) {
return translator.Localize(MessageID, ctx.Lang, MessageTemplateParam)
}
func (ctx *ActionContext[PARAM]) LocalizeEx(MessageID translator.TrCode, Langs ...string) (string, error) {
if len(Langs) == 0 {
return translator.LocalizeEx(MessageID, nil, ctx.Lang)
}
return translator.LocalizeEx(MessageID, nil, Langs...)
}
func (ctx *ActionContext[PARAM]) LocalizeExWithData(MessageID translator.TrCode, MessageTemplateParam any, Langs ...string) (string, error) {
if len(Langs) == 0 {
return translator.LocalizeEx(MessageID, MessageTemplateParam, ctx.Lang)
}
return translator.LocalizeEx(MessageID, MessageTemplateParam, Langs...)
}
var HandlersFuncRoutes map[string]gin.HandlerFunc = make(map[string]gin.HandlerFunc)
func init() {
@ -40,10 +70,17 @@ func AccountForgetSmsCodeHandler(ctx *gin.Context) {
if err != nil {
log.Println(err)
resp = resp.Error(basic.ErrParamParse)
ctx.JSON(200, resp)
return
}
resp = AccountForgetSmsCode(ctx, param)
actx := &ActionContext[AccountForgetSmsCodeParam]{
Lang: basic.GetLangString(param),
GinCtx: ctx,
Param: param,
}
resp = AccountForgetSmsCode(actx)
if resp == nil {
resp = resp.Error(basic.ErrRespNotNil)
}
@ -57,7 +94,7 @@ type AccountLoginWithEmailPasswordParam struct {
Action string `json:"action" form:"action" binding:"-"`
Device string `json:"device" form:"device" binding:"-"`
Version string `json:"version" form:"version" binding:"-"`
AppMarket int `json:"app_market" form:"app_market" binding:"-"`
AppMarket uint64 `json:"app_market" form:"app_market" binding:"-"`
Email string `json:"email" form:"email" binding:"-"`
Timestamp int64 `json:"timestamp" form:"timestamp" binding:"-"`
Token string `json:"token" form:"token" binding:"-"`
@ -71,10 +108,17 @@ func AccountLoginWithEmailPasswordHandler(ctx *gin.Context) {
if err != nil {
log.Println(err)
resp = resp.Error(basic.ErrParamParse)
ctx.JSON(200, resp)
return
}
resp = AccountLoginWithEmailPassword(ctx, param)
actx := &ActionContext[AccountLoginWithEmailPasswordParam]{
Lang: basic.GetLangString(param),
GinCtx: ctx,
Param: param,
}
resp = AccountLoginWithEmailPassword(actx)
if resp == nil {
resp = resp.Error(basic.ErrRespNotNil)
}
@ -104,10 +148,17 @@ func AccountLoginWithTelephonePasswordHandler(ctx *gin.Context) {
if err != nil {
log.Println(err)
resp = resp.Error(basic.ErrParamParse)
ctx.JSON(200, resp)
return
}
resp = AccountLoginWithTelephonePassword(ctx, param)
actx := &ActionContext[AccountLoginWithTelephonePasswordParam]{
Lang: basic.GetLangString(param),
GinCtx: ctx,
Param: param,
}
resp = AccountLoginWithTelephonePassword(actx)
if resp == nil {
resp = resp.Error(basic.ErrRespNotNil)
}
@ -132,10 +183,17 @@ func AccountRegisterEmailCodeHandler(ctx *gin.Context) {
if err != nil {
log.Println(err)
resp = resp.Error(basic.ErrParamParse)
ctx.JSON(200, resp)
return
}
resp = AccountRegisterEmailCode(ctx, param)
actx := &ActionContext[AccountRegisterEmailCodeParam]{
Lang: basic.GetLangString(param),
GinCtx: ctx,
Param: param,
}
resp = AccountRegisterEmailCode(actx)
if resp == nil {
resp = resp.Error(basic.ErrRespNotNil)
}
@ -157,10 +215,17 @@ func AccountRegisterSmsCodeHandler(ctx *gin.Context) {
if err != nil {
log.Println(err)
resp = resp.Error(basic.ErrParamParse)
ctx.JSON(200, resp)
return
}
resp = AccountRegisterSmsCode(ctx, param)
actx := &ActionContext[AccountRegisterSmsCodeParam]{
Lang: basic.GetLangString(param),
GinCtx: ctx,
Param: param,
}
resp = AccountRegisterSmsCode(actx)
if resp == nil {
resp = resp.Error(basic.ErrRespNotNil)
}
@ -182,10 +247,17 @@ func BaseGetTokenHandler(ctx *gin.Context) {
if err != nil {
log.Println(err)
resp = resp.Error(basic.ErrParamParse)
ctx.JSON(200, resp)
return
}
resp = BaseGetToken(ctx, param)
actx := &ActionContext[BaseGetTokenParam]{
Lang: basic.GetLangString(param),
GinCtx: ctx,
Param: param,
}
resp = BaseGetToken(actx)
if resp == nil {
resp = resp.Error(basic.ErrRespNotNil)
}
@ -208,10 +280,17 @@ func MemberAlterPasswordHandler(ctx *gin.Context) {
if err != nil {
log.Println(err)
resp = resp.Error(basic.ErrParamParse)
ctx.JSON(200, resp)
return
}
resp = MemberAlterPassword(ctx, param)
actx := &ActionContext[MemberAlterPasswordParam]{
Lang: basic.GetLangString(param),
GinCtx: ctx,
Param: param,
}
resp = MemberAlterPassword(actx)
if resp == nil {
resp = resp.Error(basic.ErrRespNotNil)
}

View File

@ -2,10 +2,40 @@ package actions
import (
"github.com/gin-gonic/gin"
"{{.ModuleName}}/translator"
"{{.ModuleName}}/utils/basic"
"{{.ModuleName}}/utils/log"
)
type ActionContext[PARAM any] struct {
Lang string
GinCtx *gin.Context
Param *PARAM
}
func (ctx *ActionContext[PARAM]) Localize(MessageID translator.TrCode) (string, error) {
return translator.Localize(MessageID, ctx.Lang, nil)
}
func (ctx *ActionContext[PARAM]) LocalizeWithData(MessageID translator.TrCode, MessageTemplateParam any) (string, error) {
return translator.Localize(MessageID, ctx.Lang, MessageTemplateParam)
}
func (ctx *ActionContext[PARAM]) LocalizeEx(MessageID translator.TrCode, Langs ...string) (string, error) {
if len(Langs) == 0 {
return translator.LocalizeEx(MessageID, nil, ctx.Lang)
}
return translator.LocalizeEx(MessageID, nil, Langs...)
}
func (ctx *ActionContext[PARAM]) LocalizeExWithData(MessageID translator.TrCode, MessageTemplateParam any, Langs ...string) (string, error) {
if len(Langs) == 0 {
return translator.LocalizeEx(MessageID, MessageTemplateParam, ctx.Lang)
}
return translator.LocalizeEx(MessageID, MessageTemplateParam, Langs...)
}
var HandlersFuncRoutes map[string]gin.HandlerFunc = make(map[string]gin.HandlerFunc)
func init() {
@ -30,10 +60,17 @@ func {{.FuncName}}Handler(ctx *gin.Context) {
if err != nil {
log.Println(err)
resp = resp.Error(basic.ErrParamParse)
ctx.JSON(200, resp)
return
}
actx := &ActionContext[{{.ParamStruct.ParamStructName}}]{
Lang: basic.GetLangString(param),
GinCtx: ctx,
Param: param,
}
resp = {{.FuncName}}(ctx, param)
resp = {{.FuncName}}(actx)
if resp == nil {
resp = resp.Error(basic.ErrRespNotNil)
}

View File

@ -2,10 +2,13 @@ package main
import (
"log"
"reflect"
"testing"
_ "github.com/go-sql-driver/mysql"
"github.com/iapologizewhenimwrong/Vestmore_GO/translator"
"github.com/nicksnyder/go-i18n/v2/i18n"
"github.com/pelletier/go-toml/v2"
"golang.org/x/text/language"
)
func TestMain(t *testing.T) {
@ -15,10 +18,26 @@ func TestMain(t *testing.T) {
}
func TestCaseZero(t *testing.T) {
var a string = ""
var b string
var c int = 1
a = ""
// lang := language.Make("zh_cn")
log.Println(language.Make("zh_cn"))
log.Println(language.ParseAcceptLanguage("zh_cn"))
tr := i18n.NewBundle(language.Chinese)
tr.RegisterUnmarshalFunc("toml", toml.Unmarshal)
tr.MustLoadMessageFile("./internal/i18n/zh_cn.toml")
// accept := r.Header.Get("Accept-Language")
// i18n.NewLocalizer()
localizer := i18n.NewLocalizer(tr, "zh_cn")
log.Println(localizer.Localize(&i18n.LocalizeConfig{
MessageID: "format_account_is_insufficient",
TemplateData: map[string]any{
"CatalogCurrency": "USDT",
},
}))
}
func TestTr(t *testing.T) {
log.Println(translator.Localize("账号未注册", "zh_cn", nil))
log.Println(reflect.ValueOf(a).IsZero(), reflect.ValueOf(b).IsZero(), reflect.ValueOf(c).IsZero())
}

58
translator/translator.go Normal file
View File

@ -0,0 +1,58 @@
package translator
import (
"path/filepath"
"runtime"
"github.com/nicksnyder/go-i18n/v2/i18n"
"github.com/pelletier/go-toml/v2"
"golang.org/x/text/language"
)
var Bundle *i18n.Bundle
func init() {
var err error
_, currentFile, _, _ := runtime.Caller(0)
currentDir := filepath.Dir(currentFile)
// 解析模板文件
globpath := filepath.Join(currentDir, "/*.toml")
Bundle = i18n.NewBundle(language.Chinese)
Bundle.RegisterUnmarshalFunc("toml", toml.Unmarshal)
matches, err := filepath.Glob(globpath)
if err != nil {
panic(err)
}
for _, m := range matches {
Bundle.MustLoadMessageFile(m)
}
// localizer := i18n.NewLocalizer(Bundle, "zh_cn")
// log.Println(localizer.Localize(&i18n.LocalizeConfig{
// MessageID: "format_account_is_insufficient",
// TemplateData: map[string]any{
// "CatalogCurrency": "USDT",
// },
// }))
}
func Localize(MessageID TrCode, Lang string, MessageTemplateParam any) (string, error) {
var localizer = i18n.NewLocalizer(Bundle, Lang)
return localizer.Localize(&i18n.LocalizeConfig{
MessageID: string(MessageID),
TemplateData: MessageTemplateParam,
})
}
func LocalizeEx(MessageID TrCode, MessageTemplateParam any, Langs ...string) (string, error) {
var localizer = i18n.NewLocalizer(Bundle, Langs...)
return localizer.Localize(&i18n.LocalizeConfig{
MessageID: string(MessageID),
TemplateData: MessageTemplateParam,
})
}

View File

@ -0,0 +1,538 @@
package translator
type TrCode string
// 翻译对应的标志字符串ID
const (
// account_disabled
// description: "您的账户已禁用,暂时无法操作" one: "您的账户已禁用,暂时无法操作" other: "您的账户已禁用,暂时无法操作"
AccountDisabled TrCode = "account_disabled"
// account_disabled_not_login
// description: "您的账户已禁用,暂时无法操作" one: "您的账户已禁用,暂时无法操作" other: "您的账户已禁用,暂时无法操作"
AccountDisabledNotLogin TrCode = "account_disabled_not_login"
// account_not_registered
// description: "账户未注册,请注册后再操作" one: "账户未注册,请注册后再操作" other: "账户未注册,请注册后再操作"
AccountNotRegistered TrCode = "account_not_registered"
// account_or_password_login_failed
// description: "账号或密码不正确,登录失败" one: "账号或密码不正确,登录失败" other: "账号或密码不正确,登录失败"
AccountOrPasswordLoginFailed TrCode = "account_or_password_login_failed"
// all_day_transaction
// description: "全天交易" one: "全天交易" other: "全天交易"
AllDayTransaction TrCode = "all_day_transaction"
// application_has_been_submitted
// description: "很抱歉,申请已提交交易所,无法取消" one: "很抱歉,申请已提交交易所,无法取消" other: "很抱歉,申请已提交交易所,无法取消"
ApplicationHasBeenSubmitted TrCode = "application_has_been_submitted"
// apply_cannot_be_cancelled
// description: "该笔申请已封帐无法取消" one: "该笔申请已封帐无法取消" other: "该笔申请已封帐无法取消"
ApplyCannotBeCancelled TrCode = "apply_cannot_be_cancelled"
// balance_return
// description: "(退回)" one: "(退回)" other: "(退回)"
BalanceReturn TrCode = "balance_return"
// balance_role_1
// description: "股票买入" one: "股票买入" other: "股票买入"
BalanceRole1 TrCode = "balance_role_1"
// balance_role_10
// description: "平台分成" one: "平台分成" other: "平台分成"
BalanceRole10 TrCode = "balance_role_10"
// balance_role_11
// description: "出金" one: "出金" other: "出金"
BalanceRole11 TrCode = "balance_role_11"
// balance_role_12
// description: "入金" one: "入金" other: "入金"
BalanceRole12 TrCode = "balance_role_12"
// balance_role_13
// description: "基金申购金额" one: "基金申购金额" other: "基金申购金额"
BalanceRole13 TrCode = "balance_role_13"
// balance_role_14
// description: "基金申购费" one: "基金申购费" other: "基金申购费"
BalanceRole14 TrCode = "balance_role_14"
// balance_role_15
// description: "基金管理费" one: "基金管理费" other: "基金管理费"
BalanceRole15 TrCode = "balance_role_15"
// balance_role_16
// description: "资金补扣" one: "资金补扣" other: "资金补扣"
BalanceRole16 TrCode = "balance_role_16"
// balance_role_17
// description: "资金退还" one: "资金退还" other: "资金退还"
BalanceRole17 TrCode = "balance_role_17"
// balance_role_18
// description: "基金结算获利" one: "基金结算获利" other: "基金结算获利"
BalanceRole18 TrCode = "balance_role_18"
// balance_role_19
// description: "虚拟加金" one: "虚拟加金" other: "虚拟加金"
BalanceRole19 TrCode = "balance_role_19"
// balance_role_2
// description: "买入手续费" one: "买入手续费" other: "买入手续费"
BalanceRole2 TrCode = "balance_role_2"
// balance_role_20
// description: "手动入金" one: "手动入金" other: "手动入金"
BalanceRole20 TrCode = "balance_role_20"
// balance_role_21
// description: "转移资金" one: "转移资金" other: "转移资金"
BalanceRole21 TrCode = "balance_role_21"
// balance_role_22
// description: "推广佣金" one: "推广佣金" other: "推广佣金"
BalanceRole22 TrCode = "balance_role_22"
// balance_role_23
// description: "基金超额管理费" one: "基金超额管理费" other: "基金超额管理费"
BalanceRole23 TrCode = "balance_role_23"
// balance_role_24
// description: "货币转换" one: "货币转换" other: "货币转换"
BalanceRole24 TrCode = "balance_role_24"
// balance_role_25
// description: "配资投资本金" one: "配资投资本金" other: "配资投资本金"
BalanceRole25 TrCode = "balance_role_25"
// balance_role_26
// description: "配资利息" one: "配资利息" other: "配资利息"
BalanceRole26 TrCode = "balance_role_26"
// balance_role_28
// description: "赠金" one: "赠金" other: "赠金"
BalanceRole28 TrCode = "balance_role_28"
// balance_role_3
// description: "股票卖出" one: "股票卖出" other: "股票卖出"
BalanceRole3 TrCode = "balance_role_3"
// balance_role_4
// description: "卖出手续费" one: "卖出手续费" other: "卖出手续费"
BalanceRole4 TrCode = "balance_role_4"
// balance_role_5
// description: "新股申购" one: "新股申购" other: "新股申购"
BalanceRole5 TrCode = "balance_role_5"
// balance_role_6
// description: "新股融资利息" one: "新股融资利息" other: "新股融资利息"
BalanceRole6 TrCode = "balance_role_6"
// balance_role_7
// description: "新股申购手续费" one: "新股申购手续费" other: "新股申购手续费"
BalanceRole7 TrCode = "balance_role_7"
// balance_role_8
// description: "新股中签手续费" one: "新股中签手续费" other: "新股中签手续费"
BalanceRole8 TrCode = "balance_role_8"
// balance_role_9
// description: "国配意向金" one: "国配意向金" other: "国配意向金"
BalanceRole9 TrCode = "balance_role_9"
// buy_success_content_1
// description: "您的交易 " one: "您的交易 " other: "您的交易 "
BuySuccessContent1 TrCode = "buy_success_content_1"
// buy_success_content_2
// description: " 买入 " one: " 买入 " other: " 买入 "
BuySuccessContent2 TrCode = "buy_success_content_2"
// buy_success_content_3
// description: " 已成交" one: " 已成交" other: " 已成交"
BuySuccessContent3 TrCode = "buy_success_content_3"
// buy_success_title
// description: "买入交易已成交" one: "买入交易已成交" other: "买入交易已成交"
BuySuccessTitle TrCode = "buy_success_title"
// category_not_exist
// description: "分类不存在" one: "分类不存在" other: "分类不存在"
CategoryNotExist TrCode = "category_not_exist"
// currency_exchange_status_1
// description: "待处理" one: "待处理" other: "待处理"
CurrencyExchangeStatus1 TrCode = "currency_exchange_status_1"
// currency_exchange_status_2
// description: "转换成功" one: "转换成功" other: "转换成功"
CurrencyExchangeStatus2 TrCode = "currency_exchange_status_2"
// currency_exchange_status_3
// description: "转换失败" one: "转换失败" other: "转换失败"
CurrencyExchangeStatus3 TrCode = "currency_exchange_status_3"
// currency_exchange_status_4
// description: "已取消" one: "已取消" other: "已取消"
CurrencyExchangeStatus4 TrCode = "currency_exchange_status_4"
// current_position_of_the_stock
// description: "股票当前持仓数量" one: "股票当前持仓数量" other: "股票当前持仓数量"
CurrentPositionOfTheStock TrCode = "current_position_of_the_stock"
// currently_only_supports_conversion_hkd
// description: "目前只支持转为港币 HKD $" one: "目前只支持转为港币 HKD $" other: "目前只支持转为港币 HKD $"
CurrentlyOnlySupportsConversionHkd TrCode = "currently_only_supports_conversion_hkd"
// data_not_exist
// description: "数据不存在!" one: "数据不存在!" other: "数据不存在!"
DataNotExist TrCode = "data_not_exist"
// data_not_exist_retry
// description: "数据不存在,请重试!" one: "数据不存在,请重试!" other: "数据不存在,请重试!"
DataNotExistRetry TrCode = "data_not_exist_retry"
// day
// description: "日" one: "日" other: "日"
Day TrCode = "day"
// days_ago
// description: " 天前" one: " 天前" other: " 天前"
DaysAgo TrCode = "days_ago"
// default_trading_time_period
// description: "默认交易时间段" one: "默认交易时间段" other: "默认交易时间段"
DefaultTradingTimePeriod TrCode = "default_trading_time_period"
// email_exchange_title
// description: "资金变动提示" one: "资金变动提示" other: "资金变动提示"
EmailExchangeTitle TrCode = "email_exchange_title"
// email_registered
// description: "邮箱已注册" one: "邮箱已注册" other: "邮箱已注册"
EmailRegistered TrCode = "email_registered"
// email_registered_forget_password
// description: "邮箱已注册,请直接登录,如您忘记登录密码,请找回登录密码" one: "邮箱已注册,请直接登录,如您忘记登录密码,请找回登录密码" other: "邮箱已注册,请直接登录,如您忘记登录密码,请找回登录密码"
EmailRegisteredForgetPassword TrCode = "email_registered_forget_password"
// email_verify_code
// description: "邮箱验证码" one: "邮箱验证码" other: "邮箱验证码"
EmailVerifyCode TrCode = "email_verify_code"
// email_verify_code_wrong
// description: "邮箱验证码不正确" one: "邮箱验证码不正确" other: "邮箱验证码不正确"
EmailVerifyCodeWrong TrCode = "email_verify_code_wrong"
// email_verify_code_wrong_login_fail
// description: "邮箱验证码不正确,登录失败" one: "邮箱验证码不正确,登录失败" other: "邮箱验证码不正确,登录失败"
EmailVerifyCodeWrongLoginFail TrCode = "email_verify_code_wrong_login_fail"
// financing_not_cancel
// description: "很抱歉,融资打新不允许取消" one: "很抱歉,融资打新不允许取消" other: "很抱歉,融资打新不允许取消"
FinancingNotCancel TrCode = "financing_not_cancel"
// format_account_is_insufficient
// description: "账户余额不足,请先入金" one: "{{.CatalogCurrency}} 账户余额不足,请先入金" other: "{{.CatalogCurrency}} 账户余额不足,请先入金"
FormatAccountIsInsufficient TrCode = "format_account_is_insufficient"
// fund_has_been_delisted
// description: "很抱歉,基金已下架,暂时无法申购" one: "很抱歉,基金已下架,暂时无法申购" other: "很抱歉,基金已下架,暂时无法申购"
FundHasBeenDelisted TrCode = "fund_has_been_delisted"
// fund_order_status_1
// description: "已申购" one: "已申购" other: "已申购"
FundOrderStatus1 TrCode = "fund_order_status_1"
// fund_order_status_2
// description: "已取消" one: "已取消" other: "已取消"
FundOrderStatus2 TrCode = "fund_order_status_2"
// fund_order_status_3
// description: "已结算" one: "已结算" other: "已结算"
FundOrderStatus3 TrCode = "fund_order_status_3"
// get_email_verify_code_first
// description: "请先获取邮箱验证码" one: "请先获取邮箱验证码" other: "请先获取邮箱验证码"
GetEmailVerifyCodeFirst TrCode = "get_email_verify_code_first"
// get_phone_number_verify_code_first
// description: "请先获取手机验证码" one: "请先获取手机验证码" other: "请先获取手机验证码"
GetPhoneNumberVerifyCodeFirst TrCode = "get_phone_number_verify_code_first"
// have_a_subscription_record
// description: "您已有该新股的申购记录,不能重复申请" one: "您已有该新股的申购记录,不能重复申请" other: "您已有该新股的申购记录,不能重复申请"
HaveASubscriptionRecord TrCode = "have_a_subscription_record"
// have_an_entrustment_record
// description: "您已有该新股的委托记录,不能重复委托" one: "您已有该新股的委托记录,不能重复委托" other: "您已有该新股的委托记录,不能重复委托"
HaveAnEntrustmentRecord TrCode = "have_an_entrustment_record"
// holding_amount_is_insufficient
// description: ",持有数量不足,无法卖出" one: ",持有数量不足,无法卖出" other: ",持有数量不足,无法卖出"
HoldingAmountIsInsufficient TrCode = "holding_amount_is_insufficient"
// hongkong_account_is_insufficient
// description: "港股账户余额不足,请先入金" one: "港股账户余额不足,请先入金" other: "港股账户余额不足,请先入金"
HongkongAccountIsInsufficient TrCode = "hongkong_account_is_insufficient"
// hongkong_stock_account_not_be_less_than
// description: "融资申购要求港股账户余额不低于" one: "融资申购要求港股账户余额不低于" other: "融资申购要求港股账户余额不低于"
HongkongStockAccountNotBeLessThan TrCode = "hongkong_stock_account_not_be_less_than"
// hours_ago
// description: " 小时前" one: " 小时前" other: " 小时前"
HoursAgo TrCode = "hours_ago"
// in_transaction
// description: "交易中" one: "交易中" other: "交易中"
InTransaction TrCode = "in_transaction"
// incorrect_amount_retry
// description: "金额错误,请重试" one: "金额错误,请重试" other: "金额错误,请重试"
IncorrectAmountRetry TrCode = "incorrect_amount_retry"
// incorrect_security_code_retry
// description: "证券代码错误,请重试" one: "证券代码错误,请重试" other: "证券代码错误,请重试"
IncorrectSecurityCodeRetry TrCode = "incorrect_security_code_retry"
// insufficient_account_balance
// description: "账户余额不足,转换失败" one: "账户余额不足,转换失败" other: "账户余额不足,转换失败"
InsufficientAccountBalance TrCode = "insufficient_account_balance"
// invitation_code_not_exists
// description: "邀请码不存在或有误,请检查后重试" one: "邀请码不存在或有误,请检查后重试" other: "邀请码不存在或有误,请检查后重试"
InvitationCodeNotExists TrCode = "invitation_code_not_exists"
// ipo_cash_commission
// description: "现金委托" one: "现金委托" other: "现金委托"
IpoCashCommission TrCode = "ipo_cash_commission"
// ipo_financing_10_times
// description: "融资10倍" one: "融资10倍" other: "融资10倍"
IpoFinancing10Times TrCode = "ipo_financing_10_times"
// ipo_financing_20_times
// description: "融资20倍" one: "融资20倍" other: "融资20倍"
IpoFinancing20Times TrCode = "ipo_financing_20_times"
// ipo_times
// description: " 倍" one: " 倍" other: " 倍"
IpoTimes TrCode = "ipo_times"
// market_closed_orders_cannot_be_placed
// description: "当前市场休市中,暂不能下单" one: "当前市场休市中,暂不能下单" other: "当前市场休市中,暂不能下单"
MarketClosedOrdersCannotBePlaced TrCode = "market_closed_orders_cannot_be_placed"
// max
// description: "最大" one: "最大" other: "最大"
Max TrCode = "max"
// maximum_number_of_sells
// description: "允许卖出数量最多为" one: "允许卖出数量最多为" other: "允许卖出数量最多为"
MaximumNumberOfSells TrCode = "maximum_number_of_sells"
// minimum_purchase_amount
// description: "申购金额最低" one: "申购金额最低" other: "申购金额最低"
MinimumPurchaseAmount TrCode = "minimum_purchase_amount"
// minutes_ago
// description: " 分钟前" one: " 分钟前" other: " 分钟前"
MinutesAgo TrCode = "minutes_ago"
// month
// description: "月" one: "月" other: "月"
Month TrCode = "month"
// new_shares_do_not_exist
// description: "新股不存在" one: "新股不存在" other: "新股不存在"
NewSharesDoNotExist TrCode = "new_shares_do_not_exist"
// non_default_trading_time_period
// description: "非默认交易时间段" one: "非默认交易时间段" other: "非默认交易时间段"
NonDefaultTradingTimePeriod TrCode = "non_default_trading_time_period"
// non_grey_market_trading_time
// description: "当前为非暗盘交易时间,下单失败" one: "当前为非暗盘交易时间,下单失败" other: "当前为非暗盘交易时间,下单失败"
NonGreyMarketTradingTime TrCode = "non_grey_market_trading_time"
// order_failed_odd_lot_trading
// description: "下单失败,不支持碎股交易" one: "下单失败,不支持碎股交易" other: "下单失败,不支持碎股交易"
OrderFailedOddLotTrading TrCode = "order_failed_odd_lot_trading"
// order_failed_price_cannot_be_higher_than
// description: "下单失败,价格不能高于" one: "下单失败,价格不能高于" other: "下单失败,价格不能高于"
OrderFailedPriceCannotBeHigherThan TrCode = "order_failed_price_cannot_be_higher_than"
// order_failed_price_cannot_be_lower_than
// description: "下单失败,价格不能低于" one: "下单失败,价格不能低于" other: "下单失败,价格不能低于"
OrderFailedPriceCannotBeLowerThan TrCode = "order_failed_price_cannot_be_lower_than"
// order_failed_price_is_incorrect
// description: "下单失败,价格不正确" one: "下单失败,价格不正确" other: "下单失败,价格不正确"
OrderFailedPriceIsIncorrect TrCode = "order_failed_price_is_incorrect"
// order_failed_retry
// description: "下单失败,请重试" one: "下单失败,请重试" other: "下单失败,请重试"
OrderFailedRetry TrCode = "order_failed_retry"
// order_is_not_cancel
// description: "该订单当前不支持撤单" one: "该订单当前不支持撤单" other: "该订单当前不支持撤单"
OrderIsNotCancel TrCode = "order_is_not_cancel"
// order_needs_3_minutes_before
// description: "市价单需要下单3分钟后才能撤单" one: "市价单需要下单3分钟后才能撤单" other: "市价单需要下单3分钟后才能撤单"
OrderNeeds3MinutesBefore TrCode = "order_needs_3_minutes_before"
// other
// description: "其他" one: "其他" other: "其他"
Other TrCode = "other"
// password_match_error
// description: "两次密码不一致" one: "两次密码不一致" other: "两次密码不一致"
PasswordMatchError TrCode = "password_match_error"
// password_match_error_origin
// description: "原始密码不一致" one: "原始密码不一致" other: "原始密码不一致"
PasswordMatchErrorOrigin TrCode = "password_match_error_origin"
// phone_number_country_incorrect
// description: "手机所属国家不正确,请检查" one: "手机所属国家不正确,请检查" other: "手机所属国家不正确,请检查"
PhoneNumberCountryIncorrect TrCode = "phone_number_country_incorrect"
// phone_number_not_registered
// description: "账户未注册,请注册后再操作" one: "账户未注册,请注册后再操作" other: "账户未注册,请注册后再操作"
PhoneNumberNotRegistered TrCode = "phone_number_not_registered"
// phone_number_registered
// description: "手机已注册" one: "手机已注册" other: "手机已注册"
PhoneNumberRegistered TrCode = "phone_number_registered"
// phone_number_registered_forget_password
// description: "手机号已注册,请直接登录,如您忘记登录密码,请找回登录密码" one: "手机号已注册,请直接登录,如您忘记登录密码,请找回登录密码" other: "手机号已注册,请直接登录,如您忘记登录密码,请找回登录密码"
PhoneNumberRegisteredForgetPassword TrCode = "phone_number_registered_forget_password"
// phone_number_verify_code_wrong
// description: "手机验证码不正确" one: "手机验证码不正确" other: "手机验证码不正确"
PhoneNumberVerifyCodeWrong TrCode = "phone_number_verify_code_wrong"
// phone_number_verify_code_wrong_login_fail
// description: "手机验证码不正确,登录失败" one: "手机验证码不正确,登录失败" other: "手机验证码不正确,登录失败"
PhoneNumberVerifyCodeWrongLoginFail TrCode = "phone_number_verify_code_wrong_login_fail"
// please_deposit_first
// description: ",请先入金!" one: ",请先入金!" other: ",请先入金!"
PleaseDepositFirst TrCode = "please_deposit_first"
// pretrade_not_allow_market_order
// description: "盘前交易不支持市价单,请更换重试" one: "盘前交易不支持市价单,请更换重试" other: "盘前交易不支持市价单,请更换重试"
PretradeNotAllowMarketOrder TrCode = "pretrade_not_allow_market_order"
// record_is_not_cancel
// description: "该记录当前已不允许取消" one: "该记录当前已不允许取消" other: "该记录当前已不允许取消"
RecordIsNotCancel TrCode = "record_is_not_cancel"
// record_not_exist
// description: "记录不存在" one: "记录不存在" other: "记录不存在"
RecordNotExist TrCode = "record_not_exist"
// rise
// description: "起" one: "起" other: "起"
Rise TrCode = "rise"
// sell_success_content_1
// description: "您的交易 " one: "您的交易 " other: "您的交易 "
SellSuccessContent1 TrCode = "sell_success_content_1"
// sell_success_content_2
// description: " 卖出 " one: " 卖出 " other: " 卖出 "
SellSuccessContent2 TrCode = "sell_success_content_2"
// sell_success_content_3
// description: " 已成交" one: " 已成交" other: " 已成交"
SellSuccessContent3 TrCode = "sell_success_content_3"
// sell_success_title
// description: "卖出交易已成交" one: "卖出交易已成交" other: "卖出交易已成交"
SellSuccessTitle TrCode = "sell_success_title"
// sms_verify_code_content_1
// description: "你的短讯验证码为:" one: "你的短讯验证码为:" other: "你的短讯验证码为:"
SmsVerifyCodeContent1 TrCode = "sms_verify_code_content_1"
// state_not_cancel
// description: "当前状态不允许取消" one: "当前状态不允许取消" other: "当前状态不允许取消"
StateNotCancel TrCode = "state_not_cancel"
// stock
// description: "股票" one: "股票" other: "股票"
Stock TrCode = "stock"
// stock_insufficient
// description: "您当前未持仓该股票或持仓数量不足,无法卖出" one: "您当前未持仓该股票或持仓数量不足,无法卖出" other: "您当前未持仓该股票或持仓数量不足,无法卖出"
StockInsufficient TrCode = "stock_insufficient"
// stocks_do_not_support_grey_market_trading
// description: "股票不支持暗盘交易" one: "股票不支持暗盘交易" other: "股票不支持暗盘交易"
StocksDoNotSupportGreyMarketTrading TrCode = "stocks_do_not_support_grey_market_trading"
// subscription_deadline_has_passed
// description: "当前已超过认购截止时间!" one: "当前已超过认购截止时间!" other: "当前已超过认购截止时间!"
SubscriptionDeadlineHasPassed TrCode = "subscription_deadline_has_passed"
// subscription_failed_over_purchased
// description: "申购失败,购买超额。基金当前剩余申购额度为:" one: "申购失败,购买超额。基金当前剩余申购额度为:" other: "申购失败,购买超额。基金当前剩余申购额度为:"
SubscriptionFailedOverPurchased TrCode = "subscription_failed_over_purchased"
// text_required
// description: "数据有误" one: "数据有误" other: "数据有误"
TextRequired TrCode = "text_required"
// the_market_is_closed
// description: "休市中" one: "休市中" other: "休市中"
TheMarketIsClosed TrCode = "the_market_is_closed"
// the_market_is_closed_on_weekends
// description: "周末休市中" one: "周末休市中" other: "周末休市中"
TheMarketIsClosedOnWeekends TrCode = "the_market_is_closed_on_weekends"
// the_maximum_quantity_is_limited_to_10_digits
// description: "数量最大限制10位数以内" one: "数量最大限制10位数以内" other: "数量最大限制10位数以内"
TheMaximumQuantityIsLimitedTo10Digits TrCode = "the_maximum_quantity_is_limited_to_10_digits"
// to_be_disclosed
// description: "待公布" one: "待公布" other: "待公布"
ToBeDisclosed TrCode = "to_be_disclosed"
// us_account_is_insufficient
// description: "美股账户余额不足,请先入金" one: "美股账户余额不足,请先入金" other: "美股账户余额不足,请先入金"
UsAccountIsInsufficient TrCode = "us_account_is_insufficient"
// us_stock_account_not_be_less_than
// description: "融资申购要求美股账户余额不低于" one: "融资申购要求美股账户余额不低于" other: "融资申购要求美股账户余额不低于"
UsStockAccountNotBeLessThan TrCode = "us_stock_account_not_be_less_than"
// usdt_account_is_insufficient
// description: "USDT账户余额不足请先入金" one: "USDT账户余额不足请先入金" other: "USDT账户余额不足请先入金"
UsdtAccountIsInsufficient TrCode = "usdt_account_is_insufficient"
// waiting_to_open
// description: "待开盘" one: "待开盘" other: "待开盘"
WaitingToOpen TrCode = "waiting_to_open"
// week
// description: "周" one: "周" other: "周"
Week TrCode = "week"
// withfunding_asset_total_must_large_than_order_total
// description: "下单失败,操盘资金必须大于下单金额" one: "下单失败,操盘资金必须大于下单金额" other: "下单失败,操盘资金必须大于下单金额"
WithfundingAssetTotalMustLargeThanOrderTotal TrCode = "withfunding_asset_total_must_large_than_order_total"
// withfunding_must_all_clear
// description: "下单失败,配资必须全仓卖出" one: "下单失败,配资必须全仓卖出" other: "下单失败,配资必须全仓卖出"
WithfundingMustAllClear TrCode = "withfunding_must_all_clear"
)

View File

@ -0,0 +1,165 @@
package translator
import (
"bytes"
"encoding/json"
"fmt"
"go/format"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"runtime"
"sort"
"strings"
"testing"
"text/template"
"unicode"
"github.com/pelletier/go-toml/v2"
)
var trTemplateStr = `
package translator
type TrCode string
// 翻译对应的标志字符串ID
const (
{{- range .}}
// {{.MessageID}}
// description: "{{.Desc}}" one: "{{.One}}" other: "{{.Other}}"
{{.MessageCamelID}} TrCode = "{{.MessageID}}"
{{end}}
)
`
// type TrCode string
// const (
// a TrCode = "1"
// )
type TrCodeData struct {
MessageID string
MessageCamelID string
Desc string
One string
Other string
}
func TestGenTrCode(t *testing.T) {
_, currentFile, _, _ := runtime.Caller(0)
currentDir := filepath.Dir(currentFile)
// 解析模板文件
tfile := filepath.Join(currentDir, "/zh_cn.toml")
createTrCode(tfile)
// log.Println(string(buf.Bytes()))
}
func createTrCode(filePath string) {
tomlFile, err := os.Open(filePath)
if err != nil {
panic(err)
}
var tomlMap map[string]any
err = toml.NewDecoder(tomlFile).Decode(&tomlMap)
if err != nil {
panic(err)
}
var datas []*TrCodeData
for key, valuesMap := range tomlMap {
values := valuesMap.(map[string]any)
data := &TrCodeData{}
data.MessageID = key
data.MessageCamelID = toCamelCase(key)
data.Desc = values["description"].(string)
data.One = values["one"].(string)
data.Other = values["other"].(string)
datas = append(datas, data)
}
sort.Slice(datas, func(i, j int) bool {
return datas[i].MessageID < datas[j].MessageID
})
tpl := template.New("translator")
tpl.Parse(trTemplateStr)
var buf bytes.Buffer
err = tpl.Execute(&buf, datas)
if err != nil {
panic(err)
}
wdata, err := format.Source(buf.Bytes())
if err != nil {
panic(err)
}
err = os.WriteFile("./translator_gen.go", wdata, 0644)
if err != nil {
panic(err)
}
}
type TranslateRequest struct {
Q string `json:"q"`
Source string `json:"source"`
Target string `json:"target"`
}
type TranslateResponse struct {
TranslatedText string `json:"translatedText"`
}
func TestTrOnline(t *testing.T) {
requestBody, err := json.Marshal(TranslateRequest{
Q: "Hello!",
Source: "en",
Target: "es",
})
if err != nil {
fmt.Println("Error marshaling request body:", err)
return
}
resp, err := http.Post("https://libretranslate.com/translate", "application/json", bytes.NewBuffer(requestBody))
if err != nil {
fmt.Println("Error sending request:", err)
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
fmt.Println("Error reading response body:", err)
return
}
var translationResponse TranslateResponse
err = json.Unmarshal(body, &translationResponse)
if err != nil {
fmt.Println("Error unmarshaling response:", err)
return
}
fmt.Println(translationResponse.TranslatedText)
}
func toCamelCase(s string) string {
var sb strings.Builder
capitalizeNext := true
for _, r := range s {
if r == '_' || r == '/' || r == '-' {
capitalizeNext = true
} else if capitalizeNext {
sb.WriteRune(unicode.ToUpper(r))
capitalizeNext = false
} else {
sb.WriteRune(unicode.ToLower(r))
}
}
return sb.String()
}

555
translator/zh_cn.toml Normal file
View File

@ -0,0 +1,555 @@
[email_verify_code]
description = "邮箱验证码"
one = "邮箱验证码"
other = "邮箱验证码"
[get_email_verify_code_first]
description = "请先获取邮箱验证码"
one = "请先获取邮箱验证码"
other = "请先获取邮箱验证码"
[email_verify_code_wrong]
description = "邮箱验证码不正确"
one = "邮箱验证码不正确"
other = "邮箱验证码不正确"
[email_verify_code_wrong_login_fail]
description = "邮箱验证码不正确,登录失败"
one = "邮箱验证码不正确,登录失败"
other = "邮箱验证码不正确,登录失败"
[email_registered]
description = "邮箱已注册"
one = "邮箱已注册"
other = "邮箱已注册"
[email_registered_forget_password]
description = "邮箱已注册,请直接登录,如您忘记登录密码,请找回登录密码"
one = "邮箱已注册,请直接登录,如您忘记登录密码,请找回登录密码"
other = "邮箱已注册,请直接登录,如您忘记登录密码,请找回登录密码"
[invitation_code_not_exists]
description = "邀请码不存在或有误,请检查后重试"
one = "邀请码不存在或有误,请检查后重试"
other = "邀请码不存在或有误,请检查后重试"
[password_match_error]
description = "两次密码不一致"
one = "两次密码不一致"
other = "两次密码不一致"
[account_not_registered]
description = "账户未注册,请注册后再操作"
one = "账户未注册,请注册后再操作"
other = "账户未注册,请注册后再操作"
[account_disabled]
description = "您的账户已禁用,暂时无法操作"
one = "您的账户已禁用,暂时无法操作"
other = "您的账户已禁用,暂时无法操作"
[phone_number_not_registered]
description = "账户未注册,请注册后再操作"
one = "账户未注册,请注册后再操作"
other = "账户未注册,请注册后再操作"
[phone_number_country_incorrect]
description = "手机所属国家不正确,请检查"
one = "手机所属国家不正确,请检查"
other = "手机所属国家不正确,请检查"
[phone_number_verify_code_wrong]
description = "手机验证码不正确"
one = "手机验证码不正确"
other = "手机验证码不正确"
[phone_number_registered]
description = "手机已注册"
one = "手机已注册"
other = "手机已注册"
[phone_number_registered_forget_password]
description = "手机号已注册,请直接登录,如您忘记登录密码,请找回登录密码"
one = "手机号已注册,请直接登录,如您忘记登录密码,请找回登录密码"
other = "手机号已注册,请直接登录,如您忘记登录密码,请找回登录密码"
[get_phone_number_verify_code_first]
description = "请先获取手机验证码"
one = "请先获取手机验证码"
other = "请先获取手机验证码"
[phone_number_verify_code_wrong_login_fail]
description = "手机验证码不正确,登录失败"
one = "手机验证码不正确,登录失败"
other = "手机验证码不正确,登录失败"
[account_disabled_not_login]
description = "您的账户已禁用,暂时无法操作"
one = "您的账户已禁用,暂时无法操作"
other = "您的账户已禁用,暂时无法操作"
[account_or_password_login_failed]
description = "账号或密码不正确,登录失败"
one = "账号或密码不正确,登录失败"
other = "账号或密码不正确,登录失败"
[record_not_exist]
description = "记录不存在"
one = "记录不存在"
other = "记录不存在"
[category_not_exist]
description = "分类不存在"
one = "分类不存在"
other = "分类不存在"
[data_not_exist]
description = "数据不存在!"
one = "数据不存在!"
other = "数据不存在!"
[data_not_exist_retry]
description = "数据不存在,请重试!"
one = "数据不存在,请重试!"
other = "数据不存在,请重试!"
[new_shares_do_not_exist]
description = "新股不存在"
one = "新股不存在"
other = "新股不存在"
[state_not_cancel]
description = "当前状态不允许取消"
one = "当前状态不允许取消"
other = "当前状态不允许取消"
[apply_cannot_be_cancelled]
description = "该笔申请已封帐无法取消"
one = "该笔申请已封帐无法取消"
other = "该笔申请已封帐无法取消"
[financing_not_cancel]
description = "很抱歉,融资打新不允许取消"
one = "很抱歉,融资打新不允许取消"
other = "很抱歉,融资打新不允许取消"
[application_has_been_submitted]
description = "很抱歉,申请已提交交易所,无法取消"
one = "很抱歉,申请已提交交易所,无法取消"
other = "很抱歉,申请已提交交易所,无法取消"
[fund_has_been_delisted]
description = "很抱歉,基金已下架,暂时无法申购"
one = "很抱歉,基金已下架,暂时无法申购"
other = "很抱歉,基金已下架,暂时无法申购"
[subscription_failed_over_purchased]
description = "申购失败,购买超额。基金当前剩余申购额度为:"
one = "申购失败,购买超额。基金当前剩余申购额度为:"
other = "申购失败,购买超额。基金当前剩余申购额度为:"
[minimum_purchase_amount]
description = "申购金额最低"
one = "申购金额最低"
other = "申购金额最低"
[rise]
description = "起"
one = "起"
other = "起"
[hongkong_account_is_insufficient]
description = "港股账户余额不足,请先入金"
one = "港股账户余额不足,请先入金"
other = "港股账户余额不足,请先入金"
[us_account_is_insufficient]
description = "美股账户余额不足,请先入金"
one = "美股账户余额不足,请先入金"
other = "美股账户余额不足,请先入金"
[usdt_account_is_insufficient]
description = "USDT账户余额不足请先入金"
one = "USDT账户余额不足请先入金"
other = "USDT账户余额不足请先入金"
[format_account_is_insufficient]
description = "账户余额不足,请先入金"
one = "{{.CatalogCurrency}} 账户余额不足,请先入金"
other = "{{.CatalogCurrency}} 账户余额不足,请先入金"
[subscription_deadline_has_passed]
description = "当前已超过认购截止时间!"
one = "当前已超过认购截止时间!"
other = "当前已超过认购截止时间!"
[have_a_subscription_record]
description = "您已有该新股的申购记录,不能重复申请"
one = "您已有该新股的申购记录,不能重复申请"
other = "您已有该新股的申购记录,不能重复申请"
[hongkong_stock_account_not_be_less_than]
description = "融资申购要求港股账户余额不低于"
one = "融资申购要求港股账户余额不低于"
other = "融资申购要求港股账户余额不低于"
[us_stock_account_not_be_less_than]
description = "融资申购要求美股账户余额不低于"
one = "融资申购要求美股账户余额不低于"
other = "融资申购要求美股账户余额不低于"
[please_deposit_first]
description = ",请先入金!"
one = ",请先入金!"
other = ",请先入金!"
[incorrect_amount_retry]
description = "金额错误,请重试"
one = "金额错误,请重试"
other = "金额错误,请重试"
[have_an_entrustment_record]
description = "您已有该新股的委托记录,不能重复委托"
one = "您已有该新股的委托记录,不能重复委托"
other = "您已有该新股的委托记录,不能重复委托"
[currently_only_supports_conversion_hkd]
description = "目前只支持转为港币 HKD $"
one = "目前只支持转为港币 HKD $"
other = "目前只支持转为港币 HKD $"
[insufficient_account_balance]
description = "账户余额不足,转换失败"
one = "账户余额不足,转换失败"
other = "账户余额不足,转换失败"
[record_is_not_cancel]
description = "该记录当前已不允许取消"
one = "该记录当前已不允许取消"
other = "该记录当前已不允许取消"
[order_needs_3_minutes_before]
description = "市价单需要下单3分钟后才能撤单"
one = "市价单需要下单3分钟后才能撤单"
other = "市价单需要下单3分钟后才能撤单"
[order_is_not_cancel]
description = "该订单当前不支持撤单"
one = "该订单当前不支持撤单"
other = "该订单当前不支持撤单"
[order_failed_retry]
description = "下单失败,请重试"
one = "下单失败,请重试"
other = "下单失败,请重试"
[market_closed_orders_cannot_be_placed]
description = "当前市场休市中,暂不能下单"
one = "当前市场休市中,暂不能下单"
other = "当前市场休市中,暂不能下单"
[incorrect_security_code_retry]
description = "证券代码错误,请重试"
one = "证券代码错误,请重试"
other = "证券代码错误,请重试"
[stock]
description = "股票"
one = "股票"
other = "股票"
[order_failed_odd_lot_trading]
description = "下单失败,不支持碎股交易"
one = "下单失败,不支持碎股交易"
other = "下单失败,不支持碎股交易"
[withfunding_asset_total_must_large_than_order_total]
description = "下单失败,操盘资金必须大于下单金额"
one = "下单失败,操盘资金必须大于下单金额"
other = "下单失败,操盘资金必须大于下单金额"
[order_failed_price_cannot_be_lower_than]
description = "下单失败,价格不能低于"
one = "下单失败,价格不能低于"
other = "下单失败,价格不能低于"
[order_failed_price_cannot_be_higher_than]
description = "下单失败,价格不能高于"
one = "下单失败,价格不能高于"
other = "下单失败,价格不能高于"
[order_failed_price_is_incorrect]
description = "下单失败,价格不正确"
one = "下单失败,价格不正确"
other = "下单失败,价格不正确"
[stock_insufficient]
description = "您当前未持仓该股票或持仓数量不足,无法卖出"
one = "您当前未持仓该股票或持仓数量不足,无法卖出"
other = "您当前未持仓该股票或持仓数量不足,无法卖出"
[current_position_of_the_stock]
description = "股票当前持仓数量"
one = "股票当前持仓数量"
other = "股票当前持仓数量"
[holding_amount_is_insufficient]
description = ",持有数量不足,无法卖出"
one = ",持有数量不足,无法卖出"
other = ",持有数量不足,无法卖出"
[maximum_number_of_sells]
description = "允许卖出数量最多为"
one = "允许卖出数量最多为"
other = "允许卖出数量最多为"
[stocks_do_not_support_grey_market_trading]
description = "股票不支持暗盘交易"
one = "股票不支持暗盘交易"
other = "股票不支持暗盘交易"
[non_grey_market_trading_time]
description = "当前为非暗盘交易时间,下单失败"
one = "当前为非暗盘交易时间,下单失败"
other = "当前为非暗盘交易时间,下单失败"
[pretrade_not_allow_market_order]
description = "盘前交易不支持市价单,请更换重试"
one = "盘前交易不支持市价单,请更换重试"
other = "盘前交易不支持市价单,请更换重试"
[text_required]
description = "数据有误"
one = "数据有误"
other = "数据有误"
[days_ago]
description = " 天前"
one = " 天前"
other = " 天前"
[hours_ago]
description = " 小时前"
one = " 小时前"
other = " 小时前"
[minutes_ago]
description = " 分钟前"
one = " 分钟前"
other = " 分钟前"
[balance_role_1]
description = "股票买入"
one = "股票买入"
other = "股票买入"
[balance_role_2]
description = "买入手续费"
one = "买入手续费"
other = "买入手续费"
[balance_role_3]
description = "股票卖出"
one = "股票卖出"
other = "股票卖出"
[balance_role_4]
description = "卖出手续费"
one = "卖出手续费"
other = "卖出手续费"
[balance_role_5]
description = "新股申购"
one = "新股申购"
other = "新股申购"
[balance_role_6]
description = "新股融资利息"
one = "新股融资利息"
other = "新股融资利息"
[balance_role_7]
description = "新股申购手续费"
one = "新股申购手续费"
other = "新股申购手续费"
[balance_role_8]
description = "新股中签手续费"
one = "新股中签手续费"
other = "新股中签手续费"
[balance_role_9]
description = "国配意向金"
one = "国配意向金"
other = "国配意向金"
[balance_role_10]
description = "平台分成"
one = "平台分成"
other = "平台分成"
[balance_role_11]
description = "出金"
one = "出金"
other = "出金"
[balance_role_12]
description = "入金"
one = "入金"
other = "入金"
[balance_role_13]
description = "基金申购金额"
one = "基金申购金额"
other = "基金申购金额"
[balance_role_14]
description = "基金申购费"
one = "基金申购费"
other = "基金申购费"
[balance_role_15]
description = "基金管理费"
one = "基金管理费"
other = "基金管理费"
[balance_role_16]
description = "资金补扣"
one = "资金补扣"
other = "资金补扣"
[balance_role_17]
description = "资金退还"
one = "资金退还"
other = "资金退还"
[balance_role_18]
description = "基金结算获利"
one = "基金结算获利"
other = "基金结算获利"
[balance_role_19]
description = "虚拟加金"
one = "虚拟加金"
other = "虚拟加金"
[balance_role_20]
description = "手动入金"
one = "手动入金"
other = "手动入金"
[balance_role_21]
description = "转移资金"
one = "转移资金"
other = "转移资金"
[balance_role_22]
description = "推广佣金"
one = "推广佣金"
other = "推广佣金"
[balance_role_23]
description = "基金超额管理费"
one = "基金超额管理费"
other = "基金超额管理费"
[balance_role_24]
description = "货币转换"
one = "货币转换"
other = "货币转换"
[balance_role_25]
description = "配资投资本金"
one = "配资投资本金"
other = "配资投资本金"
[balance_role_26]
description = "配资利息"
one = "配资利息"
other = "配资利息"
[balance_role_28]
description = "赠金"
one = "赠金"
other = "赠金"
[balance_return]
description = "(退回)"
one = "(退回)"
other = "(退回)"
[day]
description = "日"
one = "日"
other = "日"
[week]
description = "周"
one = "周"
other = "周"
[month]
description = "月"
one = "月"
other = "月"
[fund_order_status_1]
description = "已申购"
one = "已申购"
other = "已申购"
[fund_order_status_2]
description = "已取消"
one = "已取消"
other = "已取消"
[fund_order_status_3]
description = "已结算"
one = "已结算"
other = "已结算"
[withfunding_must_all_clear]
description = "下单失败,配资必须全仓卖出"
one = "下单失败,配资必须全仓卖出"
other = "下单失败,配资必须全仓卖出"
[sell_success_title]
description = "卖出交易已成交"
one = "卖出交易已成交"
other = "卖出交易已成交"
[sell_success_content_1]
description = "您的交易 "
one = "您的交易 "
other = "您的交易 "
[sell_success_content_2]
description = " 卖出 "
one = " 卖出 "
other = " 卖出 "
[sell_success_content_3]
description = " 已成交"
one = " 已成交"
other = " 已成交"
[buy_success_title]
description = "买入交易已成交"
one = "买入交易已成交"
other = "买入交易已成交"
[buy_success_content_1]
description = "您的交易 "
one = "您的交易 "
other = "您的交易 "
[buy_success_content_2]
description = " 买入 "
one = " 买入 "
other = " 买入 "
[buy_success_content_3]
description = " 已成交"
one = " 已成交"
other = " 已成交"
[sms_verify_code_content_1]
description = "你的短讯验证码为:"
one = "你的短讯验证码为:"
other = "你的短讯验证码为:"
[email_exchange_title]
description = "资金变动提示"
one = "资金变动提示"
other = "资金变动提示"
[currency_exchange_status_1]
description = "待处理"
one = "待处理"
other = "待处理"
[currency_exchange_status_2]
description = "转换成功"
one = "转换成功"
other = "转换成功"
[currency_exchange_status_3]
description = "转换失败"
one = "转换失败"
other = "转换失败"
[currency_exchange_status_4]
description = "已取消"
one = "已取消"
other = "已取消"
[to_be_disclosed]
description = "待公布"
one = "待公布"
other = "待公布"
[ipo_times]
description = " 倍"
one = " 倍"
other = " 倍"
[ipo_cash_commission]
description = "现金委托"
one = "现金委托"
other = "现金委托"
[password_match_error_origin]
description = "原始密码不一致"
one = "原始密码不一致"
other = "原始密码不一致"
[ipo_financing_10_times]
description = "融资10倍"
one = "融资10倍"
other = "融资10倍"
[ipo_financing_20_times]
description = "融资20倍"
one = "融资20倍"
other = "融资20倍"
[other]
description = "其他"
one = "其他"
other = "其他"
[max]
description = "最大"
one = "最大"
other = "最大"
[the_maximum_quantity_is_limited_to_10_digits]
description = "数量最大限制10位数以内"
one = "数量最大限制10位数以内"
other = "数量最大限制10位数以内"
[waiting_to_open]
description = "待开盘"
one = "待开盘"
other = "待开盘"
[the_market_is_closed_on_weekends]
description = "周末休市中"
one = "周末休市中"
other = "周末休市中"
[the_market_is_closed]
description = "休市中"
one = "休市中"
other = "休市中"
[in_transaction]
description = "交易中"
one = "交易中"
other = "交易中"
[default_trading_time_period]
description = "默认交易时间段"
one = "默认交易时间段"
other = "默认交易时间段"
[non_default_trading_time_period]
description = "非默认交易时间段"
one = "非默认交易时间段"
other = "非默认交易时间段"
[all_day_transaction]
description = "全天交易"
one = "全天交易"
other = "全天交易"
# 新增规范翻译
# ["账号未注册"]
# description = "账号未注册"
# one = "账号未注册"
# other = "账号未注册"

0
translator/zh_hk.toml Normal file
View File

27
utils/basic/lang.go Normal file
View File

@ -0,0 +1,27 @@
package basic
import "reflect"
func GetLangString(param any) string {
// 获取参数的反射值
value := reflect.ValueOf(param)
// 如果参数是指针,则获取指针指向的值
if value.Kind() == reflect.Ptr {
value = value.Elem()
}
// 如果参数是结构体
if value.Kind() == reflect.Struct {
// 通过字段名获取字段值
langField := value.FieldByName("Lang")
// 如果字段存在并且是字符串类型
if langField.IsValid() && langField.Kind() == reflect.String {
return langField.String()
}
}
// 如果无法获取有效的字符串值则返回zh_cn
return "zh_cn"
}

View File

@ -1,6 +1,9 @@
package basic
import "github.com/iapologizewhenimwrong/Vestmore_GO/utils/log"
import (
"github.com/iapologizewhenimwrong/Vestmore_GO/translator"
"github.com/iapologizewhenimwrong/Vestmore_GO/utils/log"
)
// 全局返回的结构体
type Response struct {
@ -10,6 +13,10 @@ type Response struct {
IsSuccess bool `json:"success"`
}
type ILocalize interface {
Localize(MessageID translator.TrCode) (string, error)
}
func (resp *Response) Error(errcode *ErrorCode, Data ...interface{}) *Response {
if resp == nil {
resp = &Response{}
@ -46,6 +53,20 @@ func (resp *Response) ErrorMsg(Code int, Message string, Data ...interface{}) *R
return resp
}
// 实现翻译返回错误的代码
func (resp *Response) ErrorTrCode(il ILocalize, trcode translator.TrCode, Data ...interface{}) *Response {
if resp == nil {
resp = &Response{}
}
trStr, err := il.Localize(trcode)
if err != nil {
return resp.ErrorErr(1, err)
}
return resp.ErrorMsg(1, trStr)
}
func (resp *Response) Success(Data ...interface{}) *Response {
if resp == nil {
resp = &Response{}