From 6fd328ddaa61cd75c24cd2d9b8fdc0f73c7ab974 Mon Sep 17 00:00:00 2001 From: Elias Nahum Date: Fri, 22 Jan 2016 01:37:11 -0300 Subject: Refactoring api to use translations (chunk 2) - Add spanish translations - Does not include tests - Add func to get the translations for a user locale --- api/export.go | 2 +- api/file.go | 60 +- api/import.go | 9 +- api/license.go | 16 +- api/oauth.go | 26 +- api/post.go | 109 ++-- api/preference.go | 9 +- api/server.go | 18 +- api/slackimport.go | 41 +- api/team.go | 54 +- api/user.go | 180 +++--- i18n/en.json | 1728 ++++++++++++++++++++++++++++++++++++++++------------ i18n/es.json | 928 ++++++++++++++++++++++++++++ utils/i18n.go | 9 + 14 files changed, 2537 insertions(+), 652 deletions(-) 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..31c899388 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 } @@ -394,14 +394,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 +411,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 } @@ -449,13 +449,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 +500,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 +538,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 +553,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 +583,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 +615,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..af46bf113 100644 --- a/api/license.go +++ b/api/license.go @@ -15,7 +15,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 +34,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 +50,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 } @@ -65,19 +65,19 @@ func addLicense(c *Context, w http.ResponseWriter, r *http.Request) { 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 +90,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 7cd45d310..fe89ebf19 100644 --- a/api/post.go +++ b/api/post.go @@ -20,7 +20,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") @@ -60,7 +60,7 @@ func createPost(c *Context, w http.ResponseWriter, r *http.Request) { 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 +76,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 +90,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 +129,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:]...) } } @@ -195,7 +195,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 @@ -209,7 +209,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) @@ -217,7 +217,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) @@ -227,7 +227,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) @@ -246,14 +246,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 } @@ -271,7 +271,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()) @@ -286,7 +286,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()) @@ -313,7 +313,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) @@ -364,7 +364,7 @@ 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) @@ -374,7 +374,7 @@ func handleWebhookEventsAndForget(c *Context, post *model.Post, team *model.Team 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) } } } @@ -398,25 +398,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 @@ -447,7 +439,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) @@ -555,14 +547,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 { @@ -574,6 +558,25 @@ func sendNotificationsAndForget(c *Context, post *model.Post, team *model.Team, continue } + 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 + } + + 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()) + bodyPage := NewServerTemplatePage("post_body") bodyPage.Props["SiteURL"] = c.GetSiteURL() bodyPage.Props["Nickname"] = profileMap[id].FirstName @@ -616,17 +619,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) @@ -649,17 +653,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) } } } @@ -695,7 +699,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) } }() } @@ -723,19 +727,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 } @@ -870,7 +875,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 } @@ -896,7 +901,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]] @@ -950,13 +955,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 } @@ -980,9 +985,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..57a0e0bd2 100644 --- a/api/team.go +++ b/api/team.go @@ -19,7 +19,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 +40,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 } @@ -147,7 +147,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 +188,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 +204,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 +249,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 +283,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 +300,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 } @@ -445,7 +445,7 @@ func emailTeams(c *Context, w http.ResponseWriter, r *http.Request) { bodyPage.Props = 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 +455,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 +483,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,9 +506,9 @@ 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") @@ -532,11 +532,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 +554,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 +586,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 +612,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 +639,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 +654,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 +684,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 +706,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/user.go b/api/user.go index a6b4fb654..76ed66112 100644 --- a/api/user.go +++ b/api/user.go @@ -32,7 +32,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 +64,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 +98,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 +123,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 } @@ -208,27 +208,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 +246,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 +280,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 } @@ -321,7 +323,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 +332,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,7 +362,7 @@ 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()) } }() } @@ -379,7 +381,7 @@ func SendVerifyEmailAndForget(userId, userEmail, teamName, teamDisplayName, site bodyPage.Props["VerifyUrl"] = link 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 +419,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 +437,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 +464,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 +476,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 +499,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 +527,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 +609,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 +620,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 +639,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 +651,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 +666,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 +799,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 +952,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 +977,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 +1038,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 +1052,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 +1068,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 +1087,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 +1097,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 } @@ -1173,7 +1178,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 +1191,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 +1202,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 +1224,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(user.Email, team.DisplayName, c.GetTeamURLFromTeam(team), c.GetSiteURL(), c.T("api.user.update_password.menu")) } data := make(map[string]string) @@ -1244,7 +1249,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 +1267,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 +1325,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 +1370,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 +1390,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 +1429,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 +1475,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 +1506,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 } @@ -1528,7 +1533,7 @@ func sendPasswordReset(c *Context, w http.ResponseWriter, r *http.Request) { bodyPage.Props["ResetUrl"] = link 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 +1602,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 } } @@ -1646,7 +1651,7 @@ func sendPasswordChangeEmailAndForget(email, teamDisplayName, teamURL, siteURL, bodyPage.Props["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) } }() @@ -1665,7 +1670,7 @@ func sendEmailChangeEmailAndForget(oldEmail, newEmail, teamDisplayName, teamURL, bodyPage.Props["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) } }() @@ -1685,7 +1690,7 @@ func SendEmailChangeVerifyEmailAndForget(userId, newUserEmail, teamName, teamDis bodyPage.Props["VerifyUrl"] = link 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 +1799,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 +1828,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 +1841,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 +1867,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 +1892,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 +1992,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 } @@ -2066,7 +2074,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 } @@ -2104,7 +2112,7 @@ func sendSignInChangeEmailAndForget(email, teamDisplayName, teamURL, siteURL, me bodyPage.Props["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/i18n/en.json b/i18n/en.json index ca514f71d..4edc176d6 100644 --- a/i18n/en.json +++ b/i18n/en.json @@ -1,402 +1,1330 @@ [ - { - "id": "utils.i18n.loaded", - "translation": "Loaded system translations for '%v' from '%v'" - }, - { - "id": "mattermost.current_version", - "translation": "Current version is %v (%v/%v/%v)" - }, - { - "id": "api.admin.file_read_error", - "translation": "Error reading log file" - }, - { - "id": "api.admin.init.debug", - "translation": "Initializing admin api routes" - }, - { - "id": "api.admin.test_email.subject", - "translation": "Mattermost - Testing Email Settings" - }, - { - "id": "api.admin.test_email.body", - "translation": "


It appears your Mattermost email is setup correctly!" - }, - { - "id": "api.api.render.error", - "translation": "Error rendering template %v err=%v" - }, - { - "id": "api.api.init.parsing_templates.debug", - "translation": "Parsing server templates at %v" - }, - { - "id": "api.api.init.parsing_templates.error", - "translation": "Failed to parse server templates %v" - }, - { - "id": "api.channel.init.debug", - "translation": "Initializing channel api routes" - }, - { - "id": "api.channel.create_channel.direct_channel.app_error", - "translation": "Must use createDirectChannel api service for direct message channel creation" - }, - { - "id": "api.channel.create_channel.invalid_character.app_error", - "translation": "Invalid character '__' in channel name for non-direct channel" - }, - { - "id": "api.channel.create_direct_channel.invalid_user.app_error", - "translation": "Invalid other user id " - }, - { - "id": "api.channel.create_default_channels.town_square", - "translation": "Town Square" - }, - { - "id": "api.channel.create_default_channels.off_topic", - "translation": "Off-Topic" - }, - { - "id": "api.channel.update_channel.permission.app_error", - "translation": "You do not have the appropriate permissions" - }, - { - "id": "api.channel.update_channel.deleted.app_error", - "translation": "The channel has been archived or deleted" - }, - { - "id": "api.channel.update_channel.tried.app_error", - "translation": "Tried to perform an invalid update of the default channel {{.Channel}}" - }, - { - "id": "api.channel.post_update_channel_header_message_and_forget.retrieve_user.error", - "translation": "Failed to retrieve user while trying to save update channel header message %v" - }, - { - "id": "api.channel.post_update_channel_header_message_and_forget.updated_to", - "translation": "%s updated the channel header to: %s" - }, - { - "id": "api.channel.post_update_channel_header_message_and_forget.removed", - "translation": "%s removed the channel header (was: %s)" - }, - { - "id": "api.channel.post_update_channel_header_message_and_forget.updated_from", - "translation": "%s updated the channel header from: %s to: %s" - }, - { - "id": "api.channel.post_update_channel_header_message_and_forget.join_leave.error", - "translation": "Failed to post join/leave message %v" - }, - { - "id": "api.channel.get_channels.error", - "translation": "Error in getting users profile for id=%v forcing logout" - }, - { - "id": "api.channel.get_channel_counts.app_error", - "translation": "Unable to get channel counts from the database" - }, - { - "id": "api.channel.join_channel.post_and_forget", - "translation": "%v has joined the channel." - }, - { - "id": "api.channel.join_channel.permissions.app_error", - "translation": "You do not have the appropriate permissions" - }, - { - "id": "api.channel.post_user_add_remove_message_and_forget.error", - "translation": "Failed to post join/leave message %v" - }, - { - "id": "api.channel.add_user_to_channel.deleted.app_error", - "translation": "The channel has been archived or deleted" - }, - { - "id": "api.channel.add_user_to_channel.type.app_error", - "translation": "Can not add user to this channel type" - }, - { - "id": "api.channel.add_user.to.channel.failed.app_error", - "translation": "Failed to add user to channel" - }, - { - "id": "api.channel.leave.direct.app_error", - "translation": "Cannot leave a direct message channel" - }, - { - "id": "api.channel.leave.default.app_error", - "translation": "Cannot leave the default channel {{.Channel}}" - }, - { - "id": "api.channel.leave.left", - "translation": "%v has left the channel." - }, - { - "id": "api.channel.delete_channel.permissions.app_error", - "translation": "You do not have the appropriate permissions" - }, - { - "id": "api.channel.delete_channel.deleted.app_error", - "translation": "The channel has been archived or deleted" - }, - { - "id": "api.channel.delete_channel.cannot.app_error", - "translation": "Cannot delete the default channel {{.Channel}}" - }, - { - "id": "api.channel.delete_channel.incoming_webhook.error", - "translation": "Encountered error deleting incoming webhook, id=%v" - }, - { - "id": "api.channel.delete_channel.outgoing_webhook.error", - "translation": "Encountered error deleting outgoing webhook, id=%v" - }, - { - "id": "api.channel.delete_channel.archived", - "translation": "%v has archived the channel." - }, - { - "id": "api.channel.delete_channel.failed_post.error", - "translation": "Failed to post archive message %v" - }, - { - "id": "api.channel.delete_channel.failed_send.app_error", - "translation": "Failed to send archive message" - }, - { - "id": "api.channel.get_channel_extra_info.member_limit.app_error", - "translation": "Failed to parse member limit" - }, - { - "id": "api.channel.get_channel_extra_info.deleted.app_error", - "translation": "The channel has been archived or deleted" - }, - { - "id": "api.channel.add_member.find_user.app_error", - "translation": "Failed to find user to be added" - }, - { - "id": "api.channel.add_member.find_channel.app_error", - "translation": "Failed to find channel" - }, - { - "id": "api.channel.add_member.user_adding.app_error", - "translation": "Failed to find user doing the adding" - }, - { - "id": "api.channel.add_member.added", - "translation": "%v added to the channel by %v" - }, - { - "id": "api.channel.remove_member.permissions.app_error", - "translation": "You do not have the appropriate permissions " - }, - { - "id": "api.channel.remove_member.unable.app_error", - "translation": "Unable to remove user." - }, - { - "id": "api.channel.remove_user_from_channel.deleted.app_error", - "translation": "The channel has been archived or deleted" - }, - { - "id": "api.command.no_implemented.app_error", - "translation": "Command not implemented" - }, - { - "id": "api.command.init.debug", - "translation": "Initializing command api routes" - }, - { - "id": "api.command.check_command.start.app_error", - "translation": "Command must start with /" - }, - { - "id": "api.command.logout_command.description", - "translation": "Logout" - }, - { - "id": "api.command.echo_command.under.app_error", - "translation": "Delays must be under 10000 seconds" - }, - { - "id": "api.command.echo_command.high_volume.app_error", - "translation": "High volume of echo request, cannot process request" - }, - { - "id": "api.command.echo_command.create.error", - "translation": "Unable to create /echo post, err=%v" - }, - { - "id": "api.command.echo_command.description", - "translation": "Echo back text from your account, /echo \"message\" [delay in seconds]" - }, - { - "id": "api.command.me_command.create.error", - "translation": "Unable to create /me post post, err=%v" - }, - { - "id": "api.command.me_command.description", - "translation": "Do an action, /me [message]" - }, - { - "id": "api.command.shrug_command.create.error", - "translation": "Unable to create /shrug post post, err=%v" - }, - { - "id": "api.command.shrug_command.description", - "translation": "Adds ¯\\_(ツ)_/¯ to your message, /shrug [message]" - }, - { - "id": "api.commmand.join_command.description", - "translation": "Join the open channel" - }, - { - "id": "api.command.load_test_command.description", - "translation": "Debug Load Testing" - }, - { - "id": "api.command.load_test_setup_command.create.error", - "translation": "Failed to create testing environment" - }, - { - "id": "api.command.load_test_setup_command.created.info", - "translation": "Team Created: %v" - }, - { - "id": "api.command.load_test_setup_command.login.info", - "translation": "\t User to login: %v, %v" - }, - { - "id": "api.command.load_test_setup_command.description", - "translation": "Creates a testing environment in current team. [teams] [fuzz] " - }, - { - "id": "api.command.load_test_users_command.users.description", - "translation": "Add a specified number of random users to current team " - }, - { - "id": "api.command.load_test_users_command.fuzz.description", - "translation": "Add a specified number of random users with fuzz text to current team " - }, - { - "id": "api.command.load_test_channels_command.channel.description", - "translation": "Add a specified number of random channels to current team " - }, - { - "id": "api.command.load_test_channels_command.fuzz.description", - "translation": "Add a specified number of random channels with fuzz text to current team " - }, - { - "id": "api.command.load_test_posts_command.posts.description", - "translation": "Add some random posts to current channel " - }, - { - "id": "api.command.load_test_posts_command.fuzz.description", - "translation": "Add some random posts with fuzz text to current channel " - }, - { - "id": "api.command.load_test_url_command.url.app_error", - "translation": "Command must contain a url" - }, - { - "id": "api.command.load_test_url_command.file.app_error", - "translation": "Unable to get file" - }, - { - "id": "api.command.load_test_url_command.reading.app_error", - "translation": "Encountered error reading file" - }, - { - "id": "api.command.load_test_url_command.create.error", - "translation": "Unable to create post, err=%v" - }, - { - "id": "api.command.load_test_url_command.description", - "translation": "Add a post containing the text from a given url to current channel " - }, - { - "id": "api.context.invalid_param.app_error", - "translation": "Invalid {{.Name}} parameter" - }, - { - "id": "api.context.session_expired.app_error", - "translation": "Invalid or expired session, please login again." - }, - { - "id": "api.context.token_provided.app_error", - "translation": "Session is not OAuth but token was provided in the query string" - }, - { - "id": "api.context.last_activity_at.error", - "translation": "Failed to update LastActivityAt for user_id=%v and session_id=%v, err=%v" - }, - { - "id": "api.context.log.error", - "translation": "%v:%v code=%v rid=%v uid=%v ip=%v %v [details: %v]" - }, - { - "id": "api.context.permissions.app_error", - "translation": "You do not have the appropriate permissions" - }, - { - "id": "api.context.system_permissions.app_error", - "translation": "You do not have the appropriate permissions (system)" - }, - { - "id": "api.context.unknown.app_error", - "translation": "An unknown error has occured. Please contact support." - }, - { - "id": "api.context.invalid_team_url.debug", - "translation": "TeamURL accessed when not valid. Team URL should not be used in api functions or those that are team independent" - }, - { - "id": "api.context.404.app_error", - "translation": "Sorry, we could not find the page." - }, - { - "id": "api.context.invalid_token.error", - "translation": "Invalid session token=%v, err=%v" - }, - { - "id": "api.export.options.create.app_error", - "translation": "Unable to create options file" - }, - { - "id": "api.export.options.write.app_error", - "translation": "Unable to write to options file" - }, - { - "id": "api.export.open_file.app_error", - "translation": "Unable to open file for export" - }, - { - "id": "api.export.write_file.app_error", - "translation": "Unable to write to export file" - }, - { - "id": "api.export.json.app_error", - "translation": "Unable to convert to json" - }, - { - "id": "api.export.open.app_error", - "translation": "Unable to open file" - }, - { - "id": "api.export.open_dir.app_error", - "translation": "Unable to open directory" - }, - { - "id": "api.export.read_dir.app_error", - "translation": "Unable to read directory" - }, - { - "id": "api.export.s3.app_error", - "translation": "S3 is not supported for local storage export." - } + { + "id": "api.admin.file_read_error", + "translation": "Error reading log file" + }, + { + "id": "api.admin.init.debug", + "translation": "Initializing admin api routes" + }, + { + "id": "api.admin.test_email.body", + "translation": "


It appears your Mattermost email is setup correctly!" + }, + { + "id": "api.admin.test_email.subject", + "translation": "Mattermost - Testing Email Settings" + }, + { + "id": "api.api.init.parsing_templates.debug", + "translation": "Parsing server templates at %v" + }, + { + "id": "api.api.init.parsing_templates.error", + "translation": "Failed to parse server templates %v" + }, + { + "id": "api.api.render.error", + "translation": "Error rendering template %v err=%v" + }, + { + "id": "api.channel.add_member.added", + "translation": "%v added to the channel by %v" + }, + { + "id": "api.channel.add_member.find_channel.app_error", + "translation": "Failed to find channel" + }, + { + "id": "api.channel.add_member.find_user.app_error", + "translation": "Failed to find user to be added" + }, + { + "id": "api.channel.add_member.user_adding.app_error", + "translation": "Failed to find user doing the adding" + }, + { + "id": "api.channel.add_user.to.channel.failed.app_error", + "translation": "Failed to add user to channel" + }, + { + "id": "api.channel.add_user_to_channel.deleted.app_error", + "translation": "The channel has been archived or deleted" + }, + { + "id": "api.channel.add_user_to_channel.type.app_error", + "translation": "Can not add user to this channel type" + }, + { + "id": "api.channel.create_channel.direct_channel.app_error", + "translation": "Must use createDirectChannel api service for direct message channel creation" + }, + { + "id": "api.channel.create_channel.invalid_character.app_error", + "translation": "Invalid character '__' in channel name for non-direct channel" + }, + { + "id": "api.channel.create_default_channels.off_topic", + "translation": "Off-Topic" + }, + { + "id": "api.channel.create_default_channels.town_square", + "translation": "Town Square" + }, + { + "id": "api.channel.create_direct_channel.invalid_user.app_error", + "translation": "Invalid other user id " + }, + { + "id": "api.channel.delete_channel.archived", + "translation": "%v has archived the channel." + }, + { + "id": "api.channel.delete_channel.cannot.app_error", + "translation": "Cannot delete the default channel {{.Channel}}" + }, + { + "id": "api.channel.delete_channel.deleted.app_error", + "translation": "The channel has been archived or deleted" + }, + { + "id": "api.channel.delete_channel.failed_post.error", + "translation": "Failed to post archive message %v" + }, + { + "id": "api.channel.delete_channel.failed_send.app_error", + "translation": "Failed to send archive message" + }, + { + "id": "api.channel.delete_channel.incoming_webhook.error", + "translation": "Encountered error deleting incoming webhook, id=%v" + }, + { + "id": "api.channel.delete_channel.outgoing_webhook.error", + "translation": "Encountered error deleting outgoing webhook, id=%v" + }, + { + "id": "api.channel.delete_channel.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.channel.get_channel_counts.app_error", + "translation": "Unable to get channel counts from the database" + }, + { + "id": "api.channel.get_channel_extra_info.deleted.app_error", + "translation": "The channel has been archived or deleted" + }, + { + "id": "api.channel.get_channel_extra_info.member_limit.app_error", + "translation": "Failed to parse member limit" + }, + { + "id": "api.channel.get_channels.error", + "translation": "Error in getting users profile for id=%v forcing logout" + }, + { + "id": "api.channel.init.debug", + "translation": "Initializing channel api routes" + }, + { + "id": "api.channel.join_channel.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.channel.join_channel.post_and_forget", + "translation": "%v has joined the channel." + }, + { + "id": "api.channel.leave.default.app_error", + "translation": "Cannot leave the default channel {{.Channel}}" + }, + { + "id": "api.channel.leave.direct.app_error", + "translation": "Cannot leave a direct message channel" + }, + { + "id": "api.channel.leave.left", + "translation": "%v has left the channel." + }, + { + "id": "api.channel.post_update_channel_header_message_and_forget.join_leave.error", + "translation": "Failed to post join/leave message %v" + }, + { + "id": "api.channel.post_update_channel_header_message_and_forget.removed", + "translation": "%s removed the channel header (was: %s)" + }, + { + "id": "api.channel.post_update_channel_header_message_and_forget.retrieve_user.error", + "translation": "Failed to retrieve user while trying to save update channel header message %v" + }, + { + "id": "api.channel.post_update_channel_header_message_and_forget.updated_from", + "translation": "%s updated the channel header from: %s to: %s" + }, + { + "id": "api.channel.post_update_channel_header_message_and_forget.updated_to", + "translation": "%s updated the channel header to: %s" + }, + { + "id": "api.channel.post_user_add_remove_message_and_forget.error", + "translation": "Failed to post join/leave message %v" + }, + { + "id": "api.channel.remove_member.permissions.app_error", + "translation": "You do not have the appropriate permissions " + }, + { + "id": "api.channel.remove_member.unable.app_error", + "translation": "Unable to remove user." + }, + { + "id": "api.channel.remove_user_from_channel.deleted.app_error", + "translation": "The channel has been archived or deleted" + }, + { + "id": "api.channel.update_channel.deleted.app_error", + "translation": "The channel has been archived or deleted" + }, + { + "id": "api.channel.update_channel.permission.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.channel.update_channel.tried.app_error", + "translation": "Tried to perform an invalid update of the default channel {{.Channel}}" + }, + { + "id": "api.command.check_command.start.app_error", + "translation": "Command must start with /" + }, + { + "id": "api.command.echo_command.create.error", + "translation": "Unable to create /echo post, err=%v" + }, + { + "id": "api.command.echo_command.description", + "translation": "Echo back text from your account, /echo \"message\" [delay in seconds]" + }, + { + "id": "api.command.echo_command.high_volume.app_error", + "translation": "High volume of echo request, cannot process request" + }, + { + "id": "api.command.echo_command.under.app_error", + "translation": "Delays must be under 10000 seconds" + }, + { + "id": "api.command.init.debug", + "translation": "Initializing command api routes" + }, + { + "id": "api.command.load_test_channels_command.channel.description", + "translation": "Add a specified number of random channels to current team " + }, + { + "id": "api.command.load_test_channels_command.fuzz.description", + "translation": "Add a specified number of random channels with fuzz text to current team " + }, + { + "id": "api.command.load_test_command.description", + "translation": "Debug Load Testing" + }, + { + "id": "api.command.load_test_posts_command.fuzz.description", + "translation": "Add some random posts with fuzz text to current channel " + }, + { + "id": "api.command.load_test_posts_command.posts.description", + "translation": "Add some random posts to current channel " + }, + { + "id": "api.command.load_test_setup_command.create.error", + "translation": "Failed to create testing environment" + }, + { + "id": "api.command.load_test_setup_command.created.info", + "translation": "Team Created: %v" + }, + { + "id": "api.command.load_test_setup_command.description", + "translation": "Creates a testing environment in current team. [teams] [fuzz] " + }, + { + "id": "api.command.load_test_setup_command.login.info", + "translation": "\t User to login: %v, %v" + }, + { + "id": "api.command.load_test_url_command.create.error", + "translation": "Unable to create post, err=%v" + }, + { + "id": "api.command.load_test_url_command.description", + "translation": "Add a post containing the text from a given url to current channel " + }, + { + "id": "api.command.load_test_url_command.file.app_error", + "translation": "Unable to get file" + }, + { + "id": "api.command.load_test_url_command.reading.app_error", + "translation": "Encountered error reading file" + }, + { + "id": "api.command.load_test_url_command.url.app_error", + "translation": "Command must contain a url" + }, + { + "id": "api.command.load_test_users_command.fuzz.description", + "translation": "Add a specified number of random users with fuzz text to current team " + }, + { + "id": "api.command.load_test_users_command.users.description", + "translation": "Add a specified number of random users to current team " + }, + { + "id": "api.command.logout_command.description", + "translation": "Logout" + }, + { + "id": "api.command.me_command.create.error", + "translation": "Unable to create /me post post, err=%v" + }, + { + "id": "api.command.me_command.description", + "translation": "Do an action, /me [message]" + }, + { + "id": "api.command.no_implemented.app_error", + "translation": "Command not implemented" + }, + { + "id": "api.command.shrug_command.create.error", + "translation": "Unable to create /shrug post post, err=%v" + }, + { + "id": "api.command.shrug_command.description", + "translation": "Adds ¯\\_(ツ)_/¯ to your message, /shrug [message]" + }, + { + "id": "api.commmand.join_command.description", + "translation": "Join the open channel" + }, + { + "id": "api.context.404.app_error", + "translation": "Sorry, we could not find the page." + }, + { + "id": "api.context.invalid_param.app_error", + "translation": "Invalid {{.Name}} parameter" + }, + { + "id": "api.context.invalid_team_url.debug", + "translation": "TeamURL accessed when not valid. Team URL should not be used in api functions or those that are team independent" + }, + { + "id": "api.context.invalid_token.error", + "translation": "Invalid session token=%v, err=%v" + }, + { + "id": "api.context.last_activity_at.error", + "translation": "Failed to update LastActivityAt for user_id=%v and session_id=%v, err=%v" + }, + { + "id": "api.context.log.error", + "translation": "%v:%v code=%v rid=%v uid=%v ip=%v %v [details: %v]" + }, + { + "id": "api.context.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.context.session_expired.app_error", + "translation": "Invalid or expired session, please login again." + }, + { + "id": "api.context.system_permissions.app_error", + "translation": "You do not have the appropriate permissions (system)" + }, + { + "id": "api.context.token_provided.app_error", + "translation": "Session is not OAuth but token was provided in the query string" + }, + { + "id": "api.context.unknown.app_error", + "translation": "An unknown error has occured. Please contact support." + }, + { + "id": "api.export.json.app_error", + "translation": "Unable to convert to json" + }, + { + "id": "api.export.open.app_error", + "translation": "Unable to open file" + }, + { + "id": "api.export.open_dir.app_error", + "translation": "Unable to open directory" + }, + { + "id": "api.export.open_file.app_error", + "translation": "Unable to open file for export" + }, + { + "id": "api.export.options.create.app_error", + "translation": "Unable to create options file" + }, + { + "id": "api.export.options.write.app_error", + "translation": "Unable to write to options file" + }, + { + "id": "api.export.read_dir.app_error", + "translation": "Unable to read directory" + }, + { + "id": "api.export.s3.app_error", + "translation": "S3 is not supported for local storage export." + }, + { + "id": "api.export.write_file.app_error", + "translation": "Unable to write to export file" + }, + { + "id": "api.file.file_upload.exceeds", + "translation": "File exceeds max image size." + }, + { + "id": "api.file.get_export.retrieve.app_error", + "translation": "Unable to retrieve exported file. Please re-export" + }, + { + "id": "api.file.get_export.team_admin.app_error", + "translation": "Only a team admin can retrieve exported data." + }, + { + "id": "api.file.get_file.not_found.app_error", + "translation": "Could not find file." + }, + { + "id": "api.file.get_file.public_expired.app_error", + "translation": "The public link has expired" + }, + { + "id": "api.file.get_file.public_invalid.app_error", + "translation": "The public link does not appear to be valid" + }, + { + "id": "api.file.get_public_link.disabled.app_error", + "translation": "Public links have been disabled" + }, + { + "id": "api.file.handle_images_forget.decode.error", + "translation": "Unable to decode image channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.handle_images_forget.encode_jpeg.error", + "translation": "Unable to encode image as jpeg channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.handle_images_forget.encode_preview.error", + "translation": "Unable to encode image as preview jpg channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.handle_images_forget.upload_preview.error", + "translation": "Unable to upload preview channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.handle_images_forget.upload_thumb.error", + "translation": "Unable to upload thumbnail channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.init.debug", + "translation": "Initializing file api routes" + }, + { + "id": "api.file.open_file_write_stream.configured.app_error", + "translation": "File storage not configured properly. Please configure for either S3 or local server file storage." + }, + { + "id": "api.file.open_file_write_stream.creating_dir.app_error", + "translation": "Encountered an error creating the directory for the new file" + }, + { + "id": "api.file.open_file_write_stream.local_server.app_error", + "translation": "Encountered an error writing to local server storage" + }, + { + "id": "api.file.open_file_write_stream.s3.app_error", + "translation": "S3 is not supported." + }, + { + "id": "api.file.read_file.configured.app_error", + "translation": "File storage not configured properly. Please configure for either S3 or local server file storage." + }, + { + "id": "api.file.read_file.get.app_error", + "translation": "Unable to get file from S3" + }, + { + "id": "api.file.read_file.reading_local.app_error", + "translation": "Encountered an error reading from local server storage" + }, + { + "id": "api.file.upload_file.image.app_error", + "translation": "Unable to upload image file." + }, + { + "id": "api.file.upload_file.large_image.app_error", + "translation": "Unable to upload image file. File is too large." + }, + { + "id": "api.file.upload_file.storage.app_error", + "translation": "Unable to upload file. Image storage is not configured." + }, + { + "id": "api.file.upload_file.too_large.app_error", + "translation": "Unable to upload file. File is too large." + }, + { + "id": "api.file.write_file.configured.app_error", + "translation": "File storage not configured properly. Please configure for either S3 or local server file storage." + }, + { + "id": "api.file.write_file.s3.app_error", + "translation": "Encountered an error writing to S3" + }, + { + "id": "api.file.write_file_locally.create_dir.app_error", + "translation": "Encountered an error creating the directory for the new file" + }, + { + "id": "api.file.write_file_locally.writing.app_error", + "translation": "Encountered an error writing to local server storage" + }, + { + "id": "api.import.import_post.saving.debug", + "translation": "Error saving post. user=%v, message=%v" + }, + { + "id": "api.import.import_user.joining_default.error", + "translation": "Encountered an issue joining default channels user_id=%s, team_id=%s, err=%v" + }, + { + "id": "api.import.import_user.saving.error", + "translation": "Error saving user. err=%v" + }, + { + "id": "api.import.import_user.set_email.error", + "translation": "Failed to set email verified err=%v" + }, + { + "id": "api.license.add_license.array.app_error", + "translation": "Empty array under 'license' in request" + }, + { + "id": "api.license.add_license.expired.app_error", + "translation": "License is either expired or has not yet started." + }, + { + "id": "api.license.add_license.invalid.app_error", + "translation": "Invalid license file." + }, + { + "id": "api.license.add_license.no_file.app_error", + "translation": "No file under 'license' in request" + }, + { + "id": "api.license.add_license.open.app_error", + "translation": "Could not open license file" + }, + { + "id": "api.license.add_license.save.app_error", + "translation": "License did not save properly." + }, + { + "id": "api.license.init.debug", + "translation": "Initializing license api routes" + }, + { + "id": "api.license.remove_license.remove.app_error", + "translation": "License did not remove properly." + }, + { + "id": "api.oauth.allow_oauth.bad_client.app_error", + "translation": "invalid_request: Bad client_id" + }, + { + "id": "api.oauth.allow_oauth.bad_redirect.app_error", + "translation": "invalid_request: Missing or bad redirect_uri" + }, + { + "id": "api.oauth.allow_oauth.bad_response.app_error", + "translation": "invalid_request: Bad response_type" + }, + { + "id": "api.oauth.allow_oauth.database.app_error", + "translation": "server_error: Error accessing the database" + }, + { + "id": "api.oauth.allow_oauth.redirect_callback.app_error", + "translation": "invalid_request: Supplied redirect_uri did not match registered callback_url" + }, + { + "id": "api.oauth.allow_oauth.turn_off.app_error", + "translation": "The system admin has turned off OAuth service providing." + }, + { + "id": "api.oauth.get_auth_data.find.error", + "translation": "Couldn't find auth code for code=%s" + }, + { + "id": "api.oauth.init.debug", + "translation": "Initializing oauth api routes" + }, + { + "id": "api.oauth.register_oauth_app.turn_off.app_error", + "translation": "The system admin has turned off OAuth service providing." + }, + { + "id": "api.oauth.revoke_access_token.del_code.app_error", + "translation": "Error deleting authorization code from DB" + }, + { + "id": "api.oauth.revoke_access_token.del_session.app_error", + "translation": "Error deleting session from DB" + }, + { + "id": "api.oauth.revoke_access_token.del_token.app_error", + "translation": "Error deleting access token from DB" + }, + { + "id": "api.oauth.revoke_access_token.get.app_error", + "translation": "Error getting access token from DB before deletion" + }, + { + "id": "api.post.create_post.bad_filename.error", + "translation": "Bad filename discarded, filename=%v" + }, + { + "id": "api.post.create_post.channel_root_id.app_error", + "translation": "Invalid ChannelId for RootId parameter" + }, + { + "id": "api.post.create_post.last_viewed.error", + "translation": "Encountered error updating last viewed, channel_id=%s, user_id=%s, err=%v" + }, + { + "id": "api.post.create_post.parent_id.app_error", + "translation": "Invalid ParentId parameter" + }, + { + "id": "api.post.create_post.root_id.app_error", + "translation": "Invalid RootId parameter" + }, + { + "id": "api.post.create_webhook_post.creating.app_error", + "translation": "Error creating post" + }, + { + "id": "api.post.delete_post.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.post.get_post.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.post.handle_post_events_and_forget.channel.error", + "translation": "Encountered error getting channel, channel_id=%s, err=%v" + }, + { + "id": "api.post.handle_post_events_and_forget.team.error", + "translation": "Encountered error getting team, team_id=%s, err=%v" + }, + { + "id": "api.post.handle_post_events_and_forget.user.error", + "translation": "Encountered error getting user, user_id=%s, err=%v" + }, + { + "id": "api.post.handle_webhook_events_and_forget.create_post.error", + "translation": "Failed to create response post, err=%v" + }, + { + "id": "api.post.handle_webhook_events_and_forget.event_post.error", + "translation": "Event POST failed, err=%s" + }, + { + "id": "api.post.handle_webhook_events_and_forget.getting.error", + "translation": "Encountered error getting webhooks by team, err=%v" + }, + { + "id": "api.post.init.debug", + "translation": "Initializing post api routes" + }, + { + "id": "api.post.make_direct_channel_visible.get_2_members.error", + "translation": "Failed to get 2 members for a direct channel channel_id=%v" + }, + { + "id": "api.post.make_direct_channel_visible.get_members.error", + "translation": "Failed to get channel members channel_id=%v err=%v" + }, + { + "id": "api.post.make_direct_channel_visible.save_pref.error", + "translation": "Failed to save direct channel preference user_id=%v other_user_id=%v err=%v" + }, + { + "id": "api.post.make_direct_channel_visible.update_pref.error", + "translation": "Failed to update direct channel preference user_id=%v other_user_id=%v err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.members.error", + "translation": "Failed to get channel members channel_id=%v err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.mention_body", + "translation": "You have one new mention." + }, + { + "id": "api.post.send_notifications_and_forget.mention_subject", + "translation": "New Mention" + }, + { + "id": "api.post.send_notifications_and_forget.message_body", + "translation": "You have one new message." + }, + { + "id": "api.post.send_notifications_and_forget.message_subject", + "translation": "New Direct Message" + }, + { + "id": "api.post.send_notifications_and_forget.push_mention", + "translation": " mentioned you in " + }, + { + "id": "api.post.send_notifications_and_forget.push_message", + "translation": " sent you a direct message" + }, + { + "id": "api.post.send_notifications_and_forget.push_notification.debug", + "translation": "Sending push notification to %v wi msg of '%v'" + }, + { + "id": "api.post.send_notifications_and_forget.push_notification.error", + "translation": "Failed to send push notificationid=%v, err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.retrive_profiles.error", + "translation": "Failed to retrieve user profiles team_id=%v, err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.send.error", + "translation": "Failed to send mention email successfully email=%v err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.sent", + "translation": "{{.Prefix}} {{.Filenames}} sent" + }, + { + "id": "api.post.send_notifications_and_forget.sessions.error", + "translation": "Failed to retrieve sessions in notifications id=%v, err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.user_id.error", + "translation": "Post user_id not returned by GetProfiles user_id=%v" + }, + { + "id": "api.post.update_mention_count_and_forget.update_error", + "translation": "Failed to update mention count for user_id=%v on channel_id=%v err=%v" + }, + { + "id": "api.post.update_post.find.app_error", + "translation": "We couldn't find the existing post or comment to update." + }, + { + "id": "api.post.update_post.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.post.update_post.permissions_details.app_error", + "translation": "Already delted id={{.PostId}}" + }, + { + "id": "api.post_get_post_by_id.get.app_error", + "translation": "Unable to get post" + }, + { + "id": "api.preference.init.debug", + "translation": "Initializing preference api routes" + }, + { + "id": "api.preference.save_preferences.decode.app_error", + "translation": "Unable to decode preferences from request" + }, + { + "id": "api.preference.save_preferences.set.app_error", + "translation": "Unable to set preferences for other user" + }, + { + "id": "api.preference.save_preferences.set_details.app_error", + "translation": "session.user_id={{.SessionUserId}}, preference.user_id={{.PreferenceUserId}}" + }, + { + "id": "api.server.new_server.init.info", + "translation": "Server is initializing..." + }, + { + "id": "api.server.start_server.listening.info", + "translation": "Server is listening on %v" + }, + { + "id": "api.server.start_server.rate.info", + "translation": "RateLimiter is enabled" + }, + { + "id": "api.server.start_server.rate.warn", + "translation": "RateLimitSettings not configured properly using VaryByHeader and disabling VaryByRemoteAddr" + }, + { + "id": "api.server.start_server.starting.critical", + "translation": "Error starting server, err:%v" + }, + { + "id": "api.server.start_server.starting.info", + "translation": "Starting Server..." + }, + { + "id": "api.server.start_server.starting.panic", + "translation": "Error starting server " + }, + { + "id": "api.server.stop_server.stopped.info", + "translation": "Server stopped" + }, + { + "id": "api.server.stop_server.stopping.info", + "translation": "Stopping Server..." + }, + { + "id": "api.slackimport.slack_add_channels.added", + "translation": "\r\n Channels Added \r\n" + }, + { + "id": "api.slackimport.slack_add_channels.import_failed", + "translation": "Failed to import: {{.DisplayName}}\r\n" + }, + { + "id": "api.slackimport.slack_add_channels.import_failed.debug", + "translation": "Failed to import: %s" + }, + { + "id": "api.slackimport.slack_add_channels.merge", + "translation": "Merged with existing channel: {{.DisplayName}}\r\n" + }, + { + "id": "api.slackimport.slack_add_posts.bot.warn", + "translation": "Slack bot posts are not imported yet" + }, + { + "id": "api.slackimport.slack_add_posts.msg_no_usr.debug", + "translation": "Message without user" + }, + { + "id": "api.slackimport.slack_add_posts.unsupported.warn", + "translation": "Unsupported post type: %v, %v" + }, + { + "id": "api.slackimport.slack_add_posts.user_no_exists.debug", + "translation": "User: %v does not exist!" + }, + { + "id": "api.slackimport.slack_add_posts.without_user.debug", + "translation": "Message without user" + }, + { + "id": "api.slackimport.slack_add_users.created", + "translation": "\r\n Users Created\r\n" + }, + { + "id": "api.slackimport.slack_add_users.email_pwd", + "translation": "Email, Password: {{.Email}}, {{.Password}}\r\n" + }, + { + "id": "api.slackimport.slack_add_users.unable_import", + "translation": "Unable to import user: {{.Username}}\r\n" + }, + { + "id": "api.slackimport.slack_convert_timestamp.bad.warn", + "translation": "Bad timestamp detected" + }, + { + "id": "api.slackimport.slack_import.log", + "translation": "Mattermost Slack Import Log\r\n" + }, + { + "id": "api.slackimport.slack_import.note1", + "translation": "- Some posts may not have been imported because they where not supported by this importer.\r\n" + }, + { + "id": "api.slackimport.slack_import.note2", + "translation": "- Slack bot posts are currently not supported.\r\n" + }, + { + "id": "api.slackimport.slack_import.notes", + "translation": "\r\n Notes \r\n" + }, + { + "id": "api.slackimport.slack_import.open.app_error", + "translation": "Unable to open: {{.Filename}}" + }, + { + "id": "api.slackimport.slack_import.zip.app_error", + "translation": "Unable to open zip file" + }, + { + "id": "api.team.create_team.email_disabled.app_error", + "translation": "Team sign-up with email is disabled." + }, + { + "id": "api.team.create_team_from_signup.email_disabled.app_error", + "translation": "Team sign-up with email is disabled." + }, + { + "id": "api.team.create_team_from_signup.expired_link.app_error", + "translation": "The signup link has expired" + }, + { + "id": "api.team.create_team_from_signup.invalid_link.app_error", + "translation": "The signup link does not appear to be valid" + }, + { + "id": "api.team.create_team_from_signup.unavailable.app_error", + "translation": "This URL is unavailable. Please try another." + }, + { + "id": "api.team.email_teams.sending.error", + "translation": "An error occured while sending an email in emailTeams err=%v" + }, + { + "id": "api.team.export_team.admin.app_error", + "translation": "Only a team admin can export data." + }, + { + "id": "api.team.import_team.admin.app_error", + "translation": "Only a team admin can import data." + }, + { + "id": "api.team.import_team.array.app_error", + "translation": "Empty array under 'file' in request" + }, + { + "id": "api.team.import_team.integer.app_error", + "translation": "Filesize not an integer" + }, + { + "id": "api.team.import_team.no_file.app_error", + "translation": "No file under 'file' in request" + }, + { + "id": "api.team.import_team.open.app_error", + "translation": "Could not open file" + }, + { + "id": "api.team.import_team.parse.app_error", + "translation": "Could not parse multipart form" + }, + { + "id": "api.team.import_team.unavailable.app_error", + "translation": "Filesize unavilable" + }, + { + "id": "api.team.init.debug", + "translation": "Initializing team api routes" + }, + { + "id": "api.team.invite_members.admin", + "translation": "administrator" + }, + { + "id": "api.team.invite_members.already.app_error", + "translation": "This person is already on your team" + }, + { + "id": "api.team.invite_members.member", + "translation": "member" + }, + { + "id": "api.team.invite_members.no_one.app_error", + "translation": "No one to invite." + }, + { + "id": "api.team.invite_members.send.error", + "translation": "Failed to send invite email successfully err=%v" + }, + { + "id": "api.team.invite_members.sending.info", + "translation": "sending invitation to %v %v" + }, + { + "id": "api.team.is_team_creation_allowed.disabled.app_error", + "translation": "Team creation has been disabled. Please ask your systems administrator for details." + }, + { + "id": "api.team.is_team_creation_allowed.domain.app_error", + "translation": "Email must be from a specific domain (e.g. @example.com). Please ask your systems administrator for details." + }, + { + "id": "api.team.permanent_delete_team.attempting.warn", + "translation": "Attempting to permanently delete team %v id=%v" + }, + { + "id": "api.team.permanent_delete_team.deleted.warn", + "translation": "Permanently deleted team %v id=%v" + }, + { + "id": "api.team.signup_team.email_disabled.app_error", + "translation": "Team sign-up with email is disabled." + }, + { + "id": "api.team.update_team.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.user.add_direct_channels_and_forget.failed.error", + "translation": "Failed to add direct channel preferences for user user_id=%s, team_id=%s, err=%v" + }, + { + "id": "api.user.authorize_oauth_user.bad_response.app_error", + "translation": "Bad response from token request" + }, + { + "id": "api.user.authorize_oauth_user.bad_token.app_error", + "translation": "Bad token type" + }, + { + "id": "api.user.authorize_oauth_user.invalid_state.app_error", + "translation": "Invalid state" + }, + { + "id": "api.user.authorize_oauth_user.invalid_state_team.app_error", + "translation": "Invalid state; missing team name" + }, + { + "id": "api.user.authorize_oauth_user.missing.app_error", + "translation": "Missing access token" + }, + { + "id": "api.user.authorize_oauth_user.service.app_error", + "translation": "Token request to {{.Service}} failed" + }, + { + "id": "api.user.authorize_oauth_user.token_failed.app_error", + "translation": "Token request failed" + }, + { + "id": "api.user.authorize_oauth_user.unsupported.app_error", + "translation": "Unsupported OAuth service provider" + }, + { + "id": "api.user.check_user_login_attempts.too_many.app_error", + "translation": "Your account is locked because of too many failed password attempts. Please reset your password." + }, + { + "id": "api.user.check_user_password.invalid.app_error", + "translation": "Login failed because of invalid password" + }, + { + "id": "api.user.complete_switch_with_oauth.blank_email.app_error", + "translation": "Blank email" + }, + { + "id": "api.user.complete_switch_with_oauth.parse.app_error", + "translation": "Could not parse auth data out of {{.Service}} user object" + }, + { + "id": "api.user.complete_switch_with_oauth.unavailable.app_error", + "translation": "{{.Service}} oauth not available on this server" + }, + { + "id": "api.user.create_oauth_user.already_attached.app_error", + "translation": "Team {{.DisplayName}} already has a user with the email address attached to your {{.Service}} account" + }, + { + "id": "api.user.create_oauth_user.already_used.app_error", + "translation": "This {{.Service}} account has already been used to sign up for team {{.DisplayName}}" + }, + { + "id": "api.user.create_oauth_user.create.app_error", + "translation": "Could not create user out of {{.Service}} user object" + }, + { + "id": "api.user.create_oauth_user.not_available.app_error", + "translation": "{{.Service}} oauth not avlailable on this server" + }, + { + "id": "api.user.create_profile_image.default_font.app_error", + "translation": "Could not create default profile image font" + }, + { + "id": "api.user.create_profile_image.encode.app_error", + "translation": "Could not encode default profile image" + }, + { + "id": "api.user.create_profile_image.initial.app_error", + "translation": "Could not add user initial to default profile picture" + }, + { + "id": "api.user.create_user.accepted_domain.app_error", + "translation": "The email you provided does not belong to an accepted domain. Please contact your administrator or sign up with a different email." + }, + { + "id": "api.user.create_user.joining.error", + "translation": "Encountered an issue joining default channels user_id=%s, team_id=%s, err=%v" + }, + { + "id": "api.user.create_user.save.error", + "translation": "Couldn't save the user err=%v" + }, + { + "id": "api.user.create_user.signup_email_disabled.app_error", + "translation": "User sign-up with email is disabled." + }, + { + "id": "api.user.create_user.signup_link_expired.app_error", + "translation": "The signup link has expired" + }, + { + "id": "api.user.create_user.signup_link_invalid.app_error", + "translation": "The signup link does not appear to be valid" + }, + { + "id": "api.user.create_user.team_name.app_error", + "translation": "Invalid team name" + }, + { + "id": "api.user.create_user.tutorial.error", + "translation": "Encountered error saving tutorial preference, err=%v" + }, + { + "id": "api.user.create_user.verified.error", + "translation": "Failed to set email verified err=%v" + }, + { + "id": "api.user.get_authorization_code.unsupported.app_error", + "translation": "Unsupported OAuth service provider" + }, + { + "id": "api.user.get_me.getting.error", + "translation": "Error in getting users profile for id=%v forcing logout" + }, + { + "id": "api.user.init.debug", + "translation": "Initializing user api routes" + }, + { + "id": "api.user.login.blank_pwd.app_error", + "translation": "Password field must not be blank" + }, + { + "id": "api.user.login.inactive.app_error", + "translation": "Login failed because your account has been set to inactive. Please contact an administrator." + }, + { + "id": "api.user.login.not_provided.app_error", + "translation": "Either user id or team name and user email must be provided" + }, + { + "id": "api.user.login.not_verified.app_error", + "translation": "Login failed because email address has not been verified" + }, + { + "id": "api.user.login.revoking.app_error", + "translation": "Revoking sessionId=%v for userId=%v re-login with same device Id" + }, + { + "id": "api.user.login_by_email.sign_in.app_error", + "translation": "Please sign in using {{.AuthService}}" + }, + { + "id": "api.user.login_by_oauth.not_available.app_error", + "translation": "{{.Service}} oauth not avlailable on this server" + }, + { + "id": "api.user.login_by_oauth.parse.app_error", + "translation": "Could not parse auth data out of {{.Service}} user object" + }, + { + "id": "api.user.login_ldap.blank_pwd.app_error", + "translation": "Password field must not be blank" + }, + { + "id": "api.user.login_ldap.disabled.app_error", + "translation": "LDAP not enabled on this server" + }, + { + "id": "api.user.login_ldap.need_id.app_error", + "translation": "Need an ID" + }, + { + "id": "api.user.login_ldap.not_available.app_error", + "translation": "LDAP not available on this server" + }, + { + "id": "api.user.permanent_delete_user.attempting.warn", + "translation": "Attempting to permanently delete account %v id=%v" + }, + { + "id": "api.user.permanent_delete_user.deleted.warn", + "translation": "Permanently deleted account %v id=%v" + }, + { + "id": "api.user.permanent_delete_user.system_admin.warn", + "translation": "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." + }, + { + "id": "api.user.reset_password.invalid_link.app_error", + "translation": "The reset password link does not appear to be valid" + }, + { + "id": "api.user.reset_password.link_expired.app_error", + "translation": "The reset link has expired" + }, + { + "id": "api.user.reset_password.sso.app_error", + "translation": "Cannot reset password for SSO accounts" + }, + { + "id": "api.user.reset_password.wrong_team.app_error", + "translation": "Trying to reset password for user on wrong team." + }, + { + "id": "api.user.send_email_change_email_and_forget.error", + "translation": "Failed to send email change notification email successfully err=%v" + }, + { + "id": "api.user.send_email_change_verify_email_and_forget.error", + "translation": "Failed to send email change verification email successfully err=%v" + }, + { + "id": "api.user.send_password_change_email_and_forget.error", + "translation": "Failed to send update password email successfully err=%v" + }, + { + "id": "api.user.send_password_reset.find.app_error", + "translation": "We couldn’t find an account with that address." + }, + { + "id": "api.user.send_password_reset.send.app_error", + "translation": "Failed to send password reset email successfully" + }, + { + "id": "api.user.send_password_reset.sso.app_error", + "translation": "Cannot reset password for SSO accounts" + }, + { + "id": "api.user.send_sign_in_change_email_and_forget.error", + "translation": "Failed to send update password email successfully err=%v" + }, + { + "id": "api.user.send_verify_email_and_forget.failed.error", + "translation": "Failed to send verification email successfully err=%v" + }, + { + "id": "api.user.send_welcome_email_and_forget.failed.error", + "translation": "Failed to send welcome email successfully err=%v" + }, + { + "id": "api.user.switch_to_email.context.app_error", + "translation": "Update password failed because context user_id did not match provided user's id" + }, + { + "id": "api.user.update_active.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.user.update_password.context.app_error", + "translation": "Update password failed because context user_id did not match props user_id" + }, + { + "id": "api.user.update_password.failed.app_error", + "translation": "Update password failed" + }, + { + "id": "api.user.update_password.incorrect.app_error", + "translation": "The \"Current Password\" you entered is incorrect. Please check that Caps Lock is off and try again." + }, + { + "id": "api.user.update_password.menu", + "translation": "using the settings menu" + }, + { + "id": "api.user.update_password.oauth.app_error", + "translation": "Update password failed because the user is logged in through an OAuth service" + }, + { + "id": "api.user.update_password.valid_account.app_error", + "translation": "Update password failed because we couldn't find a valid account" + }, + { + "id": "api.user.update_roles.one_admin.app_error", + "translation": "There must be at least one active admin" + }, + { + "id": "api.user.update_roles.permissions.app_error", + "translation": "You do not have the appropriate permissions" + }, + { + "id": "api.user.update_roles.system_admin_mod.app_error", + "translation": "The system admin role can only by modified by another system admin" + }, + { + "id": "api.user.update_roles.system_admin_set.app_error", + "translation": "The system admin role can only be set by another system admin" + }, + { + "id": "api.user.upload_profile_user.array.app_error", + "translation": "Empty array under 'image' in request" + }, + { + "id": "api.user.upload_profile_user.decode.app_error", + "translation": "Could not decode profile image" + }, + { + "id": "api.user.upload_profile_user.decode_config.app_error", + "translation": "Could not decode profile image config." + }, + { + "id": "api.user.upload_profile_user.encode.app_error", + "translation": "Could not encode profile image" + }, + { + "id": "api.user.upload_profile_user.no_file.app_error", + "translation": "No file under 'image' in request" + }, + { + "id": "api.user.upload_profile_user.open.app_error", + "translation": "Could not open image file" + }, + { + "id": "api.user.upload_profile_user.parse.app_error", + "translation": "Could not parse multipart form" + }, + { + "id": "api.user.upload_profile_user.storage.app_error", + "translation": "Unable to upload file. Image storage is not configured." + }, + { + "id": "api.user.upload_profile_user.too_large.app_error", + "translation": "Unable to upload profile image. File is too large." + }, + { + "id": "mattermost.current_version", + "translation": "Current version is %v (%v/%v/%v)" + }, + { + "id": "utils.i18n.loaded", + "translation": "Loaded system translations for '%v' from '%v'" + } ] \ No newline at end of file diff --git a/i18n/es.json b/i18n/es.json index ca26da673..480f23857 100644 --- a/i18n/es.json +++ b/i18n/es.json @@ -391,6 +391,934 @@ "id": "api.export.write_file.app_error", "translation": "No se puede escribir al archivo a exportar" }, + { + "id": "api.file.file_upload.exceeds", + "translation": "El archivo excede el tamaño máximo para una imagen." + }, + { + "id": "api.file.get_export.retrieve.app_error", + "translation": "No se puede recuperar el archivo exportado. Por favor vuelve a exportarlo" + }, + { + "id": "api.file.get_export.team_admin.app_error", + "translation": "Sólo un administrador del equipo puede recuperar la data exportada." + }, + { + "id": "api.file.get_file.not_found.app_error", + "translation": "No se encontró el archivo." + }, + { + "id": "api.file.get_file.public_expired.app_error", + "translation": "El enlace público ha expirado" + }, + { + "id": "api.file.get_file.public_invalid.app_error", + "translation": "El enlace público parece ser inválido" + }, + { + "id": "api.file.get_public_link.disabled.app_error", + "translation": "Los enlaces públicos han sido deshabilitados" + }, + { + "id": "api.file.handle_images_forget.decode.error", + "translation": "No se puede decodificar la imagen channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.handle_images_forget.encode_jpeg.error", + "translation": "No se puede codificar la imagen como jpeg channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.handle_images_forget.encode_preview.error", + "translation": "No se puede codificar la imagen de muestra como jpg channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.handle_images_forget.upload_preview.error", + "translation": "No se puede subir la vista previa channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.handle_images_forget.upload_thumb.error", + "translation": "No se puede subir la miniatura channelId=%v userId=%v filename=%v err=%v" + }, + { + "id": "api.file.init.debug", + "translation": "Inicializando rutas del API para los archivos" + }, + { + "id": "api.file.open_file_write_stream.configured.app_error", + "translation": "El almacenamiento de archivos no ha sido configurado apropiadamente. Por favor configuralo ya sea para S3 o para almacenamiento en el servidor local." + }, + { + "id": "api.file.open_file_write_stream.creating_dir.app_error", + "translation": "Se encontró un error al crear el directorio para el nuevo archivo" + }, + { + "id": "api.file.open_file_write_stream.local_server.app_error", + "translation": "Se encontró un error al escribir en el almacenamiento del servidor local" + }, + { + "id": "api.file.open_file_write_stream.s3.app_error", + "translation": "S3 no está soportado." + }, + { + "id": "api.file.read_file.configured.app_error", + "translation": "El almacenamiento de archivos no ha sido configurado apropiadamente. Por favor configuralo ya sea para S3 o para almacenamiento en el servidor local." + }, + { + "id": "api.file.read_file.get.app_error", + "translation": "No se puede obtener el archivo desde el S3" + }, + { + "id": "api.file.read_file.reading_local.app_error", + "translation": "Se encontró un error al leer desde el almacenamiento del servidor local" + }, + { + "id": "api.file.upload_file.image.app_error", + "translation": "No se puede subir el archivo de la imagen." + }, + { + "id": "api.file.upload_file.large_image.app_error", + "translation": "No se pudo subir la imagen. El archivo es demasiado grande." + }, + { + "id": "api.file.upload_file.storage.app_error", + "translation": "No se puede subir el archivo. El almacenamiento de imágenes no está configurado." + }, + { + "id": "api.file.upload_file.too_large.app_error", + "translation": "No se pudo subir el archivo. El archivo es demasiado grande." + }, + { + "id": "api.file.write_file.configured.app_error", + "translation": "El almacenamiento de archivos no ha sido configurado apropiadamente. Por favor configuralo ya sea para S3 o para almacenamiento en el servidor local." + }, + { + "id": "api.file.write_file.s3.app_error", + "translation": "Se encontró un error al escribir al S3" + }, + { + "id": "api.file.write_file_locally.create_dir.app_error", + "translation": "Se encontró un error al crear el directorio para el nuevo archivo" + }, + { + "id": "api.file.write_file_locally.writing.app_error", + "translation": "Se encontró un error al escribir en el almacenamiento del servidor local" + }, + { + "id": "api.import.import_post.saving.debug", + "translation": "Error guardando el mensaje. user=%v, message=%v" + }, + { + "id": "api.import.import_user.joining_default.error", + "translation": "Se encontró un problema al unirse a los canales predeterminados user_id=%s, team_id=%s, err=%v" + }, + { + "id": "api.import.import_user.saving.error", + "translation": "Error guardando el usuario. err=%v" + }, + { + "id": "api.import.import_user.set_email.error", + "translation": "Falla al asignar el correo como verificado err=%v" + }, + { + "id": "api.license.add_license.array.app_error", + "translation": "Arreglo vacío bajo 'license' en la solicitud" + }, + { + "id": "api.license.add_license.expired.app_error", + "translation": "La licencia ya expiró o todavía no ha comenzado." + }, + { + "id": "api.license.add_license.invalid.app_error", + "translation": "Archivo de licencia inválido." + }, + { + "id": "api.license.add_license.no_file.app_error", + "translation": "No hay un archivo bajo 'license' en la solicitud" + }, + { + "id": "api.license.add_license.open.app_error", + "translation": "No se pudo abrir el archivo de la licencia" + }, + { + "id": "api.license.add_license.save.app_error", + "translation": "La licencia no fue guardada correctamente." + }, + { + "id": "api.license.init.debug", + "translation": "Inicializando rutas del API para las licencias" + }, + { + "id": "api.license.remove_license.remove.app_error", + "translation": "La licencia no fue removida correctamente." + }, + { + "id": "api.oauth.allow_oauth.bad_client.app_error", + "translation": "invalid_request: Mal client_id" + }, + { + "id": "api.oauth.allow_oauth.bad_redirect.app_error", + "translation": "invalid_request: Falta o está malo el redirect_uri" + }, + { + "id": "api.oauth.allow_oauth.bad_response.app_error", + "translation": "invalid_request: Mal response_type" + }, + { + "id": "api.oauth.allow_oauth.database.app_error", + "translation": "server_error: Error accesando la base de datos" + }, + { + "id": "api.oauth.allow_oauth.redirect_callback.app_error", + "translation": "invalid_request: El redirect_uri suministrado no coincide con el callback_url registrado" + }, + { + "id": "api.oauth.allow_oauth.turn_off.app_error", + "translation": "El administrador de sistema ha desactivado el servicio de autenticación por OAuth." + }, + { + "id": "api.oauth.get_auth_data.find.error", + "translation": "No se encontró el auth code para el código=%s" + }, + { + "id": "api.oauth.init.debug", + "translation": "Inicializando rutas del API para el OAuth" + }, + { + "id": "api.oauth.register_oauth_app.turn_off.app_error", + "translation": "El administrador de sistema ha desactivado el servicio de autenticación por OAuth." + }, + { + "id": "api.oauth.revoke_access_token.del_code.app_error", + "translation": "Error eliminando el código de authorización desde la DB" + }, + { + "id": "api.oauth.revoke_access_token.del_session.app_error", + "translation": "Error eliminando la sesión desde la DB" + }, + { + "id": "api.oauth.revoke_access_token.del_token.app_error", + "translation": "Error eliminando el token de acceso desde la DB" + }, + { + "id": "api.oauth.revoke_access_token.get.app_error", + "translation": "Error obteniendo el token de acceso desde la BD antes de ser eliminado" + }, + { + "id": "api.post.create_post.bad_filename.error", + "translation": "Nombre errado de archivo descartado, archivo=%v" + }, + { + "id": "api.post.create_post.channel_root_id.app_error", + "translation": "Canal inválido para el parámetro RootId" + }, + { + "id": "api.post.create_post.last_viewed.error", + "translation": "Se encontró un error al actualizar la última vista, channel_id=%s, user_id=%s, err=%v" + }, + { + "id": "api.post.create_post.parent_id.app_error", + "translation": "Parámetro ParentId inválido" + }, + { + "id": "api.post.create_post.root_id.app_error", + "translation": "Parámetro RootId inválido" + }, + { + "id": "api.post.create_webhook_post.creating.app_error", + "translation": "Error creando el mensaje" + }, + { + "id": "api.post.delete_post.permissions.app_error", + "translation": "No tienes los permisos apropiados" + }, + { + "id": "api.post.get_post.permissions.app_error", + "translation": "No tienes los permisos apropiados" + }, + { + "id": "api.post.handle_post_events_and_forget.channel.error", + "translation": "Se encontró un error obteniendo el canal, channel_id=%s, err=%v" + }, + { + "id": "api.post.handle_post_events_and_forget.team.error", + "translation": "Se encontró un error obteniendo el equipo, team_id=%s, err=%v" + }, + { + "id": "api.post.handle_post_events_and_forget.user.error", + "translation": "Se encontró un error obteniendo el usuario, user_id=%s, err=%v" + }, + { + "id": "api.post.handle_webhook_events_and_forget.create_post.error", + "translation": "Falla al crear la respuesta del mensaje, err=%v" + }, + { + "id": "api.post.handle_webhook_events_and_forget.event_post.error", + "translation": "Fallo el Evento POST, err=%s" + }, + { + "id": "api.post.handle_webhook_events_and_forget.getting.error", + "translation": "Se encontró un error obteniendo los webhooks por equipo, err=%v" + }, + { + "id": "api.post.init.debug", + "translation": "Inicializando rutas del API para los mensajes" + }, + { + "id": "api.post.make_direct_channel_visible.get_2_members.error", + "translation": "Falla al obtener 2 miembros para un canal directo channel_id=%v" + }, + { + "id": "api.post.make_direct_channel_visible.get_members.error", + "translation": "Falla al obtener los miembros del canal channel_id=%v err=%v" + }, + { + "id": "api.post.make_direct_channel_visible.save_pref.error", + "translation": "Falla al guardar las preferencias del canal directo user_id=%v other_user_id=%v err=%v" + }, + { + "id": "api.post.make_direct_channel_visible.update_pref.error", + "translation": "Falla al actualizar las preferencias del canal directo user_id=%v other_user_id=%v err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.members.error", + "translation": "Falla al obtener los miembros del canal channel_id=%v err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.mention_body", + "translation": "Tienes una mención nueva." + }, + { + "id": "api.post.send_notifications_and_forget.mention_subject", + "translation": "Nueva Mención" + }, + { + "id": "api.post.send_notifications_and_forget.message_body", + "translation": "Tienes un mensaje nuevo." + }, + { + "id": "api.post.send_notifications_and_forget.message_subject", + "translation": "Nuevo Mensaje Directo" + }, + { + "id": "api.post.send_notifications_and_forget.push_mention", + "translation": " te mencionó en " + }, + { + "id": "api.post.send_notifications_and_forget.push_message", + "translation": " te envió un mensaje directo" + }, + { + "id": "api.post.send_notifications_and_forget.push_notification.debug", + "translation": "Enviando notificaciones push a %v con el mensaje '%v'" + }, + { + "id": "api.post.send_notifications_and_forget.push_notification.error", + "translation": "Falló el envio de la notificación push notificationid=%v, err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.retrive_profiles.error", + "translation": "Falla al recuperar los perfiles de usuario team_id=%v, err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.send.error", + "translation": "Falla al enviar el correo con la mención satisfactoriamente email=%v err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.sent", + "translation": "{{.Prefix}} {{.Filenames}} enviado" + }, + { + "id": "api.post.send_notifications_and_forget.sessions.error", + "translation": "Falla al recuperar las sesiones en las notificaciones id=%v, err=%v" + }, + { + "id": "api.post.send_notifications_and_forget.user_id.error", + "translation": "El user_id del Mensaje no fue retornado por GetProfiles user_id=%v" + }, + { + "id": "api.post.update_mention_count_and_forget.update_error", + "translation": "Falla al actualizar el contador de mensiones para user_id=%v on channel_id=%v err=%v" + }, + { + "id": "api.post.update_post.find.app_error", + "translation": "No pudimos encontrar el mensaje o comentario para actualizarlo." + }, + { + "id": "api.post.update_post.permissions.app_error", + "translation": "No tienes los permisos apropiados" + }, + { + "id": "api.post.update_post.permissions_details.app_error", + "translation": "Already delted id={{.PostId}}" + }, + { + "id": "api.post_get_post_by_id.get.app_error", + "translation": "No se puede obtener el mensaje" + }, + { + "id": "api.preference.init.debug", + "translation": "Inicializando las rutas de preferencias del API" + }, + { + "id": "api.preference.save_preferences.decode.app_error", + "translation": "No se puede decodificar las preferencias desde la solicitud" + }, + { + "id": "api.preference.save_preferences.set.app_error", + "translation": "No se puede asignar las preferencias para otro usuario" + }, + { + "id": "api.preference.save_preferences.set_details.app_error", + "translation": "session.user_id={{.SessionUserId}}, preference.user_id={{.PreferenceUserId}}" + }, + { + "id": "api.server.new_server.init.info", + "translation": "Inicializando el Servidor..." + }, + { + "id": "api.server.start_server.listening.info", + "translation": "El servidor está escuchando en %v" + }, + { + "id": "api.server.start_server.rate.info", + "translation": "Límite de velocidad está habilitado" + }, + { + "id": "api.server.start_server.rate.warn", + "translation": "La configuración del límite de velocidad no ha sido configurado apropiadamente utilizando VaryByHeader y deshabilitado VaryByRemoteAddr" + }, + { + "id": "api.server.start_server.starting.critical", + "translation": "Error arrancando el servidor, err:%v" + }, + { + "id": "api.server.start_server.starting.info", + "translation": "Arrancando el Servidor..." + }, + { + "id": "api.server.start_server.starting.panic", + "translation": "Error arrancando el servidor " + }, + { + "id": "api.server.stop_server.stopped.info", + "translation": "Servidor detenido" + }, + { + "id": "api.server.stop_server.stopping.info", + "translation": "Deteniendo el Servidor..." + }, + { + "id": "api.slackimport.slack_add_channels.added", + "translation": "\r\n Canales agregados \r\n" + }, + { + "id": "api.slackimport.slack_add_channels.import_failed", + "translation": "Falla al importar: {{.DisplayName}}\r\n" + }, + { + "id": "api.slackimport.slack_add_channels.import_failed.debug", + "translation": "Falla al importar: %s" + }, + { + "id": "api.slackimport.slack_add_channels.merge", + "translation": "Unificado al canal existente: {{.DisplayName}}\r\n" + }, + { + "id": "api.slackimport.slack_add_posts.bot.warn", + "translation": "Mensajes del Bot de Slack no han sido importados todavía" + }, + { + "id": "api.slackimport.slack_add_posts.msg_no_usr.debug", + "translation": "Mensaje sin usuario" + }, + { + "id": "api.slackimport.slack_add_posts.unsupported.warn", + "translation": "Tipo de mensaje no soportado: %v, %v" + }, + { + "id": "api.slackimport.slack_add_posts.user_no_exists.debug", + "translation": "El usuario: %v no existe!" + }, + { + "id": "api.slackimport.slack_add_posts.without_user.debug", + "translation": "Mensaje sin usuario" + }, + { + "id": "api.slackimport.slack_add_users.created", + "translation": "\r\n Usuarios creados\r\n" + }, + { + "id": "api.slackimport.slack_add_users.email_pwd", + "translation": "Correo electrónico, Contraseña: {{.Email}}, {{.Password}}\r\n" + }, + { + "id": "api.slackimport.slack_add_users.unable_import", + "translation": "No se pudo importar el usuario: {{.Username}}\r\n" + }, + { + "id": "api.slackimport.slack_convert_timestamp.bad.warn", + "translation": "Se ha detectado la marca del tiempo errada" + }, + { + "id": "api.slackimport.slack_import.log", + "translation": "Mattermost Registros de importación de Slack\r\n" + }, + { + "id": "api.slackimport.slack_import.note1", + "translation": "- Algunos mensajes puede que no hayan sido importados porque no son soportados por esta herramienta.\r\n" + }, + { + "id": "api.slackimport.slack_import.note2", + "translation": "- mensajes realizadados por el bot de Slack actualmente no son soportados.\r\n" + }, + { + "id": "api.slackimport.slack_import.notes", + "translation": "\r\n Notas \r\n" + }, + { + "id": "api.slackimport.slack_import.open.app_error", + "translation": "No se pudo abrir: {{.Filename}}" + }, + { + "id": "api.slackimport.slack_import.zip.app_error", + "translation": "No se puede abrir el archivo comprimido" + }, + { + "id": "api.team.create_team.email_disabled.app_error", + "translation": "El registro a equipos por correo electrónico está deshabilitado." + }, + { + "id": "api.team.create_team_from_signup.email_disabled.app_error", + "translation": "El registro a equipos por correo electrónico está deshabilitado." + }, + { + "id": "api.team.create_team_from_signup.expired_link.app_error", + "translation": "El enlace de registro ha expirado" + }, + { + "id": "api.team.create_team_from_signup.invalid_link.app_error", + "translation": "El enlace de registro parece ser inválido" + }, + { + "id": "api.team.create_team_from_signup.unavailable.app_error", + "translation": "Este URL no está disponible. Por favor, prueba con otra." + }, + { + "id": "api.team.email_teams.sending.error", + "translation": "Ocurrió un error al enviar un correo en emailTeams err=%v" + }, + { + "id": "api.team.export_team.admin.app_error", + "translation": "Sólo un administrador del equipo puede exportar data." + }, + { + "id": "api.team.import_team.admin.app_error", + "translation": "Sólo un administrador del equipo puede importar data." + }, + { + "id": "api.team.import_team.array.app_error", + "translation": "Solicitud con matriz vacia en 'archivo'" + }, + { + "id": "api.team.import_team.integer.app_error", + "translation": "El tamaño del archivo no es un entero" + }, + { + "id": "api.team.import_team.no_file.app_error", + "translation": "No hay un archivo bajo la solicitud de 'archivo'" + }, + { + "id": "api.team.import_team.open.app_error", + "translation": "No se pudo abrir el archivo" + }, + { + "id": "api.team.import_team.parse.app_error", + "translation": "No se pudo analizar el contenido del formulario multiparte" + }, + { + "id": "api.team.import_team.unavailable.app_error", + "translation": "El tamaño del archivo no está disponible" + }, + { + "id": "api.team.init.debug", + "translation": "Inicializando rutas del API para los Equipos" + }, + { + "id": "api.team.invite_members.admin", + "translation": "administrador" + }, + { + "id": "api.team.invite_members.already.app_error", + "translation": "Esta persona ya se encuentra en tu equipo" + }, + { + "id": "api.team.invite_members.member", + "translation": "miembro" + }, + { + "id": "api.team.invite_members.no_one.app_error", + "translation": "Nadie a quien invitar." + }, + { + "id": "api.team.invite_members.send.error", + "translation": "Falla al enviar el correo de invitación satisfactoriamente err=%v" + }, + { + "id": "api.team.invite_members.sending.info", + "translation": "enviando invtaciones a %v %v" + }, + { + "id": "api.team.is_team_creation_allowed.disabled.app_error", + "translation": "La creación de Equipos ha sido deshabilitada. Por favor pregunta a tu administrador de sistema por detalles." + }, + { + "id": "api.team.is_team_creation_allowed.domain.app_error", + "translation": "El correo electrónico debe ser de un dominio específico (e.j. @ejemplo.com). Por favor pidele más detalles tu administrador de sistemas." + }, + { + "id": "api.team.permanent_delete_team.attempting.warn", + "translation": "Intentando eliminar permanentemente al equipo %v id=%v" + }, + { + "id": "api.team.permanent_delete_team.deleted.warn", + "translation": "Equipo eliminado permanentemente %v id=%v" + }, + { + "id": "api.team.signup_team.email_disabled.app_error", + "translation": "El registro a equipos por correo electrónico está deshabilitado." + }, + { + "id": "api.team.update_team.permissions.app_error", + "translation": "No tienes los permisos apropiados" + }, + { + "id": "api.user.add_direct_channels_and_forget.failed.error", + "translation": "Falla al agragar las preferencias del canal directo para el usuario user_id=%s, team_id=%s, err=%v" + }, + { + "id": "api.user.authorize_oauth_user.bad_response.app_error", + "translation": "Respuesta errada desde la consulta del token" + }, + { + "id": "api.user.authorize_oauth_user.bad_token.app_error", + "translation": "Tipo de token errado" + }, + { + "id": "api.user.authorize_oauth_user.invalid_state.app_error", + "translation": "Estado inválido" + }, + { + "id": "api.user.authorize_oauth_user.invalid_state_team.app_error", + "translation": "Estado inválido. falta nombre del equipo" + }, + { + "id": "api.user.authorize_oauth_user.missing.app_error", + "translation": "Token de acceso ausente" + }, + { + "id": "api.user.authorize_oauth_user.service.app_error", + "translation": "La solicitud del token a {{.Service}} falló" + }, + { + "id": "api.user.authorize_oauth_user.token_failed.app_error", + "translation": "Falló la solicitud del Token" + }, + { + "id": "api.user.authorize_oauth_user.unsupported.app_error", + "translation": "Proveedor de servicios de OAuth no es compatible" + }, + { + "id": "api.user.check_user_login_attempts.too_many.app_error", + "translation": "Tu cuenta ha sido bloqueada debido a demasiados intentos fallidos. Por favor, restablece tu contraseña." + }, + { + "id": "api.user.check_user_password.invalid.app_error", + "translation": "El inicio de sesión falló porque la contraseña es inválida" + }, + { + "id": "api.user.complete_switch_with_oauth.blank_email.app_error", + "translation": "Correo electrónico en blanco" + }, + { + "id": "api.user.complete_switch_with_oauth.parse.app_error", + "translation": "No se pudo obtener la data de autorización del objeto de {{.Service}}" + }, + { + "id": "api.user.complete_switch_with_oauth.unavailable.app_error", + "translation": "OAuth para {{.Service}} no está disponible en este servidor" + }, + { + "id": "api.user.create_oauth_user.already_attached.app_error", + "translation": "El Equipo {{.DisplayName}} ya tiene un usuario con esta dirección de correo asociada a tu cuenta de {{.Service}}" + }, + { + "id": "api.user.create_oauth_user.already_used.app_error", + "translation": "Esta cuenta de {{.Service}} ya fue utilizada para registrarse en el equipo {{.DisplayName}}" + }, + { + "id": "api.user.create_oauth_user.create.app_error", + "translation": "No se pudo crear el usuario basandose en el objeto de {{.Service}}" + }, + { + "id": "api.user.create_oauth_user.not_available.app_error", + "translation": "OAuth para {{.Service}} no está disponible en este servidor" + }, + { + "id": "api.user.create_profile_image.default_font.app_error", + "translation": "No se pudo crear la letra para la imagen del pérfil perdeterminada" + }, + { + "id": "api.user.create_profile_image.encode.app_error", + "translation": "No se pudo codificar la imagen del pérfil predeterminada" + }, + { + "id": "api.user.create_profile_image.initial.app_error", + "translation": "No se pudo asignar la inicial del usuario como imagen del pérfil predeterminada" + }, + { + "id": "api.user.create_user.accepted_domain.app_error", + "translation": "El correo electrónico provisto no pertenece a un dominio permitido. Por favor contacta a un administrador o registrate con un correo electrónico diferente." + }, + { + "id": "api.user.create_user.joining.error", + "translation": "Se encontró un problema al unirse a los canales predeterminados user_id=%s, team_id=%s, err=%v" + }, + { + "id": "api.user.create_user.save.error", + "translation": "No se pudo guardar el usuario err=%v" + }, + { + "id": "api.user.create_user.signup_email_disabled.app_error", + "translation": "Registro de usuarios por correo electrónico está deshabilitado." + }, + { + "id": "api.user.create_user.signup_link_expired.app_error", + "translation": "El enlace de registro ha expirado" + }, + { + "id": "api.user.create_user.signup_link_invalid.app_error", + "translation": "El enlace de registro parece ser inválido" + }, + { + "id": "api.user.create_user.team_name.app_error", + "translation": "Nombre del equipo inválido" + }, + { + "id": "api.user.create_user.tutorial.error", + "translation": "Se encontró un error al guardar las preferencias del tutorial, err=%v" + }, + { + "id": "api.user.create_user.verified.error", + "translation": "Falla al asignar el correo como verificado err=%v" + }, + { + "id": "api.user.get_authorization_code.unsupported.app_error", + "translation": "Proveedor de servicios de OAuth no es compatible" + }, + { + "id": "api.user.get_me.getting.error", + "translation": "Error obteniendo el pérfil de usuario para id=%v forzando el cierre de sesión" + }, + { + "id": "api.user.init.debug", + "translation": "Inicializando rutas del API para los Usuarios" + }, + { + "id": "api.user.login.blank_pwd.app_error", + "translation": "El campo de contraseña no debe quedar en blanco" + }, + { + "id": "api.user.login.inactive.app_error", + "translation": "El inicio de sesión falló porque tu cuenta ha sido desactivada. Por favor contacta a un administrador." + }, + { + "id": "api.user.login.not_provided.app_error", + "translation": "Ya sea el id de usuario o el nombre del equipo y la dirección de correo del usuario deben ser suministradas" + }, + { + "id": "api.user.login.not_verified.app_error", + "translation": "El inicio de sesión falló porque la dirección de correo electrónico no ha sido verificada" + }, + { + "id": "api.user.login.revoking.app_error", + "translation": "Revocando sessionId=%v para el userId=%v vuelve a iniciar la sesión el el mismo dispositivo" + }, + { + "id": "api.user.login_by_email.sign_in.app_error", + "translation": "Por favor inicia sesión usando {{.AuthService}}" + }, + { + "id": "api.user.login_by_oauth.not_available.app_error", + "translation": "OAuth para {{.Service}} no está disponible en este servidor" + }, + { + "id": "api.user.login_by_oauth.parse.app_error", + "translation": "No se pudo obtener la data de autorización del objeto de {{.Service}}" + }, + { + "id": "api.user.login_ldap.blank_pwd.app_error", + "translation": "El campo de contraseña no debe quedar en blanco" + }, + { + "id": "api.user.login_ldap.disabled.app_error", + "translation": "LDAP no está habilitado en este servidor" + }, + { + "id": "api.user.login_ldap.need_id.app_error", + "translation": "Se necesita un ID" + }, + { + "id": "api.user.login_ldap.not_available.app_error", + "translation": "LDAP no está disponible en este servidor" + }, + { + "id": "api.user.permanent_delete_user.attempting.warn", + "translation": "Intentando eliminar permanentemente la cuenta %v id=%v" + }, + { + "id": "api.user.permanent_delete_user.deleted.warn", + "translation": "La cuenta %v ha sido eliminada permanentemente id=%v" + }, + { + "id": "api.user.permanent_delete_user.system_admin.warn", + "translation": "Estas eliminando a %v que es un administrador de sistema. Es posible que necesites asignar otra cuenta como administrador de sistema utilizando las herramientas de linea de comando." + }, + { + "id": "api.user.reset_password.invalid_link.app_error", + "translation": "El enlace para restablecer la contraseña parece ser inválido" + }, + { + "id": "api.user.reset_password.link_expired.app_error", + "translation": "El enlace para restablecer la contraseña ha expirado" + }, + { + "id": "api.user.reset_password.sso.app_error", + "translation": "No se puede restablecer la contraseña para cuentas SSO" + }, + { + "id": "api.user.reset_password.wrong_team.app_error", + "translation": "Intentando restablecer la contraseña para el usuario en el equipo equivocado." + }, + { + "id": "api.user.send_email_change_email_and_forget.error", + "translation": "Falla al enviar la notificación por correo electrónico del cambio de correo err=%v" + }, + { + "id": "api.user.send_email_change_verify_email_and_forget.error", + "translation": "Error al enviar correo electrónico de verificación de cambio de correo electrónico con éxito err=%v" + }, + { + "id": "api.user.send_password_change_email_and_forget.error", + "translation": "Falla al enviar el correo del cambio de contraseña satisfactorio err=%v" + }, + { + "id": "api.user.send_password_reset.find.app_error", + "translation": "No pudimos encontrar una cuenta con esa dirección." + }, + { + "id": "api.user.send_password_reset.send.app_error", + "translation": "Falla al enviar el correo para restablecer la contraseña satisfactorio" + }, + { + "id": "api.user.send_password_reset.sso.app_error", + "translation": "No se puede restablecer la contraseña para cuentas SSO" + }, + { + "id": "api.user.send_sign_in_change_email_and_forget.error", + "translation": "Falla al enviar el correo del cambio de contraseña satisfactorio err=%v" + }, + { + "id": "api.user.send_verify_email_and_forget.failed.error", + "translation": "Falla al enviar el correo con la verificación éxitosa del correo electrónico err=%v" + }, + { + "id": "api.user.send_welcome_email_and_forget.failed.error", + "translation": "Falla al enviar el correo de bienvenida err=%v" + }, + { + "id": "api.user.switch_to_email.context.app_error", + "translation": "La actualización de la contraseña falló porque el user_id del contexto no coincide con el id de usuario provisto" + }, + { + "id": "api.user.update_active.permissions.app_error", + "translation": "No tienes los permisos apropiados" + }, + { + "id": "api.user.update_password.context.app_error", + "translation": "La actualización de la contraseña falló debido a que el user_id del contexto no coincide con el user_id de los props" + }, + { + "id": "api.user.update_password.failed.app_error", + "translation": "Falló al actualizar la contraseña" + }, + { + "id": "api.user.update_password.incorrect.app_error", + "translation": "La \"Contraseña actual\" que ingresaste es incorrecta. Por favor revisa que tengas en Bloq Mayus apagado e intenta de nuevo." + }, + { + "id": "api.user.update_password.menu", + "translation": "utilizando la opción del menú" + }, + { + "id": "api.user.update_password.oauth.app_error", + "translation": "La actualización de la contraseña falló debido a que el usuario está vinculado a un proveedor de OAuth" + }, + { + "id": "api.user.update_password.valid_account.app_error", + "translation": "La actualización de la contraseña falló debido a que no encontramos una cuenta válida" + }, + { + "id": "api.user.update_roles.one_admin.app_error", + "translation": "Debe haber al menos un administrador activo" + }, + { + "id": "api.user.update_roles.permissions.app_error", + "translation": "No tienes los permisos apropiados" + }, + { + "id": "api.user.update_roles.system_admin_mod.app_error", + "translation": "El rol de administrador de sistema sólo puede ser modificado por otro administrador de sistema" + }, + { + "id": "api.user.update_roles.system_admin_set.app_error", + "translation": "El rol de adminsitrador de sistema sólo puede ser asignado por otro administrador de sistema" + }, + { + "id": "api.user.upload_profile_user.array.app_error", + "translation": "Solicitud con matriz vacia en 'imagen'" + }, + { + "id": "api.user.upload_profile_user.decode.app_error", + "translation": "No se pudo decodificar la imagen del pérfil" + }, + { + "id": "api.user.upload_profile_user.decode_config.app_error", + "translation": "No se pudo decodificar la configuración de la imagen del perfil." + }, + { + "id": "api.user.upload_profile_user.encode.app_error", + "translation": "No se pudo codificar la imagen del pérfil" + }, + { + "id": "api.user.upload_profile_user.no_file.app_error", + "translation": "No hay un archivo bajo la solicitud de 'imagen'" + }, + { + "id": "api.user.upload_profile_user.open.app_error", + "translation": "No se pudo abrir el archivo de imagen" + }, + { + "id": "api.user.upload_profile_user.parse.app_error", + "translation": "No se pudo analizar el contenido del formulario multiparte" + }, + { + "id": "api.user.upload_profile_user.storage.app_error", + "translation": "No se puede subir el archivo. El almacenamiento de imágenes no está configurado." + }, + { + "id": "api.user.upload_profile_user.too_large.app_error", + "translation": "No se pudo actualizar la imagen del perfil. El archivo es muy grande." + }, { "id": "mattermost.current_version", "translation": "La versión actual es %v (%v/%v/%v)" diff --git a/utils/i18n.go b/utils/i18n.go index 4b7b187a8..6811796fd 100644 --- a/utils/i18n.go +++ b/utils/i18n.go @@ -57,6 +57,15 @@ func GetTranslationsBySystemLocale() i18n.TranslateFunc { return translations } +func GetUserTranslations(locale string) i18n.TranslateFunc { + if _, ok := locales[locale]; !ok { + locale = model.DEFAULT_LOCALE + } + + translations, _ := i18n.Tfunc(locale) + return translations +} + func SetTranslations(locale string) i18n.TranslateFunc { translations, _ := i18n.Tfunc(locale) return translations -- cgit v1.2.3-1-g7c22