summaryrefslogtreecommitdiffstats
path: root/api
diff options
context:
space:
mode:
Diffstat (limited to 'api')
-rw-r--r--api/admin.go12
-rw-r--r--api/admin_test.go70
-rw-r--r--api/api.go11
-rw-r--r--api/context.go11
-rw-r--r--api/export.go2
-rw-r--r--api/file.go79
-rw-r--r--api/import.go9
-rw-r--r--api/license.go29
-rw-r--r--api/oauth.go26
-rw-r--r--api/post.go136
-rw-r--r--api/preference.go9
-rw-r--r--api/server.go18
-rw-r--r--api/slackimport.go41
-rw-r--r--api/team.go102
-rw-r--r--api/templates/email_change_body.html4
-rw-r--r--api/templates/email_change_subject.html2
-rw-r--r--api/templates/email_change_verify_body.html6
-rw-r--r--api/templates/email_change_verify_subject.html2
-rw-r--r--api/templates/email_footer.html2
-rw-r--r--api/templates/email_info.html4
-rw-r--r--api/templates/error.html8
-rw-r--r--api/templates/find_teams_body.html10
-rw-r--r--api/templates/find_teams_subject.html2
-rw-r--r--api/templates/invite_body.html8
-rw-r--r--api/templates/invite_subject.html2
-rw-r--r--api/templates/password_change_body.html4
-rw-r--r--api/templates/password_change_subject.html2
-rw-r--r--api/templates/post_body.html6
-rw-r--r--api/templates/post_subject.html2
-rw-r--r--api/templates/reset_body.html6
-rw-r--r--api/templates/reset_subject.html2
-rw-r--r--api/templates/signin_change_body.html4
-rw-r--r--api/templates/signin_change_subject.html2
-rw-r--r--api/templates/signup_team_body.html6
-rw-r--r--api/templates/signup_team_subject.html2
-rw-r--r--api/templates/verify_body.html6
-rw-r--r--api/templates/verify_subject.html2
-rw-r--r--api/templates/welcome_body.html10
-rw-r--r--api/templates/welcome_subject.html2
-rw-r--r--api/user.go299
-rw-r--r--api/web_conn.go7
-rw-r--r--api/web_hub.go3
-rw-r--r--api/web_socket.go7
-rw-r--r--api/web_team_hub.go3
-rw-r--r--api/webhook.go24
45 files changed, 582 insertions, 422 deletions
diff --git a/api/admin.go b/api/admin.go
index bdacb3afb..b19772fdf 100644
--- a/api/admin.go
+++ b/api/admin.go
@@ -27,6 +27,7 @@ func InitAdmin(r *mux.Router) {
sr.Handle("/client_props", ApiAppHandler(getClientConfig)).Methods("GET")
sr.Handle("/log_client", ApiAppHandler(logClient)).Methods("POST")
sr.Handle("/analytics/{id:[A-Za-z0-9]+}/{name:[A-Za-z0-9_]+}", ApiAppHandler(getAnalytics)).Methods("GET")
+ sr.Handle("/analytics/{name:[A-Za-z0-9_]+}", ApiAppHandler(getAnalytics)).Methods("GET")
}
func getLogs(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -153,13 +154,15 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
name := params["name"]
if name == "standard" {
- var rows model.AnalyticsRows = make([]*model.AnalyticsRow, 3)
+ var rows model.AnalyticsRows = make([]*model.AnalyticsRow, 4)
rows[0] = &model.AnalyticsRow{"channel_open_count", 0}
rows[1] = &model.AnalyticsRow{"channel_private_count", 0}
rows[2] = &model.AnalyticsRow{"post_count", 0}
+ rows[3] = &model.AnalyticsRow{"unique_user_count", 0}
openChan := Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_OPEN)
privateChan := Srv.Store.Channel().AnalyticsTypeCount(teamId, model.CHANNEL_PRIVATE)
postChan := Srv.Store.Post().AnalyticsPostCount(teamId)
+ userChan := Srv.Store.User().AnalyticsUniqueUserCount(teamId)
if r := <-openChan; r.Err != nil {
c.Err = r.Err
@@ -182,6 +185,13 @@ func getAnalytics(c *Context, w http.ResponseWriter, r *http.Request) {
rows[2].Value = float64(r.Data.(int64))
}
+ if r := <-userChan; r.Err != nil {
+ c.Err = r.Err
+ return
+ } else {
+ rows[3].Value = float64(r.Data.(int64))
+ }
+
w.Write([]byte(rows.ToJson()))
} else if name == "post_counts_day" {
if r := <-Srv.Store.Post().AnalyticsPostCountsByDay(teamId); r.Err != nil {
diff --git a/api/admin_test.go b/api/admin_test.go
index f7b6a7eeb..c2f4e9c76 100644
--- a/api/admin_test.go
+++ b/api/admin_test.go
@@ -151,7 +151,7 @@ func TestEmailTest(t *testing.T) {
}
}
-func TestGetAnalyticsStandard(t *testing.T) {
+func TestGetTeamAnalyticsStandard(t *testing.T) {
Setup()
team := &model.Team{DisplayName: "Name", Name: "z-z-" + model.NewId() + "a", Email: "test@nowhere.com", Type: model.TEAM_OPEN}
@@ -169,7 +169,7 @@ func TestGetAnalyticsStandard(t *testing.T) {
post1 := &model.Post{ChannelId: channel1.Id, Message: "a" + model.NewId() + "a"}
post1 = Client.Must(Client.CreatePost(post1)).Data.(*model.Post)
- if _, err := Client.GetAnalytics(team.Id, "standard"); err == nil {
+ if _, err := Client.GetTeamAnalytics(team.Id, "standard"); err == nil {
t.Fatal("Shouldn't have permissions")
}
@@ -180,7 +180,7 @@ func TestGetAnalyticsStandard(t *testing.T) {
Client.LoginByEmail(team.Name, user.Email, "pwd")
- if result, err := Client.GetAnalytics(team.Id, "standard"); err != nil {
+ if result, err := Client.GetTeamAnalytics(team.Id, "standard"); err != nil {
t.Fatal(err)
} else {
rows := result.Data.(model.AnalyticsRows)
@@ -214,6 +214,62 @@ func TestGetAnalyticsStandard(t *testing.T) {
t.Log(rows.ToJson())
t.Fatal()
}
+
+ if rows[3].Name != "unique_user_count" {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+
+ if rows[3].Value != 1 {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+ }
+
+ if result, err := Client.GetSystemAnalytics("standard"); err != nil {
+ t.Fatal(err)
+ } else {
+ rows := result.Data.(model.AnalyticsRows)
+
+ if rows[0].Name != "channel_open_count" {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+
+ if rows[0].Value < 2 {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+
+ if rows[1].Name != "channel_private_count" {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+
+ if rows[1].Value == 0 {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+
+ if rows[2].Name != "post_count" {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+
+ if rows[2].Value == 0 {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+
+ if rows[3].Name != "unique_user_count" {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
+
+ if rows[3].Value == 0 {
+ t.Log(rows.ToJson())
+ t.Fatal()
+ }
}
}
@@ -239,7 +295,7 @@ func TestGetPostCount(t *testing.T) {
Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId",
map[string]interface{}{"ChannelId": channel1.Id, "CreateAt": utils.MillisFromTime(utils.Yesterday())})
- if _, err := Client.GetAnalytics(team.Id, "post_counts_day"); err == nil {
+ if _, err := Client.GetTeamAnalytics(team.Id, "post_counts_day"); err == nil {
t.Fatal("Shouldn't have permissions")
}
@@ -250,7 +306,7 @@ func TestGetPostCount(t *testing.T) {
Client.LoginByEmail(team.Name, user.Email, "pwd")
- if result, err := Client.GetAnalytics(team.Id, "post_counts_day"); err != nil {
+ if result, err := Client.GetTeamAnalytics(team.Id, "post_counts_day"); err != nil {
t.Fatal(err)
} else {
rows := result.Data.(model.AnalyticsRows)
@@ -284,7 +340,7 @@ func TestUserCountsWithPostsByDay(t *testing.T) {
Srv.Store.(*store.SqlStore).GetMaster().Exec("UPDATE Posts SET CreateAt = :CreateAt WHERE ChannelId = :ChannelId",
map[string]interface{}{"ChannelId": channel1.Id, "CreateAt": utils.MillisFromTime(utils.Yesterday())})
- if _, err := Client.GetAnalytics(team.Id, "user_counts_with_posts_day"); err == nil {
+ if _, err := Client.GetTeamAnalytics(team.Id, "user_counts_with_posts_day"); err == nil {
t.Fatal("Shouldn't have permissions")
}
@@ -295,7 +351,7 @@ func TestUserCountsWithPostsByDay(t *testing.T) {
Client.LoginByEmail(team.Name, user.Email, "pwd")
- if result, err := Client.GetAnalytics(team.Id, "user_counts_with_posts_day"); err != nil {
+ if result, err := Client.GetTeamAnalytics(team.Id, "user_counts_with_posts_day"); err != nil {
t.Fatal(err)
} else {
rows := result.Data.(model.AnalyticsRows)
diff --git a/api/api.go b/api/api.go
index d0f41bcab..d202172d0 100644
--- a/api/api.go
+++ b/api/api.go
@@ -19,16 +19,25 @@ var ServerTemplates *template.Template
type ServerTemplatePage Page
-func NewServerTemplatePage(templateName string) *ServerTemplatePage {
+func NewServerTemplatePage(templateName, locale string) *ServerTemplatePage {
return &ServerTemplatePage{
TemplateName: templateName,
Props: make(map[string]string),
+ Extra: make(map[string]string),
+ Html: make(map[string]template.HTML),
ClientCfg: utils.ClientCfg,
+ Locale: locale,
}
}
func (me *ServerTemplatePage) Render() string {
var text bytes.Buffer
+
+ T := utils.GetUserTranslations(me.Locale)
+ me.Props["Footer"] = T("api.templates.email_footer")
+ me.Html["EmailInfo"] = template.HTML(T("api.templates.email_info",
+ map[string]interface{}{"FeedbackEmail": me.ClientCfg["FeedbackEmail"], "SiteName": me.ClientCfg["SiteName"]}))
+
if err := ServerTemplates.ExecuteTemplate(&text, me.TemplateName, me); err != nil {
l4g.Error(utils.T("api.api.render.error"), me.TemplateName, err)
}
diff --git a/api/context.go b/api/context.go
index b152d6da8..41a52fa0c 100644
--- a/api/context.go
+++ b/api/context.go
@@ -5,6 +5,7 @@ package api
import (
"fmt"
+ "html/template"
"net"
"net/http"
"net/url"
@@ -31,11 +32,14 @@ type Context struct {
siteURL string
SessionTokenIndex int64
T goi18n.TranslateFunc
+ Locale string
}
type Page struct {
TemplateName string
Props map[string]string
+ Extra map[string]string
+ Html map[string]template.HTML
ClientCfg map[string]string
ClientLicense map[string]string
User *model.User
@@ -43,6 +47,7 @@ type Page struct {
Channel *model.Channel
PostID string
SessionTokenIndex int64
+ Locale string
}
func ApiAppHandler(h func(*Context, http.ResponseWriter, *http.Request)) http.Handler {
@@ -86,7 +91,7 @@ func (h handler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
l4g.Debug("%v", r.URL.Path)
c := &Context{}
- c.T = utils.GetTranslations(w, r)
+ c.T, c.Locale = utils.GetTranslationsAndLocale(w, r)
c.RequestId = model.NewId()
c.IpAddress = GetIpAddress(r)
@@ -505,6 +510,10 @@ func RenderWebError(err *model.AppError, w http.ResponseWriter, r *http.Request)
props["SiteURL"] = GetProtocol(r) + "://" + r.Host
}
+ T, _ := utils.GetTranslationsAndLocale(w, r)
+ props["Title"] = T("api.templates.error.title", map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})
+ props["Link"] = T("api.templates.error.link")
+
w.WriteHeader(err.StatusCode)
ServerTemplates.ExecuteTemplate(w, "error.html", Page{Props: props, ClientCfg: utils.ClientCfg})
}
diff --git a/api/export.go b/api/export.go
index 77b821147..f2f8f87ab 100644
--- a/api/export.go
+++ b/api/export.go
@@ -267,7 +267,7 @@ func copyDirToExportWriter(writer ExportWriter, inPath string, outPath string) *
} else {
fromFile, err := os.Open(inPath + "/" + fileInfo.Name())
if err != nil {
- return model.NewAppError("copyDirToExportWriter", "api.export.open.app_error", err.Error())
+ return model.NewLocAppError("copyDirToExportWriter", "api.export.open.app_error", nil, err.Error())
}
io.Copy(toFile, fromFile)
}
diff --git a/api/file.go b/api/file.go
index 46e81691e..44ae775c9 100644
--- a/api/file.go
+++ b/api/file.go
@@ -58,7 +58,7 @@ const (
var fileInfoCache *utils.Cache = utils.NewLru(1000)
func InitFile(r *mux.Router) {
- l4g.Debug("Initializing file api routes")
+ l4g.Debug(utils.T("api.file.init.debug"))
sr := r.PathPrefix("/files").Subrouter()
sr.Handle("/upload", ApiUserRequired(uploadFile)).Methods("POST")
@@ -70,13 +70,13 @@ func InitFile(r *mux.Router) {
func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
if len(utils.Cfg.FileSettings.DriverName) == 0 {
- c.Err = model.NewAppError("uploadFile", "Unable to upload file. Image storage is not configured.", "")
+ c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.storage.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
if r.ContentLength > model.MAX_FILE_SIZE {
- c.Err = model.NewAppError("uploadFile", "Unable to upload file. File is too large.", "")
+ c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.too_large.app_error", nil, "")
c.Err.StatusCode = http.StatusRequestEntityTooLarge
return
}
@@ -139,10 +139,10 @@ func uploadFile(c *Context, w http.ResponseWriter, r *http.Request) {
// Decode image config first to check dimensions before loading the whole thing into memory later on
config, _, err := image.DecodeConfig(bytes.NewReader(buf.Bytes()))
if err != nil {
- c.Err = model.NewAppError("uploadFile", "Unable to upload image file.", err.Error())
+ c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.image.app_error", nil, err.Error())
return
} else if config.Width*config.Height > MaxImageSize {
- c.Err = model.NewAppError("uploadFile", "Unable to upload image file. File is too large.", "File exceeds max image size.")
+ c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.large_image.app_error", nil, c.T("api.file.file_upload.exceeds"))
return
}
}
@@ -180,7 +180,7 @@ func handleImagesAndForget(filenames []string, fileData [][]byte, teamId, channe
// Decode image bytes into Image object
img, imgType, err := image.Decode(bytes.NewReader(fileData[i]))
if err != nil {
- l4g.Error("Unable to decode image channelId=%v userId=%v filename=%v err=%v", channelId, userId, filename, err)
+ l4g.Error(utils.T("api.file.handle_images_forget.decode.error"), channelId, userId, filename, err)
return
}
@@ -233,12 +233,12 @@ func handleImagesAndForget(filenames []string, fileData [][]byte, teamId, channe
buf := new(bytes.Buffer)
err = jpeg.Encode(buf, thumbnail, &jpeg.Options{Quality: 90})
if err != nil {
- l4g.Error("Unable to encode image as jpeg channelId=%v userId=%v filename=%v err=%v", channelId, userId, filename, err)
+ l4g.Error(utils.T("api.file.handle_images_forget.encode_jpeg.error"), channelId, userId, filename, err)
return
}
if err := writeFile(buf.Bytes(), dest+name+"_thumb.jpg"); err != nil {
- l4g.Error("Unable to upload thumbnail channelId=%v userId=%v filename=%v err=%v", channelId, userId, filename, err)
+ l4g.Error(utils.T("api.file.handle_images_forget.upload_thumb.error"), channelId, userId, filename, err)
return
}
}()
@@ -256,12 +256,12 @@ func handleImagesAndForget(filenames []string, fileData [][]byte, teamId, channe
err = jpeg.Encode(buf, preview, &jpeg.Options{Quality: 90})
if err != nil {
- l4g.Error("Unable to encode image as preview jpg channelId=%v userId=%v filename=%v err=%v", channelId, userId, filename, err)
+ l4g.Error(utils.T("api.file.handle_images_forget.encode_preview.error"), channelId, userId, filename, err)
return
}
if err := writeFile(buf.Bytes(), dest+name+"_preview.jpg"); err != nil {
- l4g.Error("Unable to upload preview channelId=%v userId=%v filename=%v err=%v", channelId, userId, filename, err)
+ l4g.Error(utils.T("api.file.handle_images_forget.upload_preview.error"), channelId, userId, filename, err)
return
}
}()
@@ -294,7 +294,7 @@ type ImageGetResult struct {
func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
if len(utils.Cfg.FileSettings.DriverName) == 0 {
- c.Err = model.NewAppError("uploadFile", "Unable to get file info. Image storage is not configured.", "")
+ c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.storage.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -351,7 +351,7 @@ func getFileInfo(c *Context, w http.ResponseWriter, r *http.Request) {
func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
if len(utils.Cfg.FileSettings.DriverName) == 0 {
- c.Err = model.NewAppError("uploadFile", "Unable to get file. Image storage is not configured.", "")
+ c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.storage.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -379,6 +379,7 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
hash := r.URL.Query().Get("h")
data := r.URL.Query().Get("d")
teamId := r.URL.Query().Get("t")
+ isDownload := r.URL.Query().Get("download") == "1"
cchan := Srv.Store.Channel().CheckPermissionsTo(c.Session.TeamId, channelId, c.Session.UserId)
@@ -394,14 +395,14 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
if len(hash) > 0 && len(data) > 0 && len(teamId) == 26 {
if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt)) {
- c.Err = model.NewAppError("getFile", "The public link does not appear to be valid", "")
+ c.Err = model.NewLocAppError("getFile", "api.file.get_file.public_invalid.app_error", nil, "")
return
}
props := model.MapFromJson(strings.NewReader(data))
t, err := strconv.ParseInt(props["time"], 10, 64)
if err != nil || model.GetMillis()-t > 1000*60*60*24*7 { // one week
- c.Err = model.NewAppError("getFile", "The public link has expired", "")
+ c.Err = model.NewLocAppError("getFile", "api.file.get_file.public_expired.app_error", nil, "")
return
}
} else if !c.HasPermissionsToChannel(cchan, "getFile") {
@@ -411,7 +412,7 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
f := <-fileData
if f == nil {
- c.Err = model.NewAppError("getFile", "Could not find file.", "path="+path)
+ c.Err = model.NewLocAppError("getFile", "api.file.get_file.not_found.app_error", nil, "path="+path)
c.Err.StatusCode = http.StatusNotFound
return
}
@@ -420,16 +421,18 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", strconv.Itoa(len(f)))
w.Header().Del("Content-Type") // Content-Type will be set automatically by the http writer
- // attach extra headers to trigger a download on IE, Edge, and Safari
- ua := user_agent.New(r.UserAgent())
- bname, _ := ua.Browser()
+ if isDownload {
+ // attach extra headers to trigger a download on IE, Edge, and Safari
+ ua := user_agent.New(r.UserAgent())
+ bname, _ := ua.Browser()
- if bname == "Edge" || bname == "Internet Explorer" || bname == "Safari" {
- // trim off anything before the final / so we just get the file's name
- parts := strings.Split(filename, "/")
+ if bname == "Edge" || bname == "Internet Explorer" || bname == "Safari" {
+ // trim off anything before the final / so we just get the file's name
+ parts := strings.Split(filename, "/")
- w.Header().Set("Content-Type", "application/octet-stream")
- w.Header().Set("Content-Disposition", "attachment;filename=\""+parts[len(parts)-1]+"\"")
+ w.Header().Set("Content-Type", "application/octet-stream")
+ w.Header().Set("Content-Disposition", "attachment;filename=\""+parts[len(parts)-1]+"\"")
+ }
}
w.Write(f)
@@ -449,13 +452,13 @@ func getFileAndForget(path string, fileData chan []byte) {
func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
if len(utils.Cfg.FileSettings.DriverName) == 0 {
- c.Err = model.NewAppError("uploadFile", "Unable to get link. Image storage is not configured.", "")
+ c.Err = model.NewLocAppError("uploadFile", "api.file.upload_file.storage.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
if !utils.Cfg.FileSettings.EnablePublicLink {
- c.Err = model.NewAppError("getPublicLink", "Public links have been disabled", "")
+ c.Err = model.NewLocAppError("getPublicLink", "api.file.get_public_link.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
}
@@ -500,13 +503,13 @@ func getPublicLink(c *Context, w http.ResponseWriter, r *http.Request) {
func getExport(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.HasPermissionsToTeam(c.Session.TeamId, "export") || !c.IsTeamAdmin() {
- c.Err = model.NewAppError("getExport", "Only a team admin can retrieve exported data.", "userId="+c.Session.UserId)
+ c.Err = model.NewLocAppError("getExport", "api.file.get_export.team_admin.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden
return
}
data, err := readFile(EXPORT_PATH + EXPORT_FILENAME)
if err != nil {
- c.Err = model.NewAppError("getExport", "Unable to retrieve exported file. Please re-export", err.Error())
+ c.Err = model.NewLocAppError("getExport", "api.file.get_export.retrieve.app_error", nil, err.Error())
return
}
@@ -538,14 +541,14 @@ func writeFile(f []byte, path string) *model.AppError {
}
if err != nil {
- return model.NewAppError("writeFile", "Encountered an error writing to S3", err.Error())
+ return model.NewLocAppError("writeFile", "api.file.write_file.s3.app_error", nil, err.Error())
}
} else if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_LOCAL {
if err := writeFileLocally(f, utils.Cfg.FileSettings.Directory+path); err != nil {
return err
}
} else {
- return model.NewAppError("writeFile", "File storage not configured properly. Please configure for either S3 or local server file storage.", "")
+ return model.NewLocAppError("writeFile", "api.file.write_file.configured.app_error", nil, "")
}
return nil
@@ -553,11 +556,11 @@ func writeFile(f []byte, path string) *model.AppError {
func writeFileLocally(f []byte, path string) *model.AppError {
if err := os.MkdirAll(filepath.Dir(path), 0774); err != nil {
- return model.NewAppError("writeFile", "Encountered an error creating the directory for the new file", err.Error())
+ return model.NewLocAppError("writeFile", "api.file.write_file_locally.create_dir.app_error", nil, err.Error())
}
if err := ioutil.WriteFile(path, f, 0644); err != nil {
- return model.NewAppError("writeFile", "Encountered an error writing to local server storage", err.Error())
+ return model.NewLocAppError("writeFile", "api.file.write_file_locally.writing.app_error", nil, err.Error())
}
return nil
@@ -583,31 +586,31 @@ func readFile(path string) ([]byte, *model.AppError) {
if f != nil {
return f, nil
} else if tries >= 3 {
- return nil, model.NewAppError("readFile", "Unable to get file from S3", "path="+path+", err="+err.Error())
+ return nil, model.NewLocAppError("readFile", "api.file.read_file.get.app_error", nil, "path="+path+", err="+err.Error())
}
time.Sleep(3000 * time.Millisecond)
}
} else if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_LOCAL {
if f, err := ioutil.ReadFile(utils.Cfg.FileSettings.Directory + path); err != nil {
- return nil, model.NewAppError("readFile", "Encountered an error reading from local server storage", err.Error())
+ return nil, model.NewLocAppError("readFile", "api.file.read_file.reading_local.app_error", nil, err.Error())
} else {
return f, nil
}
} else {
- return nil, model.NewAppError("readFile", "File storage not configured properly. Please configure for either S3 or local server file storage.", "")
+ return nil, model.NewLocAppError("readFile", "api.file.read_file.configured.app_error", nil, "")
}
}
func openFileWriteStream(path string) (io.Writer, *model.AppError) {
if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_S3 {
- return nil, model.NewAppError("openFileWriteStream", "S3 is not supported.", "")
+ return nil, model.NewLocAppError("openFileWriteStream", "api.file.open_file_write_stream.s3.app_error", nil, "")
} else if utils.Cfg.FileSettings.DriverName == model.IMAGE_DRIVER_LOCAL {
if err := os.MkdirAll(filepath.Dir(utils.Cfg.FileSettings.Directory+path), 0774); err != nil {
- return nil, model.NewAppError("openFileWriteStream", "Encountered an error creating the directory for the new file", err.Error())
+ return nil, model.NewLocAppError("openFileWriteStream", "api.file.open_file_write_stream.creating_dir.app_error", nil, err.Error())
}
if fileHandle, err := os.Create(utils.Cfg.FileSettings.Directory + path); err != nil {
- return nil, model.NewAppError("openFileWriteStream", "Encountered an error writing to local server storage", err.Error())
+ return nil, model.NewLocAppError("openFileWriteStream", "api.file.open_file_write_stream.local_server.app_error", nil, err.Error())
} else {
fileHandle.Chmod(0644)
return fileHandle, nil
@@ -615,7 +618,7 @@ func openFileWriteStream(path string) (io.Writer, *model.AppError) {
}
- return nil, model.NewAppError("openFileWriteStream", "File storage not configured properly. Please configure for either S3 or local server file storage.", "")
+ return nil, model.NewLocAppError("openFileWriteStream", "api.file.open_file_write_stream.configured.app_error", nil, "")
}
func closeFileWriteStream(file io.Writer) {
diff --git a/api/import.go b/api/import.go
index 5c8f99348..7590277b0 100644
--- a/api/import.go
+++ b/api/import.go
@@ -6,6 +6,7 @@ package api
import (
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
)
//
@@ -17,7 +18,7 @@ func ImportPost(post *model.Post) {
post.Hashtags, _ = model.ParseHashtags(post.Message)
if result := <-Srv.Store.Post().Save(post); result.Err != nil {
- l4g.Debug("Error saving post. user=" + post.UserId + ", message=" + post.Message)
+ l4g.Debug(utils.T("api.import.import_post.saving.debug"), post.UserId, post.Message)
}
}
@@ -25,17 +26,17 @@ func ImportUser(user *model.User) *model.User {
user.MakeNonNil()
if result := <-Srv.Store.User().Save(user); result.Err != nil {
- l4g.Error("Error saving user. err=%v", result.Err)
+ l4g.Error(utils.T("api.import.import_user.saving.error"), result.Err)
return nil
} else {
ruser := result.Data.(*model.User)
if err := JoinDefaultChannels(ruser, ""); err != nil {
- l4g.Error("Encountered an issue joining default channels user_id=%s, team_id=%s, err=%v", ruser.Id, ruser.TeamId, err)
+ l4g.Error(utils.T("api.import.import_user.joining_default.error"), ruser.Id, ruser.TeamId, err)
}
if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
- l4g.Error("Failed to set email verified err=%v", cresult.Err)
+ l4g.Error(utils.T("api.import.import_user.set_email.error"), cresult.Err)
}
return ruser
diff --git a/api/license.go b/api/license.go
index 5b3809651..5c602a68e 100644
--- a/api/license.go
+++ b/api/license.go
@@ -5,6 +5,7 @@ package api
import (
"bytes"
+ "fmt"
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
"github.com/mattermost/platform/model"
@@ -15,7 +16,7 @@ import (
)
func InitLicense(r *mux.Router) {
- l4g.Debug("Initializing license api routes")
+ l4g.Debug(utils.T("api.license.init.debug"))
sr := r.PathPrefix("/license").Subrouter()
sr.Handle("/add", ApiAdminSystemRequired(addLicense)).Methods("POST")
@@ -34,13 +35,13 @@ func addLicense(c *Context, w http.ResponseWriter, r *http.Request) {
fileArray, ok := m.File["license"]
if !ok {
- c.Err = model.NewAppError("addLicense", "No file under 'license' in request", "")
+ c.Err = model.NewLocAppError("addLicense", "api.license.add_license.no_file.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
if len(fileArray) <= 0 {
- c.Err = model.NewAppError("addLicense", "Empty array under 'license' in request", "")
+ c.Err = model.NewLocAppError("addLicense", "api.license.add_license.array.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
@@ -50,7 +51,7 @@ func addLicense(c *Context, w http.ResponseWriter, r *http.Request) {
file, err := fileData.Open()
defer file.Close()
if err != nil {
- c.Err = model.NewAppError("addLicense", "Could not open license file", err.Error())
+ c.Err = model.NewLocAppError("addLicense", "api.license.add_license.open.app_error", nil, err.Error())
return
}
@@ -63,21 +64,33 @@ func addLicense(c *Context, w http.ResponseWriter, r *http.Request) {
if success, licenseStr := utils.ValidateLicense(data); success {
license = model.LicenseFromJson(strings.NewReader(licenseStr))
+ if result := <-Srv.Store.User().AnalyticsUniqueUserCount(""); result.Err != nil {
+ c.Err = model.NewAppError("addLicense", "Unable to count total unique users.", fmt.Sprintf("err=%v", result.Err.Error()))
+ return
+ } else {
+ uniqueUserCount := result.Data.(int64)
+
+ if uniqueUserCount > int64(*license.Features.Users) {
+ c.Err = model.NewAppError("addLicense", fmt.Sprintf("This license only supports %d users, when your system has %d unique users. Unique users are counted distinctly by email address. You can see total user count under Site Reports -> View Statistics.", *license.Features.Users, uniqueUserCount), "")
+ return
+ }
+ }
+
if ok := utils.SetLicense(license); !ok {
c.LogAudit("failed - expired or non-started license")
- c.Err = model.NewAppError("addLicense", "License is either expired or has not yet started.", "")
+ c.Err = model.NewLocAppError("addLicense", "api.license.add_license.expired.app_error", nil, "")
return
}
if err := writeFileLocally(data, utils.LicenseLocation()); err != nil {
c.LogAudit("failed - could not save license file")
- c.Err = model.NewAppError("addLicense", "License did not save properly.", "path="+utils.LicenseLocation())
+ c.Err = model.NewLocAppError("addLicense", "api.license.add_license.save.app_error", nil, "path="+utils.LicenseLocation())
utils.RemoveLicense()
return
}
} else {
c.LogAudit("failed - invalid license")
- c.Err = model.NewAppError("addLicense", "Invalid license file.", "")
+ c.Err = model.NewLocAppError("addLicense", "api.license.add_license.invalid.app_error", nil, "")
return
}
@@ -90,7 +103,7 @@ func removeLicense(c *Context, w http.ResponseWriter, r *http.Request) {
if ok := utils.RemoveLicense(); !ok {
c.LogAudit("failed - could not remove license file")
- c.Err = model.NewAppError("removeLicense", "License did not remove properly.", "")
+ c.Err = model.NewLocAppError("removeLicense", "api.license.remove_license.remove.app_error", nil, "")
return
}
diff --git a/api/oauth.go b/api/oauth.go
index eb5e0e496..1ae3dbf78 100644
--- a/api/oauth.go
+++ b/api/oauth.go
@@ -14,7 +14,7 @@ import (
)
func InitOAuth(r *mux.Router) {
- l4g.Debug("Initializing oauth api routes")
+ l4g.Debug(utils.T("api.oauth.init.debug"))
sr := r.PathPrefix("/oauth").Subrouter()
@@ -24,7 +24,7 @@ func InitOAuth(r *mux.Router) {
func registerOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewAppError("registerOAuthApp", "The system admin has turned off OAuth service providing.", "")
+ c.Err = model.NewLocAppError("registerOAuthApp", "api.oauth.register_oauth_app.turn_off.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -58,7 +58,7 @@ func registerOAuthApp(c *Context, w http.ResponseWriter, r *http.Request) {
func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableOAuthServiceProvider {
- c.Err = model.NewAppError("allowOAuth", "The system admin has turned off OAuth service providing.", "")
+ c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.turn_off.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -70,19 +70,19 @@ func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
responseType := r.URL.Query().Get("response_type")
if len(responseType) == 0 {
- c.Err = model.NewAppError("allowOAuth", "invalid_request: Bad response_type", "")
+ c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_response.app_error", nil, "")
return
}
clientId := r.URL.Query().Get("client_id")
if len(clientId) != 26 {
- c.Err = model.NewAppError("allowOAuth", "invalid_request: Bad client_id", "")
+ c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_client.app_error", nil, "")
return
}
redirectUri := r.URL.Query().Get("redirect_uri")
if len(redirectUri) == 0 {
- c.Err = model.NewAppError("allowOAuth", "invalid_request: Missing or bad redirect_uri", "")
+ c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.bad_redirect.app_error", nil, "")
return
}
@@ -91,7 +91,7 @@ func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
var app *model.OAuthApp
if result := <-Srv.Store.OAuth().GetApp(clientId); result.Err != nil {
- c.Err = model.NewAppError("allowOAuth", "server_error: Error accessing the database", "")
+ c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.database.app_error", nil, "")
return
} else {
app = result.Data.(*model.OAuthApp)
@@ -99,7 +99,7 @@ func allowOAuth(c *Context, w http.ResponseWriter, r *http.Request) {
if !app.IsValidRedirectURL(redirectUri) {
c.LogAudit("fail - redirect_uri did not match registered callback")
- c.Err = model.NewAppError("allowOAuth", "invalid_request: Supplied redirect_uri did not match registered callback_url", "")
+ c.Err = model.NewLocAppError("allowOAuth", "api.oauth.allow_oauth.redirect_callback.app_error", nil, "")
return
}
@@ -132,7 +132,7 @@ func RevokeAccessToken(token string) *model.AppError {
var accessData *model.AccessData
if result := <-Srv.Store.OAuth().GetAccessData(token); result.Err != nil {
- return model.NewAppError("RevokeAccessToken", "Error getting access token from DB before deletion", "")
+ return model.NewLocAppError("RevokeAccessToken", "api.oauth.revoke_access_token.get.app_error", nil, "")
} else {
accessData = result.Data.(*model.AccessData)
}
@@ -141,15 +141,15 @@ func RevokeAccessToken(token string) *model.AppError {
cchan := Srv.Store.OAuth().RemoveAuthData(accessData.AuthCode)
if result := <-tchan; result.Err != nil {
- return model.NewAppError("RevokeAccessToken", "Error deleting access token from DB", "")
+ return model.NewLocAppError("RevokeAccessToken", "api.oauth.revoke_access_token.del_token.app_error", nil, "")
}
if result := <-cchan; result.Err != nil {
- return model.NewAppError("RevokeAccessToken", "Error deleting authorization code from DB", "")
+ return model.NewLocAppError("RevokeAccessToken", "api.oauth.revoke_access_token.del_code.app_error", nil, "")
}
if result := <-schan; result.Err != nil {
- return model.NewAppError("RevokeAccessToken", "Error deleting session from DB", "")
+ return model.NewLocAppError("RevokeAccessToken", "api.oauth.revoke_access_token.del_session.app_error", nil, "")
}
return nil
@@ -157,7 +157,7 @@ func RevokeAccessToken(token string) *model.AppError {
func GetAuthData(code string) *model.AuthData {
if result := <-Srv.Store.OAuth().GetAuthData(code); result.Err != nil {
- l4g.Error("Couldn't find auth code for code=%s", code)
+ l4g.Error(utils.T("api.oauth.get_auth_data.find.error"), code)
return nil
} else {
return result.Data.(*model.AuthData)
diff --git a/api/post.go b/api/post.go
index 42c3c304d..d3807653d 100644
--- a/api/post.go
+++ b/api/post.go
@@ -10,6 +10,7 @@ import (
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
+ "html/template"
"net/http"
"net/url"
"path/filepath"
@@ -20,7 +21,7 @@ import (
)
func InitPost(r *mux.Router) {
- l4g.Debug("Initializing post api routes")
+ l4g.Debug(utils.T("api.post.init.debug"))
r.Handle("/posts/search", ApiUserRequired(searchPosts)).Methods("GET")
r.Handle("/posts/{post_id}", ApiUserRequired(getPostById)).Methods("GET")
@@ -53,14 +54,16 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) {
if rp, err := CreatePost(c, post, true); err != nil {
c.Err = err
- if strings.Contains(c.Err.Message, "parameter") {
+ if c.Err.Id == "api.post.create_post.root_id.app_error" ||
+ c.Err.Id == "api.post.create_post.channel_root_id.app_error" ||
+ c.Err.Id == "api.post.create_post.parent_id.app_error" {
c.Err.StatusCode = http.StatusBadRequest
}
return
} else {
if result := <-Srv.Store.Channel().UpdateLastViewedAt(post.ChannelId, c.Session.UserId); result.Err != nil {
- l4g.Error("Encountered error updating last viewed, channel_id=%s, user_id=%s, err=%v", post.ChannelId, c.Session.UserId, result.Err)
+ l4g.Error(utils.T("api.post.create_post.last_viewed.error"), post.ChannelId, c.Session.UserId, result.Err)
}
w.Write([]byte(rp.ToJson()))
@@ -76,11 +79,11 @@ func CreatePost(c *Context, post *model.Post, triggerWebhooks bool) (*model.Post
// Verify the parent/child relationships are correct
if pchan != nil {
if presult := <-pchan; presult.Err != nil {
- return nil, model.NewAppError("createPost", "Invalid RootId parameter", "")
+ return nil, model.NewLocAppError("createPost", "api.post.create_post.root_id.app_error", nil, "")
} else {
list := presult.Data.(*model.PostList)
if len(list.Posts) == 0 || !list.IsChannelId(post.ChannelId) {
- return nil, model.NewAppError("createPost", "Invalid ChannelId for RootId parameter", "")
+ return nil, model.NewLocAppError("createPost", "api.post.create_post.channel_root_id.app_error", nil, "")
}
if post.ParentId == "" {
@@ -90,7 +93,7 @@ func CreatePost(c *Context, post *model.Post, triggerWebhooks bool) (*model.Post
if post.RootId != post.ParentId {
parent := list.Posts[post.ParentId]
if parent == nil {
- return nil, model.NewAppError("createPost", "Invalid ParentId parameter", "")
+ return nil, model.NewLocAppError("createPost", "api.post.create_post.parent_id.app_error", nil, "")
}
}
}
@@ -129,7 +132,7 @@ func CreatePost(c *Context, post *model.Post, triggerWebhooks bool) (*model.Post
doRemove = true
}
if doRemove {
- l4g.Error("Bad filename discarded, filename=%v", path)
+ l4g.Error(utils.T("api.post.create_post.bad_filename.error"), path)
post.Filenames = append(post.Filenames[:i], post.Filenames[i+1:]...)
}
}
@@ -217,7 +220,7 @@ func CreateWebhookPost(c *Context, channelId, text, overrideUsername, overrideIc
}
if _, err := CreatePost(c, post, false); err != nil {
- return nil, model.NewAppError("CreateWebhookPost", "Error creating post", "err="+err.Message)
+ return nil, model.NewLocAppError("CreateWebhookPost", "api.post.create_webhook_post.creating.app_error", nil, "err="+err.Message)
}
return post, nil
@@ -231,7 +234,7 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
var team *model.Team
if result := <-tchan; result.Err != nil {
- l4g.Error("Encountered error getting team, team_id=%s, err=%v", c.Session.TeamId, result.Err)
+ l4g.Error(utils.T("api.post.handle_post_events_and_forget.team.error"), c.Session.TeamId, result.Err)
return
} else {
team = result.Data.(*model.Team)
@@ -239,7 +242,7 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
var channel *model.Channel
if result := <-cchan; result.Err != nil {
- l4g.Error("Encountered error getting channel, channel_id=%s, err=%v", post.ChannelId, result.Err)
+ l4g.Error(utils.T("api.post.handle_post_events_and_forget.channel.error"), post.ChannelId, result.Err)
return
} else {
channel = result.Data.(*model.Channel)
@@ -249,7 +252,7 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
var user *model.User
if result := <-uchan; result.Err != nil {
- l4g.Error("Encountered error getting user, user_id=%s, err=%v", post.UserId, result.Err)
+ l4g.Error(utils.T("api.post.handle_post_events_and_forget.user.error"), post.UserId, result.Err)
return
} else {
user = result.Data.(*model.User)
@@ -268,14 +271,14 @@ func handlePostEventsAndForget(c *Context, post *model.Post, triggerWebhooks boo
func makeDirectChannelVisible(teamId string, channelId string) {
var members []model.ChannelMember
if result := <-Srv.Store.Channel().GetMembers(channelId); result.Err != nil {
- l4g.Error("Failed to get channel members channel_id=%v err=%v", channelId, result.Err.Message)
+ l4g.Error(utils.T("api.post.make_direct_channel_visible.get_members.error"), channelId, result.Err.Message)
return
} else {
members = result.Data.([]model.ChannelMember)
}
if len(members) != 2 {
- l4g.Error("Failed to get 2 members for a direct channel channel_id=%v", channelId)
+ l4g.Error(utils.T("api.post.make_direct_channel_visible.get_2_members.error"), channelId)
return
}
@@ -293,7 +296,7 @@ func makeDirectChannelVisible(teamId string, channelId string) {
}
if saveResult := <-Srv.Store.Preference().Save(&model.Preferences{*preference}); saveResult.Err != nil {
- l4g.Error("Failed to save direct channel preference user_id=%v other_user_id=%v err=%v", member.UserId, otherUserId, saveResult.Err.Message)
+ l4g.Error(utils.T("api.post.make_direct_channel_visible.save_pref.error"), member.UserId, otherUserId, saveResult.Err.Message)
} else {
message := model.NewMessage(teamId, channelId, member.UserId, model.ACTION_PREFERENCE_CHANGED)
message.Add("preference", preference.ToJson())
@@ -308,7 +311,7 @@ func makeDirectChannelVisible(teamId string, channelId string) {
preference.Value = "true"
if updateResult := <-Srv.Store.Preference().Save(&model.Preferences{preference}); updateResult.Err != nil {
- l4g.Error("Failed to update direct channel preference user_id=%v other_user_id=%v err=%v", member.UserId, otherUserId, updateResult.Err.Message)
+ l4g.Error(utils.T("api.post.make_direct_channel_visible.update_pref.error"), member.UserId, otherUserId, updateResult.Err.Message)
} else {
message := model.NewMessage(teamId, channelId, member.UserId, model.ACTION_PREFERENCE_CHANGED)
message.Add("preference", preference.ToJson())
@@ -335,7 +338,7 @@ func handleWebhookEventsAndForget(c *Context, post *model.Post, team *model.Team
hooks := []*model.OutgoingWebhook{}
if result := <-hchan; result.Err != nil {
- l4g.Error("Encountered error getting webhooks by team, err=%v", result.Err)
+ l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.getting.error"), result.Err)
return
} else {
hooks = result.Data.([]*model.OutgoingWebhook)
@@ -386,17 +389,17 @@ func handleWebhookEventsAndForget(c *Context, post *model.Post, team *model.Team
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
req.Header.Set("Accept", "application/json")
if resp, err := client.Do(req); err != nil {
- l4g.Error("Event POST failed, err=%s", err.Error())
+ l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.event_post.error"), err.Error())
} else {
respProps := model.MapFromJson(resp.Body)
// copy the context and create a mock session for posting the message
mockSession := model.Session{UserId: hook.CreatorId, TeamId: hook.TeamId, IsOAuth: false}
- newContext := &Context{mockSession, model.NewId(), "", c.Path, nil, c.teamURLValid, c.teamURL, c.siteURL, 0, c.T}
+ newContext := &Context{mockSession, model.NewId(), "", c.Path, nil, c.teamURLValid, c.teamURL, c.siteURL, 0, c.T, c.Locale}
if text, ok := respProps["text"]; ok {
if _, err := CreateWebhookPost(newContext, post.ChannelId, text, respProps["username"], respProps["icon_url"], post.Props, post.Type); err != nil {
- l4g.Error("Failed to create response post, err=%v", err)
+ l4g.Error(utils.T("api.post.handle_webhook_events_and_forget.create_post.error"), err)
}
}
}
@@ -420,25 +423,17 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
var channelName string
var bodyText string
var subjectText string
- if channel.Type == model.CHANNEL_DIRECT {
- bodyText = "You have one new message."
- subjectText = "New Direct Message"
- } else {
- bodyText = "You have one new mention."
- subjectText = "New Mention"
- channelName = channel.DisplayName
- }
var mentionedUsers []string
if result := <-uchan; result.Err != nil {
- l4g.Error("Failed to retrieve user profiles team_id=%v, err=%v", c.Session.TeamId, result.Err)
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.retrive_profiles.error"), c.Session.TeamId, result.Err)
return
} else {
profileMap := result.Data.(map[string]*model.User)
if _, ok := profileMap[post.UserId]; !ok {
- l4g.Error("Post user_id not returned by GetProfiles user_id=%v", post.UserId)
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.user_id.error"), post.UserId)
return
}
senderName := profileMap[post.UserId].Username
@@ -469,7 +464,7 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
// Find out who is a member of the channel, only keep those profiles
if eResult := <-echan; eResult.Err != nil {
- l4g.Error("Failed to get channel members channel_id=%v err=%v", post.ChannelId, eResult.Err.Message)
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.members.error"), post.ChannelId, eResult.Err.Message)
return
} else {
tempProfileMap := make(map[string]*model.User)
@@ -577,14 +572,6 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
// Build and send the emails
tm := time.Unix(post.CreateAt/1000, 0)
- subjectPage := NewServerTemplatePage("post_subject")
- subjectPage.Props["SiteURL"] = c.GetSiteURL()
- subjectPage.Props["TeamDisplayName"] = team.DisplayName
- subjectPage.Props["SubjectText"] = subjectText
- subjectPage.Props["Month"] = tm.Month().String()[:3]
- subjectPage.Props["Day"] = fmt.Sprintf("%d", tm.Day())
- subjectPage.Props["Year"] = fmt.Sprintf("%d", tm.Year())
-
for id, doSend := range toEmailMap {
if !doSend {
@@ -596,20 +583,37 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
continue
}
- bodyPage := NewServerTemplatePage("post_body")
+ userLocale := utils.GetUserTranslations(profileMap[id].Locale)
+
+ if channel.Type == model.CHANNEL_DIRECT {
+ bodyText = userLocale("api.post.send_notifications_and_forget.message_body")
+ subjectText = userLocale("api.post.send_notifications_and_forget.message_subject")
+ } else {
+ bodyText = userLocale("api.post.send_notifications_and_forget.mention_body")
+ subjectText = userLocale("api.post.send_notifications_and_forget.mention_subject")
+ channelName = channel.DisplayName
+ }
+
+ month := userLocale(tm.Month().String())
+ day := fmt.Sprintf("%d", tm.Day())
+ year := fmt.Sprintf("%d", tm.Year())
+ zone, _ := tm.Zone()
+
+ subjectPage := NewServerTemplatePage("post_subject", c.Locale)
+ subjectPage.Props["Subject"] = userLocale("api.templates.post_subject",
+ map[string]interface{}{"SubjectText": subjectText, "TeamDisplayName": team.DisplayName,
+ "Month": month[:3], "Day": day, "Year": year})
+
+ bodyPage := NewServerTemplatePage("post_body", c.Locale)
bodyPage.Props["SiteURL"] = c.GetSiteURL()
- bodyPage.Props["Nickname"] = profileMap[id].FirstName
- bodyPage.Props["TeamDisplayName"] = team.DisplayName
- bodyPage.Props["ChannelName"] = channelName
- bodyPage.Props["BodyText"] = bodyText
- bodyPage.Props["SenderName"] = senderName
- bodyPage.Props["Hour"] = fmt.Sprintf("%02d", tm.Hour())
- bodyPage.Props["Minute"] = fmt.Sprintf("%02d", tm.Minute())
- bodyPage.Props["Month"] = tm.Month().String()[:3]
- bodyPage.Props["Day"] = fmt.Sprintf("%d", tm.Day())
- bodyPage.Props["TimeZone"], _ = tm.Zone()
bodyPage.Props["PostMessage"] = model.ClearMentionTags(post.Message)
bodyPage.Props["TeamLink"] = teamURL + "/channels/" + channel.Name
+ bodyPage.Props["BodyText"] = bodyText
+ bodyPage.Props["Button"] = userLocale("api.templates.post_body.button")
+ bodyPage.Html["Info"] = template.HTML(userLocale("api.templates.post_body.info",
+ map[string]interface{}{"ChannelName": channelName, "SenderName": senderName,
+ "Hour": fmt.Sprintf("%02d", tm.Hour()), "Minute": fmt.Sprintf("%02d", tm.Minute()),
+ "TimeZone": zone, "Month": month, "Day": day}))
// attempt to fill in a message body if the post doesn't have any text
if len(strings.TrimSpace(bodyPage.Props["PostMessage"])) == 0 && len(post.Filenames) > 0 {
@@ -638,17 +642,18 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
attachmentPrefix += "s"
}
- bodyPage.Props["PostMessage"] = fmt.Sprintf("%s: %s sent", attachmentPrefix, filenamesString)
+ bodyPage.Props["PostMessage"] = userLocale("api.post.send_notifications_and_forget.sent",
+ map[string]interface{}{"Prefix": attachmentPrefix, "Filenames": filenamesString})
}
if err := utils.SendMail(profileMap[id].Email, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("Failed to send mention email successfully email=%v err=%v", profileMap[id].Email, err)
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.send.error"), profileMap[id].Email, err)
}
if *utils.Cfg.EmailSettings.SendPushNotifications {
sessionChan := Srv.Store.Session().GetSessions(id)
if result := <-sessionChan; result.Err != nil {
- l4g.Error("Failed to retrieve sessions in notifications id=%v, err=%v", id, result.Err)
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.sessions.error"), id, result.Err)
} else {
sessions := result.Data.([]*model.Session)
alreadySeen := make(map[string]string)
@@ -671,17 +676,17 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
}
if channel.Type == model.CHANNEL_DIRECT {
- msg.Message = senderName + " sent you a direct message"
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_message")
} else {
- msg.Message = senderName + " mentioned you in " + channelName
+ msg.Message = senderName + userLocale("api.post.send_notifications_and_forget.push_mention") + channelName
}
httpClient := http.Client{}
request, _ := http.NewRequest("POST", *utils.Cfg.EmailSettings.PushNotificationServer+"/api/v1/send_push", strings.NewReader(msg.ToJson()))
- l4g.Debug("Sending push notification to " + msg.DeviceId + " with msg of '" + msg.Message + "'")
+ l4g.Debug(utils.T("api.post.send_notifications_and_forget.push_notification.debug"), msg.DeviceId, msg.Message)
if _, err := httpClient.Do(request); err != nil {
- l4g.Error("Failed to send push notificationid=%v, err=%v", id, err)
+ l4g.Error(utils.T("api.post.send_notifications_and_forget.push_notification.error"), id, err)
}
}
}
@@ -717,7 +722,7 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team,
func updateMentionCountAndForget(channelId, userId string) {
go func() {
if result := <-Srv.Store.Channel().IncrementMentionCount(channelId, userId); result.Err != nil {
- l4g.Error("Failed to update mention count for user_id=%v on channel_id=%v err=%v", userId, channelId, result.Err)
+ l4g.Error(utils.T("api.post.update_mention_count_and_forget.update_error"), userId, channelId, result.Err)
}
}()
}
@@ -745,19 +750,20 @@ func updatePost(c *Context, w http.ResponseWriter, r *http.Request) {
oldPost = result.Data.(*model.PostList).Posts[post.Id]
if oldPost == nil {
- c.Err = model.NewAppError("updatePost", "We couldn't find the existing post or comment to update.", "id="+post.Id)
+ c.Err = model.NewLocAppError("updatePost", "api.post.update_post.find.app_error", nil, "id="+post.Id)
c.Err.StatusCode = http.StatusBadRequest
return
}
if oldPost.UserId != c.Session.UserId {
- c.Err = model.NewAppError("updatePost", "You do not have the appropriate permissions", "oldUserId="+oldPost.UserId)
+ c.Err = model.NewLocAppError("updatePost", "api.post.update_post.permissions.app_error", nil, "oldUserId="+oldPost.UserId)
c.Err.StatusCode = http.StatusForbidden
return
}
if oldPost.DeleteAt != 0 {
- c.Err = model.NewAppError("updatePost", "You do not have the appropriate permissions", "Already delted id="+post.Id)
+ c.Err = model.NewLocAppError("updatePost", "api.post.update_post.permissions.app_error", nil,
+ c.T("api.post.update_post.permissions_details.app_error", map[string]interface{}{"PostId": post.Id}))
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -892,7 +898,7 @@ func getPost(c *Context, w http.ResponseWriter, r *http.Request) {
list := result.Data.(*model.PostList)
if !list.IsChannelId(channelId) {
- c.Err = model.NewAppError("getPost", "You do not have the appropriate permissions", "")
+ c.Err = model.NewLocAppError("getPost", "api.post.get_post.permissions.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -918,7 +924,7 @@ func getPostById(c *Context, w http.ResponseWriter, r *http.Request) {
list := result.Data.(*model.PostList)
if len(list.Order) != 1 {
- c.Err = model.NewAppError("getPostById", "Unable to get post", "")
+ c.Err = model.NewLocAppError("getPostById", "api.post_get_post_by_id.get.app_error", nil, "")
return
}
post := list.Posts[list.Order[0]]
@@ -972,13 +978,13 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
}
if post.ChannelId != channelId {
- c.Err = model.NewAppError("deletePost", "You do not have the appropriate permissions", "")
+ c.Err = model.NewLocAppError("deletePost", "api.post.delete_post.permissions.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
if post.UserId != c.Session.UserId && !c.IsTeamAdmin() {
- c.Err = model.NewAppError("deletePost", "You do not have the appropriate permissions", "")
+ c.Err = model.NewLocAppError("deletePost", "api.post.delete_post.permissions.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -1002,9 +1008,11 @@ func deletePost(c *Context, w http.ResponseWriter, r *http.Request) {
func getPostsBefore(c *Context, w http.ResponseWriter, r *http.Request) {
getPostsBeforeOrAfter(c, w, r, true)
}
+
func getPostsAfter(c *Context, w http.ResponseWriter, r *http.Request) {
getPostsBeforeOrAfter(c, w, r, false)
}
+
func getPostsBeforeOrAfter(c *Context, w http.ResponseWriter, r *http.Request, before bool) {
params := mux.Vars(r)
diff --git a/api/preference.go b/api/preference.go
index f5c96f1dd..9550b6c92 100644
--- a/api/preference.go
+++ b/api/preference.go
@@ -7,11 +7,12 @@ import (
l4g "github.com/alecthomas/log4go"
"github.com/gorilla/mux"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
"net/http"
)
func InitPreference(r *mux.Router) {
- l4g.Debug("Initializing preference api routes")
+ l4g.Debug(utils.T("api.preference.init.debug"))
sr := r.PathPrefix("/preferences").Subrouter()
sr.Handle("/", ApiUserRequired(getAllPreferences)).Methods("GET")
@@ -33,14 +34,16 @@ func getAllPreferences(c *Context, w http.ResponseWriter, r *http.Request) {
func savePreferences(c *Context, w http.ResponseWriter, r *http.Request) {
preferences, err := model.PreferencesFromJson(r.Body)
if err != nil {
- c.Err = model.NewAppError("savePreferences", "Unable to decode preferences from request", err.Error())
+ c.Err = model.NewLocAppError("savePreferences", "api.preference.save_preferences.decode.app_error", nil, err.Error())
c.Err.StatusCode = http.StatusBadRequest
return
}
for _, preference := range preferences {
if c.Session.UserId != preference.UserId {
- c.Err = model.NewAppError("savePreferences", "Unable to set preferences for other user", "session.user_id="+c.Session.UserId+", preference.user_id="+preference.UserId)
+ c.Err = model.NewLocAppError("savePreferences", "api.preference.save_preferences.set.app_error", nil,
+ c.T("api.preference.save_preferences.set_details.app_error",
+ map[string]interface{}{"SessionUserId": c.Session.UserId, "PreferenceUserId": preference.UserId}))
c.Err.StatusCode = http.StatusUnauthorized
return
}
diff --git a/api/server.go b/api/server.go
index 33428009f..070ed7a70 100644
--- a/api/server.go
+++ b/api/server.go
@@ -25,7 +25,7 @@ var Srv *Server
func NewServer() {
- l4g.Info("Server is initializing...")
+ l4g.Info(utils.T("api.server.new_server.init.info"))
Srv = &Server{}
Srv.Store = store.NewSqlStore()
@@ -35,13 +35,13 @@ func NewServer() {
}
func StartServer() {
- l4g.Info("Starting Server...")
- l4g.Info("Server is listening on " + utils.Cfg.ServiceSettings.ListenAddress)
+ l4g.Info(utils.T("api.server.start_server.starting.info"))
+ l4g.Info(utils.T("api.server.start_server.listening.info"), utils.Cfg.ServiceSettings.ListenAddress)
var handler http.Handler = Srv.Router
if utils.Cfg.RateLimitSettings.EnableRateLimiter {
- l4g.Info("RateLimiter is enabled")
+ l4g.Info(utils.T("api.server.start_server.rate.info"))
vary := throttled.VaryBy{}
@@ -53,7 +53,7 @@ func StartServer() {
vary.Headers = strings.Fields(utils.Cfg.RateLimitSettings.VaryByHeader)
if utils.Cfg.RateLimitSettings.VaryByRemoteAddr {
- l4g.Warn("RateLimitSettings not configured properly using VaryByHeader and disabling VaryByRemoteAddr")
+ l4g.Warn(utils.T("api.server.start_server.rate.warn"))
vary.RemoteAddr = false
}
}
@@ -71,20 +71,20 @@ func StartServer() {
go func() {
err := manners.ListenAndServe(utils.Cfg.ServiceSettings.ListenAddress, handler)
if err != nil {
- l4g.Critical("Error starting server, err:%v", err)
+ l4g.Critical(utils.T("api.server.start_server.starting.critical"), err)
time.Sleep(time.Second)
- panic("Error starting server " + err.Error())
+ panic(utils.T("api.server.start_server.starting.panic") + err.Error())
}
}()
}
func StopServer() {
- l4g.Info("Stopping Server...")
+ l4g.Info(utils.T("api.server.stop_server.stopping.info"))
manners.Close()
Srv.Store.Close()
hub.Stop()
- l4g.Info("Server stopped")
+ l4g.Info(utils.T("api.server.stop_server.stopped.info"))
}
diff --git a/api/slackimport.go b/api/slackimport.go
index e0a0ff036..6497ac261 100644
--- a/api/slackimport.go
+++ b/api/slackimport.go
@@ -9,6 +9,7 @@ import (
"encoding/json"
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
"io"
"mime/multipart"
"strconv"
@@ -44,7 +45,7 @@ func SlackConvertTimeStamp(ts string) int64 {
timeStamp, err := strconv.ParseInt(timeString, 10, 64)
if err != nil {
- l4g.Warn("Bad timestamp detected")
+ l4g.Warn(utils.T("api.slackimport.slack_convert_timestamp.bad.warn"))
return 1
}
return timeStamp * 1000 // Convert to milliseconds
@@ -91,7 +92,7 @@ func SlackParsePosts(data io.Reader) []SlackPost {
func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map[string]*model.User {
// Log header
- log.WriteString("\r\n Users Created\r\n")
+ log.WriteString(utils.T("api.slackimport.slack_add_users.created"))
log.WriteString("===============\r\n\r\n")
addedUsers := make(map[string]*model.User)
@@ -118,9 +119,9 @@ func SlackAddUsers(teamId string, slackusers []SlackUser, log *bytes.Buffer) map
if mUser := ImportUser(&newUser); mUser != nil {
addedUsers[sUser.Id] = mUser
- log.WriteString("Email, Password: " + newUser.Email + ", " + password + "\r\n")
+ log.WriteString(utils.T("api.slackimport.slack_add_users.email_pwd", map[string]interface{}{"Email": newUser.Email, "Password": password}))
} else {
- log.WriteString("Unable to import user: " + sUser.Username + "\r\n")
+ log.WriteString(utils.T("api.slackimport.slack_add_users.unable_import", map[string]interface{}{"Username": sUser.Username}))
}
}
@@ -132,10 +133,10 @@ func SlackAddPosts(channel *model.Channel, posts []SlackPost, users map[string]*
switch {
case sPost.Type == "message" && (sPost.SubType == "" || sPost.SubType == "file_share"):
if sPost.User == "" {
- l4g.Debug("Message without user")
+ l4g.Debug(utils.T("api.slackimport.slack_add_posts.without_user.debug"))
continue
} else if users[sPost.User] == nil {
- l4g.Debug("User: " + sPost.User + " does not exist!")
+ l4g.Debug(utils.T("api.slackimport.slack_add_posts.user_no_exists.debug"), sPost.User)
continue
}
newPost := model.Post{
@@ -147,10 +148,10 @@ func SlackAddPosts(channel *model.Channel, posts []SlackPost, users map[string]*
ImportPost(&newPost)
case sPost.Type == "message" && sPost.SubType == "file_comment":
if sPost.Comment["user"] == "" {
- l4g.Debug("Message without user")
+ l4g.Debug(utils.T("api.slackimport.slack_add_posts.msg_no_usr.debug"))
continue
} else if users[sPost.Comment["user"]] == nil {
- l4g.Debug("User: " + sPost.User + " does not exist!")
+ l4g.Debug(utils.T("api.slackimport.slack_add_posts.user_no_exists.debug"), sPost.User)
continue
}
newPost := model.Post{
@@ -163,16 +164,16 @@ func SlackAddPosts(channel *model.Channel, posts []SlackPost, users map[string]*
case sPost.Type == "message" && sPost.SubType == "bot_message":
// In the future this will use the "Action Post" spec to post
// a message without using a username. For now we just warn that we don't handle this case
- l4g.Warn("Slack bot posts are not imported yet")
+ l4g.Warn(utils.T("api.slackimport.slack_add_posts.bot.warn"))
default:
- l4g.Warn("Unsupported post type: " + sPost.Type + ", " + sPost.SubType)
+ l4g.Warn(utils.T("api.slackimport.slack_add_posts.unsupported.warn"), sPost.Type, sPost.SubType)
}
}
}
func SlackAddChannels(teamId string, slackchannels []SlackChannel, posts map[string][]SlackPost, users map[string]*model.User, log *bytes.Buffer) map[string]*model.Channel {
// Write Header
- log.WriteString("\r\n Channels Added \r\n")
+ log.WriteString(utils.T("api.slackimport.slack_add_channels.added"))
log.WriteString("=================\r\n\r\n")
addedChannels := make(map[string]*model.Channel)
@@ -188,12 +189,12 @@ func SlackAddChannels(teamId string, slackchannels []SlackChannel, posts map[str
if mChannel == nil {
// Maybe it already exists?
if result := <-Srv.Store.Channel().GetByName(teamId, sChannel.Name); result.Err != nil {
- l4g.Debug("Failed to import: %s", newChannel.DisplayName)
- log.WriteString("Failed to import: " + newChannel.DisplayName + "\r\n")
+ l4g.Debug(utils.T("api.slackimport.slack_add_channels.import_failed.debug"), newChannel.DisplayName)
+ log.WriteString(utils.T("api.slackimport.slack_add_channels.import_failed", map[string]interface{}{"DisplayName": newChannel.DisplayName}))
continue
} else {
mChannel = result.Data.(*model.Channel)
- log.WriteString("Merged with existing channel: " + newChannel.DisplayName + "\r\n")
+ log.WriteString(utils.T("api.slackimport.slack_add_channels.merge", map[string]interface{}{"DisplayName": newChannel.DisplayName}))
}
}
log.WriteString(newChannel.DisplayName + "\r\n")
@@ -207,11 +208,11 @@ func SlackAddChannels(teamId string, slackchannels []SlackChannel, posts map[str
func SlackImport(fileData multipart.File, fileSize int64, teamID string) (*model.AppError, *bytes.Buffer) {
zipreader, err := zip.NewReader(fileData, fileSize)
if err != nil || zipreader.File == nil {
- return model.NewAppError("SlackImport", "Unable to open zip file", err.Error()), nil
+ return model.NewLocAppError("SlackImport", "api.slackimport.slack_import.zip.app_error", nil, err.Error()), nil
}
// Create log file
- log := bytes.NewBufferString("Mattermost Slack Import Log\r\n")
+ log := bytes.NewBufferString(utils.T("api.slackimport.slack_import.log"))
var channels []SlackChannel
var users []SlackUser
@@ -219,7 +220,7 @@ func SlackImport(fileData multipart.File, fileSize int64, teamID string) (*model
for _, file := range zipreader.File {
reader, err := file.Open()
if err != nil {
- return model.NewAppError("SlackImport", "Unable to open: "+file.Name, err.Error()), log
+ return model.NewLocAppError("SlackImport", "api.slackimport.slack_import.open.app_error", map[string]interface{}{"Filename": file.Name}, err.Error()), log
}
if file.Name == "channels.json" {
channels = SlackParseChannels(reader)
@@ -243,11 +244,11 @@ func SlackImport(fileData multipart.File, fileSize int64, teamID string) (*model
addedUsers := SlackAddUsers(teamID, users, log)
SlackAddChannels(teamID, channels, posts, addedUsers, log)
- log.WriteString("\r\n Notes \r\n")
+ log.WriteString(utils.T("api.slackimport.slack_import.notes"))
log.WriteString("=======\r\n\r\n")
- log.WriteString("- Some posts may not have been imported because they where not supported by this importer.\r\n")
- log.WriteString("- Slack bot posts are currently not supported.\r\n")
+ log.WriteString(utils.T("api.slackimport.slack_import.note1"))
+ log.WriteString(utils.T("api.slackimport.slack_import.note2"))
return nil, log
}
diff --git a/api/team.go b/api/team.go
index e2dd8807e..779a6affe 100644
--- a/api/team.go
+++ b/api/team.go
@@ -11,6 +11,7 @@ import (
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
"github.com/mattermost/platform/utils"
+ "html/template"
"net/http"
"net/url"
"strconv"
@@ -19,7 +20,7 @@ import (
)
func InitTeam(r *mux.Router) {
- l4g.Debug("Initializing team api routes")
+ l4g.Debug(utils.T("api.team.init.debug"))
sr := r.PathPrefix("/teams").Subrouter()
sr.Handle("/create", ApiAppHandler(createTeam)).Methods("POST")
@@ -40,7 +41,7 @@ func InitTeam(r *mux.Router) {
func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.EmailSettings.EnableSignUpWithEmail {
- c.Err = model.NewAppError("signupTeam", "Team sign-up with email is disabled.", "")
+ c.Err = model.NewLocAppError("signupTeam", "api.team.signup_team.email_disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -57,10 +58,16 @@ func signupTeam(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- subjectPage := NewServerTemplatePage("signup_team_subject")
- subjectPage.Props["SiteURL"] = c.GetSiteURL()
- bodyPage := NewServerTemplatePage("signup_team_body")
+ subjectPage := NewServerTemplatePage("signup_team_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.signup_team_subject",
+ map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})
+
+ bodyPage := NewServerTemplatePage("signup_team_body", c.Locale)
bodyPage.Props["SiteURL"] = c.GetSiteURL()
+ bodyPage.Props["Title"] = c.T("api.templates.signup_team_body.title")
+ bodyPage.Props["Button"] = c.T("api.templates.signup_team_body.button")
+ bodyPage.Html["Info"] = template.HTML(c.T("api.templates.signup_team_body.button",
+ map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]}))
props := make(map[string]string)
props["email"] = email
@@ -147,7 +154,7 @@ func createTeamFromSSO(c *Context, w http.ResponseWriter, r *http.Request) {
func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.EmailSettings.EnableSignUpWithEmail {
- c.Err = model.NewAppError("createTeamFromSignup", "Team sign-up with email is disabled.", "")
+ c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.email_disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -188,13 +195,13 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
teamSignup.User.Password = password
if !model.ComparePassword(teamSignup.Hash, fmt.Sprintf("%v:%v", teamSignup.Data, utils.Cfg.EmailSettings.InviteSalt)) {
- c.Err = model.NewAppError("createTeamFromSignup", "The signup link does not appear to be valid", "")
+ c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.invalid_link.app_error", nil, "")
return
}
t, err := strconv.ParseInt(props["time"], 10, 64)
if err != nil || model.GetMillis()-t > 1000*60*60 { // one hour
- c.Err = model.NewAppError("createTeamFromSignup", "The signup link has expired", "")
+ c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.expired_link.app_error", nil, "")
return
}
@@ -204,7 +211,7 @@ func createTeamFromSignup(c *Context, w http.ResponseWriter, r *http.Request) {
}
if found {
- c.Err = model.NewAppError("createTeamFromSignup", "This URL is unavailable. Please try another.", "d="+teamSignup.Team.Name)
+ c.Err = model.NewLocAppError("createTeamFromSignup", "api.team.create_team_from_signup.unavailable.app_error", nil, "d="+teamSignup.Team.Name)
return
}
@@ -249,7 +256,7 @@ func createTeam(c *Context, w http.ResponseWriter, r *http.Request) {
func CreateTeam(c *Context, team *model.Team) *model.Team {
if !utils.Cfg.EmailSettings.EnableSignUpWithEmail {
- c.Err = model.NewAppError("createTeam", "Team sign-up with email is disabled.", "")
+ c.Err = model.NewLocAppError("createTeam", "api.team.create_team.email_disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return nil
}
@@ -283,7 +290,7 @@ func isTeamCreationAllowed(c *Context, email string) bool {
email = strings.ToLower(email)
if !utils.Cfg.TeamSettings.EnableTeamCreation {
- c.Err = model.NewAppError("isTeamCreationAllowed", "Team creation has been disabled. Please ask your systems administrator for details.", "")
+ c.Err = model.NewLocAppError("isTeamCreationAllowed", "api.team.is_team_creation_allowed.disabled.app_error", nil, "")
return false
}
@@ -300,7 +307,7 @@ func isTeamCreationAllowed(c *Context, email string) bool {
}
if len(utils.Cfg.TeamSettings.RestrictCreationToDomains) > 0 && !matched {
- c.Err = model.NewAppError("isTeamCreationAllowed", "Email must be from a specific domain (e.g. @example.com). Please ask your systems administrator for details.", "")
+ c.Err = model.NewLocAppError("isTeamCreationAllowed", "api.team.is_team_creation_allowed.domain.app_error", nil, "")
return false
}
@@ -427,10 +434,16 @@ func emailTeams(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- subjectPage := NewServerTemplatePage("find_teams_subject")
- subjectPage.ClientCfg["SiteURL"] = c.GetSiteURL()
- bodyPage := NewServerTemplatePage("find_teams_body")
- bodyPage.ClientCfg["SiteURL"] = c.GetSiteURL()
+ siteURL := c.GetSiteURL()
+ subjectPage := NewServerTemplatePage("find_teams_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.find_teams_subject",
+ map[string]interface{}{"SiteName": utils.ClientCfg["SiteName"]})
+
+ bodyPage := NewServerTemplatePage("find_teams_body", c.Locale)
+ bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = c.T("api.templates.find_teams_body.title")
+ bodyPage.Props["Found"] = c.T("api.templates.find_teams_body.found")
+ bodyPage.Props["NotFound"] = c.T("api.templates.find_teams_body.not_found")
if result := <-Srv.Store.Team().GetTeamsForEmail(email); result.Err != nil {
c.Err = result.Err
@@ -442,10 +455,10 @@ func emailTeams(c *Context, w http.ResponseWriter, r *http.Request) {
for _, team := range teams {
props[team.Name] = c.GetTeamURLFromTeam(team)
}
- bodyPage.Props = props
+ bodyPage.Extra = props
if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("An error occured while sending an email in emailTeams err=%v", err)
+ l4g.Error(utils.T("api.team.email_teams.sending.error"), err)
}
w.Write([]byte(model.MapToJson(m)))
@@ -455,7 +468,7 @@ func emailTeams(c *Context, w http.ResponseWriter, r *http.Request) {
func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
invites := model.InvitesFromJson(r.Body)
if len(invites.Invites) == 0 {
- c.Err = model.NewAppError("Team.InviteMembers", "No one to invite.", "")
+ c.Err = model.NewLocAppError("Team.InviteMembers", "api.team.invite_members.no_one.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
@@ -483,7 +496,7 @@ func inviteMembers(c *Context, w http.ResponseWriter, r *http.Request) {
for i, invite := range invites.Invites {
if result := <-Srv.Store.User().GetByEmail(c.Session.TeamId, invite["email"]); result.Err == nil || result.Err.Message != store.MISSING_ACCOUNT_ERROR {
invNum = int64(i)
- c.Err = model.NewAppError("invite_members", "This person is already on your team", strconv.FormatInt(invNum, 10))
+ c.Err = model.NewLocAppError("invite_members", "api.team.invite_members.already.app_error", nil, strconv.FormatInt(invNum, 10))
return
}
}
@@ -506,21 +519,24 @@ func InviteMembers(c *Context, team *model.Team, user *model.User, invites []str
senderRole := ""
if c.IsTeamAdmin() {
- senderRole = "administrator"
+ senderRole = c.T("api.team.invite_members.admin")
} else {
- senderRole = "member"
+ senderRole = c.T("api.team.invite_members.member")
}
- subjectPage := NewServerTemplatePage("invite_subject")
- subjectPage.Props["SenderName"] = sender
- subjectPage.Props["TeamDisplayName"] = team.DisplayName
+ subjectPage := NewServerTemplatePage("invite_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.invite_subject",
+ map[string]interface{}{"SenderName": sender, "TeamDisplayName": team.DisplayName, "SiteName": utils.ClientCfg["SiteName"]})
- bodyPage := NewServerTemplatePage("invite_body")
+ bodyPage := NewServerTemplatePage("invite_body", c.Locale)
bodyPage.Props["SiteURL"] = c.GetSiteURL()
- bodyPage.Props["TeamURL"] = c.GetTeamURL()
- bodyPage.Props["TeamDisplayName"] = team.DisplayName
- bodyPage.Props["SenderName"] = sender
- bodyPage.Props["SenderStatus"] = senderRole
+ bodyPage.Props["Title"] = c.T("api.templates.invite_body.title")
+ bodyPage.Html["Info"] = template.HTML(c.T("api.templates.invite_body.info",
+ map[string]interface{}{"SenderStatus": senderRole, "SenderName": sender, "TeamDisplayName": team.DisplayName}))
+ bodyPage.Props["Button"] = c.T("api.templates.invite_body.button")
+ bodyPage.Html["ExtraInfo"] = template.HTML(c.T("api.templates.invite_body.extra_info",
+ map[string]interface{}{"TeamDisplayName": team.DisplayName, "TeamURL": c.GetTeamURL()}))
+
props := make(map[string]string)
props["email"] = invite
props["id"] = team.Id
@@ -532,11 +548,11 @@ func InviteMembers(c *Context, team *model.Team, user *model.User, invites []str
bodyPage.Props["Link"] = fmt.Sprintf("%s/signup_user_complete/?d=%s&h=%s", c.GetSiteURL(), url.QueryEscape(data), url.QueryEscape(hash))
if !utils.Cfg.EmailSettings.SendEmailNotifications {
- l4g.Info("sending invitation to %v %v", invite, bodyPage.Props["Link"])
+ l4g.Info(utils.T("api.team.invite_members.sending.info"), invite, bodyPage.Props["Link"])
}
if err := utils.SendMail(invite, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("Failed to send invite email successfully err=%v", err)
+ l4g.Error(utils.T("api.team.invite_members.send.error"), err)
}
}
}
@@ -554,7 +570,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
team.Id = c.Session.TeamId
if !c.IsTeamAdmin() {
- c.Err = model.NewAppError("updateTeam", "You do not have the appropriate permissions", "userId="+c.Session.UserId)
+ c.Err = model.NewLocAppError("updateTeam", "api.team.update_team.permissions.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -586,7 +602,7 @@ func updateTeam(c *Context, w http.ResponseWriter, r *http.Request) {
}
func PermanentDeleteTeam(c *Context, team *model.Team) *model.AppError {
- l4g.Warn("Attempting to permanently delete team %v id=%v", team.Name, team.Id)
+ l4g.Warn(utils.T("api.team.permanent_delete_team.attempting.warn"), team.Name, team.Id)
c.Path = "/teams/permanent_delete"
c.LogAuditWithUserId("", fmt.Sprintf("attempt teamId=%v", team.Id))
@@ -612,7 +628,7 @@ func PermanentDeleteTeam(c *Context, team *model.Team) *model.AppError {
return result.Err
}
- l4g.Warn("Permanently deleted team %v id=%v", team.Name, team.Id)
+ l4g.Warn(utils.T("api.team.permanent_delete_team.deleted.warn"), team.Name, team.Id)
c.LogAuditWithUserId("", fmt.Sprintf("success teamId=%v", team.Id))
return nil
@@ -639,13 +655,13 @@ func getMyTeam(c *Context, w http.ResponseWriter, r *http.Request) {
func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.HasPermissionsToTeam(c.Session.TeamId, "import") || !c.IsTeamAdmin() {
- c.Err = model.NewAppError("importTeam", "Only a team admin can import data.", "userId="+c.Session.UserId)
+ c.Err = model.NewLocAppError("importTeam", "api.team.import_team.admin.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden
return
}
if err := r.ParseMultipartForm(10000000); err != nil {
- c.Err = model.NewAppError("importTeam", "Could not parse multipart form", err.Error())
+ c.Err = model.NewLocAppError("importTeam", "api.team.import_team.parse.app_error", nil, err.Error())
return
}
@@ -654,27 +670,27 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
fileSizeStr, ok := r.MultipartForm.Value["filesize"]
if !ok {
- c.Err = model.NewAppError("importTeam", "Filesize unavilable", "")
+ c.Err = model.NewLocAppError("importTeam", "api.team.import_team.unavailable.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
fileSize, err := strconv.ParseInt(fileSizeStr[0], 10, 64)
if err != nil {
- c.Err = model.NewAppError("importTeam", "Filesize not an integer", "")
+ c.Err = model.NewLocAppError("importTeam", "api.team.import_team.integer.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
fileInfoArray, ok := r.MultipartForm.File["file"]
if !ok {
- c.Err = model.NewAppError("importTeam", "No file under 'file' in request", "")
+ c.Err = model.NewLocAppError("importTeam", "api.team.import_team.no_file.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
if len(fileInfoArray) <= 0 {
- c.Err = model.NewAppError("importTeam", "Empty array under 'file' in request", "")
+ c.Err = model.NewLocAppError("importTeam", "api.team.import_team.array.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
@@ -684,7 +700,7 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
fileData, err := fileInfo.Open()
defer fileData.Close()
if err != nil {
- c.Err = model.NewAppError("importTeam", "Could not open file", err.Error())
+ c.Err = model.NewLocAppError("importTeam", "api.team.import_team.open.app_error", nil, err.Error())
c.Err.StatusCode = http.StatusBadRequest
return
}
@@ -706,7 +722,7 @@ func importTeam(c *Context, w http.ResponseWriter, r *http.Request) {
func exportTeam(c *Context, w http.ResponseWriter, r *http.Request) {
if !c.HasPermissionsToTeam(c.Session.TeamId, "export") || !c.IsTeamAdmin() {
- c.Err = model.NewAppError("exportTeam", "Only a team admin can export data.", "userId="+c.Session.UserId)
+ c.Err = model.NewLocAppError("exportTeam", "api.team.export_team.admin.app_error", nil, "userId="+c.Session.UserId)
c.Err.StatusCode = http.StatusForbidden
return
}
diff --git a/api/templates/email_change_body.html b/api/templates/email_change_body.html
index 7349aee6f..4f28584c4 100644
--- a/api/templates/email_change_body.html
+++ b/api/templates/email_change_body.html
@@ -17,8 +17,8 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You updated your email</h2>
- <p>You email address for {{.Props.TeamDisplayName}} has been changed to {{.Props.NewEmail}}.<br>If you did not make this change, please contact the system administrator.</p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{.Props.Info}}</p>
</td>
</tr>
<tr>
diff --git a/api/templates/email_change_subject.html b/api/templates/email_change_subject.html
index 4ff8026f1..afabc2191 100644
--- a/api/templates/email_change_subject.html
+++ b/api/templates/email_change_subject.html
@@ -1 +1 @@
-{{define "email_change_subject"}}[{{.ClientCfg.SiteName}}] Your email address has changed for {{.Props.TeamDisplayName}}{{end}}
+{{define "email_change_subject"}}[{{.ClientCfg.SiteName}}] {{.Props.Subject}}{{end}}
diff --git a/api/templates/email_change_verify_body.html b/api/templates/email_change_verify_body.html
index 9d2c559b3..0d0c0aaba 100644
--- a/api/templates/email_change_verify_body.html
+++ b/api/templates/email_change_verify_body.html
@@ -17,10 +17,10 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You updated your email</h2>
- <p>To finish updating your email address for {{.Props.TeamDisplayName}}, please click the link below to confirm this is the right address.</p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{.Props.Info}}</p>
<p style="margin: 20px 0 15px">
- <a href="{{.Props.VerifyUrl}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Verify Email</a>
+ <a href="{{.Props.VerifyUrl}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">{{.Props.VerifyButton}}</a>
</p>
</td>
</tr>
diff --git a/api/templates/email_change_verify_subject.html b/api/templates/email_change_verify_subject.html
index 744aaccfc..4fc4f4846 100644
--- a/api/templates/email_change_verify_subject.html
+++ b/api/templates/email_change_verify_subject.html
@@ -1 +1 @@
-{{define "email_change_verify_subject"}}[{{.ClientCfg.SiteName}}] Verify new email address for {{.Props.TeamDisplayName}}{{end}}
+{{define "email_change_verify_subject"}}[{{.ClientCfg.SiteName}}] {{.Props.Subject}}{{end}}
diff --git a/api/templates/email_footer.html b/api/templates/email_footer.html
index e3ff9c584..6dc7fa483 100644
--- a/api/templates/email_footer.html
+++ b/api/templates/email_footer.html
@@ -6,7 +6,7 @@
</p>
<p style="padding: 0 50px;">
(c) 2015 Mattermost, Inc. 855 El Camino Real, 13A-168, Palo Alto, CA, 94301.<br>
- To change your notification preferences, log in to your team site and go to Account Settings > Notifications.
+ {{.Props.Footer}}
</p>
</td>
diff --git a/api/templates/email_info.html b/api/templates/email_info.html
index 48725d144..0a34f18a0 100644
--- a/api/templates/email_info.html
+++ b/api/templates/email_info.html
@@ -1,9 +1,7 @@
{{define "email_info"}}
<td style="color: #999; padding-top: 20px; line-height: 25px; font-size: 13px;">
- Any questions at all, mail us any time: <a href="mailto:{{.ClientCfg.FeedbackEmail}}" style="text-decoration: none; color:#2389D7;">{{.ClientCfg.FeedbackEmail}}</a>.<br>
- Best wishes,<br>
- The {{.ClientCfg.SiteName}} Team<br>
+ {{.Html.EmailInfo}}
</td>
{{end}}
diff --git a/api/templates/error.html b/api/templates/error.html
index 6944f6c68..2b6211be2 100644
--- a/api/templates/error.html
+++ b/api/templates/error.html
@@ -11,8 +11,8 @@
<script src="/static/js/bootstrap-3.3.5.min.js"></script>
<script src="/static/js/react-bootstrap-0.25.1.min.js"></script>
- <link id="favicon" rel="icon" href="/static/images/favicon.ico" type="image/x-icon">
- <link rel="shortcut icon" href="/static/images/favicon.ico" type="image/x-icon">
+ <link id="favicon" rel="icon" href="/static/images/favicon/favicon-16x16.png" type="image/x-icon">
+ <link rel="shortcut icon" href="/static/images/favicon/favicon-16x16.png" type="image/x-icon">
<link href='/static/css/google-fonts.css' rel='stylesheet' type='text/css'>
<link rel="stylesheet" href="/static/css/styles.css">
@@ -22,9 +22,9 @@
<div class="container-fluid">
<div class="error__container">
<div class="error__icon"><i class="fa fa-exclamation-triangle"></i></div>
- <h2>{{ .ClientCfg.SiteName }} needs your help:</h2>
+ <h2>{{.Props.Title}}</h2>
<p>{{ .Props.Message }}</p>
- <a href="{{.Props.SiteURL}}">Go back to team site</a>
+ <a href="{{.Props.SiteURL}}">{{.Props.Link}}</a>
</div>
</div>
</body>
diff --git a/api/templates/find_teams_body.html b/api/templates/find_teams_body.html
index 0b52af033..1324091aa 100644
--- a/api/templates/find_teams_body.html
+++ b/api/templates/find_teams_body.html
@@ -17,14 +17,14 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">Finding teams</h2>
- <p>{{ if .Props }}
- Your request to find teams associated with your email found the following:<br>
- {{range $index, $element := .Props}}
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{ if .Extra }}
+ {{.Props.Found}}<br>
+ {{range $index, $element := .Extra}}
<a href="{{ $element }}" style="text-decoration: none; color:#2389D7;">{{ $index }}</a><br>
{{ end }}
{{ else }}
- We could not find any teams for the given email.
+ {{.Props.NotFound}}
{{ end }}
</p>
</td>
diff --git a/api/templates/find_teams_subject.html b/api/templates/find_teams_subject.html
index f3a1437b3..ebc339562 100644
--- a/api/templates/find_teams_subject.html
+++ b/api/templates/find_teams_subject.html
@@ -1 +1 @@
-{{define "find_teams_subject"}}Your {{ .ClientCfg.SiteName }} Teams{{end}}
+{{define "find_teams_subject"}}{{.Props.Subject}}{{end}}
diff --git a/api/templates/invite_body.html b/api/templates/invite_body.html
index a81d0c3d5..2b6bde6d3 100644
--- a/api/templates/invite_body.html
+++ b/api/templates/invite_body.html
@@ -17,13 +17,13 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You've been invited</h2>
- <p>The team {{.Props.SenderStatus}} <strong>{{.Props.SenderName}}</strong>, has invited you to join <strong>{{.Props.TeamDisplayName}}</strong>.</p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{.Html.Info}}</p>
<p style="margin: 30px 0 15px">
- <a href="{{.Props.Link}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Join Team</a>
+ <a href="{{.Props.Link}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">{{.Props.Button}}</a>
</p>
<br/>
- <p>Mattermost lets you share messages and files from your PC or phone, with instant search and archiving. After you’ve joined <strong>{{.Props.TeamDisplayName}}</strong>, you can sign-in to your new team and access these features anytime from the web address:<br/><br/><a href="{{.Props.TeamURL}}">{{.Props.TeamURL}}</a></p>
+ <p>{{.Html.ExtraInfo}}</p>
</td>
</tr>
<tr>
diff --git a/api/templates/invite_subject.html b/api/templates/invite_subject.html
index 10f68969f..504915d50 100644
--- a/api/templates/invite_subject.html
+++ b/api/templates/invite_subject.html
@@ -1 +1 @@
-{{define "invite_subject"}}{{ .Props.SenderName }} invited you to join {{ .Props.TeamDisplayName }} Team on {{.ClientCfg.SiteName}}{{end}}
+{{define "invite_subject"}}{{.Props.Subject}}{{end}}
diff --git a/api/templates/password_change_body.html b/api/templates/password_change_body.html
index 6199a3423..2c4ba10ca 100644
--- a/api/templates/password_change_body.html
+++ b/api/templates/password_change_body.html
@@ -17,8 +17,8 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You updated your password</h2>
- <p>Your password has been updated for {{.Props.TeamDisplayName}} on {{ .Props.TeamURL }} by {{.Props.Method}}.<br>If this change wasn't initiated by you, please contact your system administrator.</p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{.Html.Info}}</p>
</td>
</tr>
<tr>
diff --git a/api/templates/password_change_subject.html b/api/templates/password_change_subject.html
index 0cbf052c1..897f1210d 100644
--- a/api/templates/password_change_subject.html
+++ b/api/templates/password_change_subject.html
@@ -1 +1 @@
-{{define "password_change_subject"}}Your password has been updated for {{.Props.TeamDisplayName}} on {{ .ClientCfg.SiteName }}{{end}}
+{{define "password_change_subject"}}{{.Props.Subject}}{{end}}
diff --git a/api/templates/post_body.html b/api/templates/post_body.html
index 468d5e205..54f34d1dd 100644
--- a/api/templates/post_body.html
+++ b/api/templates/post_body.html
@@ -17,10 +17,10 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You were mentioned</h2>
- <p>CHANNEL: {{.Props.ChannelName}}<br>{{.Props.SenderName}} - {{.Props.Hour}}:{{.Props.Minute}} {{.Props.TimeZone}}, {{.Props.Month}} {{.Props.Day}}<br><pre style="text-align:left;font-family: 'Lato', sans-serif; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">{{.Props.PostMessage}}</pre></p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.BodyText}}</h2>
+ <p>{{.Html.Info}}<br><pre style="text-align:left;font-family: 'Lato', sans-serif; white-space: pre-wrap; white-space: -moz-pre-wrap; white-space: -pre-wrap; white-space: -o-pre-wrap; word-wrap: break-word;">{{.Props.PostMessage}}</pre></p>
<p style="margin: 20px 0 15px">
- <a href="{{.Props.TeamLink}}" style="background: #2389D7; display: inline-block; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 170px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Go To Channel</a>
+ <a href="{{.Props.TeamLink}}" style="background: #2389D7; display: inline-block; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 170px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">{{.Props.Button}}</a>
</p>
</td>
</tr>
diff --git a/api/templates/post_subject.html b/api/templates/post_subject.html
index f53353d85..60daaa432 100644
--- a/api/templates/post_subject.html
+++ b/api/templates/post_subject.html
@@ -1 +1 @@
-{{define "post_subject"}}[{{.ClientCfg.SiteName}}] {{.Props.TeamDisplayName}} Team Notifications for {{.Props.Month}} {{.Props.Day}}, {{.Props.Year}}{{end}}
+{{define "post_subject"}}[{{.ClientCfg.SiteName}}] {{.Props.Subject}}{{end}}
diff --git a/api/templates/reset_body.html b/api/templates/reset_body.html
index a608c804a..69cd44957 100644
--- a/api/templates/reset_body.html
+++ b/api/templates/reset_body.html
@@ -17,10 +17,10 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You requested a password reset</h2>
- <p>To change your password, click "Reset Password" below.<br>If you did not mean to reset your password, please ignore this email and your password will remain the same.</p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{.Html.Info}}</p>
<p style="margin: 20px 0 15px">
- <a href="{{.Props.ResetUrl}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Reset Password</a>
+ <a href="{{.Props.ResetUrl}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">{{.Props.Button}}</a>
</p>
</td>
</tr>
diff --git a/api/templates/reset_subject.html b/api/templates/reset_subject.html
index 87ad7bc38..a2852d332 100644
--- a/api/templates/reset_subject.html
+++ b/api/templates/reset_subject.html
@@ -1 +1 @@
-{{define "reset_subject"}}Reset your password{{end}}
+{{define "reset_subject"}}{{.Props.Subject}}{{end}}
diff --git a/api/templates/signin_change_body.html b/api/templates/signin_change_body.html
index 5b96df944..af8577f0f 100644
--- a/api/templates/signin_change_body.html
+++ b/api/templates/signin_change_body.html
@@ -17,8 +17,8 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You updated your sign-in method</h2>
- <p>You updated your sign-in method for {{.Props.TeamDisplayName}} on {{ .Props.TeamURL }} to {{.Props.Method}}.<br>If this change wasn't initiated by you, please contact your system administrator.</p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{.Html.Info}}</p>
</td>
</tr>
<tr>
diff --git a/api/templates/signin_change_subject.html b/api/templates/signin_change_subject.html
index b1d644a28..606dc4df3 100644
--- a/api/templates/signin_change_subject.html
+++ b/api/templates/signin_change_subject.html
@@ -1 +1 @@
-{{define "signin_change_subject"}}You updated your sign-in method for {{.Props.TeamDisplayName}} on {{ .ClientCfg.SiteName }}{{end}}
+{{define "signin_change_subject"}}{{.Props.Subject}}{{end}}
diff --git a/api/templates/signup_team_body.html b/api/templates/signup_team_body.html
index 2f384ac43..683a9891e 100644
--- a/api/templates/signup_team_body.html
+++ b/api/templates/signup_team_body.html
@@ -17,11 +17,11 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">Thanks for creating a team!</h2>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
<p style="margin: 20px 0 25px">
- <a href="{{.Props.Link}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Set up your team</a>
+ <a href="{{.Props.Link}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">{{.Props.Button}}</a>
</p>
- {{ .ClientCfg.SiteName }} is one place for all your team communication, searchable and available anywhere.<br>You'll get more out of {{ .ClientCfg.SiteName }} when your team is in constant communication--let's get them on board.<br></p>
+ {{.Html.Info}}<br></p>
</td>
</tr>
<tr>
diff --git a/api/templates/signup_team_subject.html b/api/templates/signup_team_subject.html
index 4fc5b3d72..413a5c8c1 100644
--- a/api/templates/signup_team_subject.html
+++ b/api/templates/signup_team_subject.html
@@ -1 +1 @@
-{{define "signup_team_subject"}}{{ .ClientCfg.SiteName }} Team Setup{{end}} \ No newline at end of file
+{{define "signup_team_subject"}}{{.Props.Subject}}{{end}} \ No newline at end of file
diff --git a/api/templates/verify_body.html b/api/templates/verify_body.html
index c42b2a372..2b0d25f94 100644
--- a/api/templates/verify_body.html
+++ b/api/templates/verify_body.html
@@ -17,10 +17,10 @@
<table border="0" cellpadding="0" cellspacing="0" style="padding: 20px 50px 0; text-align: center; margin: 0 auto">
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You've joined the {{ .Props.TeamDisplayName }} team</h2>
- <p>Please verify your email address by clicking below.</p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{.Props.Info}}</p>
<p style="margin: 20px 0 15px">
- <a href="{{.Props.VerifyUrl}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Verify Email</a>
+ <a href="{{.Props.VerifyUrl}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">{{.Props.Button}}</a>
</p>
</td>
</tr>
diff --git a/api/templates/verify_subject.html b/api/templates/verify_subject.html
index 9a3a11282..ad7fc2aaa 100644
--- a/api/templates/verify_subject.html
+++ b/api/templates/verify_subject.html
@@ -1 +1 @@
-{{define "verify_subject"}}[{{ .Props.TeamDisplayName }} {{ .ClientCfg.SiteName }}] Email Verification{{end}}
+{{define "verify_subject"}}{{.Props.Subject}}{{end}}
diff --git a/api/templates/welcome_body.html b/api/templates/welcome_body.html
index 71d838b08..b5ca9beb3 100644
--- a/api/templates/welcome_body.html
+++ b/api/templates/welcome_body.html
@@ -18,19 +18,19 @@
{{if .Props.VerifyUrl }}
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 10px;">You've joined the {{ .Props.TeamDisplayName }} team</h2>
- <p>Please verify your email address by clicking below.</p>
+ <h2 style="font-weight: normal; margin-top: 10px;">{{.Props.Title}}</h2>
+ <p>{{.Props.Info}}</p>
<p style="margin: 20px 0 15px">
- <a href="{{.Props.VerifyUrl}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">Verify Email</a>
+ <a href="{{.Props.VerifyUrl}}" style="background: #2389D7; border-radius: 3px; color: #fff; border: none; outline: none; min-width: 200px; padding: 15px 25px; font-size: 14px; font-family: inherit; cursor: pointer; -webkit-appearance: none;text-decoration: none;">{{.Props.Button}}</a>
</p>
</td>
</tr>
{{end}}
<tr>
<td style="border-bottom: 1px solid #ddd; padding: 0 0 20px;">
- <h2 style="font-weight: normal; margin-top: 25px; line-height: 1.5;">You can sign-in to your new team from the web address:</h2>
+ <h2 style="font-weight: normal; margin-top: 25px; line-height: 1.5;">{{.Props.Info2}}</h2>
<a href="{{.Props.TeamURL}}">{{.Props.TeamURL}}</a>
- <p>Mattermost lets you share messages and files from your PC or phone, with instant search and archiving.</p>
+ <p>{{.Props.Info3}}</p>
</td>
</tr>
</table>
diff --git a/api/templates/welcome_subject.html b/api/templates/welcome_subject.html
index c3b70ef20..95189b900 100644
--- a/api/templates/welcome_subject.html
+++ b/api/templates/welcome_subject.html
@@ -1 +1 @@
-{{define "welcome_subject"}}You joined {{ .Props.TeamDisplayName }}{{end}}
+{{define "welcome_subject"}}{{.Props.Subject}}{{end}}
diff --git a/api/user.go b/api/user.go
index a6b4fb654..473f0da54 100644
--- a/api/user.go
+++ b/api/user.go
@@ -17,6 +17,7 @@ import (
"github.com/mattermost/platform/utils"
"github.com/mssola/user_agent"
"hash/fnv"
+ "html/template"
"image"
"image/color"
"image/draw"
@@ -32,7 +33,7 @@ import (
)
func InitUser(r *mux.Router) {
- l4g.Debug("Initializing user api routes")
+ l4g.Debug(utils.T("api.user.init.debug"))
sr := r.PathPrefix("/users").Subrouter()
sr.Handle("/create", ApiAppHandler(createUser)).Methods("POST")
@@ -64,7 +65,7 @@ func InitUser(r *mux.Router) {
func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.EmailSettings.EnableSignUpWithEmail || !utils.Cfg.TeamSettings.EnableUserCreation {
- c.Err = model.NewAppError("signupTeam", "User sign-up with email is disabled.", "")
+ c.Err = model.NewLocAppError("signupTeam", "api.user.create_user.signup_email_disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -98,18 +99,18 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(strings.NewReader(data))
if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.EmailSettings.InviteSalt)) {
- c.Err = model.NewAppError("createUser", "The signup link does not appear to be valid", "")
+ c.Err = model.NewLocAppError("createUser", "api.user.create_user.signup_link_invalid.app_error", nil, "")
return
}
t, err := strconv.ParseInt(props["time"], 10, 64)
if err != nil || model.GetMillis()-t > 1000*60*60*48 { // 48 hours
- c.Err = model.NewAppError("createUser", "The signup link has expired", "")
+ c.Err = model.NewLocAppError("createUser", "api.user.create_user.signup_link_expired.app_error", nil, "")
return
}
if user.TeamId != props["id"] {
- c.Err = model.NewAppError("createUser", "Invalid team name", data)
+ c.Err = model.NewLocAppError("createUser", "api.user.create_user.team_name.app_error", nil, data)
return
}
@@ -123,7 +124,7 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
}
if !CheckUserDomain(user, utils.Cfg.TeamSettings.RestrictCreationToDomains) {
- c.Err = model.NewAppError("createUser", "The email you provided does not belong to an accepted domain. Please contact your administrator or sign up with a different email.", "")
+ c.Err = model.NewLocAppError("createUser", "api.user.create_user.accepted_domain.app_error", nil, "")
return
}
@@ -134,7 +135,7 @@ func createUser(c *Context, w http.ResponseWriter, r *http.Request) {
}
if sendWelcomeEmail {
- sendWelcomeEmailAndForget(ruser.Id, ruser.Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team), ruser.EmailVerified)
+ sendWelcomeEmailAndForget(c, ruser.Id, ruser.Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team), ruser.EmailVerified)
}
w.Write([]byte(ruser.ToJson()))
@@ -208,27 +209,27 @@ func CreateUser(team *model.Team, user *model.User) (*model.User, *model.AppErro
user.MakeNonNil()
if result := <-Srv.Store.User().Save(user); result.Err != nil {
- l4g.Error("Couldn't save the user err=%v", result.Err)
+ l4g.Error(utils.T("api.user.create_user.save.error"), result.Err)
return nil, result.Err
} else {
ruser := result.Data.(*model.User)
// Soft error if there is an issue joining the default channels
if err := JoinDefaultChannels(ruser, channelRole); err != nil {
- l4g.Error("Encountered an issue joining default channels user_id=%s, team_id=%s, err=%v", ruser.Id, ruser.TeamId, err)
+ l4g.Error(utils.T("api.user.create_user.joining.error"), ruser.Id, ruser.TeamId, err)
}
addDirectChannelsAndForget(ruser)
if user.EmailVerified {
if cresult := <-Srv.Store.User().VerifyEmail(ruser.Id); cresult.Err != nil {
- l4g.Error("Failed to set email verified err=%v", cresult.Err)
+ l4g.Error(utils.T("api.user.create_user.verified.error"), cresult.Err)
}
}
pref := model.Preference{UserId: ruser.Id, Category: model.PREFERENCE_CATEGORY_TUTORIAL_STEPS, Name: ruser.Id, Value: "0"}
if presult := <-Srv.Store.Preference().Save(&model.Preferences{pref}); presult.Err != nil {
- l4g.Error("Encountered error saving tutorial preference, err=%v", presult.Err.Message)
+ l4g.Error(utils.T("api.user.create_user.tutorial.error"), presult.Err.Message)
}
ruser.Sanitize(map[string]bool{})
@@ -246,14 +247,14 @@ func CreateOAuthUser(c *Context, w http.ResponseWriter, r *http.Request, service
var user *model.User
provider := einterfaces.GetOauthProvider(service)
if provider == nil {
- c.Err = model.NewAppError("CreateOAuthUser", service+" oauth not avlailable on this server", "")
+ c.Err = model.NewLocAppError("CreateOAuthUser", "api.user.create_oauth_user.not_available.app_error", map[string]interface{}{"Service": service}, "")
return nil
} else {
user = provider.GetUserFromJson(userData)
}
if user == nil {
- c.Err = model.NewAppError("CreateOAuthUser", "Could not create user out of "+service+" user object", "")
+ c.Err = model.NewLocAppError("CreateOAuthUser", "api.user.create_oauth_user.create.app_error", map[string]interface{}{"Service": service}, "")
return nil
}
@@ -280,12 +281,14 @@ func CreateOAuthUser(c *Context, w http.ResponseWriter, r *http.Request, service
}
if result := <-suchan; result.Err == nil {
- c.Err = model.NewAppError("signupCompleteOAuth", "This "+service+" account has already been used to sign up for team "+team.DisplayName, "email="+user.Email)
+ c.Err = model.NewLocAppError("signupCompleteOAuth", "api.user.create_oauth_user.already_used.app_error",
+ map[string]interface{}{"Service": service, "DisplayName": team.DisplayName}, "email="+user.Email)
return nil
}
if result := <-euchan; result.Err == nil {
- c.Err = model.NewAppError("signupCompleteOAuth", "Team "+team.DisplayName+" already has a user with the email address attached to your "+service+" account", "email="+user.Email)
+ c.Err = model.NewLocAppError("signupCompleteOAuth", "api.user.create_oauth_user.already_attached.app_error",
+ map[string]interface{}{"Service": service, "DisplayName": team.DisplayName}, "email="+user.Email)
return nil
}
@@ -306,13 +309,19 @@ func CreateOAuthUser(c *Context, w http.ResponseWriter, r *http.Request, service
return ruser
}
-func sendWelcomeEmailAndForget(userId, email, teamName, teamDisplayName, siteURL, teamURL string, verified bool) {
+func sendWelcomeEmailAndForget(c *Context, userId, email, teamName, teamDisplayName, siteURL, teamURL string, verified bool) {
go func() {
- subjectPage := NewServerTemplatePage("welcome_subject")
- subjectPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage := NewServerTemplatePage("welcome_body")
+ subjectPage := NewServerTemplatePage("welcome_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.welcome_subject", map[string]interface{}{"TeamDisplayName": teamDisplayName})
+
+ bodyPage := NewServerTemplatePage("welcome_body", c.Locale)
bodyPage.Props["SiteURL"] = siteURL
+ bodyPage.Props["Title"] = c.T("api.templates.welcome_body.title", map[string]interface{}{"TeamDisplayName": teamDisplayName})
+ bodyPage.Props["Info"] = c.T("api.templates.welcome_body.info")
+ bodyPage.Props["Button"] = c.T("api.templates.welcome_body.button")
+ bodyPage.Props["Info2"] = c.T("api.templates.welcome_body.info2")
+ bodyPage.Props["Info3"] = c.T("api.templates.welcome_body.info3")
bodyPage.Props["TeamURL"] = teamURL
if !verified {
@@ -321,7 +330,7 @@ func sendWelcomeEmailAndForget(userId, email, teamName, teamDisplayName, siteURL
}
if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("Failed to send welcome email successfully err=%v", err)
+ l4g.Error(utils.T("api.user.send_welcome_email_and_forget.failed.error"), err)
}
}()
}
@@ -330,7 +339,7 @@ func addDirectChannelsAndForget(user *model.User) {
go func() {
var profiles map[string]*model.User
if result := <-Srv.Store.User().GetProfiles(user.TeamId); result.Err != nil {
- l4g.Error("Failed to add direct channel preferences for user user_id=%s, team_id=%s, err=%v", user.Id, user.TeamId, result.Err.Error())
+ l4g.Error(utils.T("api.user.add_direct_channels_and_forget.failed.error"), user.Id, user.TeamId, result.Err.Error())
return
} else {
profiles = result.Data.(map[string]*model.User)
@@ -360,26 +369,29 @@ func addDirectChannelsAndForget(user *model.User) {
}
if result := <-Srv.Store.Preference().Save(&preferences); result.Err != nil {
- l4g.Error("Failed to add direct channel preferences for new user user_id=%s, eam_id=%s, err=%v", user.Id, user.TeamId, result.Err.Error())
+ l4g.Error(utils.T("api.user.add_direct_channels_and_forget.failed.error"), user.Id, user.TeamId, result.Err.Error())
}
}()
}
-func SendVerifyEmailAndForget(userId, userEmail, teamName, teamDisplayName, siteURL, teamURL string) {
+func SendVerifyEmailAndForget(c *Context, userId, userEmail, teamName, teamDisplayName, siteURL, teamURL string) {
go func() {
link := fmt.Sprintf("%s/verify_email?uid=%s&hid=%s&teamname=%s&email=%s", siteURL, userId, model.HashPassword(userId), teamName, userEmail)
- subjectPage := NewServerTemplatePage("verify_subject")
- subjectPage.Props["SiteURL"] = siteURL
- subjectPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage := NewServerTemplatePage("verify_body")
+ subjectPage := NewServerTemplatePage("verify_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.verify_subject",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName, "SiteName": utils.ClientCfg["SiteName"]})
+
+ bodyPage := NewServerTemplatePage("verify_body", c.Locale)
bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["TeamDisplayName"] = teamDisplayName
+ bodyPage.Props["Title"] = c.T("api.templates.verify_body.title", map[string]interface{}{"TeamDisplayName": teamDisplayName})
+ bodyPage.Props["Info"] = c.T("api.templates.verify_body.info")
bodyPage.Props["VerifyUrl"] = link
+ bodyPage.Props["Button"] = c.T("api.templates.verify_body.button")
if err := utils.SendMail(userEmail, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("Failed to send verification email successfully err=%v", err)
+ l4g.Error(utils.T("api.user.send_verify_email_and_forget.failed.error"), err)
}
}()
}
@@ -417,7 +429,8 @@ func LoginByEmail(c *Context, w http.ResponseWriter, r *http.Request, email, nam
user := result.Data.(*model.User)
if len(user.AuthData) != 0 {
- c.Err = model.NewAppError("LoginByEmail", "Please sign in using "+user.AuthService, "")
+ c.Err = model.NewLocAppError("LoginByEmail", "api.user.login_by_email.sign_in.app_error",
+ map[string]interface{}{"AuthService": user.AuthService}, "")
return nil
}
@@ -434,14 +447,16 @@ func LoginByOAuth(c *Context, w http.ResponseWriter, r *http.Request, service st
authData := ""
provider := einterfaces.GetOauthProvider(service)
if provider == nil {
- c.Err = model.NewAppError("LoginByOAuth", service+" oauth not avlailable on this server", "")
+ c.Err = model.NewLocAppError("LoginByOAuth", "api.user.login_by_oauth.not_available.app_error",
+ map[string]interface{}{"Service": service}, "")
return nil
} else {
authData = provider.GetAuthDataFromJson(userData)
}
if len(authData) == 0 {
- c.Err = model.NewAppError("LoginByOAuth", "Could not parse auth data out of "+service+" user object", "")
+ c.Err = model.NewLocAppError("LoginByOAuth", "api.user.login_by_oauth.parse.app_error",
+ map[string]interface{}{"Service": service}, "")
return nil
}
@@ -459,7 +474,7 @@ func LoginByOAuth(c *Context, w http.ResponseWriter, r *http.Request, service st
func checkUserLoginAttempts(c *Context, user *model.User) bool {
if user.FailedAttempts >= utils.Cfg.ServiceSettings.MaximumLoginAttempts {
c.LogAuditWithUserId(user.Id, "fail")
- c.Err = model.NewAppError("checkUserLoginAttempts", "Your account is locked because of too many failed password attempts. Please reset your password.", "user_id="+user.Id)
+ c.Err = model.NewLocAppError("checkUserLoginAttempts", "api.user.check_user_login_attempts.too_many.app_error", nil, "user_id="+user.Id)
c.Err.StatusCode = http.StatusForbidden
return false
}
@@ -471,7 +486,7 @@ func checkUserPassword(c *Context, user *model.User, password string) bool {
if !model.ComparePassword(user.Password, password) {
c.LogAuditWithUserId(user.Id, "fail")
- c.Err = model.NewAppError("checkUserPassword", "Login failed because of invalid password", "user_id="+user.Id)
+ c.Err = model.NewLocAppError("checkUserPassword", "api.user.check_user_password.invalid.app_error", nil, "user_id="+user.Id)
c.Err.StatusCode = http.StatusForbidden
if result := <-Srv.Store.User().UpdateFailedPasswordAttempts(user.Id, user.FailedAttempts+1); result.Err != nil {
@@ -494,13 +509,13 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User,
c.LogAuditWithUserId(user.Id, "attempt")
if !user.EmailVerified && utils.Cfg.EmailSettings.RequireEmailVerification {
- c.Err = model.NewAppError("Login", "Login failed because email address has not been verified", "user_id="+user.Id)
+ c.Err = model.NewLocAppError("Login", "api.user.login.not_verified.app_error", nil, "user_id="+user.Id)
c.Err.StatusCode = http.StatusForbidden
return
}
if user.DeleteAt > 0 {
- c.Err = model.NewAppError("Login", "Login failed because your account has been set to inactive. Please contact an administrator.", "user_id="+user.Id)
+ c.Err = model.NewLocAppError("Login", "api.user.login.inactive.app_error", nil, "user_id="+user.Id)
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -522,7 +537,7 @@ func Login(c *Context, w http.ResponseWriter, r *http.Request, user *model.User,
sessions := result.Data.([]*model.Session)
for _, session := range sessions {
if session.DeviceId == deviceId {
- l4g.Debug("Revoking sessionId=" + session.Id + " for userId=" + user.Id + " re-login with same device Id")
+ l4g.Debug(utils.T("api.user.login.revoking.app_error"), session.Id, user.Id)
RevokeSessionById(c, session.Id)
if c.Err != nil {
c.LogError(c.Err)
@@ -604,7 +619,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
props := model.MapFromJson(r.Body)
if len(props["password"]) == 0 {
- c.Err = model.NewAppError("login", "Password field must not be blank", "")
+ c.Err = model.NewLocAppError("login", "api.user.login.blank_pwd.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -615,7 +630,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
} else if len(props["email"]) != 0 && len(props["name"]) != 0 {
user = LoginByEmail(c, w, r, props["email"], props["name"], props["password"], props["device_id"])
} else {
- c.Err = model.NewAppError("login", "Either user id or team name and user email must be provided", "")
+ c.Err = model.NewLocAppError("login", "api.user.login.not_provided.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -634,7 +649,7 @@ func login(c *Context, w http.ResponseWriter, r *http.Request) {
func loginLdap(c *Context, w http.ResponseWriter, r *http.Request) {
if !*utils.Cfg.LdapSettings.Enable {
- c.Err = model.NewAppError("loginLdap", "LDAP not enabled on this server", "")
+ c.Err = model.NewLocAppError("loginLdap", "api.user.login_ldap.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -646,13 +661,13 @@ func loginLdap(c *Context, w http.ResponseWriter, r *http.Request) {
teamName := props["teamName"]
if len(password) == 0 {
- c.Err = model.NewAppError("loginLdap", "Password field must not be blank", "")
+ c.Err = model.NewLocAppError("loginLdap", "api.user.login_ldap.blank_pwd.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
if len(id) == 0 {
- c.Err = model.NewAppError("loginLdap", "Need an ID", "")
+ c.Err = model.NewLocAppError("loginLdap", "api.user.login_ldap.need_id.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -661,7 +676,7 @@ func loginLdap(c *Context, w http.ResponseWriter, r *http.Request) {
ldapInterface := einterfaces.GetLdapInterface()
if ldapInterface == nil {
- c.Err = model.NewAppError("loginLdap", "LDAP not available on this server", "")
+ c.Err = model.NewLocAppError("loginLdap", "api.user.login_ldap.not_available.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -794,7 +809,7 @@ func getMe(c *Context, w http.ResponseWriter, r *http.Request) {
if result := <-Srv.Store.User().Get(c.Session.UserId); result.Err != nil {
c.Err = result.Err
c.RemoveSessionCookie(w, r)
- l4g.Error("Error in getting users profile for id=%v forcing logout", c.Session.UserId)
+ l4g.Error(utils.T("api.user.get_me.getting.error"), c.Session.UserId)
return
} else if HandleEtag(result.Data.(*model.User).Etag(), w, r) {
return
@@ -947,11 +962,11 @@ func createProfileImage(username string, userId string) ([]byte, *model.AppError
fontBytes, err := ioutil.ReadFile(utils.FindDir("web/static/fonts") + utils.Cfg.FileSettings.InitialFont)
if err != nil {
- return nil, model.NewAppError("createProfileImage", "Could not create default profile image font", err.Error())
+ return nil, model.NewLocAppError("createProfileImage", "api.user.create_profile_image.default_font.app_error", nil, err.Error())
}
font, err := freetype.ParseFont(fontBytes)
if err != nil {
- return nil, model.NewAppError("createProfileImage", "Could not create default profile image font", err.Error())
+ return nil, model.NewLocAppError("createProfileImage", "api.user.create_profile_image.default_font.app_error", nil, err.Error())
}
width := int(utils.Cfg.FileSettings.ProfileWidth)
@@ -972,13 +987,13 @@ func createProfileImage(username string, userId string) ([]byte, *model.AppError
pt := freetype.Pt(width/6, height*2/3)
_, err = c.DrawString(initial, pt)
if err != nil {
- return nil, model.NewAppError("createProfileImage", "Could not add user initial to default profile picture", err.Error())
+ return nil, model.NewLocAppError("createProfileImage", "api.user.create_profile_image.initial.app_error", nil, err.Error())
}
buf := new(bytes.Buffer)
if imgErr := png.Encode(buf, dstImg); imgErr != nil {
- return nil, model.NewAppError("createProfileImage", "Could not encode default profile image", imgErr.Error())
+ return nil, model.NewLocAppError("createProfileImage", "api.user.create_profile_image.encode.app_error", nil, imgErr.Error())
} else {
return buf.Bytes(), nil
}
@@ -1033,13 +1048,13 @@ func getProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
if len(utils.Cfg.FileSettings.DriverName) == 0 {
- c.Err = model.NewAppError("uploadProfileImage", "Unable to upload file. Image storage is not configured.", "")
+ c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.storage.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
if err := r.ParseMultipartForm(10000000); err != nil {
- c.Err = model.NewAppError("uploadProfileImage", "Could not parse multipart form", "")
+ c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.parse.app_error", nil, "")
return
}
@@ -1047,13 +1062,13 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
imageArray, ok := m.File["image"]
if !ok {
- c.Err = model.NewAppError("uploadProfileImage", "No file under 'image' in request", "")
+ c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.no_file.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
if len(imageArray) <= 0 {
- c.Err = model.NewAppError("uploadProfileImage", "Empty array under 'image' in request", "")
+ c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.array.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
@@ -1063,17 +1078,17 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
file, err := imageData.Open()
defer file.Close()
if err != nil {
- c.Err = model.NewAppError("uploadProfileImage", "Could not open image file", err.Error())
+ c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.open.app_error", nil, err.Error())
return
}
// Decode image config first to check dimensions before loading the whole thing into memory later on
config, _, err := image.DecodeConfig(file)
if err != nil {
- c.Err = model.NewAppError("uploadProfileFile", "Could not decode profile image config.", err.Error())
+ c.Err = model.NewLocAppError("uploadProfileFile", "api.user.upload_profile_user.decode_config.app_error", nil, err.Error())
return
} else if config.Width*config.Height > MaxImageSize {
- c.Err = model.NewAppError("uploadProfileFile", "Unable to upload profile image. File is too large.", err.Error())
+ c.Err = model.NewLocAppError("uploadProfileFile", "api.user.upload_profile_user.too_large.app_error", nil, err.Error())
return
}
@@ -1082,7 +1097,7 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
// Decode image into Image object
img, _, err := image.Decode(file)
if err != nil {
- c.Err = model.NewAppError("uploadProfileImage", "Could not decode profile image", err.Error())
+ c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.decode.app_error", nil, err.Error())
return
}
@@ -1092,7 +1107,7 @@ func uploadProfileImage(c *Context, w http.ResponseWriter, r *http.Request) {
buf := new(bytes.Buffer)
err = png.Encode(buf, img)
if err != nil {
- c.Err = model.NewAppError("uploadProfileImage", "Could not encode profile image", err.Error())
+ c.Err = model.NewLocAppError("uploadProfileImage", "api.user.upload_profile_user.encode.app_error", nil, err.Error())
return
}
@@ -1136,10 +1151,10 @@ func updateUser(c *Context, w http.ResponseWriter, r *http.Request) {
l4g.Error(tresult.Err.Message)
} else {
team := tresult.Data.(*model.Team)
- sendEmailChangeEmailAndForget(rusers[1].Email, rusers[0].Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL())
+ sendEmailChangeEmailAndForget(c, rusers[1].Email, rusers[0].Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL())
if utils.Cfg.EmailSettings.RequireEmailVerification {
- SendEmailChangeVerifyEmailAndForget(rusers[0].Id, rusers[0].Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team))
+ SendEmailChangeVerifyEmailAndForget(c, rusers[0].Id, rusers[0].Email, team.Name, team.DisplayName, c.GetSiteURL(), c.GetTeamURLFromTeam(team))
}
}
}
@@ -1173,7 +1188,7 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
}
if userId != c.Session.UserId {
- c.Err = model.NewAppError("updatePassword", "Update password failed because context user_id did not match props user_id", "")
+ c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.context.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -1186,7 +1201,7 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
}
if result.Data == nil {
- c.Err = model.NewAppError("updatePassword", "Update password failed because we couldn't find a valid account", "")
+ c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.valid_account.app_error", nil, "")
c.Err.StatusCode = http.StatusBadRequest
return
}
@@ -1197,19 +1212,19 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
if user.AuthData != "" {
c.LogAudit("failed - tried to update user password who was logged in through oauth")
- c.Err = model.NewAppError("updatePassword", "Update password failed because the user is logged in through an OAuth service", "auth_service="+user.AuthService)
+ c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.oauth.app_error", nil, "auth_service="+user.AuthService)
c.Err.StatusCode = http.StatusForbidden
return
}
if !model.ComparePassword(user.Password, currentPassword) {
- c.Err = model.NewAppError("updatePassword", "The \"Current Password\" you entered is incorrect. Please check that Caps Lock is off and try again.", "")
+ c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.incorrect.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
if uresult := <-Srv.Store.User().UpdatePassword(c.Session.UserId, model.HashPassword(newPassword)); uresult.Err != nil {
- c.Err = model.NewAppError("updatePassword", "Update password failed", uresult.Err.Error())
+ c.Err = model.NewLocAppError("updatePassword", "api.user.update_password.failed.app_error", nil, uresult.Err.Error())
c.Err.StatusCode = http.StatusForbidden
return
} else {
@@ -1219,7 +1234,7 @@ func updatePassword(c *Context, w http.ResponseWriter, r *http.Request) {
l4g.Error(tresult.Err.Message)
} else {
team := tresult.Data.(*model.Team)
- sendPasswordChangeEmailAndForget(user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL(), "using the settings menu")
+ sendPasswordChangeEmailAndForget(c, user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL(), c.T("api.user.update_password.menu"))
}
data := make(map[string]string)
@@ -1244,7 +1259,7 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
}
if model.IsInRole(new_roles, model.ROLE_SYSTEM_ADMIN) && !c.IsSystemAdmin() {
- c.Err = model.NewAppError("updateRoles", "The system admin role can only be set by another system admin", "")
+ c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.system_admin_set.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -1262,13 +1277,13 @@ func updateRoles(c *Context, w http.ResponseWriter, r *http.Request) {
}
if !c.IsTeamAdmin() {
- c.Err = model.NewAppError("updateRoles", "You do not have the appropriate permissions", "userId="+user_id)
+ c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.permissions.app_error", nil, "userId="+user_id)
c.Err.StatusCode = http.StatusForbidden
return
}
if user.IsInRole(model.ROLE_SYSTEM_ADMIN) && !c.IsSystemAdmin() {
- c.Err = model.NewAppError("updateRoles", "The system admin role can only by modified by another system admin", "")
+ c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.system_admin_mod.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -1320,7 +1335,7 @@ func UpdateRoles(c *Context, user *model.User, roles string) *model.User {
}
if activeAdmins <= 0 {
- c.Err = model.NewAppError("updateRoles", "There must be at least one active admin", "")
+ c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.one_admin.app_error", nil, "")
return nil
}
}
@@ -1365,7 +1380,7 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) {
}
if !c.IsTeamAdmin() {
- c.Err = model.NewAppError("updateActive", "You do not have the appropriate permissions", "userId="+user_id)
+ c.Err = model.NewLocAppError("updateActive", "api.user.update_active.permissions.app_error", nil, "userId="+user_id)
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -1385,7 +1400,7 @@ func updateActive(c *Context, w http.ResponseWriter, r *http.Request) {
}
if activeAdmins <= 0 {
- c.Err = model.NewAppError("updateRoles", "There must be at least one active admin", "userId="+user_id)
+ c.Err = model.NewLocAppError("updateRoles", "api.user.update_roles.one_admin.app_error", nil, "userId="+user_id)
return
}
}
@@ -1424,12 +1439,12 @@ func UpdateActive(c *Context, user *model.User, active bool) *model.User {
}
func PermanentDeleteUser(c *Context, user *model.User) *model.AppError {
- l4g.Warn("Attempting to permanently delete account %v id=%v", user.Email, user.Id)
+ l4g.Warn(utils.T("api.user.permanent_delete_user.attempting.warn"), user.Email, user.Id)
c.Path = "/users/permanent_delete"
c.LogAuditWithUserId(user.Id, fmt.Sprintf("attempt userId=%v", user.Id))
c.LogAuditWithUserId("", fmt.Sprintf("attempt userId=%v", user.Id))
if user.IsInRole(model.ROLE_SYSTEM_ADMIN) {
- l4g.Warn("You are deleting %v that is a system administrator. You may need to set another account as the system administrator using the command line tools.", user.Email)
+ l4g.Warn(utils.T("api.user.permanent_delete_user.system_admin.warn"), user.Email)
}
UpdateActive(c, user, false)
@@ -1470,7 +1485,7 @@ func PermanentDeleteUser(c *Context, user *model.User) *model.AppError {
return result.Err
}
- l4g.Warn("Permanently deleted account %v id=%v", user.Email, user.Id)
+ l4g.Warn(utils.T("api.user.permanent_delete_user.deleted.warn"), user.Email, user.Id)
c.LogAuditWithUserId("", fmt.Sprintf("success userId=%v", user.Id))
return nil
@@ -1501,14 +1516,14 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
var user *model.User
if result := <-Srv.Store.User().GetByEmail(team.Id, email); result.Err != nil {
- c.Err = model.NewAppError("sendPasswordReset", "We couldn’t find an account with that address.", "email="+email+" team_id="+team.Id)
+ c.Err = model.NewLocAppError("sendPasswordReset", "api.user.send_password_reset.find.app_error", nil, "email="+email+" team_id="+team.Id)
return
} else {
user = result.Data.(*model.User)
}
if len(user.AuthData) != 0 {
- c.Err = model.NewAppError("sendPasswordReset", "Cannot reset password for SSO accounts", "userId="+user.Id+", teamId="+team.Id)
+ c.Err = model.NewLocAppError("sendPasswordReset", "api.user.send_password_reset.sso.app_error", nil, "userId="+user.Id+", teamId="+team.Id)
return
}
@@ -1521,14 +1536,18 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) {
link := fmt.Sprintf("%s/reset_password?d=%s&h=%s", c.GetTeamURLFromTeam(team), url.QueryEscape(data), url.QueryEscape(hash))
- subjectPage := NewServerTemplatePage("reset_subject")
- subjectPage.Props["SiteURL"] = c.GetSiteURL()
- bodyPage := NewServerTemplatePage("reset_body")
+ subjectPage := NewServerTemplatePage("reset_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.reset_subject")
+
+ bodyPage := NewServerTemplatePage("reset_body", c.Locale)
bodyPage.Props["SiteURL"] = c.GetSiteURL()
+ bodyPage.Props["Title"] = c.T("api.templates.reset_body.title")
+ bodyPage.Html["Info"] = template.HTML(c.T("api.templates.reset_body.info"))
bodyPage.Props["ResetUrl"] = link
+ bodyPage.Props["Button"] = c.T("api.templates.reset_body.button")
if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil {
- c.Err = model.NewAppError("sendPasswordReset", "Failed to send password reset email successfully", "err="+err.Message)
+ c.Err = model.NewLocAppError("sendPasswordReset", "api.user.send_password_reset.send.app_error", nil, "err="+err.Message)
return
}
@@ -1597,25 +1616,25 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
}
if len(user.AuthData) != 0 {
- c.Err = model.NewAppError("resetPassword", "Cannot reset password for SSO accounts", "userId="+user.Id+", teamId="+team.Id)
+ c.Err = model.NewLocAppError("resetPassword", "api.user.reset_password.sso.app_error", nil, "userId="+user.Id+", teamId="+team.Id)
return
}
if user.TeamId != team.Id {
- c.Err = model.NewAppError("resetPassword", "Trying to reset password for user on wrong team.", "userId="+user.Id+", teamId="+team.Id)
+ c.Err = model.NewLocAppError("resetPassword", "api.user.reset_password.wrong_team.app_error", nil, "userId="+user.Id+", teamId="+team.Id)
c.Err.StatusCode = http.StatusForbidden
return
}
if !c.IsSystemAdmin() {
if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", props["data"], utils.Cfg.EmailSettings.PasswordResetSalt)) {
- c.Err = model.NewAppError("resetPassword", "The reset password link does not appear to be valid", "")
+ c.Err = model.NewLocAppError("resetPassword", "api.user.reset_password.invalid_link.app_error", nil, "")
return
}
t, err := strconv.ParseInt(timeStr, 10, 64)
if err != nil || model.GetMillis()-t > 1000*60*60 { // one hour
- c.Err = model.NewAppError("resetPassword", "The reset link has expired", "")
+ c.Err = model.NewLocAppError("resetPassword", "api.user.reset_password.link_expired.app_error", nil, "")
return
}
}
@@ -1627,65 +1646,71 @@ func resetPassword(c *Context, w http.ResponseWriter, r *http.Request) {
c.LogAuditWithUserId(userId, "success")
}
- sendPasswordChangeEmailAndForget(user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL(), "using a reset password link")
+ sendPasswordChangeEmailAndForget(c, user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL(), c.T("api.user.reset_password.method"))
props["new_password"] = ""
w.Write([]byte(model.MapToJson(props)))
}
-func sendPasswordChangeEmailAndForget(email, teamDisplayName, teamURL, siteURL, method string) {
+func sendPasswordChangeEmailAndForget(c *Context, email, teamDisplayName, teamURL, siteURL, method string) {
go func() {
- subjectPage := NewServerTemplatePage("password_change_subject")
- subjectPage.Props["SiteURL"] = siteURL
- subjectPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage := NewServerTemplatePage("password_change_body")
+ subjectPage := NewServerTemplatePage("password_change_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.password_change_subject",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName, "SiteName": utils.ClientCfg["SiteName"]})
+
+ bodyPage := NewServerTemplatePage("password_change_body", c.Locale)
bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage.Props["TeamURL"] = teamURL
- bodyPage.Props["Method"] = method
+ bodyPage.Props["Title"] = c.T("api.templates.password_change_body.title")
+ bodyPage.Html["Info"] = template.HTML(c.T("api.templates.password_change_body.info",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName, "TeamURL": teamURL, "Method": method}))
if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("Failed to send update password email successfully err=%v", err)
+ l4g.Error(utils.T("api.user.send_password_change_email_and_forget.error"), err)
}
}()
}
-func sendEmailChangeEmailAndForget(oldEmail, newEmail, teamDisplayName, teamURL, siteURL string) {
+func sendEmailChangeEmailAndForget(c *Context, oldEmail, newEmail, teamDisplayName, teamURL, siteURL string) {
go func() {
- subjectPage := NewServerTemplatePage("email_change_subject")
- subjectPage.Props["SiteURL"] = siteURL
- subjectPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage := NewServerTemplatePage("email_change_body")
+ subjectPage := NewServerTemplatePage("email_change_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.email_change_body",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName})
+
+ bodyPage := NewServerTemplatePage("email_change_body", c.Locale)
bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage.Props["TeamURL"] = teamURL
- bodyPage.Props["NewEmail"] = newEmail
+ bodyPage.Props["Title"] = c.T("api.templates.email_change_body.title")
+ bodyPage.Props["Info"] = c.T("api.templates.email_change_body.info",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName, "NewEmail": newEmail})
if err := utils.SendMail(oldEmail, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("Failed to send email change notification email successfully err=%v", err)
+ l4g.Error(utils.T("api.user.send_email_change_email_and_forget.error"), err)
}
}()
}
-func SendEmailChangeVerifyEmailAndForget(userId, newUserEmail, teamName, teamDisplayName, siteURL, teamURL string) {
+func SendEmailChangeVerifyEmailAndForget(c *Context, userId, newUserEmail, teamName, teamDisplayName, siteURL, teamURL string) {
go func() {
link := fmt.Sprintf("%s/verify_email?uid=%s&hid=%s&teamname=%s&email=%s", siteURL, userId, model.HashPassword(userId), teamName, newUserEmail)
- subjectPage := NewServerTemplatePage("email_change_verify_subject")
- subjectPage.Props["SiteURL"] = siteURL
- subjectPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage := NewServerTemplatePage("email_change_verify_body")
+ subjectPage := NewServerTemplatePage("email_change_verify_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.email_change_verify_subject",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName})
+
+ bodyPage := NewServerTemplatePage("email_change_verify_body", c.Locale)
bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["TeamDisplayName"] = teamDisplayName
+ bodyPage.Props["Title"] = c.T("api.templates.email_change_verify_body.title")
+ bodyPage.Props["Info"] = c.T("api.templates.email_change_verify_body.info",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName})
bodyPage.Props["VerifyUrl"] = link
+ bodyPage.Props["VerifyButton"] = c.T("api.templates.email_change_verify_body.button")
if err := utils.SendMail(newUserEmail, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("Failed to send email change verification email successfully err=%v", err)
+ l4g.Error(utils.T("api.user.send_email_change_verify_email_and_forget.error"), err)
}
}()
}
@@ -1794,7 +1819,7 @@ func GetAuthorizationCode(c *Context, service, teamName string, props map[string
sso := utils.Cfg.GetSSOService(service)
if sso != nil && !sso.Enable {
- return "", model.NewAppError("GetAuthorizationCode", "Unsupported OAuth service provider", "service="+service)
+ return "", model.NewLocAppError("GetAuthorizationCode", "api.user.get_authorization_code.unsupported.app_error", nil, "service="+service)
}
clientId := sso.Id
@@ -1823,12 +1848,12 @@ func GetAuthorizationCode(c *Context, service, teamName string, props map[string
func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser, *model.Team, map[string]string, *model.AppError) {
sso := utils.Cfg.GetSSOService(service)
if sso == nil || !sso.Enable {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Unsupported OAuth service provider", "service="+service)
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.unsupported.app_error", nil, "service="+service)
}
stateStr := ""
if b, err := b64.StdEncoding.DecodeString(state); err != nil {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Invalid state", err.Error())
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, err.Error())
} else {
stateStr = string(b)
}
@@ -1836,13 +1861,13 @@ func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser
stateProps := model.MapFromJson(strings.NewReader(stateStr))
if !model.ComparePassword(stateProps["hash"], sso.Id) {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Invalid state", "")
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state.app_error", nil, "")
}
ok := true
teamName := ""
if teamName, ok = stateProps["team"]; !ok {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Invalid state; missing team name", "")
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.invalid_state_team.app_error", nil, "")
}
tchan := Srv.Store.Team().GetByName(teamName)
@@ -1862,20 +1887,20 @@ func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser
var ar *model.AccessResponse
if resp, err := client.Do(req); err != nil {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Token request failed", err.Error())
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.token_failed.app_error", nil, err.Error())
} else {
ar = model.AccessResponseFromJson(resp.Body)
if ar == nil {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Bad response from token request", "")
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_response.app_error", nil, "")
}
}
if strings.ToLower(ar.TokenType) != model.ACCESS_TOKEN_TYPE {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Bad token type", "token_type="+ar.TokenType)
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.bad_token.app_error", nil, "token_type="+ar.TokenType)
}
if len(ar.AccessToken) == 0 {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Missing access token", "")
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.missing.app_error", nil, "")
}
p = url.Values{}
@@ -1887,7 +1912,8 @@ func AuthorizeOAuthUser(service, code, state, redirectUri string) (io.ReadCloser
req.Header.Set("Authorization", "Bearer "+ar.AccessToken)
if resp, err := client.Do(req); err != nil {
- return nil, nil, nil, model.NewAppError("AuthorizeOAuthUser", "Token request to "+service+" failed", err.Error())
+ return nil, nil, nil, model.NewLocAppError("AuthorizeOAuthUser", "api.user.authorize_oauth_user.service.app_error",
+ map[string]interface{}{"Service": service}, err.Error())
} else {
if result := <-tchan; result.Err != nil {
return nil, nil, nil, result.Err
@@ -1986,19 +2012,21 @@ func CompleteSwitchWithOAuth(c *Context, w http.ResponseWriter, r *http.Request,
authData := ""
provider := einterfaces.GetOauthProvider(service)
if provider == nil {
- c.Err = model.NewAppError("CompleteClaimWithOAuth", service+" oauth not avlailable on this server", "")
+ c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.unavailable.app_error",
+ map[string]interface{}{"Service": service}, "")
return
} else {
authData = provider.GetAuthDataFromJson(userData)
}
if len(authData) == 0 {
- c.Err = model.NewAppError("CompleteClaimWithOAuth", "Could not parse auth data out of "+service+" user object", "")
+ c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.parse.app_error",
+ map[string]interface{}{"Service": service}, "")
return
}
if len(email) == 0 {
- c.Err = model.NewAppError("CompleteClaimWithOAuth", "Blank email", "")
+ c.Err = model.NewLocAppError("CompleteClaimWithOAuth", "api.user.complete_switch_with_oauth.blank_email.app_error", nil, "")
return
}
@@ -2020,7 +2048,7 @@ func CompleteSwitchWithOAuth(c *Context, w http.ResponseWriter, r *http.Request,
return
}
- sendSignInChangeEmailAndForget(user.Email, team.DisplayName, c.GetSiteURL()+"/"+team.Name, c.GetSiteURL(), strings.Title(service)+" SSO")
+ sendSignInChangeEmailAndForget(c, user.Email, team.DisplayName, c.GetSiteURL()+"/"+team.Name, c.GetSiteURL(), strings.Title(service)+" SSO")
}
func switchToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
@@ -2066,7 +2094,7 @@ func switchToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
if user.Id != c.Session.UserId {
c.LogAudit("fail - user ids didn't match")
- c.Err = model.NewAppError("switchToEmail", "Update password failed because context user_id did not match provided user's id", "")
+ c.Err = model.NewLocAppError("switchToEmail", "api.user.switch_to_email.context.app_error", nil, "")
c.Err.StatusCode = http.StatusForbidden
return
}
@@ -2077,7 +2105,7 @@ func switchToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
return
}
- sendSignInChangeEmailAndForget(user.Email, team.DisplayName, c.GetSiteURL()+"/"+team.Name, c.GetSiteURL(), "email and password")
+ sendSignInChangeEmailAndForget(c, user.Email, team.DisplayName, c.GetSiteURL()+"/"+team.Name, c.GetSiteURL(), c.T("api.templates.signin_change_email.body.method_email"))
RevokeAllSession(c, c.Session.UserId)
if c.Err != nil {
@@ -2091,20 +2119,21 @@ func switchToEmail(c *Context, w http.ResponseWriter, r *http.Request) {
w.Write([]byte(model.MapToJson(m)))
}
-func sendSignInChangeEmailAndForget(email, teamDisplayName, teamURL, siteURL, method string) {
+func sendSignInChangeEmailAndForget(c *Context, email, teamDisplayName, teamURL, siteURL, method string) {
go func() {
- subjectPage := NewServerTemplatePage("signin_change_subject")
- subjectPage.Props["SiteURL"] = siteURL
- subjectPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage := NewServerTemplatePage("signin_change_body")
+ subjectPage := NewServerTemplatePage("signin_change_subject", c.Locale)
+ subjectPage.Props["Subject"] = c.T("api.templates.singin_change_email.subject",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName, "SiteName": utils.ClientCfg["SiteName"]})
+
+ bodyPage := NewServerTemplatePage("signin_change_body", c.Locale)
bodyPage.Props["SiteURL"] = siteURL
- bodyPage.Props["TeamDisplayName"] = teamDisplayName
- bodyPage.Props["TeamURL"] = teamURL
- bodyPage.Props["Method"] = method
+ bodyPage.Props["Title"] = c.T("api.templates.signin_change_email.body.title")
+ bodyPage.Html["Info"] = template.HTML(c.T("api.templates.singin_change_email.body.info",
+ map[string]interface{}{"TeamDisplayName": teamDisplayName, "TeamURL": teamURL, "Method": method}))
if err := utils.SendMail(email, subjectPage.Render(), bodyPage.Render()); err != nil {
- l4g.Error("Failed to send update password email successfully err=%v", err)
+ l4g.Error(utils.T("api.user.send_sign_in_change_email_and_forget.error"), err)
}
}()
diff --git a/api/web_conn.go b/api/web_conn.go
index 2b0e29038..515a8ab31 100644
--- a/api/web_conn.go
+++ b/api/web_conn.go
@@ -8,6 +8,7 @@ import (
"github.com/gorilla/websocket"
"github.com/mattermost/platform/model"
"github.com/mattermost/platform/store"
+ "github.com/mattermost/platform/utils"
"time"
)
@@ -33,11 +34,11 @@ func NewWebConn(ws *websocket.Conn, teamId string, userId string, sessionId stri
pchan := Srv.Store.User().UpdateLastPingAt(userId, model.GetMillis())
if result := <-achan; result.Err != nil {
- l4g.Error("Failed to update LastActivityAt for user_id=%v and session_id=%v, err=%v", userId, sessionId, result.Err)
+ l4g.Error(utils.T("api.web_conn.new_web_conn.last_activity.error"), userId, sessionId, result.Err)
}
if result := <-pchan; result.Err != nil {
- l4g.Error("Failed to updated LastPingAt for user_id=%v, err=%v", userId, result.Err)
+ l4g.Error(utils.T("api.web_conn.new_web_conn.last_ping.error"), userId, result.Err)
}
}()
@@ -56,7 +57,7 @@ func (c *WebConn) readPump() {
go func() {
if result := <-Srv.Store.User().UpdateLastPingAt(c.UserId, model.GetMillis()); result.Err != nil {
- l4g.Error("Failed to updated LastPingAt for user_id=%v, err=%v", c.UserId, result.Err)
+ l4g.Error(utils.T("api.web_conn.new_web_conn.last_ping.error"), c.UserId, result.Err)
}
}()
diff --git a/api/web_hub.go b/api/web_hub.go
index 4361d1035..5fe9d6ae8 100644
--- a/api/web_hub.go
+++ b/api/web_hub.go
@@ -6,6 +6,7 @@ package api
import (
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
)
type Hub struct {
@@ -86,7 +87,7 @@ func (h *Hub) Start() {
nh.broadcast <- msg
}
case s := <-h.stop:
- l4g.Debug("stopping %v connections", s)
+ l4g.Debug(utils.T("api.web_hub.start.stopping.debug"), s)
for _, v := range h.teamHubs {
v.Stop()
}
diff --git a/api/web_socket.go b/api/web_socket.go
index 995e2a677..7590e6646 100644
--- a/api/web_socket.go
+++ b/api/web_socket.go
@@ -8,11 +8,12 @@ import (
"github.com/gorilla/mux"
"github.com/gorilla/websocket"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
"net/http"
)
func InitWebSocket(r *mux.Router) {
- l4g.Debug("Initializing web socket api routes")
+ l4g.Debug(utils.T("api.web_socket.init.debug"))
r.Handle("/websocket", ApiUserRequired(connect)).Methods("GET")
hub.Start()
}
@@ -28,8 +29,8 @@ func connect(c *Context, w http.ResponseWriter, r *http.Request) {
ws, err := upgrader.Upgrade(w, r, nil)
if err != nil {
- l4g.Error("websocket connect err: %v", err)
- c.Err = model.NewAppError("connect", "Failed to upgrade websocket connection", "")
+ l4g.Error(utils.T("api.web_socket.connect.error"), err)
+ c.Err = model.NewLocAppError("connect", "api.web_socket.connect.upgrade.app_error", nil, "")
return
}
diff --git a/api/web_team_hub.go b/api/web_team_hub.go
index bb9ed9526..55300c828 100644
--- a/api/web_team_hub.go
+++ b/api/web_team_hub.go
@@ -6,6 +6,7 @@ package api
import (
l4g "github.com/alecthomas/log4go"
"github.com/mattermost/platform/model"
+ "github.com/mattermost/platform/utils"
)
type TeamHub struct {
@@ -65,7 +66,7 @@ func (h *TeamHub) Start() {
case s := <-h.stop:
if s {
- l4g.Debug("team hub stopping for teamId=%v", h.teamId)
+ l4g.Debug(utils.T("api.web_team_hun.start.debug"), h.teamId)
for webCon := range h.connections {
webCon.WebSocket.Close()
diff --git a/api/webhook.go b/api/webhook.go
index a9a88b7b8..1372fe335 100644
--- a/api/webhook.go
+++ b/api/webhook.go
@@ -12,7 +12,7 @@ import (
)
func InitWebhook(r *mux.Router) {
- l4g.Debug("Initializing webhook api routes")
+ l4g.Debug(utils.T("api.webhook.init.debug"))
sr := r.PathPrefix("/hooks").Subrouter()
sr.Handle("/incoming/create", ApiUserRequired(createIncomingHook)).Methods("POST")
@@ -27,7 +27,7 @@ func InitWebhook(r *mux.Router) {
func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
- c.Err = model.NewAppError("createIncomingHook", "Incoming webhooks have been disabled by the system admin.", "")
+ c.Err = model.NewLocAppError("createIncomingHook", "api.webhook.create_incoming.disabled.app_errror", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -74,7 +74,7 @@ func createIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
- c.Err = model.NewAppError("deleteIncomingHook", "Incoming webhooks have been disabled by the system admin.", "")
+ c.Err = model.NewLocAppError("deleteIncomingHook", "api.webhook.delete_incoming.disabled.app_errror", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -95,7 +95,7 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
if c.Session.UserId != result.Data.(*model.IncomingWebhook).UserId && !c.IsTeamAdmin() {
c.LogAudit("fail - inappropriate permissions")
- c.Err = model.NewAppError("deleteIncomingHook", "Inappropriate permissions to delete incoming webhook", "user_id="+c.Session.UserId)
+ c.Err = model.NewLocAppError("deleteIncomingHook", "api.webhook.delete_incoming.permissions.app_errror", nil, "user_id="+c.Session.UserId)
return
}
}
@@ -111,7 +111,7 @@ func deleteIncomingHook(c *Context, w http.ResponseWriter, r *http.Request) {
func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
- c.Err = model.NewAppError("getIncomingHooks", "Incoming webhooks have been disabled by the system admin.", "")
+ c.Err = model.NewLocAppError("getIncomingHooks", "api.webhook.get_incoming.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -127,7 +127,7 @@ func getIncomingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
- c.Err = model.NewAppError("createOutgoingHook", "Outgoing webhooks have been disabled by the system admin.", "")
+ c.Err = model.NewLocAppError("createOutgoingHook", "api.webhook.create_outgoing.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -167,7 +167,7 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
}
}
} else if len(hook.TriggerWords) == 0 {
- c.Err = model.NewAppError("createOutgoingHook", "Either trigger_words or channel_id must be set", "")
+ c.Err = model.NewLocAppError("createOutgoingHook", "api.webhook.create_outgoing.triggers.app_error", nil, "")
return
}
@@ -183,7 +183,7 @@ func createOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableOutgoingWebhooks {
- c.Err = model.NewAppError("getOutgoingHooks", "Outgoing webhooks have been disabled by the system admin.", "")
+ c.Err = model.NewLocAppError("getOutgoingHooks", "api.webhook.get_outgoing.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -199,7 +199,7 @@ func getOutgoingHooks(c *Context, w http.ResponseWriter, r *http.Request) {
func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
- c.Err = model.NewAppError("deleteOutgoingHook", "Outgoing webhooks have been disabled by the system admin.", "")
+ c.Err = model.NewLocAppError("deleteOutgoingHook", "api.webhook.delete_outgoing.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -220,7 +220,7 @@ func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
} else {
if c.Session.UserId != result.Data.(*model.OutgoingWebhook).CreatorId && !c.IsTeamAdmin() {
c.LogAudit("fail - inappropriate permissions")
- c.Err = model.NewAppError("deleteOutgoingHook", "Inappropriate permissions to delete outcoming webhook", "user_id="+c.Session.UserId)
+ c.Err = model.NewLocAppError("deleteOutgoingHook", "api.webhook.delete_outgoing.permissions.app_error", nil, "user_id="+c.Session.UserId)
return
}
}
@@ -236,7 +236,7 @@ func deleteOutgoingHook(c *Context, w http.ResponseWriter, r *http.Request) {
func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request) {
if !utils.Cfg.ServiceSettings.EnableIncomingWebhooks {
- c.Err = model.NewAppError("regenOutgoingHookToken", "Outgoing webhooks have been disabled by the system admin.", "")
+ c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.webhook.regen_outgoing_token.disabled.app_error", nil, "")
c.Err.StatusCode = http.StatusNotImplemented
return
}
@@ -260,7 +260,7 @@ func regenOutgoingHookToken(c *Context, w http.ResponseWriter, r *http.Request)
if c.Session.UserId != hook.CreatorId && !c.IsTeamAdmin() {
c.LogAudit("fail - inappropriate permissions")
- c.Err = model.NewAppError("regenOutgoingHookToken", "Inappropriate permissions to regenerate outcoming webhook token", "user_id="+c.Session.UserId)
+ c.Err = model.NewLocAppError("regenOutgoingHookToken", "api.webhook.regen_outgoing_token.permissions.app_error", nil, "user_id="+c.Session.UserId)
return
}
}