diff --git a/routing.go b/routing.go index b6cb4f1..b189a5a 100644 --- a/routing.go +++ b/routing.go @@ -10,15 +10,43 @@ import ( "regexp" "github.com/getsentry/raven-go" + "github.com/nicksnyder/go-i18n/v2/i18n" "github.com/retailcrm/api-client-go/v5" "github.com/retailcrm/mg-transport-api-client-go/v1" + "golang.org/x/text/language" + "gopkg.in/yaml.v2" ) var ( - templates = template.Must(template.ParseFiles("templates/form.html", "templates/home.html")) + templates = template.Must(template.ParseFiles("templates/header.html", "templates/form.html", "templates/home.html")) validPath = regexp.MustCompile("^/(save|settings)/([a-zA-Z0-9]+)$") + localizer *i18n.Localizer + bundle = &i18n.Bundle{DefaultLanguage: language.English} + matcher = language.NewMatcher([]language.Tag{ + language.English, + language.Russian, + language.Spanish, + }) ) +func init() { + bundle.RegisterUnmarshalFunc("yml", yaml.Unmarshal) + files, err := ioutil.ReadDir("translate") + if err != nil { + logger.Error(err) + } + for _, f := range files { + if !f.IsDir() { + bundle.MustLoadMessageFile("translate/" + f.Name()) + } + } +} + +func setLocale(al string) { + tag, _ := language.MatchStrings(matcher, al) + localizer = i18n.NewLocalizer(bundle, tag.String()) +} + // Response struct type Response struct { Success bool `json:"success"` @@ -53,8 +81,19 @@ func makeHandler(fn func(http.ResponseWriter, *http.Request, string)) http.Handl } func connectHandler(w http.ResponseWriter, r *http.Request) { + setLocale(r.Header.Get("Accept-Language")) p := Connection{} - renderTemplate(w, "home", &p) + + res := struct { + Conn *Connection + Locale map[string]interface{} + }{ + &p, + map[string]interface{}{ + "ButConnect": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "but_connect"}), + }, + } + renderTemplate(w, "home", &res) } func addBotHandler(w http.ResponseWriter, r *http.Request) { @@ -73,13 +112,13 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { } if b.Token == "" { - http.Error(w, "set bot token", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "no_bot_token"}), http.StatusInternalServerError) return } cl, _ := getBotByToken(b.Token) if cl.ID != 0 { - http.Error(w, "bot already created", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "bot_already_created"}), http.StatusInternalServerError) return } @@ -94,13 +133,13 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { c, err := getConnection(b.ClientID) if err != nil { - http.Error(w, "could not find account, please contact technical support", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) logger.Error(b.ClientID, err.Error()) return } if c.MGURL == "" || c.MGToken == "" { - http.Error(w, "could not find account, please contact technical support", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) logger.Error(b.ClientID) return } @@ -118,7 +157,7 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { var client = v1.New(c.MGURL, c.MGToken) data, status, err := client.ActivateTransportChannel(ch) if status != http.StatusCreated { - http.Error(w, "error while activating the channel", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_activating_channel"}), http.StatusInternalServerError) logger.Error(c.APIURL, status, err.Error(), data) return } @@ -133,7 +172,9 @@ func addBotHandler(w http.ResponseWriter, r *http.Request) { return } + jsonString, _ := json.Marshal(b) w.WriteHeader(http.StatusCreated) + w.Write(jsonString) } func activityBotHandler(w http.ResponseWriter, r *http.Request) { @@ -164,14 +205,14 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { c, err := getConnection(b.ClientID) if err != nil { - http.Error(w, "could not find account, please contact technical support", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) logger.Error(b.ClientID, err.Error()) return } if c.MGURL == "" || c.MGToken == "" { - http.Error(w, "could not find account, please contact technical support", http.StatusInternalServerError) - logger.Error(b.ClientID, "could not find account, please contact technical support") + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "not_find_account"}), http.StatusInternalServerError) + logger.Error(b.ClientID, "not find account") return } @@ -180,14 +221,14 @@ func activityBotHandler(w http.ResponseWriter, r *http.Request) { if b.Active { data, status, err := client.DeactivateTransportChannel(ch.ID) if status > http.StatusOK { - http.Error(w, "error while deactivating the channel", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_deactivating_channel"}), http.StatusInternalServerError) logger.Error(b.ClientID, status, err.Error(), data) return } } else { data, status, err := client.ActivateTransportChannel(ch) if status > http.StatusCreated { - http.Error(w, "error while activating the channel", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_activating_channel"}), http.StatusInternalServerError) logger.Error(b.ClientID, status, err.Error(), data) return } @@ -228,6 +269,8 @@ func mappingHandler(w http.ResponseWriter, r *http.Request) { } func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { + setLocale(r.Header.Get("Accept-Language")) + p, err := getConnection(uid) if err != nil { raven.CaptureErrorAndWait(err, nil) @@ -246,13 +289,25 @@ func settingsHandler(w http.ResponseWriter, r *http.Request, uid string) { sites, _, _ := client.Sites() res := struct { - Conn *Connection - Bots Bots - Sites map[string]v5.Site + Conn *Connection + Bots Bots + Sites map[string]v5.Site + Locale map[string]interface{} }{ p, bots, sites.Sites, + map[string]interface{}{ + "ButConnect": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "but_connect"}), + "TabSettings": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "tab_settings"}), + "TabBots": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "tab_bots"}), + "TabMapping": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "tab_mapping"}), + "TableName": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "table_name"}), + "TableToken": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "table_token"}), + "TableActivity": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "table_activity"}), + "MapSites": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "map_sites"}), + "MapOption": localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "map_option"}), + }, } renderTemplate(w, "form", res) @@ -292,6 +347,7 @@ func saveHandler(w http.ResponseWriter, r *http.Request) { } func createHandler(w http.ResponseWriter, r *http.Request) { + setLocale(r.Header.Get("Accept-Language")) c := Connection{ ClientID: GenerateToken(), APIURL: string([]byte(r.FormValue("api_url"))), @@ -307,7 +363,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { cl, _ := getConnectionByURL(c.APIURL) if cl.ID != 0 { - http.Error(w, "connection already created", http.StatusBadRequest) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "connection_already_created"}), http.StatusBadRequest) return } @@ -315,13 +371,13 @@ func createHandler(w http.ResponseWriter, r *http.Request) { cr, status, errr := client.APICredentials() if errr.RuntimeErr != nil { - http.Error(w, "set correct crm url or key", http.StatusBadRequest) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_url_key"}), http.StatusBadRequest) logger.Error(c.APIURL, status, err.Error(), cr) return } if !cr.Success { - http.Error(w, "set correct crm url or key", http.StatusBadRequest) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_url_key"}), http.StatusBadRequest) logger.Error(c.APIURL, status, err.Error(), cr) return } @@ -351,7 +407,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { data, status, errr := client.IntegrationModuleEdit(integration) if errr.RuntimeErr != nil { - http.Error(w, "error while creating integration", http.StatusBadRequest) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_integration"}), http.StatusBadRequest) logger.Error(c.APIURL, status, errr.RuntimeErr, data) return } @@ -368,7 +424,7 @@ func createHandler(w http.ResponseWriter, r *http.Request) { err = c.createConnection() if err != nil { raven.CaptureErrorAndWait(err, nil) - http.Error(w, "error while creating connection", http.StatusInternalServerError) + http.Error(w, localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "error_creating_connection"}), http.StatusInternalServerError) return } @@ -381,7 +437,7 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { res := Response{Success: false} if r.Method != http.MethodPost { - res.Error = "set POST" + res.Error = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "set_method"}) jsonString, _ := json.Marshal(res) w.Write(jsonString) return @@ -390,7 +446,7 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { body, err := ioutil.ReadAll(r.Body) if err != nil { raven.CaptureErrorAndWait(err, nil) - res.Error = "incorrect data" + res.Error = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_data"}) jsonString, _ := json.Marshal(res) w.Write(jsonString) return @@ -401,7 +457,7 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { err = json.Unmarshal(body, &rec) if err != nil { raven.CaptureErrorAndWait(err, nil) - res.Error = "incorrect data" + res.Error = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_data"}) jsonString, _ := json.Marshal(res) w.Write(jsonString) return @@ -409,7 +465,7 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { if err := rec.setConnectionActivity(); err != nil { raven.CaptureErrorAndWait(err, nil) - res.Error = "incorrect data" + res.Error = localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_data"}) jsonString, _ := json.Marshal(res) w.Write(jsonString) return @@ -422,11 +478,11 @@ func activityHandler(w http.ResponseWriter, r *http.Request) { func validate(c Connection) error { if c.APIURL == "" || c.APIKEY == "" { - return errors.New("missing crm url or key") + return errors.New(localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "missing_url_key"})) } if res, _ := regexp.MatchString(`https://?[\da-z\.-]+\.(retailcrm\.(ru|pro)|ecomlogic\.com)`, c.APIURL); !res { - return errors.New("set correct crm url") + return errors.New(localizer.MustLocalize(&i18n.LocalizeConfig{MessageID: "incorrect_url"})) } return nil diff --git a/run.go b/run.go index 7d6b0a7..34fe7d8 100644 --- a/run.go +++ b/run.go @@ -49,5 +49,6 @@ func (x *RunCommand) Execute(args []string) error { func start() { setWrapperRoutes() setTransportRoutes() + http.Handle("/web/", http.StripPrefix("/web/", http.FileServer(http.Dir("web")))) http.ListenAndServe(config.HTTPServer.Listen, nil) } diff --git a/templates/form.html b/templates/form.html index c8c74b8..e514fd2 100644 --- a/templates/form.html +++ b/templates/form.html @@ -1,20 +1,11 @@ - -
- - - - - - - - +{{template "header"}}