summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.editorconfig8
-rw-r--r--api/file.go5
-rw-r--r--api/post.go2
-rw-r--r--i18n/en.json112
-rw-r--r--i18n/es.json72
-rw-r--r--i18n/pt.json74
-rw-r--r--webapp/components/admin_console/compliance_settings.jsx2
-rw-r--r--webapp/components/admin_console/service_settings.jsx5
-rw-r--r--webapp/components/admin_console/user_item.jsx2
-rw-r--r--webapp/components/analytics/team_analytics.jsx2
-rw-r--r--webapp/components/channel_header.jsx2
-rw-r--r--webapp/components/channel_view.jsx19
-rw-r--r--webapp/components/invite_member_modal.jsx18
-rw-r--r--webapp/components/logged_in.jsx23
-rw-r--r--webapp/components/msg_typing.jsx12
-rw-r--r--webapp/components/permalink_view.jsx25
-rw-r--r--webapp/components/popover_list_members.jsx9
-rw-r--r--webapp/components/post.jsx2
-rw-r--r--webapp/components/posts_view.jsx26
-rw-r--r--webapp/components/posts_view_container.jsx12
-rw-r--r--webapp/components/rhs_root_post.jsx2
-rw-r--r--webapp/components/search_results_item.jsx3
-rw-r--r--webapp/components/user_settings/user_settings_display.jsx2
-rw-r--r--webapp/components/user_settings/user_settings_security.jsx3
-rw-r--r--webapp/i18n/en.json60
-rw-r--r--webapp/i18n/es.json87
-rw-r--r--webapp/i18n/pt.json58
-rw-r--r--webapp/stores/post_store.jsx6
-rw-r--r--webapp/utils/constants.jsx4
29 files changed, 471 insertions, 186 deletions
diff --git a/.editorconfig b/.editorconfig
index 15dd92ecd..5325248da 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -14,7 +14,13 @@ indent_style = tab
indent_style = space
indent_size = 4
-[web/react/package.json]
+[webapp/package.json]
+indent_size = 2
+
+[i18n/**.json]
+indent_size = 2
+
+[webapp/i18n/**.json]
indent_size = 2
[Makefile]
diff --git a/api/file.go b/api/file.go
index 9150e4bfe..f0873f884 100644
--- a/api/file.go
+++ b/api/file.go
@@ -394,6 +394,11 @@ func getFile(c *Context, w http.ResponseWriter, r *http.Request) {
getFileAndForget(path, fileData)
if len(hash) > 0 && len(data) > 0 && len(teamId) == 26 {
+ if !utils.Cfg.FileSettings.EnablePublicLink {
+ c.Err = model.NewLocAppError("getFile", "api.file.get_file.public_disabled.app_error", nil, "")
+ return
+ }
+
if !model.ComparePassword(hash, fmt.Sprintf("%v:%v", data, utils.Cfg.FileSettings.PublicLinkSalt)) {
c.Err = model.NewLocAppError("getFile", "api.file.get_file.public_invalid.app_error", nil, "")
return
diff --git a/api/post.go b/api/post.go
index 36fd4ee79..2fe5feb8e 100644
--- a/api/post.go
+++ b/api/post.go
@@ -172,8 +172,6 @@ func CreateWebhookPost(c *Context, channelId, text, overrideUsername, overrideIc
if utils.Cfg.ServiceSettings.EnablePostIconOverride {
if len(overrideIconUrl) != 0 {
post.AddProp("override_icon_url", overrideIconUrl)
- } else {
- post.AddProp("override_icon_url", model.DEFAULT_WEBHOOK_ICON)
}
}
diff --git a/i18n/en.json b/i18n/en.json
index 9ffc6d1c4..52e4fca8a 100644
--- a/i18n/en.json
+++ b/i18n/en.json
@@ -476,6 +476,10 @@
"translation": "Could not find file."
},
{
+ "id": "api.file.get_file.public_disabled.app_error",
+ "translation": "Public links have been disabled by the system administrator"
+ },
+ {
"id": "api.file.get_file.public_invalid.app_error",
"translation": "The public link does not appear to be valid"
},
@@ -1292,14 +1296,6 @@
"translation": "You joined {{ .TeamDisplayName }}"
},
{
- "id": "api.user.update_mfa.not_available.app_error",
- "translation": "MFA not configured or available on this server"
- },
- {
- "id": "api.user.generate_mfa_qr.not_available.app_error",
- "translation": "MFA not configured or available on this server"
- },
- {
"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"
},
@@ -1336,16 +1332,16 @@
"translation": "Unsupported OAuth service provider"
},
{
- "id": "api.user.check_user_mfa.not_available.app_error",
- "translation": "MFA is not configured or supported on this server"
+ "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_mfa.bad_code.app_error",
"translation": "Invalid MFA token."
},
{
- "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_mfa.not_available.app_error",
+ "translation": "MFA is not configured or supported on this server"
},
{
"id": "api.user.check_user_password.invalid.app_error",
@@ -1432,6 +1428,10 @@
"translation": "LDAP not available on this server"
},
{
+ "id": "api.user.generate_mfa_qr.not_available.app_error",
+ "translation": "MFA not configured or available on this server"
+ },
+ {
"id": "api.user.get_authorization_code.unsupported.app_error",
"translation": "Unsupported OAuth service provider"
},
@@ -1576,6 +1576,10 @@
"translation": "You do not have the appropriate permissions"
},
{
+ "id": "api.user.update_mfa.not_available.app_error",
+ "translation": "MFA not configured or available on this server"
+ },
+ {
"id": "api.user.update_password.context.app_error",
"translation": "Update password failed because context user_id did not match props user_id"
},
@@ -1756,72 +1760,72 @@
"translation": "Compliance export started for job '{{.JobName}}' at '{{.FilePath}}'"
},
{
- "id": "ent.mfa.license_disable.app_error",
- "translation": "Your license does not support using multi-factor authentication"
+ "id": "ent.ldap.do_login.bind_admin_user.app_error",
+ "translation": "Unable to bind to LDAP server. Check BindUsername and BindPassword."
},
{
- "id": "ent.mfa.generate_qr_code.create_code.app_error",
- "translation": "Error generating QR code"
+ "id": "ent.ldap.do_login.invalid_password.app_error",
+ "translation": "Invalid Password"
},
{
- "id": "ent.mfa.generate_qr_code.save_secret.app_error",
- "translation": "Error saving the MFA secret"
+ "id": "ent.ldap.do_login.licence_disable.app_error",
+ "translation": "LDAP functionality disabled by current license. Please contact your system administrator about upgrading your enterprise license."
},
{
- "id": "ent.mfa.activate.authenticate.app_error",
- "translation": "Error attempting to authenticate MFA token"
+ "id": "ent.ldap.do_login.matched_to_many_users.app_error",
+ "translation": "Username given matches multiple users"
},
{
- "id": "ent.mfa.activate.bad_token.app_error",
- "translation": "Invalid MFA token"
+ "id": "ent.ldap.do_login.search_ldap_server.app_error",
+ "translation": "Failed to search LDAP server"
},
{
- "id": "ent.mfa.activate.save_active.app_erro",
- "translation": "Unable to update MFA active status for the user"
+ "id": "ent.ldap.do_login.unable_to_connect.app_error",
+ "translation": "Unable to connect to LDAP server"
},
{
- "id": "ent.mfa.deactivate.save_active.app_erro",
- "translation": "Unable to update MFA active status for the user"
+ "id": "ent.ldap.do_login.unable_to_create_user.app_error",
+ "translation": "Credentials valid but unable to create user."
},
{
- "id": "ent.mfa.deactivate.save_secret.app_error",
- "translation": "Error clearing the MFA secret"
+ "id": "ent.ldap.do_login.user_not_registered.app_error",
+ "translation": "User not registered on LDAP server"
},
{
- "id": "ent.mfa.validate_token.authenticate.app_error",
- "translation": "Error trying to authenticate MFA token"
+ "id": "ent.mfa.activate.authenticate.app_error",
+ "translation": "Error attempting to authenticate MFA token"
},
{
- "id": "ent.ldap.do_login.bind_admin_user.app_error",
- "translation": "Unable to bind to LDAP server. Check BindUsername and BindPassword."
+ "id": "ent.mfa.activate.bad_token.app_error",
+ "translation": "Invalid MFA token"
},
{
- "id": "ent.ldap.do_login.invalid_password.app_error",
- "translation": "Invalid Password"
+ "id": "ent.mfa.activate.save_active.app_erro",
+ "translation": "Unable to update MFA active status for the user"
},
{
- "id": "ent.ldap.do_login.licence_disable.app_error",
- "translation": "LDAP functionality disabled by current license. Please contact your system administrator about upgrading your enterprise license."
+ "id": "ent.mfa.deactivate.save_active.app_erro",
+ "translation": "Unable to update MFA active status for the user"
},
{
- "id": "ent.ldap.do_login.matched_to_many_users.app_error",
- "translation": "Username given matches multiple users"
+ "id": "ent.mfa.deactivate.save_secret.app_error",
+ "translation": "Error clearing the MFA secret"
},
{
- "id": "ent.ldap.do_login.search_ldap_server.app_error",
- "translation": "Failed to search LDAP server"
+ "id": "ent.mfa.generate_qr_code.create_code.app_error",
+ "translation": "Error generating QR code"
},
{
- "id": "ent.ldap.do_login.unable_to_connect.app_error",
- "translation": "Unable to connect to LDAP server"
+ "id": "ent.mfa.generate_qr_code.save_secret.app_error",
+ "translation": "Error saving the MFA secret"
},
{
- "id": "ent.ldap.do_login.unable_to_create_user.app_error",
- "translation": "Credentials valid but unable to create user."
+ "id": "ent.mfa.license_disable.app_error",
+ "translation": "Your license does not support using multi-factor authentication"
},
{
- "id": "ent.ldap.do_login.user_not_registered.app_error",
- "translation": "User not registered on LDAP server"
+ "id": "ent.mfa.validate_token.authenticate.app_error",
+ "translation": "Error trying to authenticate MFA token"
},
{
"id": "manaultesting.get_channel_id.no_found.debug",
@@ -3188,14 +3192,6 @@
"translation": "We couldn't update the team name"
},
{
- "id": "store.sql_user.update_mfa_secret.app_error",
- "translation": "We encountered an error updating the user's MFA secret"
- },
- {
- "id": "store.sql_user.update_mfa_active.app_error",
- "translation": "We encountered an error updating the user's MFA active status"
- },
- {
"id": "store.sql_user.analytics_unique_user_count.app_error",
"translation": "We couldn't get the unique user count"
},
@@ -3316,6 +3312,14 @@
"translation": "We couldn't update the last_ping_at"
},
{
+ "id": "store.sql_user.update_mfa_active.app_error",
+ "translation": "We encountered an error updating the user's MFA active status"
+ },
+ {
+ "id": "store.sql_user.update_mfa_secret.app_error",
+ "translation": "We encountered an error updating the user's MFA secret"
+ },
+ {
"id": "store.sql_user.update_password.app_error",
"translation": "We couldn't update the user password"
},
diff --git a/i18n/es.json b/i18n/es.json
index 76b3bf162..52654f4af 100644
--- a/i18n/es.json
+++ b/i18n/es.json
@@ -476,6 +476,10 @@
"translation": "No se encontró el archivo."
},
{
+ "id": "api.file.get_file.public_disabled.app_error",
+ "translation": "Los enlaces públicos han sido deshabilitados por un administrador del sistema"
+ },
+ {
"id": "api.file.get_file.public_invalid.app_error",
"translation": "El enlace público parece ser inválido"
},
@@ -696,6 +700,14 @@
"translation": "Error obteniendo el token de acceso desde la BD antes de ser eliminado"
},
{
+ "id": "api.post.check_for_out_of_channel_mentions.message.multiple",
+ "translation": "{{.Usernames}} y {{.LastUsername}} fueron mencionados, pero no recibieron una notificación porque no pertenecen a este canal."
+ },
+ {
+ "id": "api.post.check_for_out_of_channel_mentions.message.one",
+ "translation": "{{.Username}} fue mencionado, pero no recibió una notificación porque no pertenece a este canal."
+ },
+ {
"id": "api.post.create_post.bad_filename.error",
"translation": "Nombre errado de archivo descartado, archivo=%v"
},
@@ -1324,6 +1336,14 @@
"translation": "Tu cuenta ha sido bloqueada debido a demasiados intentos fallidos. Por favor, restablece tu contraseña."
},
{
+ "id": "api.user.check_user_mfa.bad_code.app_error",
+ "translation": "Token AMF inválido."
+ },
+ {
+ "id": "api.user.check_user_mfa.not_available.app_error",
+ "translation": "AMF on está configurado o no es soportado en este servidor"
+ },
+ {
"id": "api.user.check_user_password.invalid.app_error",
"translation": "El inicio de sesión falló porque la contraseña es inválida"
},
@@ -1408,6 +1428,10 @@
"translation": "LDAP no está disponible en este servidor"
},
{
+ "id": "api.user.generate_mfa_qr.not_available.app_error",
+ "translation": "AMF no está configurado o disponible en este servidor"
+ },
+ {
"id": "api.user.get_authorization_code.unsupported.app_error",
"translation": "Proveedor de servicios de OAuth no es compatible"
},
@@ -1548,6 +1572,10 @@
"translation": "No tienes los permisos apropiados"
},
{
+ "id": "api.user.update_mfa.not_available.app_error",
+ "translation": "AMF no está configurado o disponible en este servidor"
+ },
+ {
"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"
},
@@ -1760,6 +1788,42 @@
"translation": "Usuario no registrado en el servidor LDAP"
},
{
+ "id": "ent.mfa.activate.authenticate.app_error",
+ "translation": "Error intentando autenticar el token AMF"
+ },
+ {
+ "id": "ent.mfa.activate.bad_token.app_error",
+ "translation": "Token AMF inválido"
+ },
+ {
+ "id": "ent.mfa.activate.save_active.app_erro",
+ "translation": "No se pudo actualizar el estado activo AMF para el usuario"
+ },
+ {
+ "id": "ent.mfa.deactivate.save_active.app_erro",
+ "translation": "No se pudo actualizar el estado activo AMF para el usuario"
+ },
+ {
+ "id": "ent.mfa.deactivate.save_secret.app_error",
+ "translation": "Error al limpiar el secreto AMF"
+ },
+ {
+ "id": "ent.mfa.generate_qr_code.create_code.app_error",
+ "translation": "Error generando el código QR"
+ },
+ {
+ "id": "ent.mfa.generate_qr_code.save_secret.app_error",
+ "translation": "Error guardando el secreto AMF"
+ },
+ {
+ "id": "ent.mfa.license_disable.app_error",
+ "translation": "Tu licencia no soporta la autenticación de múltiples factores"
+ },
+ {
+ "id": "ent.mfa.validate_token.authenticate.app_error",
+ "translation": "Error intentando autenticar el token AMF"
+ },
+ {
"id": "manaultesting.get_channel_id.no_found.debug",
"translation": "No pudimos encontrar el canal: %v, búsqueda realizada con estas posibilidades %v"
},
@@ -3244,6 +3308,14 @@
"translation": "No pudimos actualizar el campo last_ping_at"
},
{
+ "id": "store.sql_user.update_mfa_active.app_error",
+ "translation": "Encontramos un error al actualizar el estado activo AMF del usuario"
+ },
+ {
+ "id": "store.sql_user.update_mfa_secret.app_error",
+ "translation": "Encontramos un error al actualizar el secreto AMF del usuario"
+ },
+ {
"id": "store.sql_user.update_password.app_error",
"translation": "No pudimos actualizar la contraseña del usuario"
},
diff --git a/i18n/pt.json b/i18n/pt.json
index 39b67833c..631198e1f 100644
--- a/i18n/pt.json
+++ b/i18n/pt.json
@@ -476,6 +476,10 @@
"translation": "Não foi possível encontrar o arquivo."
},
{
+ "id": "api.file.get_file.public_disabled.app_error",
+ "translation": "Public links have been disabled by the system administrator"
+ },
+ {
"id": "api.file.get_file.public_invalid.app_error",
"translation": "O link público não parece ser válido"
},
@@ -696,6 +700,14 @@
"translation": "Erro ao obter o token de acesso do BD antes da exclusão"
},
{
+ "id": "api.post.check_for_out_of_channel_mentions.message.multiple",
+ "translation": "{{.Usernames}} e {{.LastUsername}} foram mencionados, mas eles não receberam notificação porque eles não pertencem a este canal."
+ },
+ {
+ "id": "api.post.check_for_out_of_channel_mentions.message.one",
+ "translation": "{{.Username}} foi mencionado, mas eles não receberam uma notificação porque eles não pertencem a este canal."
+ },
+ {
"id": "api.post.create_post.bad_filename.error",
"translation": "Nome ruim do arquivo descartado, nome do arquivo=%v"
},
@@ -1284,6 +1296,14 @@
"translation": "Você se juntou {{ .TeamDisplayName }}"
},
{
+ "id": "api.user.update_mfa.not_available.app_error",
+ "translation": "MFA não configurado ou disponível neste servidor"
+ },
+ {
+ "id": "api.user.generate_mfa_qr.not_available.app_error",
+ "translation": "MFA não configurado ou disponível neste servidor"
+ },
+ {
"id": "api.user.add_direct_channels_and_forget.failed.error",
"translation": "Falha ao adicionar preferencias diretas ao canal para o usuário user_id=%s, team_id=%s, err=%v"
},
@@ -1320,6 +1340,14 @@
"translation": "Provedor de serviço OAuth não suportado"
},
{
+ "id": "api.user.check_user_mfa.not_available.app_error",
+ "translation": "MFA não configurado ou disponível neste servidor"
+ },
+ {
+ "id": "api.user.check_user_mfa.bad_code.app_error",
+ "translation": "Token MFA inválido."
+ },
+ {
"id": "api.user.check_user_login_attempts.too_many.app_error",
"translation": "A sua conta está bloqueada por causa de muitas tentativas de senha que falharam. Por favor, redefina sua senha."
},
@@ -1728,6 +1756,42 @@
"translation": "Exportação de compliance tarefa '{{.JobName}}' iniciada no '{{.FilePath}}'"
},
{
+ "id": "ent.mfa.license_disable.app_error",
+ "translation": "Sua licença não suporta o uso de autenticação multi-fator"
+ },
+ {
+ "id": "ent.mfa.generate_qr_code.create_code.app_error",
+ "translation": "Erro ao gerar QR code"
+ },
+ {
+ "id": "ent.mfa.generate_qr_code.save_secret.app_error",
+ "translation": "Erro ao salvar o segredo MFA"
+ },
+ {
+ "id": "ent.mfa.activate.authenticate.app_error",
+ "translation": "Erro ao tentar autenticar o token MFA"
+ },
+ {
+ "id": "ent.mfa.activate.bad_token.app_error",
+ "translation": "Token MFA inválido"
+ },
+ {
+ "id": "ent.mfa.activate.save_active.app_erro",
+ "translation": "Não foi possível atualizar o status ativo MFA para o usuário"
+ },
+ {
+ "id": "ent.mfa.deactivate.save_active.app_erro",
+ "translation": "Não foi possível atualizar o status ativo MFA para o usuário"
+ },
+ {
+ "id": "ent.mfa.deactivate.save_secret.app_error",
+ "translation": "Erro ao limpar o segredo MFA"
+ },
+ {
+ "id": "ent.mfa.validate_token.authenticate.app_error",
+ "translation": "Erro ao tentar autenticar o token MFA"
+ },
+ {
"id": "ent.ldap.do_login.bind_admin_user.app_error",
"translation": "Não foi possível ligar ao servidor LDAP. Verifique BindUsername e BindPassword."
},
@@ -3124,6 +3188,14 @@
"translation": "Não foi possível atualizar o nome da equipe"
},
{
+ "id": "store.sql_user.update_mfa_secret.app_error",
+ "translation": "Foi encontrado um erro ao atualizar o segredo MFA do usuário"
+ },
+ {
+ "id": "store.sql_user.update_mfa_active.app_error",
+ "translation": "Encontramos um erro ao atualizar o status ativo MFA do usuário"
+ },
+ {
"id": "store.sql_user.analytics_unique_user_count.app_error",
"translation": "Não foi possível obter o número de usuários únicos"
},
@@ -3659,4 +3731,4 @@
"id": "web.watcher_fail.error",
"translation": "Falha ao adicionar diretório observador %v"
}
-]
+] \ No newline at end of file
diff --git a/webapp/components/admin_console/compliance_settings.jsx b/webapp/components/admin_console/compliance_settings.jsx
index fb2ae26f9..206bb0faa 100644
--- a/webapp/components/admin_console/compliance_settings.jsx
+++ b/webapp/components/admin_console/compliance_settings.jsx
@@ -223,7 +223,7 @@ export default class ComplianceSettings extends React.Component {
</label>
<p className='help-text'>
<FormattedMessage
- id='admin.compliance.enableDesc'
+ id='admin.compliance.enableDailyDesc'
defaultMessage='When true, Mattermost will generate a daily compliance report.'
/>
</p>
diff --git a/webapp/components/admin_console/service_settings.jsx b/webapp/components/admin_console/service_settings.jsx
index 41ea5ea34..c72c97326 100644
--- a/webapp/components/admin_console/service_settings.jsx
+++ b/webapp/components/admin_console/service_settings.jsx
@@ -84,10 +84,13 @@ class ServiceSettings extends React.Component {
config.ServiceSettings.EnableDeveloper = ReactDOM.findDOMNode(this.refs.EnableDeveloper).checked;
config.ServiceSettings.EnableSecurityFixAlert = ReactDOM.findDOMNode(this.refs.EnableSecurityFixAlert).checked;
config.ServiceSettings.EnableInsecureOutgoingConnections = ReactDOM.findDOMNode(this.refs.EnableInsecureOutgoingConnections).checked;
- config.ServiceSettings.EnableMultifactorAuthentication = ReactDOM.findDOMNode(this.refs.EnableMultifactorAuthentication).checked;
config.ServiceSettings.EnableCommands = ReactDOM.findDOMNode(this.refs.EnableCommands).checked;
config.ServiceSettings.EnableOnlyAdminIntegrations = ReactDOM.findDOMNode(this.refs.EnableOnlyAdminIntegrations).checked;
+ if (this.refs.EnablMultifactorAuthentication) {
+ config.ServiceSettings.EnableMultifactorAuthentication = ReactDOM.findDOMNode(this.refs.EnableMultifactorAuthentication).checked;
+ }
+
//config.ServiceSettings.EnableOAuthServiceProvider = ReactDOM.findDOMNode(this.refs.EnableOAuthServiceProvider).checked;
var MaximumLoginAttempts = DefaultMaximumLoginAttempts;
diff --git a/webapp/components/admin_console/user_item.jsx b/webapp/components/admin_console/user_item.jsx
index 91f567d4d..c00050584 100644
--- a/webapp/components/admin_console/user_item.jsx
+++ b/webapp/components/admin_console/user_item.jsx
@@ -333,7 +333,7 @@ export default class UserItem extends React.Component {
<div>
<FormattedMessage
id='admin.user_item.confirmDemoteDescription'
- defaultMessage="If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you\'ll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command."
+ defaultMessage="If you demote yourself from the System Admin role and there is not another user with System Admin privileges, you'll need to re-assign a System Admin by accessing the Mattermost server through a terminal and running the following command."
/>
<br/>
<br/>
diff --git a/webapp/components/analytics/team_analytics.jsx b/webapp/components/analytics/team_analytics.jsx
index efc965f24..9b4eb1f94 100644
--- a/webapp/components/analytics/team_analytics.jsx
+++ b/webapp/components/analytics/team_analytics.jsx
@@ -154,7 +154,7 @@ class TeamAnalytics extends React.Component {
<TableChart
title={
<FormattedMessage
- id='analytics.team.activeUsers'
+ id='analytics.team.recentUsers'
defaultMessage='Recent Active Users'
/>
}
diff --git a/webapp/components/channel_header.jsx b/webapp/components/channel_header.jsx
index 6bb466c3e..482aabc01 100644
--- a/webapp/components/channel_header.jsx
+++ b/webapp/components/channel_header.jsx
@@ -216,9 +216,9 @@ export default class ChannelHeader extends React.Component {
if (!isDirect) {
popoverListMembers = (
<PopoverListMembers
+ channel={channel}
members={this.state.users}
memberCount={this.state.userCount}
- channelId={channel.id}
/>
);
}
diff --git a/webapp/components/channel_view.jsx b/webapp/components/channel_view.jsx
index 54d796ac1..4cca5aa98 100644
--- a/webapp/components/channel_view.jsx
+++ b/webapp/components/channel_view.jsx
@@ -8,7 +8,6 @@ import PostsViewContainer from 'components/posts_view_container.jsx';
import CreatePost from 'components/create_post.jsx';
import ChannelStore from 'stores/channel_store.jsx';
-import UserStore from 'stores/user_store.jsx';
export default class ChannelView extends React.Component {
constructor(props) {
@@ -23,14 +22,12 @@ export default class ChannelView extends React.Component {
getStateFromStores(props) {
const channel = ChannelStore.getByName(props.params.channel);
const channelId = channel ? channel.id : '';
- const profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
return {
- channelId,
- profiles
+ channelId
};
}
isStateValid() {
- return this.state.channelId !== '' && this.state.profiles;
+ return this.state.channelId !== '';
}
updateState() {
this.setState(this.getStateFromStores(this.props));
@@ -44,13 +41,6 @@ export default class ChannelView extends React.Component {
componentWillReceiveProps(nextProps) {
this.setState(this.getStateFromStores(nextProps));
}
- shouldComponentUpdate(nextProps, nextState) {
- if (nextState.channelId !== this.state.channelId) {
- return true;
- }
-
- return false;
- }
render() {
return (
<div
@@ -60,7 +50,7 @@ export default class ChannelView extends React.Component {
<ChannelHeader
channelId={this.state.channelId}
/>
- <PostsViewContainer profiles={this.state.profiles}/>
+ <PostsViewContainer profiles={this.props.profiles}/>
<div
className='post-create__container'
id='post-create'
@@ -75,5 +65,6 @@ ChannelView.defaultProps = {
};
ChannelView.propTypes = {
- params: React.PropTypes.object.isRequired
+ params: React.PropTypes.object.isRequired,
+ profiles: React.PropTypes.object
};
diff --git a/webapp/components/invite_member_modal.jsx b/webapp/components/invite_member_modal.jsx
index 1f8fd6133..81c3a9629 100644
--- a/webapp/components/invite_member_modal.jsx
+++ b/webapp/components/invite_member_modal.jsx
@@ -50,6 +50,7 @@ class InviteMemberModal extends React.Component {
constructor(props) {
super(props);
+ this.teamChange = this.teamChange.bind(this);
this.handleToggle = this.handleToggle.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleHide = this.handleHide.bind(this);
@@ -68,16 +69,27 @@ class InviteMemberModal extends React.Component {
emailEnabled: global.window.mm_config.SendEmailNotifications === 'true',
userCreationEnabled: global.window.mm_config.EnableUserCreation === 'true',
showConfirmModal: false,
- isSendingEmails: false
+ isSendingEmails: false,
+ teamType: null
};
}
+ teamChange() {
+ const team = TeamStore.getCurrent();
+ const teamType = team ? team.type : null;
+ this.setState({
+ teamType
+ });
+ }
+
componentDidMount() {
ModalStore.addModalListener(ActionTypes.TOGGLE_INVITE_MEMBER_MODAL, this.handleToggle);
+ TeamStore.addChangeListener(this.teamChange);
}
componentWillUnmount() {
ModalStore.removeModalListener(ActionTypes.TOGGLE_INVITE_MEMBER_MODAL, this.handleToggle);
+ TeamStore.removeChangeListener(this.teamChange);
}
handleToggle(value) {
@@ -224,7 +236,7 @@ class InviteMemberModal extends React.Component {
var currentUser = UserStore.getCurrentUser();
const {formatMessage} = this.props.intl;
- if (currentUser != null) {
+ if (currentUser != null && this.state.teamType != null) {
var inviteSections = [];
var inviteIds = this.state.inviteIds;
for (var i = 0; i < inviteIds.length; i++) {
@@ -398,7 +410,7 @@ class InviteMemberModal extends React.Component {
);
} else if (this.state.userCreationEnabled) {
var teamInviteLink = null;
- if (currentUser && TeamStore.getCurrent().type === 'O') {
+ if (currentUser && this.state.teamType === 'O') {
var link = (
<a
href='#'
diff --git a/webapp/components/logged_in.jsx b/webapp/components/logged_in.jsx
index f7a6be647..0c4571083 100644
--- a/webapp/components/logged_in.jsx
+++ b/webapp/components/logged_in.jsx
@@ -47,11 +47,12 @@ export default class LoggedIn extends React.Component {
this.onUserChanged = this.onUserChanged.bind(this);
this.state = {
- user: null
+ user: null,
+ profiles: null
};
}
isValidState() {
- return this.state.user != null;
+ return this.state.user != null && this.state.profiles != null;
}
onUserChanged() {
// Grab the current user
@@ -84,7 +85,13 @@ export default class LoggedIn extends React.Component {
browserHistory.push(Utils.getTeamURLFromAddressBar() + '/tutorial');
}
- this.setState({user});
+ // Get profiles
+ const profiles = UserStore.getProfiles();
+
+ this.setState({
+ user,
+ profiles
+ });
}
componentWillMount() {
// Emit view action
@@ -232,7 +239,10 @@ export default class LoggedIn extends React.Component {
</div>
</div>
<div className='row main'>
- {this.props.center}
+ {React.cloneElement(this.props.center, {
+ user: this.state.user,
+ profiles: this.state.profiles
+ })}
</div>
</div>
);
@@ -266,7 +276,10 @@ LoggedIn.defaultProps = {
};
LoggedIn.propTypes = {
- children: React.PropTypes.arrayOf(React.PropTypes.element),
+ children: React.PropTypes.oneOfType([
+ React.PropTypes.arrayOf(React.PropTypes.element),
+ React.PropTypes.element
+ ]),
navbar: React.PropTypes.element,
sidebar: React.PropTypes.element,
center: React.PropTypes.element,
diff --git a/webapp/components/msg_typing.jsx b/webapp/components/msg_typing.jsx
index b2d414287..631eea78d 100644
--- a/webapp/components/msg_typing.jsx
+++ b/webapp/components/msg_typing.jsx
@@ -40,13 +40,15 @@ class MsgTyping extends React.Component {
}
updateTypingText(typingUsers) {
- if (!typingUsers) {
- return;
+ let text = '';
+ let users = {};
+ let numUsers = 0;
+ if (typingUsers) {
+ users = Object.keys(typingUsers);
+ numUsers = users.length;
}
- const users = Object.keys(typingUsers);
- let text = '';
- switch (users.length) {
+ switch (numUsers) {
case 0:
text = '';
break;
diff --git a/webapp/components/permalink_view.jsx b/webapp/components/permalink_view.jsx
index 2ebe52356..2c32d643d 100644
--- a/webapp/components/permalink_view.jsx
+++ b/webapp/components/permalink_view.jsx
@@ -7,7 +7,6 @@ import ChannelHeader from 'components/channel_header.jsx';
import PostFocusView from 'components/post_focus_view.jsx';
import ChannelStore from 'stores/channel_store.jsx';
-import UserStore from 'stores/user_store.jsx';
import TeamStore from 'stores/team_store.jsx';
import {Link} from 'react-router';
@@ -30,17 +29,15 @@ export default class PermalinkView extends React.Component {
const channelName = channel ? channel.name : '';
const team = TeamStore.getCurrent();
const teamName = team ? team.name : '';
- const profiles = JSON.parse(JSON.stringify(UserStore.getProfiles()));
return {
channelId,
channelName,
- profiles,
teamName,
postId
};
}
isStateValid() {
- return this.state.channelId !== '' && this.state.profiles && this.state.teamName;
+ return this.state.channelId !== '' && this.state.teamName;
}
updateState() {
this.setState(this.getStateFromStores(this.props));
@@ -56,21 +53,6 @@ export default class PermalinkView extends React.Component {
componentWillReceiveProps(nextProps) {
this.setState(this.getStateFromStores(nextProps));
}
- shouldComponentUpdate(nextProps, nextState) {
- if (nextState.postId !== this.state.postId) {
- return true;
- }
-
- if (nextState.channelId !== this.state.channelId) {
- return true;
- }
-
- if (nextState.teamName !== this.state.teamName) {
- return true;
- }
-
- return false;
- }
render() {
if (!this.isStateValid()) {
return null;
@@ -83,7 +65,7 @@ export default class PermalinkView extends React.Component {
<ChannelHeader
channelId={this.state.channelId}
/>
- <PostFocusView profiles={this.state.profiles}/>
+ <PostFocusView profiles={this.props.profiles}/>
<div
id='archive-link-home'
>
@@ -106,5 +88,6 @@ PermalinkView.defaultProps = {
};
PermalinkView.propTypes = {
- params: React.PropTypes.object.isRequired
+ params: React.PropTypes.object.isRequired,
+ profiles: React.PropTypes.object
};
diff --git a/webapp/components/popover_list_members.jsx b/webapp/components/popover_list_members.jsx
index cd583e4c3..226a1889c 100644
--- a/webapp/components/popover_list_members.jsx
+++ b/webapp/components/popover_list_members.jsx
@@ -9,8 +9,6 @@ import * as Utils from 'utils/utils.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import Constants from 'utils/constants.jsx';
-import ChannelStore from 'stores/channel_store.jsx';
-
import {FormattedMessage} from 'react-intl';
import React from 'react';
@@ -57,7 +55,6 @@ export default class PopoverListMembers extends React.Component {
const members = this.props.members;
const teamMembers = UserStore.getProfilesUsernameMap();
const currentUserId = UserStore.getCurrentId();
- const ch = ChannelStore.getCurrent();
if (members && teamMembers) {
members.sort((a, b) => {
@@ -69,7 +66,7 @@ export default class PopoverListMembers extends React.Component {
members.forEach((m, i) => {
let button = '';
- if (currentUserId !== m.id && ch.type !== 'D') {
+ if (currentUserId !== m.id && this.props.channel.type !== 'D') {
button = (
<a
href='#'
@@ -177,7 +174,7 @@ export default class PopoverListMembers extends React.Component {
}
PopoverListMembers.propTypes = {
+ channel: React.PropTypes.object.isRequired,
members: React.PropTypes.array.isRequired,
- memberCount: React.PropTypes.number,
- channelId: React.PropTypes.string.isRequired
+ memberCount: React.PropTypes.number
};
diff --git a/webapp/components/post.jsx b/webapp/components/post.jsx
index f2818188a..30c47ee22 100644
--- a/webapp/components/post.jsx
+++ b/webapp/components/post.jsx
@@ -188,6 +188,8 @@ export default class Post extends React.Component {
if (post.props && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') {
if (post.props.override_icon_url) {
src = post.props.override_icon_url;
+ } else {
+ src = Constants.DEFAULT_WEBHOOK_LOGO;
}
} else if (Utils.isSystemMessage(post)) {
src = Constants.SYSTEM_MESSAGE_PROFILE_IMAGE;
diff --git a/webapp/components/posts_view.jsx b/webapp/components/posts_view.jsx
index 647c7f086..ffe04daa1 100644
--- a/webapp/components/posts_view.jsx
+++ b/webapp/components/posts_view.jsx
@@ -173,24 +173,15 @@ export default class PostsView extends React.Component {
const postFromWebhook = Boolean(post.props && post.props.from_webhook);
const prevPostFromWebhook = Boolean(prevPost.props && prevPost.props.from_webhook);
const prevPostUserId = Utils.isSystemMessage(prevPost) ? '' : prevPost.user_id;
- let prevWebhookName = '';
- if (prevPost.props && prevPost.props.override_username) {
- prevWebhookName = prevPost.props.override_username;
- }
- let curWebhookName = '';
- if (post.props && post.props.override_username) {
- curWebhookName = post.props.override_username;
- }
// consider posts from the same user if:
// the previous post was made by the same user as the current post,
// the previous post was made within 5 minutes of the current post,
- // the previous post and current post are both from webhooks or both not,
- // the previous post and current post have the same webhook usernames
+ // the current post is not from a webhook
+ // the previous post is not from a webhook
if (prevPostUserId === postUserId &&
post.create_at - prevPost.create_at <= 1000 * 60 * 5 &&
- postFromWebhook === prevPostFromWebhook &&
- prevWebhookName === curWebhookName) {
+ !postFromWebhook && !prevPostFromWebhook) {
sameUser = true;
}
@@ -213,13 +204,11 @@ export default class PostsView extends React.Component {
// the previous post was made by the same user as the current post,
// the previous post is not a comment,
// the current post is not a comment,
- // the previous post and current post are both from webhooks or both not,
- // the previous post and current post have the same webhook usernames
+ // the current post is not from a webhook
if (prevPostUserId === postUserId &&
!prevPostIsComment &&
!postIsComment &&
- postFromWebhook === prevPostFromWebhook &&
- prevWebhookName === curWebhookName) {
+ !postFromWebhook) {
hideProfilePic = true;
}
}
@@ -319,7 +308,7 @@ export default class PostsView extends React.Component {
if (this.props.scrollType === PostsView.SCROLL_TYPE_BOTTOM) {
this.scrollToBottom();
} else if (this.props.scrollType === PostsView.SCROLL_TYPE_NEW_MESSAGE) {
- window.requestAnimationFrame(() => {
+ window.setTimeout(window.requestAnimationFrame(() => {
// If separator exists scroll to it. Otherwise scroll to bottom.
if (this.refs.newMessageSeparator) {
var objDiv = this.refs.postlist;
@@ -327,7 +316,7 @@ export default class PostsView extends React.Component {
} else if (this.refs.postlist) {
this.refs.postlist.scrollTop = this.refs.postlist.scrollHeight;
}
- });
+ }), 0);
} else if (this.props.scrollType === PostsView.SCROLL_TYPE_POST && this.props.scrollPostId) {
window.requestAnimationFrame(() => {
const postNode = ReactDOM.findDOMNode(this.refs[this.props.scrollPostId]);
@@ -385,6 +374,7 @@ export default class PostsView extends React.Component {
componentWillUnmount() {
window.removeEventListener('resize', this.handleResize);
this.scrollStopAction.cancel();
+ PreferenceStore.removeChangeListener(this.updateState);
}
componentDidUpdate() {
if (this.props.postList != null) {
diff --git a/webapp/components/posts_view_container.jsx b/webapp/components/posts_view_container.jsx
index 7e334d4b0..a49c77f8d 100644
--- a/webapp/components/posts_view_container.jsx
+++ b/webapp/components/posts_view_container.jsx
@@ -8,7 +8,6 @@ import ChannelStore from 'stores/channel_store.jsx';
import PostStore from 'stores/post_store.jsx';
import UserStore from 'stores/user_store.jsx';
-import * as Utils from 'utils/utils.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import Constants from 'utils/constants.jsx';
@@ -158,17 +157,6 @@ export default class PostsViewContainer extends React.Component {
this.setState({scrollType: PostsView.SCROLL_TYPE_FREE});
}
}
- shouldComponentUpdate(nextProps, nextState) {
- if (!Utils.areObjectsEqual(this.state, nextState)) {
- return true;
- }
-
- if (!Utils.areObjectsEqual(this.props, nextProps)) {
- return true;
- }
-
- return false;
- }
render() {
const postLists = this.state.postLists;
const channels = this.state.channels;
diff --git a/webapp/components/rhs_root_post.jsx b/webapp/components/rhs_root_post.jsx
index 26b392aa1..7a7c5f692 100644
--- a/webapp/components/rhs_root_post.jsx
+++ b/webapp/components/rhs_root_post.jsx
@@ -217,6 +217,8 @@ export default class RhsRootPost extends React.Component {
if (post.props && post.props.from_webhook && global.window.mm_config.EnablePostIconOverride === 'true') {
if (post.props.override_icon_url) {
src = post.props.override_icon_url;
+ } else {
+ src = Constants.DEFAULT_WEBHOOK_LOGO;
}
} else if (Utils.isSystemMessage(post)) {
src = Constants.SYSTEM_MESSAGE_PROFILE_IMAGE;
diff --git a/webapp/components/search_results_item.jsx b/webapp/components/search_results_item.jsx
index 219aa7093..75cbcb2a0 100644
--- a/webapp/components/search_results_item.jsx
+++ b/webapp/components/search_results_item.jsx
@@ -5,7 +5,6 @@ import UserStore from 'stores/user_store.jsx';
import UserProfile from './user_profile.jsx';
import * as GlobalActions from 'action_creators/global_actions.jsx';
import * as TextFormatting from 'utils/text_formatting.jsx';
-import * as Utils from 'utils/utils.jsx';
import Constants from 'utils/constants.jsx';
@@ -88,7 +87,7 @@ export default class SearchResultsItem extends React.Component {
</li>
<li>
<Link
- to={Utils.getTeamURLFromAddressBar() + '/pl/' + this.props.post.id}
+ to={'/' + window.location.pathname.split('/')[1] + '/pl/' + this.props.post.id}
className='search-item__jump'
>
<FormattedMessage
diff --git a/webapp/components/user_settings/user_settings_display.jsx b/webapp/components/user_settings/user_settings_display.jsx
index d815bd371..d169e01b5 100644
--- a/webapp/components/user_settings/user_settings_display.jsx
+++ b/webapp/components/user_settings/user_settings_display.jsx
@@ -304,7 +304,7 @@ export default class UserSettingsDisplay extends React.Component {
describe = (
<FormattedMessage
id='user.settings.display.showUsername'
- defaultMessage='Show username (team default)'
+ defaultMessage='Show username (default)'
/>
);
} else if (this.state.nameFormat === 'full_name') {
diff --git a/webapp/components/user_settings/user_settings_security.jsx b/webapp/components/user_settings/user_settings_security.jsx
index e4044e6d0..ff5a898a9 100644
--- a/webapp/components/user_settings/user_settings_security.jsx
+++ b/webapp/components/user_settings/user_settings_security.jsx
@@ -1,6 +1,7 @@
// Copyright (c) 2015 Mattermost, Inc. All Rights Reserved.
// See License.txt for license information.
+import $ from 'jquery';
import SettingItemMin from '../setting_item_min.jsx';
import SettingItemMax from '../setting_item_max.jsx';
import AccessHistoryModal from '../access_history_modal.jsx';
@@ -247,7 +248,7 @@ class SecurityTab extends React.Component {
extraInfo = (
<span>
<FormattedMessage
- id='user.settings.mfa.addHelp'
+ id='user.settings.mfa.addHelpQr'
defaultMessage='Please scan the QR code with the Google Authenticator app on your smartphone and fill in the token with one provided by the app.'
/>
</span>
diff --git a/webapp/i18n/en.json b/webapp/i18n/en.json
index 2efa90ac5..3c543a7c5 100644
--- a/webapp/i18n/en.json
+++ b/webapp/i18n/en.json
@@ -30,10 +30,10 @@
"add_incoming_webhook.name": "Name",
"add_incoming_webhook.save": "Save",
"add_integration.header": "Add Integration",
- "add_integration.incomingWebhook.title": "Incoming Webhook",
"add_integration.incomingWebhook.description": "Create webhook URLs for use in external integrations.",
- "add_integration.outgoingWebhook.title": "Outgoing Webhook",
+ "add_integration.incomingWebhook.title": "Incoming Webhook",
"add_integration.outgoingWebhook.description": "Create webhooks to send new message events to an external integration.",
+ "add_integration.outgoingWebhook.title": "Outgoing Webhook",
"add_outgoing_webhook.callbackUrls": "Callback URLs (One Per Line)",
"add_outgoing_webhook.callbackUrlsRequired": "One or more callback URLs are required",
"add_outgoing_webhook.cancel": "Cancel",
@@ -43,17 +43,19 @@
"add_outgoing_webhook.name": "Name",
"add_outgoing_webhook.save": "Save",
"add_outgoing_webhook.triggerWOrds": "Trigger Words (One Per Line)",
+ "add_outgoing_webhook.triggerWords": "Trigger Words (One Per Line)",
"add_outgoing_webhook.triggerWordsOrChannelRequired": "A valid channel or a list of trigger words is required",
"admin.audits.reload": "Reload",
"admin.audits.title": "User Activity",
"admin.compliance.directoryDescription": "Directory to which compliance reports are written. If blank, will be set to ./data/.",
"admin.compliance.directoryExample": "Ex \"./data/\"",
"admin.compliance.directoryTitle": "Compliance Directory Location:",
+ "admin.compliance.enableDailyDesc": "When true, Mattermost will generate a daily compliance report.",
"admin.compliance.enableDailyTitle": "Enable Daily Report:",
- "admin.compliance.enableDesc": "When true, Mattermost will generate a daily compliance report.",
+ "admin.compliance.enableDesc": "When true, Mattermost allows compliance reporting",
"admin.compliance.enableTitle": "Enable Compliance:",
"admin.compliance.false": "false",
- "admin.compliance.noLicense": "<h4 class=\"banner__heading\">Note:</h4><p>Compliance is an enterprise feature. Your current license does not support Compliance. Click <a href=\"http://mattermost.com\" target=\"_blank\">here</a> for information and pricing on enterprise licenses.</p>",
+ "admin.compliance.noLicense": "<h4 class=\"banner__heading\">Note:</h4><p>Compliance is an enterprise feature. Your current license does not support Compliance. Click <a href=\"http://mattermost.com\"target=\"_blank\">here</a> for information and pricing on enterprise licenses.</p>",
"admin.compliance.save": "Save",
"admin.compliance.saving": "Saving Config...",
"admin.compliance.title": "Compliance Settings",
@@ -233,7 +235,7 @@
"admin.ldap.lastnameAttrDesc": "The attribute in the LDAP server that will be used to populate the last name of users in Mattermost.",
"admin.ldap.lastnameAttrEx": "Ex \"sn\"",
"admin.ldap.lastnameAttrTitle": "Last Name Attribute:",
- "admin.ldap.noLicense": "<h4 class=\"banner__heading\">Note:</h4><p>LDAP is an enterprise feature. Your current license does not support LDAP. Click <a href=\"http://mattermost.com\" target=\"_blank\">here</a> for information and pricing on enterprise licenses.</p>",
+ "admin.ldap.noLicense": "<h4 class=\"banner__heading\">Note:</h4><p>LDAP is an enterprise feature. Your current license does not support LDAP. Click <a href=\"http://mattermost.com\"target=\"_blank\">here</a> for information and pricing on enterprise licenses.</p>",
"admin.ldap.portDesc": "The port Mattermost will use to connect to the LDAP server. Default is 389.",
"admin.ldap.portEx": "Ex \"389\"",
"admin.ldap.portTitle": "LDAP Port:",
@@ -251,7 +253,10 @@
"admin.ldap.usernameAttrEx": "Ex \"sAMAccountName\"",
"admin.ldap.usernameAttrTitle": "Username Attribute:",
"admin.licence.keyMigration": "If you’re migrating servers you may need to remove your license key from this server in order to install it on a new server. To start, <a href=\"http://mattermost.com\" target=\"_blank\">disable all Enterprise Edition features on this server</a>. This will enable the ability to remove the license key and downgrade this server from Enterprise Edition to Team Edition.",
+ "admin.license.choose": "Choose File",
"admin.license.chooseFile": "Choose File",
+ "admin.license.edition": "Edition: ",
+ "admin.license.key": "License Key: ",
"admin.license.keyRemove": "Remove Enterprise License and Downgrade Server",
"admin.license.noFile": "No file uploaded",
"admin.license.removing": "Removing License...",
@@ -328,15 +333,13 @@
"admin.select_team.close": "Close",
"admin.select_team.select": "Select",
"admin.select_team.selectTeam": "Select Team",
- "admin.service.mfaTitle": "Enable Multi-factor Authentication:",
- "admin.service.mfaDesc": "When true, users will be given the option to add multi-factor authentication to their account. They will need a smartphone and an authenticator app such as Google Authenticator.",
"admin.service.attemptDescription": "Login attempts allowed before user is locked out and required to reset password via email.",
"admin.service.attemptExample": "Ex \"10\"",
"admin.service.attemptTitle": "Maximum Login Attempts:",
"admin.service.cmdsDesc": "When true, user created slash commands will be allowed.",
"admin.service.cmdsTitle": "Enable Slash Commands: ",
- "admin.service.corsDescription": "Enable HTTP Cross origin request from specific domains (separate by a spacebar). Use \"*\" if you want to allow CORS from any domain or leave it blank to disable it.",
- "admin.service.corsEx": "http://example.com https://example.com",
+ "admin.service.corsDescription": "Enable HTTP Cross origin request from a specific domain. Use \"*\" if you want to allow CORS from any domain or leave it blank to disable it.",
+ "admin.service.corsEx": "http://example.com",
"admin.service.corsTitle": "Allow Cross-origin Requests from:",
"admin.service.developerDesc": "(Developer Option) When true, extra information around errors will be displayed in the UI.",
"admin.service.developerTitle": "Enable Developer Mode: ",
@@ -353,6 +356,8 @@
"admin.service.listenAddress": "Listen Address:",
"admin.service.listenDescription": "The address to which to bind and listen. Entering \":8065\" will bind to all interfaces or you can choose one like \"127.0.0.1:8065\". Changing this will require a server restart before taking effect.",
"admin.service.listenExample": "Ex \":8065\"",
+ "admin.service.mfaDesc": "When true, users will be given the option to add multi-factor authentication to their account. They will need a smartphone and an authenticator app such as Google Authenticator.",
+ "admin.service.mfaTitle": "Enable Multi-factor Authentication:",
"admin.service.mobileSessionDays": "Session Length for Mobile Device in Days:",
"admin.service.mobileSessionDaysDesc": "The native mobile session will expire after the number of days specified and will require a user to login again.",
"admin.service.outWebhooksDesc": "When true, outgoing webhooks will be allowed.",
@@ -512,6 +517,7 @@
"analytics.team.privateGroups": "Private Groups",
"analytics.team.publicChannels": "Public Channels",
"analytics.team.recentActive": "Recent Active Users",
+ "analytics.team.recentUsers": "Recent Active Users",
"analytics.team.title": "Team Statistics for {team}",
"analytics.team.totalPosts": "Total Posts",
"analytics.team.totalUsers": "Total Users",
@@ -576,10 +582,10 @@
"authorize.title": "An application would like to connect to your {teamName} account",
"backstage_navbar.backToMattermost": "Back to {siteName}",
"backstage_sidebar.integrations": "Integrations",
- "backstage_sidebar.integrations.installed": "Installed Integrations",
"backstage_sidebar.integrations.add": "Add Integration",
"backstage_sidebar.integrations.add.incomingWebhook": "Incoming Webhook",
"backstage_sidebar.integrations.add.outgoingWebhook": "Outgoing Webhook",
+ "backstage_sidebar.integrations.installed": "Installed Integrations",
"center_panel.recent": "Click here to jump to recent messages. ",
"chanel_header.addMembers": "Add Members",
"change_url.close": "Close",
@@ -702,6 +708,7 @@
"claim.oauth_to_email.pwdNotMatch": "Password do not match.",
"claim.oauth_to_email.switchTo": "Switch {type} to email and password",
"claim.oauth_to_email.title": "Switch {type} Account to Email",
+ "claim.oauth_to_email_newPwd": "Enter a new password for your {team} {site} account",
"confirm_modal.cancel": "Cancel",
"create_comment.addComment": "Add a comment...",
"create_comment.comment": "Add Comment",
@@ -763,8 +770,9 @@
"file_upload.filesAbove": "Files above {max}MB could not be uploaded: {filenames}",
"file_upload.limited": "Uploads limited to {count} files maximum. Please use additional posts for more files.",
"file_upload.pasted": "Image Pasted at ",
- "filtered_user_list.count": "{count, number} {count, plural, one {member} other {members}}",
- "filtered_user_list.countTotal": "{count, number} {count, plural, one {member} other {members}} of {total} Total",
+ "filtered_user_list.count": "{count} {count, plural, one {member} other {members}}",
+ "filtered_user_list.countTotal": "{count} {count, plural, one {member} other {members}} of {total} Total",
+ "filtered_user_list.member": "Member",
"filtered_user_list.search": "Search members",
"find_team.email": "Email",
"find_team.findDescription": "An email was sent with links to any teams to which you are a member.",
@@ -800,13 +808,13 @@
"get_team_invite_link_modal.helpDisabled": "User creation has been disabled for your team. Please ask your team administrator for details.",
"get_team_invite_link_modal.title": "Team Invite Link",
"installed_integrations.add": "Add Integration",
- "installed_integrations.allFilter": "All",
+ "installed_integrations.allFilter": "All ({count})",
"installed_integrations.delete": "Delete",
"installed_integrations.header": "Installed Integrations",
- "installed_integrations.incomingWebhooksFilter": "Incoming Webhooks ({count})",
"installed_integrations.incomingWebhookType": "(Incoming Webhook)",
- "installed_integrations.outgoingWebhooksFilter": "Outgoing Webhooks ({count})",
+ "installed_integrations.incomingWebhooksFilter": "Incoming Webhooks ({count})",
"installed_integrations.outgoingWebhookType": "(Outgoing Webhook)",
+ "installed_integrations.outgoingWebhooksFilter": "Outgoing Webhooks ({count})",
"installed_integrations.regenToken": "Regen Token",
"installed_integrations.search": "Search Integrations",
"intro_messages.DM": "This is the start of your direct message history with {teammate}.<br />Direct messages and files shared here are not shown to people outside this area.",
@@ -859,10 +867,6 @@
"login.session_expired": " Your session has expired. Please login again.",
"login.signTo": "Sign in to:",
"login.verified": " Email Verified",
- "login_mfa.token": "MFA Token",
- "login_mfa.enterToken": "To complete the sign in process, please enter a token from your smartphone's authenticator",
- "login_mfa.submit": "Submit",
- "login_mfa.tokenReq": "Please enter an MFA token",
"login_email.badTeam": "Bad team name",
"login_email.email": "Email",
"login_email.emailReq": "An email is required",
@@ -875,6 +879,10 @@
"login_ldap.pwdReq": "An LDAP password is required",
"login_ldap.signin": "Sign in",
"login_ldap.username": "LDAP Username",
+ "login_mfa.enterToken": "To complete the sign in process, please enter a token from your smartphone's authenticator",
+ "login_mfa.submit": "Submit",
+ "login_mfa.token": "MFA Token",
+ "login_mfa.tokenReq": "Please enter an MFA token",
"login_username.badTeam": "Bad team name",
"login_username.pwd": "Password",
"login_username.pwdReq": "A password is required",
@@ -934,7 +942,7 @@
"password_form.title": "Password Reset",
"password_form.update": "Your password has been updated successfully.",
"password_send.checkInbox": "Please check your inbox.",
- "password_send.description": "To reset your password, enter the email address you used to sign up.",
+ "password_send.description": "To reset your password, enter the email address you used to sign up",
"password_send.email": "Email",
"password_send.error": "Please enter a valid email address.",
"password_send.link": "<p>A password reset link has been sent to <b>{email}</b></p>",
@@ -1073,6 +1081,7 @@
"signup_user_completed.validEmail": "Please enter a valid email address",
"signup_user_completed.welcome": "Welcome to:",
"signup_user_completed.whatis": "What's your email address?",
+ "signup_user_completed.withLdap": "With your LDAP credentials",
"sso_signup.find": "Find my teams",
"sso_signup.gitlab": "Create team with GitLab Account",
"sso_signup.google": "Create team with Google Apps Account",
@@ -1294,11 +1303,11 @@
"user.settings.general.confirmEmail": "Confirm Email",
"user.settings.general.email": "Email",
"user.settings.general.emailGitlabCantUpdate": "Login occurs through GitLab. Email cannot be updated. Email address used for notifications is {email}.",
- "user.settings.general.emailLdapCantUpdate": "Login occurs through LDAP. Email cannot be updated. Email address used for notifications is {email}.",
"user.settings.general.emailHelp1": "Email is used for sign-in, notifications, and password reset. Email requires verification if changed.",
"user.settings.general.emailHelp2": "Email has been disabled by your system administrator. No notification emails will be sent until it is enabled.",
"user.settings.general.emailHelp3": "Email is used for sign-in, notifications, and password reset.",
"user.settings.general.emailHelp4": "A verification email was sent to {email}.",
+ "user.settings.general.emailLdapCantUpdate": "Login occurs through LDAP. Email cannot be updated. Email address used for notifications is {email}.",
"user.settings.general.emailMatch": "The new emails you entered do not match.",
"user.settings.general.emptyName": "Click 'Edit' to add your full name",
"user.settings.general.emptyNickname": "Click 'Edit' to add a nickname",
@@ -1333,6 +1342,13 @@
"user.settings.integrations.commandsDescription": "Manage your slash commands",
"user.settings.integrations.title": "Integration Settings",
"user.settings.languages.change": "Change interface language",
+ "user.settings.mfa.add": "Add MFA to your account",
+ "user.settings.mfa.addHelp": "To add multi-factor authentication to your account you must have a smartphone with Google Authenticator installed.",
+ "user.settings.mfa.addHelpQr": "Please scan the QR code with the Google Authenticator app on your smartphone and fill in the token with one provided by the app.",
+ "user.settings.mfa.enterToken": "Token",
+ "user.settings.mfa.qrCode": "QR Code",
+ "user.settings.mfa.remove": "Remove MFA from your account",
+ "user.settings.mfa.removeHelp": "Removing multi-factor authentication will make your account more vulnerable to attacks.",
"user.settings.modal.advanced": "Advanced",
"user.settings.modal.confirmBtns": "Yes, Discard",
"user.settings.modal.confirmMsg": "You have unsaved changes, are you sure you want to discard them?",
@@ -1388,7 +1404,7 @@
"user.settings.security.switchEmail": "Switch to using email and password",
"user.settings.security.switchGitlab": "Switch to using GitLab SSO",
"user.settings.security.switchGoogle": "Switch to using Google SSO",
- "user.settings.security.switchLda": "Switch to using LDAP",
+ "user.settings.security.switchLdap": "Switch to using LDAP",
"user.settings.security.title": "Security Settings",
"user.settings.security.viewHistory": "View Access History",
"user_list.notFound": "No users found :(",
diff --git a/webapp/i18n/es.json b/webapp/i18n/es.json
index 109861c43..8cc9e5db6 100644
--- a/webapp/i18n/es.json
+++ b/webapp/i18n/es.json
@@ -22,13 +22,37 @@
"activity_log_modal.android": "Android",
"activity_log_modal.androidNativeApp": "Android App Nativa",
"activity_log_modal.iphoneNativeApp": "iPhone App Nativa",
+ "add_incoming_webhook.cancel": "Cancelar",
+ "add_incoming_webhook.channel": "Canal",
+ "add_incoming_webhook.channelRequired": "Es obligatorio asignar un canal válido",
+ "add_incoming_webhook.description": "Descripción",
+ "add_incoming_webhook.header": "Agregar un Webhook de Entrada",
+ "add_incoming_webhook.name": "Nombre",
+ "add_incoming_webhook.save": "Guardar",
+ "add_integration.header": "Agregar Integración",
+ "add_integration.incomingWebhook.description": "Crea webhook URLs para utilizarlas con integraciones externas.",
+ "add_integration.incomingWebhook.title": "Webhook de Entrada",
+ "add_integration.outgoingWebhook.description": "Crea webhooks para enviar mensajes a integraciones externas.",
+ "add_integration.outgoingWebhook.title": "Webhook de salida",
+ "add_outgoing_webhook.callbackUrls": "Callback URLs (Uno por Línea)",
+ "add_outgoing_webhook.callbackUrlsRequired": "Se require uno o más URLs para los callback",
+ "add_outgoing_webhook.cancel": "Cancelar",
+ "add_outgoing_webhook.channel": "Canal",
+ "add_outgoing_webhook.description": "Descripción",
+ "add_outgoing_webhook.header": "Agregar Webhook de Salida",
+ "add_outgoing_webhook.name": "Nombre",
+ "add_outgoing_webhook.save": "Guardar",
+ "add_outgoing_webhook.triggerWOrds": "Palabras gatilladoras (Una por línea)",
+ "add_outgoing_webhook.triggerWords": "Palabras gatilladoras (Una por Línea)",
+ "add_outgoing_webhook.triggerWordsOrChannelRequired": "Se require al menos un canal válido o una lista de palabras gatilladoras",
"admin.audits.reload": "Recargar",
"admin.audits.title": "Auditorías del Servidor",
"admin.compliance.directoryDescription": "Directorio en el que se escriben los informes de cumplimiento. Si se deja en blanco, se utilizará ./data/.",
"admin.compliance.directoryExample": "Ej \"./data/\"",
"admin.compliance.directoryTitle": "Ubicación del Directorio de Cumplimiento:",
+ "admin.compliance.enableDailyDesc": "Cuando es verdadero, Mattermost generará un reporte de cumplimiento diario.",
"admin.compliance.enableDailyTitle": "Habilitar Informes Diarios:",
- "admin.compliance.enableDesc": "Cuando es verdadero, Mattermost generará un informe diario de cumplimiento.",
+ "admin.compliance.enableDesc": "Cuando es verdadero, Mattermost permite la creación de reportes de cumplimiento",
"admin.compliance.enableTitle": "Habilitar el Cumplimiento:",
"admin.compliance.false": "falso",
"admin.compliance.noLicense": "<h4 class=\"banner__heading\">Nota:</h4><p>El Cumplimiento es una característica de la edición enterprise. Tu licencia actual no soporta Cumplimiento. Pincha <a href=\"http://mattermost.com\" target=\"_blank\">aquí</a> para información y precio de las licencias enterprise.</p>",
@@ -211,7 +235,7 @@
"admin.ldap.lastnameAttrDesc": "El atributo en el servidor LDAP que será utilizado para poblar el apellido de los usuarios en Mattermost.",
"admin.ldap.lastnameAttrEx": "Ej \"sn\"",
"admin.ldap.lastnameAttrTitle": "Atributo Apellido:",
- "admin.ldap.noLicense": "<h4 class=\"banner__heading\">Nota:</h4><p>LDAP es una característica de la edición enterprise. Tu licencia actual no soporta LDAP. Pincha <a href=\"http://mattermost.com\" target=\"_blank\">aquí</a> para obtener información y precios de las licencias de la edición enterprise.</p>",
+ "admin.ldap.noLicense": "<h4 class=\"banner__heading\">Nota:</h4><p>LDAP es una característica de la edición enterprise. Tu licencia actual no soporta LDAP. Pincha <a href=\"http://mattermost.com\" target=\"_blank\">aquí</a> para obtener información y precios de las licencias enterprise.</p>",
"admin.ldap.portDesc": "El puerto que Mattermost utilizará para conectarse al servidor LDAP. El predeterminado es 389.",
"admin.ldap.portEx": "Ej \"389\"",
"admin.ldap.portTitle": "Puerto LDAP:",
@@ -229,7 +253,10 @@
"admin.ldap.usernameAttrEx": "Ej \"sAMAccountName\"",
"admin.ldap.usernameAttrTitle": "Atributo Usuario:",
"admin.licence.keyMigration": "Si estás migrando servidores es posible que necesites remover tu licencia de este servidor para poder instalarlo en un servidor nuevo. Para empezar, <a href=\"http://mattermost.com\" target=\"_blank\">deshabilita todas las características de la Edición Enterprise de este servidor</a>. Esta operación habilitará la opción para remover la licencia y degradar este servidor de la Edición Enterprise a la Edición Team.",
+ "admin.license.choose": "Seleccionar Archivo",
"admin.license.chooseFile": "Escoger Archivo",
+ "admin.license.edition": "Edición: ",
+ "admin.license.key": "Licencia: ",
"admin.license.keyRemove": "Remover la Licencia Enterprise y Degradar el Servidor",
"admin.license.noFile": "No se subió ningún archivo",
"admin.license.removing": "Removiendo Licencia...",
@@ -311,8 +338,8 @@
"admin.service.attemptTitle": "Máximo de intentos de conexión:",
"admin.service.cmdsDesc": "Cuando es verdadero, se permite la creación de comandos de barra por usuarios.",
"admin.service.cmdsTitle": "Habilitar Comandos de Barra: ",
- "admin.service.corsDescription": "Habilita las solicitudes HTTP de origen cruzado para dominios en específico (separados por un espacio). Utiliza \"*\" si quieres habilitar CORS desde cualquier dominio o deja el campo en blanco para deshabilitarlo.",
- "admin.service.corsEx": "http://ejemplo.com https://ejemplo.com",
+ "admin.service.corsDescription": "Habilitar solicitudes HTTP de origen cruzado desde un dominio específico. Utiliza \"*\" si quieres permitir CORS desde cualquier dominio o dejalo en blanco para deshabilitarlo.",
+ "admin.service.corsEx": "http://ejemplo.com",
"admin.service.corsTitle": "Permitir Solicitudes de Origen Cruzado desde:",
"admin.service.developerDesc": "(Opción de Desarrollador) Cuando está asignado en verdadero, información extra sobre errores se muestra en el UI.",
"admin.service.developerTitle": "Habilitar modo de Desarrollador: ",
@@ -329,6 +356,8 @@
"admin.service.listenAddress": "Dirección de escucha:",
"admin.service.listenDescription": "La dirección a la que se unirá y escuchará. Ingresar \":8065\" se podrá unir a todas las interfaces o podrá seleccionar una como ej: \"127.0.0.1:8065\". Cambiando este valor es necesario reiniciar el servidor.",
"admin.service.listenExample": "Ej \":8065\"",
+ "admin.service.mfaDesc": "Cuando es verdadero, los usuarios tendrán la opción de agregar autenticación de múltiples factores a sus cuentas. Necesitarán un teléfono inteligente y una app de autenticación como Google Authenticator.",
+ "admin.service.mfaTitle": "Habilitar Autenticación de Múltiples Factores:",
"admin.service.mobileSessionDays": "Duración de la Sesión en Días para Dispositivos Moviles:",
"admin.service.mobileSessionDaysDesc": "La sesión nativa de los dispositivos moviles expirará luego de transcurrido el numero de días especificado y se solicitará al usuario que inicie sesión nuevamente.",
"admin.service.outWebhooksDesc": "Cuando es verdadero, los webhooks de salida serán permitidos.",
@@ -488,6 +517,7 @@
"analytics.team.privateGroups": "Grupos Privados",
"analytics.team.publicChannels": "Canales Públicos",
"analytics.team.recentActive": "Usuarios Recientemente Activos",
+ "analytics.team.recentUsers": "Usuarios Recientemente Activos",
"analytics.team.title": "Estádisticas del Equipo {team}",
"analytics.team.totalPosts": "Total de Mensajes",
"analytics.team.totalUsers": "Total de Usuarios",
@@ -550,6 +580,12 @@
"authorize.app": "La app <strong>{appName}</strong> quiere tener la habilidad de accesar y modificar tu información básica.",
"authorize.deny": "Denegar",
"authorize.title": "Una aplicación quiere conectarse con tu cuenta de {teamName}",
+ "backstage_navbar.backToMattermost": "Volver a {siteName}",
+ "backstage_sidebar.integrations": "Integraciones",
+ "backstage_sidebar.integrations.add": "Agregar Integración",
+ "backstage_sidebar.integrations.add.incomingWebhook": "Webhook de Entrada",
+ "backstage_sidebar.integrations.add.outgoingWebhook": "Webhook de Salida",
+ "backstage_sidebar.integrations.installed": "Integraciones Instaladas",
"center_panel.recent": "Pincha aquí para ir a los mensajes más recientes. ",
"chanel_header.addMembers": "Agregar Miembros",
"change_url.close": "Cerrar",
@@ -626,6 +662,7 @@
"channel_notifications.preferences": "Preferencias de Notificación para ",
"channel_notifications.sendDesktop": "Enviar notificaciones de escritorio",
"channel_notifications.unreadInfo": "El nombre del canal está en negritas en la barra lateral cuando hay mensajes sin leer. Al elegir \"Sólo para menciones\" sólo lo dejará en negritas cuando seas mencionado.",
+ "channel_select.placeholder": "--- Selecciona un canal ---",
"choose_auth_page.emailCreate": "Crea un nuevo equipo con tu cuenta de correo",
"choose_auth_page.find": "Encontrar mi equipo",
"choose_auth_page.gitlabCreate": "Crear un nuevo equipo con una cuenta de GitLab",
@@ -671,6 +708,7 @@
"claim.oauth_to_email.pwdNotMatch": "Las contraseñas no coinciden.",
"claim.oauth_to_email.switchTo": "Cambiar {type} a correo electrónico y contraseña",
"claim.oauth_to_email.title": "Cambiar la cuenta de {type} a Correo Electrónico",
+ "claim.oauth_to_email_newPwd": "Ingresa una nueva contraseña para tu cuenta de {team} en {site}",
"confirm_modal.cancel": "Cancelar",
"create_comment.addComment": "Agregar un comentario...",
"create_comment.comment": "Agregar Comentario",
@@ -732,8 +770,9 @@
"file_upload.filesAbove": "No se pueden subir archivos de más de {max}MB: {filenames}",
"file_upload.limited": "Se pueden subir un máximo de {count} archivos. Por favor envía otros mensajes para adjuntar más archivos.",
"file_upload.pasted": "Imagen Pegada el ",
- "filtered_user_list.count": "{count, number} {count, plural, one {Miembro} other {Miembros}}",
- "filtered_user_list.countTotal": "{count, number} {count, plural, one {Miembro} other {Miembros}} de {total} Total",
+ "filtered_user_list.count": "{count} {count, plural, one {miembro} other {miembros}}",
+ "filtered_user_list.countTotal": "{count} {count, plural, one {miembro} other {miembros}} de {total} Total",
+ "filtered_user_list.member": "Miembro",
"filtered_user_list.search": "Buscar miembros",
"find_team.email": "Correo electrónico",
"find_team.findDescription": "Enviamos un correo electrónico con los equipos a los que perteneces.",
@@ -768,6 +807,16 @@
"get_team_invite_link_modal.help": "Envía el siguiente enlace a tus compañeros para que se registren a este equipo. El enlace de invitación al equipo puede ser compartido con multiples compañeros y el mismo no cambiará a menos que sea regenerado en la Configuración del Equipo por un Administrador del Equipo.",
"get_team_invite_link_modal.helpDisabled": "La creación de usuario ha sido deshabilitada para tu equipo. Por favor solicita más detalles a tu administrador de equipo.",
"get_team_invite_link_modal.title": "Enlace de Invitación al Equipo",
+ "installed_integrations.add": "Agregar Integración",
+ "installed_integrations.allFilter": "Todos ({count})",
+ "installed_integrations.delete": "Eliminar",
+ "installed_integrations.header": "Integraciones Instaladas",
+ "installed_integrations.incomingWebhookType": "(Webhook de Entrada)",
+ "installed_integrations.incomingWebhooksFilter": "Webhooks de Entrada ({count})",
+ "installed_integrations.outgoingWebhookType": "(Webhook de Salida)",
+ "installed_integrations.outgoingWebhooksFilter": "Webhooks de Salida ({count})",
+ "installed_integrations.regenToken": "Regenerar Token",
+ "installed_integrations.search": "Buscar Integraciones",
"intro_messages.DM": "Este es el inicio de tu historial de mensajes directos con {teammate}.<br />Los mensajes directos y archivos que se comparten aquí no son mostrados a personas fuera de esta área.",
"intro_messages.anyMember": " Cualquier miembro se puede unir y leer este canal.",
"intro_messages.beginning": "Inicio de {name}",
@@ -830,6 +879,10 @@
"login_ldap.pwdReq": "La contraseña LDAP es obligatoria",
"login_ldap.signin": "Entrar",
"login_ldap.username": "Usuario LDAP",
+ "login_mfa.enterToken": "Para completar el proceso de inicio de sesión, por favor ingresa el token provisto por el autenticador de tu teléfono inteligente",
+ "login_mfa.submit": "Enviar",
+ "login_mfa.token": "Token AMF",
+ "login_mfa.tokenReq": "Por favor ingresa un token AMF",
"login_username.badTeam": "Mal nombre de equipo",
"login_username.pwd": "Contraseña",
"login_username.pwdReq": "La contraseña es obligatoria",
@@ -873,6 +926,7 @@
"navbar_dropdown.console": "Consola de Sistema",
"navbar_dropdown.create": "Crear nuevo Equipo",
"navbar_dropdown.help": "Ayuda",
+ "navbar_dropdown.integrations": "Integraciones",
"navbar_dropdown.inviteMember": "Invitar Nuevo Miembro",
"navbar_dropdown.logout": "Cerrar sesión",
"navbar_dropdown.manageMembers": "Administrar Miembros",
@@ -888,7 +942,7 @@
"password_form.title": "Restablecer Contraseña",
"password_form.update": "Tu contraseña ha sido actualizada satisfactoriamente.",
"password_send.checkInbox": "Por favor revisa tu bandeja de entrada.",
- "password_send.description": "Para restablecer tu contraseña, ingresa la dirección de correo electrónico que utilizaste para registrarte.",
+ "password_send.description": "Para reiniciar tu contraseña, ingresa la dirección de correo que utilizaste en el registro",
"password_send.email": "Correo electrónico",
"password_send.error": "Por favor ingresa una dirección correo electrónico válida.",
"password_send.link": "<p>Se ha enviado un enlace para restablecer la contraseña a <b>{email}</b></p>",
@@ -1027,6 +1081,7 @@
"signup_user_completed.validEmail": "Por favor ingresa una dirección de correo electrónico válida",
"signup_user_completed.welcome": "Bienvenido a:",
"signup_user_completed.whatis": "¿Cuál es tu dirección de correo electrónico?",
+ "signup_user_completed.withLdap": "Con tus credenciales de LDAP",
"sso_signup.find": "Encontrar mi equipo",
"sso_signup.gitlab": "Crea un equipo con una cuenta de GitLab",
"sso_signup.google": "Crea un equipo con una cuenta de Google Apps",
@@ -1247,17 +1302,22 @@
"user.settings.general.close": "Cerrar",
"user.settings.general.confirmEmail": "Confirmar Correo electrónico",
"user.settings.general.email": "Correo electrónico",
+ "user.settings.general.emailGitlabCantUpdate": "El inicio de sesión ocurre a través GitLab. El correo electrónico no puede ser actualizado. La dirección de correo electrónico utilizada para las notificaciones es {email}.",
"user.settings.general.emailHelp1": "El correo electrónico es utilizado para iniciar sesión, recibir notificaciones y para restablecer la contraseña. Si se cambia el correo electrónico deberás verificarlo nuevamente.",
"user.settings.general.emailHelp2": "El correo ha sido deshabilitado por el administrador de sistemas. No llegarán correos de notificación hasta que se vuelva a habilitar.",
"user.settings.general.emailHelp3": "El correo electrónico es utilizado para iniciar sesión, recibir notificaciones y para restablecer la contraseña.",
"user.settings.general.emailHelp4": "Un correo de verificación ha sido enviado a {email}.",
+ "user.settings.general.emailLdapCantUpdate": "El inicio de sesión ocurre a través LDAP. El correo electrónico no puede ser actualizado. La dirección de correo electrónico utilizada para las notificaciones es {email}.",
"user.settings.general.emailMatch": "El nuevo correo electrónico introducido no coincide.",
+ "user.settings.general.emptyName": "Pincha 'Editar' para agregar tu nombre completo",
+ "user.settings.general.emptyNickname": "Pincha 'Edita' para agregar un sobrenombre",
"user.settings.general.firstName": "Nombre",
"user.settings.general.fullName": "Nombre completo",
"user.settings.general.imageTooLarge": "No se puede subir la imagen del perfil. El archivo es muy grande.",
"user.settings.general.imageUpdated": "Última actualizacón de la imagen {date}",
"user.settings.general.lastName": "Apellido",
"user.settings.general.loginGitlab": "Inicio de sesión realizado a través de GitLab ({email})",
+ "user.settings.general.loginLdap": "Inicio de sesión realizado a través de LDAP ({email})",
"user.settings.general.newAddress": "Nueva dirección: {email}<br />Revisa tu correo electrónico para verificar tu nueva dirección.",
"user.settings.general.nickname": "Sobrenombre",
"user.settings.general.nicknameExtra": "Utiliza un Sobrenombre por el cual te conocen que sea diferente de tu nombre y del nombre de tu usuario. Esto se utiliza con mayor frecuencia cuando dos o más personas tienen nombres y nombres de usuario que suenan similares.",
@@ -1282,6 +1342,13 @@
"user.settings.integrations.commandsDescription": "Administra tus comandos de barra",
"user.settings.integrations.title": "Configuraciones de Integración",
"user.settings.languages.change": "Cambia el idioma con el que se muestra la intefaz de usuario",
+ "user.settings.mfa.add": "Agrega AMF a tu cuenta",
+ "user.settings.mfa.addHelp": "Para agregar autenticación de múltiples factores a tu cuenta debes tener un teléfono inteligente con Google Authenticator instalado.",
+ "user.settings.mfa.addHelpQr": "Por favor escanea el código QR con la app de Google Authenticator en tu teléfono inteligente e ingresa el token provisto por la app.",
+ "user.settings.mfa.enterToken": "Token",
+ "user.settings.mfa.qrCode": "Código QR",
+ "user.settings.mfa.remove": "Remover AMF de tu cuenta",
+ "user.settings.mfa.removeHelp": "Al remover la autenticación de múltples factores hará que tu cuenta sea vulnerable a ataques.",
"user.settings.modal.advanced": "Avanzada",
"user.settings.modal.confirmBtns": "Sí, Descartar",
"user.settings.modal.confirmMsg": "Tienes cambios sin guardar, ¿Estás seguro que los quieres descartar?",
@@ -1322,18 +1389,22 @@
"user.settings.security.emailPwd": "Correo electrónico y Contraseña",
"user.settings.security.gitlab": "GitLab SSO",
"user.settings.security.lastUpdated": "Última actualización {date} a las {time}",
+ "user.settings.security.loginGitlab": "Inicio de sesión realizado a través de Gitlab",
+ "user.settings.security.loginLdap": "Inicio de sesión realizado a través de LDAP",
"user.settings.security.logoutActiveSessions": "Visualizar y cerrar las sesiones activas",
"user.settings.security.method": "Método de inicio de sesión",
"user.settings.security.newPassword": "Nueva Contraseña",
"user.settings.security.oneSignin": "Sólo puedes tener un método de inicio de sesión a la vez. El cambio del método de inicio de sesión te enviará un correo notificandote que el cambio se realizó con éxito.",
"user.settings.security.password": "Contraseña",
+ "user.settings.security.passwordGitlabCantUpdate": "El inicio de sesión ocurre a través GitLab. La contraseña no se puede actualizar.",
+ "user.settings.security.passwordLdapCantUpdate": "El inicio de sesión ocurre a través LDAP. La contraseña no se puede actualizar.",
"user.settings.security.passwordLengthError": "La nueva contraseña debe contener al menos {chars} carácteres",
"user.settings.security.passwordMatchError": "La nueva contraseña que ingresaste no coincide",
"user.settings.security.retypePassword": "Reescribe la Nueva Contraseña",
"user.settings.security.switchEmail": "Cambiar para utilizar correo electrónico y contraseña",
"user.settings.security.switchGitlab": "Cambiar para utilizar GitLab SSO",
"user.settings.security.switchGoogle": "Cambiar para utilizar Google SSO",
- "user.settings.security.switchLda": "Cambiar a utilizar LDAP",
+ "user.settings.security.switchLdap": "Cambiar a utilizar LDAP",
"user.settings.security.title": "Configuración de Seguridad",
"user.settings.security.viewHistory": "Visualizar historial de acceso",
"user_list.notFound": "No se encontraron usuarios :(",
diff --git a/webapp/i18n/pt.json b/webapp/i18n/pt.json
index a234b696c..7525306e6 100644
--- a/webapp/i18n/pt.json
+++ b/webapp/i18n/pt.json
@@ -22,6 +22,28 @@
"activity_log_modal.android": "Android",
"activity_log_modal.androidNativeApp": "App Nativo Android",
"activity_log_modal.iphoneNativeApp": "App Nativo para iPhone",
+ "add_incoming_webhook.cancel": "Cancelar",
+ "add_incoming_webhook.channel": "Canal",
+ "add_incoming_webhook.channelRequired": "Um canal válido é necessário",
+ "add_incoming_webhook.description": "Descrição",
+ "add_incoming_webhook.header": "Adicionar Webhooks Entrada",
+ "add_incoming_webhook.name": "Nome",
+ "add_incoming_webhook.save": "Salvar",
+ "add_integration.header": "Adicionar Integração",
+ "add_integration.incomingWebhook.title": "Webhooks Entrada",
+ "add_integration.incomingWebhook.description": "Criar URLs webhook para usar em integrações externas",
+ "add_integration.outgoingWebhook.title": "Webhooks Saída",
+ "add_integration.outgoingWebhook.description": "Criar webhook para enviar novos eventos de mensagens para uma integração externa.",
+ "add_outgoing_webhook.callbackUrls": "URLs Callback (Uma Por Linha)",
+ "add_outgoing_webhook.callbackUrlsRequired": "Uma ou mais URLs callback são necessárias",
+ "add_outgoing_webhook.cancel": "Cancelar",
+ "add_outgoing_webhook.channel": "Canal",
+ "add_outgoing_webhook.description": "Descrição",
+ "add_outgoing_webhook.header": "Adicionar Webhooks Saída",
+ "add_outgoing_webhook.name": "Nome",
+ "add_outgoing_webhook.save": "Salvar",
+ "add_outgoing_webhook.triggerWOrds": "Palavras Gatilho (Uma Por Linha)",
+ "add_outgoing_webhook.triggerWordsOrChannelRequired": "Um canal válido ou uma lista de palavras gatilho é necessário",
"admin.audits.reload": "Recarregar",
"admin.audits.title": "Atividade de Usuário",
"admin.compliance.directoryDescription": "Diretório o qual os relatórios compliance são gravados, Se estiver em branco, será usado ./data/.",
@@ -306,6 +328,8 @@
"admin.select_team.close": "Fechar",
"admin.select_team.select": "Selecionar",
"admin.select_team.selectTeam": "Selecione Equipe",
+ "admin.service.mfaTitle": "Ativar Autenticação Multi-Fator:",
+ "admin.service.mfaDesc": "Quando verdadeiro, vai ser dada a opção do usuário adicionar autenticação multi-fator em sua conta. Eles irão precisar de um smartphone e um app autenticador como o Google Authenticator.",
"admin.service.attemptDescription": "Tentativas de login permitidas antes que do usuário ser bloqueado e necessário redefinir a senha por e-mail.",
"admin.service.attemptExample": "Ex \"10\"",
"admin.service.attemptTitle": "Máxima Tentativas de Login:",
@@ -550,6 +574,12 @@
"authorize.app": "O app <strong>{appName}</strong> gostaria de ter a capacidade de acessar e modificar suas informações básicas.",
"authorize.deny": "Negar",
"authorize.title": "Um aplicativo gostaria de conectar na sua conta {teamName}",
+ "backstage_navbar.backToMattermost": "Voltar para {siteName}",
+ "backstage_sidebar.integrations": "Integrações",
+ "backstage_sidebar.integrations.installed": "Integrações Instaladas",
+ "backstage_sidebar.integrations.add": "Adicionar Integração",
+ "backstage_sidebar.integrations.add.incomingWebhook": "Webhooks Entrada",
+ "backstage_sidebar.integrations.add.outgoingWebhook": "Webhooks Saída",
"center_panel.recent": "Clique aqui para pular para mensagens recentes. ",
"chanel_header.addMembers": "Adicionar Membros",
"change_url.close": "Fechar",
@@ -626,6 +656,7 @@
"channel_notifications.preferences": "Preferências de Notificação para ",
"channel_notifications.sendDesktop": "Enviar notificações de desktop",
"channel_notifications.unreadInfo": "O nome do canal fica em negrito na barra lateral quando houver mensagens não lidas. Selecionando \"Apenas menções\" o canal vai ficar em negrito apenas quando você for mencionado.",
+ "channel_select.placeholder": "--- Selecione um canal ---",
"choose_auth_page.emailCreate": "Criar uma nova equipe com endereço de email",
"choose_auth_page.find": "Encontrar minhas equipes",
"choose_auth_page.gitlabCreate": "Criar uma equipe com uma conta GitLab",
@@ -768,6 +799,16 @@
"get_team_invite_link_modal.help": "Enviar o link abaixo para sua equipe de trabalho para que eles se inscrevam no site da sua equipe. O Link de Convite de Equipe como ele não muda pode ser compartilhado com várias pessoas ao menos que seja re-gerado em Configurações de Equipe pelo Administrador de Equipe.",
"get_team_invite_link_modal.helpDisabled": "Criação de usuários está desabilitada para sua equipe. Por favor peça ao administrador de equipe por detalhes.",
"get_team_invite_link_modal.title": "Link para Convite de Equipe",
+ "installed_integrations.add": "Adicionar Integração",
+ "installed_integrations.allFilter": "Todos",
+ "installed_integrations.delete": "Deletar",
+ "installed_integrations.header": "Integrações Instaladas",
+ "installed_integrations.incomingWebhooksFilter": "Webhooks Entrada ({count})",
+ "installed_integrations.incomingWebhookType": "(Webhooks Entrada)",
+ "installed_integrations.outgoingWebhooksFilter": "Webhooks Saída ({count})",
+ "installed_integrations.outgoingWebhookType": "(Webhooks Saída)",
+ "installed_integrations.regenToken": "Regen Token",
+ "installed_integrations.search": "Pesquisar Integrações",
"intro_messages.DM": "Este é o início do seu histórico de mensagens diretas com {teammate}.<br />Mensagens diretas e arquivos compartilhados aqui não são mostrados para pessoas de fora desta área.",
"intro_messages.anyMember": " Qualquer membro pode participar e ler este canal.",
"intro_messages.beginning": "Início do {name}",
@@ -818,6 +859,10 @@
"login.session_expired": " Sua sessão expirou. Por favor faça login novamente.",
"login.signTo": "Login em:",
"login.verified": " Email Verificado",
+ "login_mfa.token": "Token MFA",
+ "login_mfa.enterToken": "Para completar o login em processo, por favor entre um token do seu autenticador no smartphone",
+ "login_mfa.submit": "Enviar",
+ "login_mfa.tokenReq": "Por favor entre um token MFA",
"login_email.badTeam": "Nome ruim de equipe",
"login_email.email": "E-mail",
"login_email.emailReq": "Um email é necessário",
@@ -873,6 +918,7 @@
"navbar_dropdown.console": "Console do Sistema",
"navbar_dropdown.create": "Criar uma Nova Equipe",
"navbar_dropdown.help": "Ajuda",
+ "navbar_dropdown.integrations": "Integrações",
"navbar_dropdown.inviteMember": "Convidar Membros da Equipe",
"navbar_dropdown.logout": "Logout",
"navbar_dropdown.manageMembers": "Gerenciar Membros",
@@ -1238,6 +1284,7 @@
"user.settings.display.theme.customTheme": "Tema Customizado",
"user.settings.display.theme.describe": "Abrir para gerenciar seu tema",
"user.settings.display.theme.import": "Importar tema de cores do Slack",
+ "user.settings.display.theme.otherThemes": "Veja outros temas",
"user.settings.display.theme.themeColors": "Tema de Cores",
"user.settings.display.theme.title": "Tema",
"user.settings.display.title": "Configurações de Exibição",
@@ -1246,17 +1293,22 @@
"user.settings.general.close": "Fechar",
"user.settings.general.confirmEmail": "Confirmar o email",
"user.settings.general.email": "E-mail",
+ "user.settings.general.emailGitlabCantUpdate": "Login ocorre através do GitLab. Email não pode ser atualizado. Endereço de email utilizado para notificações é {email}.",
+ "user.settings.general.emailLdapCantUpdate": "Login ocorre através de LDAP. Email não pode ser atualizado. Endereço de email utilizado para notificações é {email}.",
"user.settings.general.emailHelp1": "Email é usado para login, notificações, e redefinição de senha. Requer verificação de email se alterado.",
"user.settings.general.emailHelp2": "Email foi desativado pelo seu administrador de sistema. Nenhuma notificação por email será enviada até isto ser habilitado.",
"user.settings.general.emailHelp3": "Email é usado para login, notificações e redefinição de senha.",
"user.settings.general.emailHelp4": "Uma verificação por email foi enviada para {email}.",
"user.settings.general.emailMatch": "Os novos emails que você inseriu não correspondem.",
+ "user.settings.general.emptyName": "Clique 'Editar' para adicionar seu nome completo",
+ "user.settings.general.emptyNickname": "Clique 'Editar' para adicionar um apelido",
"user.settings.general.firstName": "Primeiro nome",
"user.settings.general.fullName": "Nome Completo",
"user.settings.general.imageTooLarge": "Não é possível fazer upload da imagem de perfil. O arquivo é muito grande.",
"user.settings.general.imageUpdated": "Imagem última atualização {date}",
"user.settings.general.lastName": "Último Nome",
"user.settings.general.loginGitlab": "Login feito através do GitLab ({email})",
+ "user.settings.general.loginLdap": "Login feito através de LDAP ({email})",
"user.settings.general.newAddress": "Novo Endereço: {email}<br />Verifique seu email para checar o endereço acima.",
"user.settings.general.nickname": "Apelido",
"user.settings.general.nicknameExtra": "Use Apelidos para um nome você pode ser chamado assim, isso é diferente de seu primeiro nome e nome de usuário. Este é mais frequentemente usado quando duas ou mais pessoas têm nomes semelhantes de usuário.",
@@ -1321,11 +1373,15 @@
"user.settings.security.emailPwd": "Email e Senha",
"user.settings.security.gitlab": "GitLab SSO",
"user.settings.security.lastUpdated": "Última atualização {date} {time}",
+ "user.settings.security.loginGitlab": "Login feito através do GitLab",
+ "user.settings.security.loginLdap": "Login feito através de LDAP",
"user.settings.security.logoutActiveSessions": "Ver e fazer Logout das Sessões Ativas",
"user.settings.security.method": "Método de Login",
"user.settings.security.newPassword": "Nova Senha",
"user.settings.security.oneSignin": "Você pode ter somente um método de login por vez. Trocando o método de login será enviado um email de notificação se você alterar com sucesso.",
"user.settings.security.password": "Senha",
+ "user.settings.security.passwordGitlabCantUpdate": "Login ocorreu através do GitLab. Senha não pode ser atualizada.",
+ "user.settings.security.passwordLdapCantUpdate": "Login ocorreu através de LDAP. Senha não pode ser atualizada.",
"user.settings.security.passwordLengthError": "Novas senhas precisam ter pelo menos {chars} characters",
"user.settings.security.passwordMatchError": "As novas senhas que você inseriu não correspondem",
"user.settings.security.retypePassword": "Digite Novamente a nova Senha",
@@ -1347,4 +1403,4 @@
"web.footer.terms": "Termos",
"web.header.back": "Voltar",
"web.root.singup_info": "Toda comunicação em um só lugar, pesquisável e acessível em qualquer lugar"
-}
+} \ No newline at end of file
diff --git a/webapp/stores/post_store.jsx b/webapp/stores/post_store.jsx
index 36393f5cd..3f2f75796 100644
--- a/webapp/stores/post_store.jsx
+++ b/webapp/stores/post_store.jsx
@@ -96,7 +96,7 @@ class PostStoreClass extends EventEmitter {
let post = null;
if (posts.posts.hasOwnProperty(postId)) {
- post = Object.assign({}, posts.posts[postId]);
+ post = posts.posts[postId];
}
return post;
@@ -104,7 +104,7 @@ class PostStoreClass extends EventEmitter {
getAllPosts(id) {
if (this.postsInfo.hasOwnProperty(id)) {
- return Object.assign({}, this.postsInfo[id].postList);
+ return this.postsInfo[id].postList;
}
return null;
@@ -531,8 +531,8 @@ PostStore.dispatchToken = AppDispatcher.register((payload) => {
switch (action.type) {
case ActionTypes.RECEIVED_POSTS: {
const id = PostStore.currentFocusedPostId == null ? action.id : PostStore.currentFocusedPostId;
- PostStore.checkBounds(id, action.numRequested, makePostListNonNull(action.post_list), action.before);
PostStore.storePosts(id, makePostListNonNull(action.post_list));
+ PostStore.checkBounds(id, action.numRequested, makePostListNonNull(action.post_list), action.before);
PostStore.emitChange();
break;
}
diff --git a/webapp/utils/constants.jsx b/webapp/utils/constants.jsx
index 1d6bbd8a0..72c4404c7 100644
--- a/webapp/utils/constants.jsx
+++ b/webapp/utils/constants.jsx
@@ -14,6 +14,7 @@ import patchIcon from 'images/icons/patch.png';
import genericIcon from 'images/icons/generic.png';
import logoImage from 'images/logo_compact.png';
+import logoWebhook from 'images/webhook_icon.jpg';
import solarizedDarkCSS from '!!file?name=files/code_themes/[hash].[ext]!highlight.js/styles/solarized-dark.css';
import solarizedDarkIcon from 'images/themes/code_themes/solarized-dark.png';
@@ -619,5 +620,6 @@ export default {
MAX_PASSWORD_LENGTH: 50,
TIME_SINCE_UPDATE_INTERVAL: 30000,
MIN_HASHTAG_LINK_LENGTH: 3,
- EMOJI_PATH: '/static/emoji'
+ EMOJI_PATH: '/static/emoji',
+ DEFAULT_WEBHOOK_LOGO: logoWebhook
};