[i18n] Make error messages translatable.

Make all strings passing through `json_error` and `JsonableError`
translatable.

Fixes #727
This commit is contained in:
Umair Khan
2016-05-25 18:02:02 +05:00
committed by Tim Abbott
parent 4b28fcd2f3
commit 08fbd57245
25 changed files with 251 additions and 198 deletions

View File

@@ -1,5 +1,6 @@
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.http import HttpResponseRedirect
from django.contrib.auth import REDIRECT_FIELD_NAME
from django.views.decorators.csrf import csrf_exempt
@@ -92,7 +93,7 @@ def require_realm_admin(func):
@wraps(func)
def wrapper(request, user_profile, *args, **kwargs):
if not user_profile.is_realm_admin:
raise JsonableError("Must be a realm administrator")
raise JsonableError(_("Must be a realm administrator"))
return func(request, user_profile, *args, **kwargs)
return wrapper
@@ -144,21 +145,22 @@ def validate_api_key(role, api_key):
try:
profile = get_deployment_or_userprofile(role)
except UserProfile.DoesNotExist:
raise JsonableError("Invalid user: %s" % (role,))
raise JsonableError(_("Invalid user: %s") % (role,))
except Deployment.DoesNotExist:
raise JsonableError("Invalid deployment: %s" % (role,))
raise JsonableError(_("Invalid deployment: %s") % (role,))
if api_key != profile.api_key:
if len(api_key) != 32:
reason = "Incorrect API key length (keys should be 32 characters long)"
reason = _("Incorrect API key length (keys should be 32 "
"characters long) for role '%s'")
else:
reason = "Invalid API key"
raise JsonableError(reason + " for role '%s'" % (role,))
reason = _("Invalid API key for role '%s'")
raise JsonableError(reason % (role,))
if not profile.is_active:
raise JsonableError("Account not active")
raise JsonableError(_("Account not active"))
try:
if profile.realm.deactivated:
raise JsonableError("Realm for account has been deactivated")
raise JsonableError(_("Realm for account has been deactivated"))
except AttributeError:
# Deployment objects don't have realms
pass
@@ -176,11 +178,11 @@ def api_key_only_webhook_view(client_name):
try:
user_profile = UserProfile.objects.get(api_key=api_key)
except UserProfile.DoesNotExist:
raise JsonableError("Invalid API key")
raise JsonableError(_("Invalid API key"))
if not user_profile.is_active:
raise JsonableError("Account not active")
raise JsonableError(_("Account not active"))
if user_profile.realm.deactivated:
raise JsonableError("Realm for account has been deactivated")
raise JsonableError(_("Realm for account has been deactivated"))
request.user = user_profile
request._email = user_profile.email
@@ -309,10 +311,10 @@ def authenticated_rest_api_view(view_func):
auth_type, encoded_value = request.META['HTTP_AUTHORIZATION'].split()
# case insensitive per RFC 1945
if auth_type.lower() != "basic":
return json_error("Only Basic authentication is supported.")
return json_error(_("Only Basic authentication is supported."))
role, api_key = base64.b64decode(encoded_value).split(":")
except ValueError:
return json_error("Invalid authorization header for basic auth")
return json_error(_("Invalid authorization header for basic auth"))
except KeyError:
return json_unauthorized("Missing authorization header for basic auth")
@@ -361,12 +363,12 @@ def process_as_post(view_func):
def authenticate_log_and_execute_json(request, view_func, *args, **kwargs):
if not request.user.is_authenticated():
return json_error("Not logged in", status=401)
return json_error(_("Not logged in"), status=401)
user_profile = request.user
if not user_profile.is_active:
raise JsonableError("Account not active")
raise JsonableError(_("Account not active"))
if user_profile.realm.deactivated:
raise JsonableError("Realm for account has been deactivated")
raise JsonableError(_("Realm for account has been deactivated"))
process_client(request, user_profile, True)
request._email = user_profile.email
return view_func(request, user_profile, *args, **kwargs)
@@ -403,7 +405,7 @@ def internal_notify_view(view_func):
@wraps(view_func)
def _wrapped_view_func(request, *args, **kwargs):
if not authenticate_notify(request):
return json_error('Access denied', status=403)
return json_error(_('Access denied'), status=403)
if not hasattr(request, '_tornado_handler'):
# We got called through the non-Tornado server somehow.
# This is not a security check; it's an internal assertion

View File

@@ -5,6 +5,7 @@ from typing import (
Optional, Sequence, Tuple, TypeVar, Union
)
from django.utils.translation import ugettext as _
from django.conf import settings
from django.core import validators
from django.contrib.sessions.models import Session
@@ -775,16 +776,16 @@ def recipient_for_emails(emails, not_forged_mirror_message,
try:
user_profile = get_user_profile_by_email(email)
except UserProfile.DoesNotExist:
raise ValidationError("Invalid email '%s'" % (email,))
raise ValidationError(_("Invalid email '%s'") % (email,))
if (not user_profile.is_active and not user_profile.is_mirror_dummy) or \
user_profile.realm.deactivated:
raise ValidationError("'%s' is no longer using Zulip." % (email,))
raise ValidationError(_("'%s' is no longer using Zulip.") % (email,))
recipient_profile_ids.add(user_profile.id)
normalized_emails.add(user_profile.email)
realm_domains.add(user_profile.realm.domain)
if not_forged_mirror_message and user_profile.id not in recipient_profile_ids:
raise ValidationError("User not authorized for this query")
raise ValidationError(_("User not authorized for this query"))
# Prevent cross realm private messages unless it is between only two realms
# and one of users is a zuliper
@@ -794,9 +795,9 @@ def recipient_for_emails(emails, not_forged_mirror_message,
admin_realm_admin_emails = {u.email for u in admin_realm.get_admin_users()}
# We allow settings.CROSS_REALM_BOT_EMAILS for the hardcoded emails for the feedback and notification bots
if not (normalized_emails & admin_realm_admin_emails or normalized_emails & settings.CROSS_REALM_BOT_EMAILS):
raise ValidationError("You can't send private messages outside of your organization.")
raise ValidationError(_("You can't send private messages outside of your organization."))
if len(realm_domains) > 2:
raise ValidationError("You can't send private messages outside of your organization.")
raise ValidationError(_("You can't send private messages outside of your organization."))
# If the private message is just between the sender and
# another person, force it to be a personal internally
@@ -867,11 +868,11 @@ def check_send_message(*args, **kwargs):
def check_stream_name(stream_name):
# type: (text_type) -> None
if stream_name == "":
raise JsonableError("Stream can't be empty")
raise JsonableError(_("Stream can't be empty"))
if len(stream_name) > Stream.MAX_NAME_LENGTH:
raise JsonableError("Stream name too long")
raise JsonableError(_("Stream name too long"))
if not valid_stream_name(stream_name):
raise JsonableError("Invalid stream name")
raise JsonableError(_("Invalid stream name"))
def send_pm_if_empty_stream(sender, stream, stream_name):
# type: (UserProfile, Stream, text_type) -> None
@@ -927,9 +928,9 @@ def check_message(sender, client, message_type_name, message_to,
# Use the users default stream
message_to = [sender.default_sending_stream.name]
elif len(message_to) == 0:
raise JsonableError("Message must have recipients")
raise JsonableError(_("Message must have recipients"))
if len(message_content.strip()) == 0:
raise JsonableError("Message must not be empty")
raise JsonableError(_("Message must not be empty"))
message_content = truncate_body(message_content)
if realm is None:
@@ -937,27 +938,27 @@ def check_message(sender, client, message_type_name, message_to,
if message_type_name == 'stream':
if len(message_to) > 1:
raise JsonableError("Cannot send to multiple streams")
raise JsonableError(_("Cannot send to multiple streams"))
stream_name = message_to[0].strip()
check_stream_name(stream_name)
if subject_name is None:
raise JsonableError("Missing topic")
raise JsonableError(_("Missing topic"))
subject = subject_name.strip()
if subject == "":
raise JsonableError("Topic can't be empty")
raise JsonableError(_("Topic can't be empty"))
subject = truncate_topic(subject)
## FIXME: Commented out temporarily while we figure out what we want
# if not valid_stream_name(subject):
# return json_error("Invalid subject name")
# return json_error(_("Invalid subject name"))
stream = get_stream(stream_name, realm)
send_pm_if_empty_stream(sender, stream, stream_name)
if stream is None:
raise JsonableError("Stream does not exist")
raise JsonableError(_("Stream does not exist"))
recipient = get_recipient(Recipient.STREAM, stream.id)
if not stream.invite_only:
@@ -975,7 +976,7 @@ def check_message(sender, client, message_type_name, message_to,
pass
else:
# All other cases are an error.
raise JsonableError("Not authorized to send to stream '%s'" % (stream.name,))
raise JsonableError(_("Not authorized to send to stream '%s'") % (stream.name,))
elif message_type_name == 'private':
mirror_message = client and client.name in ["zephyr_mirror", "irc_mirror", "jabber_mirror", "JabberMirror"]
@@ -987,7 +988,7 @@ def check_message(sender, client, message_type_name, message_to,
assert isinstance(e.messages[0], six.string_types)
raise JsonableError(e.messages[0])
else:
raise JsonableError("Invalid message type")
raise JsonableError(_("Invalid message type"))
message = Message()
message.sender = sender
@@ -1003,7 +1004,7 @@ def check_message(sender, client, message_type_name, message_to,
message.sending_client = client
if not message.maybe_render_content(realm.domain):
raise JsonableError("Unable to render message")
raise JsonableError(_("Unable to render message"))
if client.name == "zephyr_mirror":
id = already_sent_mirrored_message_id(message)
@@ -1110,11 +1111,11 @@ def validate_user_access_to_subscribers_helper(user_profile, stream_dict, check_
raise ValidationError("Requesting user not on given realm")
if stream_dict["realm__domain"] == "mit.edu" and not stream_dict["invite_only"]:
raise JsonableError("You cannot get subscribers for public streams in this realm")
raise JsonableError(_("You cannot get subscribers for public streams in this realm"))
if (user_profile is not None and stream_dict["invite_only"] and
not check_user_subscribed()):
raise JsonableError("Unable to retrieve subscribers for invite-only stream")
raise JsonableError(_("Unable to retrieve subscribers for invite-only stream"))
# sub_dict is a dictionary mapping stream_id => whether the user is subscribed to that stream
def bulk_get_subscriber_user_ids(stream_dicts, user_profile, sub_dict):
@@ -1642,7 +1643,7 @@ def _default_stream_permision_check(user_profile, stream):
else:
user = user_profile
if stream.invite_only and not subscribed_to_stream(user, stream):
raise JsonableError('Insufficient permission')
raise JsonableError(_('Insufficient permission'))
def do_change_default_sending_stream(user_profile, stream, log=True):
# type: (UserProfile, Stream, bool) -> None
@@ -1729,10 +1730,10 @@ def do_make_stream_public(user_profile, realm, stream_name):
stream = get_stream(stream_name, realm)
if not stream:
raise JsonableError('Unknown stream "%s"' % (stream_name,))
raise JsonableError(_('Unknown stream "%s"') % (stream_name,))
if not subscribed_to_stream(user_profile, stream):
raise JsonableError('You are not invited to this stream.')
raise JsonableError(_('You are not invited to this stream.'))
stream.invite_only = False
stream.save(update_fields=['invite_only'])
@@ -1743,7 +1744,7 @@ def do_make_stream_private(realm, stream_name):
stream = get_stream(stream_name, realm)
if not stream:
raise JsonableError('Unknown stream "%s"' % (stream_name,))
raise JsonableError(_('Unknown stream "%s"') % (stream_name,))
stream.invite_only = True
stream.save(update_fields=['invite_only'])
@@ -1756,13 +1757,13 @@ def do_rename_stream(realm, old_name, new_name, log=True):
stream = get_stream(old_name, realm)
if not stream:
raise JsonableError('Unknown stream "%s"' % (old_name,))
raise JsonableError(_('Unknown stream "%s"') % (old_name,))
# Will raise if there's an issue.
check_stream_name(new_name)
if get_stream(new_name, realm) and old_name.lower() != new_name.lower():
raise JsonableError('Stream name "%s" is already taken' % (new_name,))
raise JsonableError(_('Stream name "%s" is already taken') % (new_name,))
old_name = stream.name
stream.name = new_name
@@ -2029,7 +2030,7 @@ def do_remove_default_stream(realm, stream_name):
# type: (Realm, text_type) -> None
stream = get_stream(stream_name, realm)
if stream is None:
raise JsonableError("Stream does not exist")
raise JsonableError(_("Stream does not exist"))
DefaultStream.objects.filter(realm=realm, stream=stream).delete()
def get_default_streams_for_realm(realm):
@@ -2210,20 +2211,20 @@ def do_update_message_flags(user_profile, operation, flag, messages, all, stream
# Hack to let you star any message
if msgs.count() == 0:
if not len(messages) == 1:
raise JsonableError("Invalid message(s)")
raise JsonableError(_("Invalid message(s)"))
if flag != "starred":
raise JsonableError("Invalid message(s)")
raise JsonableError(_("Invalid message(s)"))
# Check that the user could have read the relevant message
try:
message = Message.objects.get(id=messages[0])
except Message.DoesNotExist:
raise JsonableError("Invalid message(s)")
raise JsonableError(_("Invalid message(s)"))
recipient = Recipient.objects.get(id=message.recipient_id)
if recipient.type != Recipient.STREAM:
raise JsonableError("Invalid message(s)")
raise JsonableError(_("Invalid message(s)"))
stream = Stream.objects.select_related("realm").get(id=recipient.type_id)
if not stream.is_public():
raise JsonableError("Invalid message(s)")
raise JsonableError(_("Invalid message(s)"))
# OK, this is a message that you legitimately have access
# to via narrowing to the stream it is on, even though you
@@ -2322,7 +2323,7 @@ def do_update_message(user_profile, message_id, subject, propagate_mode, content
try:
message = Message.objects.select_related().get(id=message_id)
except Message.DoesNotExist:
raise JsonableError("Unknown message id")
raise JsonableError(_("Unknown message id"))
event = {'type': 'update_message',
'sender': user_profile.email,
@@ -2340,7 +2341,7 @@ def do_update_message(user_profile, message_id, subject, propagate_mode, content
user_profile.is_realm_admin):
pass
else:
raise JsonableError("You don't have permission to edit this message")
raise JsonableError(_("You don't have permission to edit this message"))
# Set first_rendered_content to be the oldest version of the
# rendered content recorded; which is the current version if the
@@ -2363,7 +2364,7 @@ def do_update_message(user_profile, message_id, subject, propagate_mode, content
rendered_content = message.render_markdown(content)
if not rendered_content:
raise JsonableError("We were unable to render your updated message")
raise JsonableError(_("We were unable to render your updated message"))
update_user_message_flags(message, ums)
@@ -2386,7 +2387,7 @@ def do_update_message(user_profile, message_id, subject, propagate_mode, content
orig_subject = message.subject
subject = subject.strip()
if subject == "":
raise JsonableError("Topic can't be empty")
raise JsonableError(_("Topic can't be empty"))
subject = truncate_topic(subject)
event["orig_subject"] = orig_subject
event["propagate_mode"] = propagate_mode
@@ -2851,7 +2852,7 @@ def do_events_register(user_profile, user_client, apply_markdown=True,
narrow=narrow)
if queue_id is None:
raise JsonableError("Could not allocate event queue")
raise JsonableError(_("Could not allocate event queue"))
if event_types is not None:
event_types_set = set(event_types) # type: Optional[Set[str]]
else:
@@ -2988,11 +2989,11 @@ def do_invite_users(user_profile, invitee_emails, streams):
try:
validators.validate_email(email)
except ValidationError:
errors.append((email, "Invalid address."))
errors.append((email, _("Invalid address.")))
continue
if not email_allowed_for_realm(email, user_profile.realm):
errors.append((email, "Outside your domain."))
errors.append((email, _("Outside your domain.")))
continue
try:
@@ -3007,7 +3008,7 @@ def do_invite_users(user_profile, invitee_emails, streams):
# Other users should not already exist at all.
user_email_is_unique(email)
except ValidationError:
skipped.append((email, "Already has an account."))
skipped.append((email, _("Already has an account.")))
continue
# The logged in user is the referrer.
@@ -3022,12 +3023,12 @@ def do_invite_users(user_profile, invitee_emails, streams):
new_prereg_users.append(prereg_user)
if errors:
ret_error = "Some emails did not validate, so we didn't send any invitations."
ret_error = _("Some emails did not validate, so we didn't send any invitations.")
ret_error_data = {'errors': errors}
if skipped and len(skipped) == len(invitee_emails):
# All e-mails were skipped, so we didn't actually invite anyone.
ret_error = "We weren't able to invite anyone."
ret_error = _("We weren't able to invite anyone.")
ret_error_data = {'errors': skipped}
return ret_error, ret_error_data
@@ -3039,8 +3040,9 @@ def do_invite_users(user_profile, invitee_emails, streams):
lambda event: do_send_confirmation_email(user, user_profile))
if skipped:
ret_error = "Some of those addresses are already using Zulip, \
so we didn't send them an invitation. We did send invitations to everyone else!"
ret_error = _("Some of those addresses are already using Zulip, "
"so we didn't send them an invitation. We did send "
"invitations to everyone else!")
ret_error_data = {'errors': skipped}
return ret_error, ret_error_data
@@ -3163,7 +3165,7 @@ def do_get_streams(user_profile, include_public=True, include_subscribed=True,
include_all_active=False):
# type: (UserProfile, bool, bool, bool) -> List[Dict[str, Any]]
if include_all_active and not user_profile.is_api_super_user:
raise JsonableError("User not authorized for this query")
raise JsonableError(_("User not authorized for this query"))
# Listing public streams are disabled for the mit.edu realm.
include_public = include_public and user_profile.realm.domain != "mit.edu"

View File

@@ -1,6 +1,7 @@
from __future__ import absolute_import
from typing import Any
from django.utils.translation import ugettext as _
from django.conf import settings
from django.utils.timezone import now
from collections import deque
@@ -470,15 +471,15 @@ def fetch_events(query):
client = allocate_client_descriptor(new_queue_data)
queue_id = client.event_queue.id
else:
raise JsonableError("Missing 'queue_id' argument")
raise JsonableError(_("Missing 'queue_id' argument"))
else:
if last_event_id is None:
raise JsonableError("Missing 'last_event_id' argument")
raise JsonableError(_("Missing 'last_event_id' argument"))
client = get_client_descriptor(queue_id)
if client is None:
raise JsonableError("Bad event queue id: %s" % (queue_id,))
raise JsonableError(_("Bad event queue id: %s") % (queue_id,))
if user_profile_id != client.user_profile_id:
raise JsonableError("You are not authorized to get events from this queue")
raise JsonableError(_("You are not authorized to get events from this queue"))
client.event_queue.prune(last_event_id)
was_connected = client.finish_current_handler()

View File

@@ -1,10 +1,12 @@
from zerver.lib.request import JsonableError
from django.utils.translation import ugettext as _
def check_supported_events_narrow_filter(narrow):
for element in narrow:
operator = element[0]
if operator not in ["stream", "topic", "sender", "is"]:
raise JsonableError("Operator %s not supported." % (operator,))
raise JsonableError(_("Operator %s not supported.") % (operator,))
def build_narrow_filter(narrow):
check_supported_events_narrow_filter(narrow)

View File

@@ -3,6 +3,8 @@ from functools import wraps
import ujson
from six.moves import zip
from django.utils.translation import ugettext as _
class JsonableError(Exception):
def __init__(self, error, status_code=400):
self.error = error
@@ -20,7 +22,7 @@ class RequestVariableMissingError(JsonableError):
self.status_code = status_code
def to_json_error_msg(self):
return "Missing '%s' argument" % (self.var_name,)
return _("Missing '%s' argument") % (self.var_name,)
class RequestVariableConversionError(JsonableError):
def __init__(self, var_name, bad_value, status_code=400):
@@ -29,7 +31,8 @@ class RequestVariableConversionError(JsonableError):
self.status_code = status_code
def to_json_error_msg(self):
return "Bad value for '%s': %s" % (self.var_name, self.bad_value)
return (_("Bad value for '%(var_name)s': %(value)s") %
{'var_name': self.var_name, 'value': self.bad_value})
# Used in conjunction with @has_request_variables, below
class REQ(object):
@@ -69,7 +72,7 @@ class REQ(object):
self.argument_type = argument_type
if converter and validator:
raise Exception('converter and validator are mutually exclusive')
raise Exception(_('converter and validator are mutually exclusive'))
# Extracts variables from the request object and passes them as
# named function arguments. The request object must be the first
@@ -117,12 +120,12 @@ def has_request_variables(view_func):
try:
val = ujson.loads(request.body)
except ValueError:
raise JsonableError('Malformed JSON')
raise JsonableError(_('Malformed JSON'))
kwargs[param.func_var_name] = val
continue
elif param.argument_type is not None:
# This is a view bug, not a user error, and thus should throw a 500.
raise Exception("Invalid argument type")
raise Exception(_("Invalid argument type"))
default_assigned = False
try:
@@ -146,7 +149,7 @@ def has_request_variables(view_func):
try:
val = ujson.loads(val)
except:
raise JsonableError('argument "%s" is not valid json.' % (param.post_var_name,))
raise JsonableError(_('argument "%s" is not valid json.') % (param.post_var_name,))
error = param.validator(param.post_var_name, val)
if error:

View File

@@ -1,5 +1,6 @@
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.conf import settings
from django.template.defaultfilters import slugify
from django.utils.encoding import force_text
@@ -254,7 +255,7 @@ def claim_attachment(path_id, message):
attachment.save()
return True
except Attachment.DoesNotExist:
raise JsonableError("The upload was not successful. Please reupload the file again in a new message.")
raise JsonableError(_("The upload was not successful. Please reupload the file again in a new message."))
return False
def create_attachment(file_name, path_id, user_profile):

View File

@@ -26,21 +26,22 @@ To extend this concept, it's simply a matter of writing your own validator
for any particular type of object.
'''
from __future__ import absolute_import
from django.utils.translation import ugettext as _
import six
def check_string(var_name, val):
if not isinstance(val, six.string_types):
return '%s is not a string' % (var_name,)
return _('%s is not a string') % (var_name,)
return None
def check_int(var_name, val):
if not isinstance(val, int):
return '%s is not an integer' % (var_name,)
return _('%s is not an integer') % (var_name,)
return None
def check_bool(var_name, val):
if not isinstance(val, bool):
return '%s is not a boolean' % (var_name,)
return _('%s is not a boolean') % (var_name,)
return None
def check_none_or(sub_validator):
@@ -54,10 +55,11 @@ def check_none_or(sub_validator):
def check_list(sub_validator, length=None):
def f(var_name, val):
if not isinstance(val, list):
return '%s is not a list' % (var_name,)
return _('%s is not a list') % (var_name,)
if length is not None and length != len(val):
return '%s should have exactly %d items' % (var_name, length)
return (_('%(container)s should have exactly %(length)s items') %
{'container': var_name, 'length': length})
if sub_validator:
for i, item in enumerate(val):
@@ -75,11 +77,12 @@ def check_dict(required_keys):
def f(var_name, val):
if not isinstance(val, dict):
return '%s is not a dict' % (var_name,)
return _('%s is not a dict') % (var_name,)
for k, sub_validator in required_keys:
if k not in val:
return '%s key is missing from %s' % (k, var_name)
return (_('%(key_name)s key is missing from %(var_name)s') %
{'key_name': k, 'var_name': var_name})
vname = '%s["%s"]' % (var_name, k)
error = sub_validator(vname, val[k])
if error:
@@ -101,12 +104,15 @@ def check_variable_type(allowed_type_funcs):
for func in allowed_type_funcs:
if not func(var_name, val):
return None
return '%s is not an allowed_type' % (var_name,)
return _('%s is not an allowed_type') % (var_name,)
return enumerated_type_check
def equals(expected_val):
def f(var_name, val):
if val != expected_val:
return '%s != %r (%r is wrong)' % (var_name, expected_val, val)
return (_('%(variable)s != %(expected_value)s (%(value)s is wrong)') %
{'variable': var_name,
'expected_value': expected_val,
'value': val})
return None
return f

View File

@@ -1,6 +1,8 @@
from __future__ import absolute_import
from django.conf import settings
from django.utils.translation import ugettext as _
from zerver.lib.response import json_error
from django.db import connection
from zerver.lib.utils import statsd
@@ -264,7 +266,7 @@ class JsonErrorHandler(object):
return json_error(exception.to_json_error_msg(), status=status_code)
if request.error_format == "JSON":
logging.error(traceback.format_exc())
return json_error("Internal server error", status=500)
return json_error(_("Internal server error"), status=500)
return None
class TagRequests(object):
@@ -278,7 +280,7 @@ class TagRequests(object):
def csrf_failure(request, reason=""):
if request.error_format == "JSON":
return json_error("CSRF Error: %s" % (reason,), status=403)
return json_error(_("CSRF Error: %s") % (reason,), status=403)
else:
return html_csrf_failure(request, reason)
@@ -299,7 +301,7 @@ class RateLimitMiddleware(object):
def process_exception(self, request, exception):
if isinstance(exception, RateLimited):
resp = json_error("API usage exceeded rate limit, try again in %s secs" % (request._ratelimit_secs_to_freedom,), status=429)
resp = json_error(_("API usage exceeded rate limit, try again in %s secs") % (request._ratelimit_secs_to_freedom,), status=429)
resp['Retry-After'] = request._ratelimit_secs_to_freedom
return resp

View File

@@ -1,5 +1,6 @@
# -*- coding: utf-8 -*-
from django.test import TestCase
from django.utils.translation import ugettext as _
from zerver.lib.actions import do_deactivate_realm, do_deactivate_user, \
do_reactivate_user
@@ -25,7 +26,7 @@ class DecoratorTestCase(TestCase):
if not isinstance(lst, list):
raise ValueError('not a list')
if 13 in lst:
raise JsonableError('13 is an unlucky number!')
raise JsonableError(_('13 is an unlucky number!'))
return lst
@has_request_variables

View File

@@ -1,5 +1,6 @@
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.views.decorators.csrf import csrf_exempt
from zerver.models import get_client
@@ -30,9 +31,9 @@ def notify(request):
def cleanup_event_queue(request, user_profile, queue_id=REQ()):
client = get_client_descriptor(queue_id)
if client is None:
return json_error("Bad event queue id: %s" % (queue_id,))
return json_error(_("Bad event queue id: %s") % (queue_id,))
if user_profile.id != client.user_profile_id:
return json_error("You are not authorized to access this queue")
return json_error(_("You are not authorized to access this queue"))
request._log_data['extra'] = "[%s]" % (queue_id,)
client.cleanup()
return json_success()

View File

@@ -1,6 +1,7 @@
from __future__ import absolute_import
from typing import Any
from django.utils.translation import ugettext as _
from django.conf import settings
from django.contrib.auth import authenticate, login, get_backends
from django.core.urlresolvers import reverse
@@ -267,9 +268,9 @@ from zerver.lib.ccache import make_ccache
def webathena_kerberos_login(request, user_profile,
cred=REQ(default=None)):
if cred is None:
return json_error("Could not find Kerberos credential")
return json_error(_("Could not find Kerberos credential"))
if not user_profile.realm.domain == "mit.edu":
return json_error("Webathena login only for mit.edu realm")
return json_error(_("Webathena login only for mit.edu realm"))
try:
parsed_cred = ujson.loads(cred)
@@ -281,7 +282,7 @@ def webathena_kerberos_login(request, user_profile,
assert(user == user_profile.email.split("@")[0])
ccache = make_ccache(parsed_cred)
except Exception:
return json_error("Invalid Kerberos cache")
return json_error(_("Invalid Kerberos cache"))
# TODO: Send these data via (say) rabbitmq
try:
@@ -292,7 +293,7 @@ def webathena_kerberos_login(request, user_profile,
base64.b64encode(ccache)])
except Exception:
logging.exception("Error updating the user's ccache")
return json_error("We were unable to setup mirroring for you")
return json_error(_("We were unable to setup mirroring for you"))
return json_success()
@@ -324,13 +325,13 @@ def api_endpoint_docs(request):
@has_request_variables
def json_invite_users(request, user_profile, invitee_emails=REQ()):
if not invitee_emails:
return json_error("You must specify at least one email address.")
return json_error(_("You must specify at least one email address."))
invitee_emails = set(re.split(r'[, \n]', invitee_emails))
stream_names = request.POST.getlist('stream')
if not stream_names:
return json_error("You must specify at least one stream for invitees to join.")
return json_error(_("You must specify at least one stream for invitees to join."))
# We unconditionally sub you to the notifications stream if it
# exists and is public.
@@ -342,7 +343,7 @@ def json_invite_users(request, user_profile, invitee_emails=REQ()):
for stream_name in stream_names:
stream = get_stream(stream_name, user_profile.realm)
if stream is None:
return json_error("Stream does not exist: %s. No invites were sent." % (stream_name,))
return json_error(_("Stream does not exist: %s. No invites were sent.") % (stream_name,))
streams.append(stream)
ret_error, error_data = do_invite_users(user_profile, invitee_emails, streams)
@@ -403,7 +404,7 @@ def remote_user_sso(request):
try:
remote_user = request.META["REMOTE_USER"]
except KeyError:
raise JsonableError("No REMOTE_USER set.")
raise JsonableError(_("No REMOTE_USER set."))
user_profile = authenticate(remote_user=remote_user)
return login_or_register_remote_user(request, remote_user, user_profile)
@@ -414,16 +415,16 @@ def remote_user_jwt(request):
json_web_token = request.POST["json_web_token"]
payload, signing_input, header, signature = jwt.load(json_web_token)
except KeyError:
raise JsonableError("No JSON web token passed in request")
raise JsonableError(_("No JSON web token passed in request"))
except jwt.DecodeError:
raise JsonableError("Bad JSON web token")
raise JsonableError(_("Bad JSON web token"))
remote_user = payload.get("user", None)
if remote_user is None:
raise JsonableError("No user specified in JSON web token claims")
raise JsonableError(_("No user specified in JSON web token claims"))
domain = payload.get('realm', None)
if domain is None:
raise JsonableError("No domain specified in JSON web token claims")
raise JsonableError(_("No domain specified in JSON web token claims"))
email = "%s@%s" % (remote_user, domain)
@@ -435,9 +436,9 @@ def remote_user_jwt(request):
# that the request.backend attribute gets set.
user_profile = authenticate(username=email, use_dummy_backend=True)
except (jwt.DecodeError, jwt.ExpiredSignature):
raise JsonableError("Bad JSON web token signature")
raise JsonableError(_("Bad JSON web token signature"))
except KeyError:
raise JsonableError("Realm not authorized for JWT login")
raise JsonableError(_("Realm not authorized for JWT login"))
except UserProfile.DoesNotExist:
user_profile = None
@@ -918,7 +919,7 @@ def update_pointer_backend(request, user_profile,
message__id=pointer
)
except UserMessage.DoesNotExist:
raise JsonableError("Invalid message ID")
raise JsonableError(_("Invalid message ID"))
request._log_data["extra"] = "[%s]" % (pointer,)
update_flags = (request.client.name.lower() in ['android', "zulipandroid"])
@@ -935,7 +936,7 @@ def generate_client_id():
def export(request, user_profile):
if (Message.objects.filter(sender__realm=user_profile.realm).count() > 1000000 or
UserMessage.objects.filter(user_profile__realm=user_profile.realm).count() > 3000000):
return json_error("Realm has too much data for non-batched export.")
return json_error(_("Realm has too much data for non-batched export."))
response = {}
@@ -1039,13 +1040,13 @@ def update_realm(request, user_profile, name=REQ(validator=check_string, default
@has_request_variables
def json_upload_file(request, user_profile):
if len(request.FILES) == 0:
return json_error("You must specify a file to upload")
return json_error(_("You must specify a file to upload"))
if len(request.FILES) != 1:
return json_error("You may only upload one file at a time")
return json_error(_("You may only upload one file at a time"))
user_file = list(request.FILES.values())[0]
if ((settings.MAX_FILE_UPLOAD_SIZE * 1024 * 1024) < user_file._get_size()):
return json_error("File Upload is larger than allowed limit")
return json_error(_("File Upload is larger than allowed limit"))
uri = upload_message_image_through_web_client(request, user_file, user_profile)
return json_success({'uri': uri})
@@ -1064,7 +1065,7 @@ def get_uploaded_file(request, realm_id, filename,
realm_id = get_realm_for_filename(url_path)
if realm_id is None:
# File does not exist
return json_error("That file does not exist.", status=404)
return json_error(_("That file does not exist."), status=404)
# Internal users can access all uploads so we can receive attachments in cross-realm messages
if user_profile.realm.id == int(realm_id) or user_profile.realm.domain == 'zulip.com':
@@ -1087,29 +1088,29 @@ def api_fetch_api_key(request, username=REQ(), password=REQ()):
else:
user_profile = authenticate(username=username, password=password, return_data=return_data)
if return_data.get("inactive_user") == True:
return json_error("Your account has been disabled.", data={"reason": "user disable"}, status=403)
return json_error(_("Your account has been disabled."), data={"reason": "user disable"}, status=403)
if return_data.get("inactive_realm") == True:
return json_error("Your realm has been deactivated.", data={"reason": "realm deactivated"}, status=403)
return json_error(_("Your realm has been deactivated."), data={"reason": "realm deactivated"}, status=403)
if return_data.get("password_auth_disabled") == True:
return json_error("Password auth is disabled in your team.", data={"reason": "password auth disabled"}, status=403)
return json_error(_("Password auth is disabled in your team."), data={"reason": "password auth disabled"}, status=403)
if user_profile is None:
if return_data.get("valid_attestation") == True:
# We can leak that the user is unregistered iff they present a valid authentication string for the user.
return json_error("This user is not registered; do so from a browser.", data={"reason": "unregistered"}, status=403)
return json_error("Your username or password is incorrect.", data={"reason": "incorrect_creds"}, status=403)
return json_error(_("This user is not registered; do so from a browser."), data={"reason": "unregistered"}, status=403)
return json_error(_("Your username or password is incorrect."), data={"reason": "incorrect_creds"}, status=403)
return json_success({"api_key": user_profile.api_key, "email": user_profile.email})
@authenticated_json_post_view
@has_request_variables
def json_fetch_api_key(request, user_profile, password=REQ(default='')):
if password_auth_enabled(user_profile.realm) and not user_profile.check_password(password):
return json_error("Your username or password is incorrect.")
return json_error(_("Your username or password is incorrect."))
return json_success({"api_key": user_profile.api_key})
@csrf_exempt
def api_fetch_google_client_id(request):
if not settings.GOOGLE_CLIENT_ID:
return json_error("GOOGLE_CLIENT_ID is not configured", status=400)
return json_error(_("GOOGLE_CLIENT_ID is not configured"), status=400)
return json_success({"google_client_id": settings.GOOGLE_CLIENT_ID})
def get_status_list(requesting_user_profile):
@@ -1121,7 +1122,7 @@ def update_active_status_backend(request, user_profile, status=REQ(),
new_user_input=REQ(validator=check_bool, default=False)):
status_val = UserPresence.status_from_string(status)
if status_val is None:
raise JsonableError("Invalid presence status: %s" % (status,))
raise JsonableError(_("Invalid presence status: %s") % (status,))
else:
update_user_presence(user_profile, request.client, now(), status_val,
new_user_input)
@@ -1186,9 +1187,9 @@ def events_register_backend(request, user_profile, apply_markdown=True,
@has_request_variables
def json_refer_friend(request, user_profile, email=REQ()):
if not email:
return json_error("No email address specified")
return json_error(_("No email address specified"))
if user_profile.invites_granted - user_profile.invites_used <= 0:
return json_error("Insufficient invites")
return json_error(_("Insufficient invites"))
do_refer_friend(user_profile, email);
@@ -1203,7 +1204,7 @@ def json_set_muted_topics(request, user_profile,
def add_push_device_token(request, user_profile, token, kind, ios_app_id=None):
if token == '' or len(token) > 4096:
return json_error('Empty or invalid length token')
return json_error(_('Empty or invalid length token'))
# If another user was previously logged in on the same device and didn't
# properly log out, the token will still be registered to the wrong account
@@ -1230,13 +1231,13 @@ def add_android_reg_id(request, user_profile, token=REQ()):
def remove_push_device_token(request, user_profile, token, kind):
if token == '' or len(token) > 4096:
return json_error('Empty or invalid length token')
return json_error(_('Empty or invalid length token'))
try:
token = PushDeviceToken.objects.get(token=token, kind=kind)
token.delete()
except PushDeviceToken.DoesNotExist:
return json_error("Token does not exist")
return json_error(_("Token does not exist"))
return json_success()

View File

@@ -1,5 +1,6 @@
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.conf import settings
from django.core import validators
from django.core.exceptions import ValidationError
@@ -81,7 +82,7 @@ class BadNarrowOperator(JsonableError):
self.status_code = status_code
def to_json_error_msg(self):
return 'Invalid narrow operator: ' + self.desc
return _('Invalid narrow operator: {}').format(self.desc)
# When you add a new operator to this, also update zerver/lib/narrow.py
class NarrowBuilder(object):
@@ -352,7 +353,7 @@ def narrow_parameter(json):
def is_public_stream(stream, realm):
if not valid_stream_name(stream):
raise JsonableError("Invalid stream name")
raise JsonableError(_("Invalid stream name"))
stream = get_stream(stream, realm)
if stream is None:
return False
@@ -615,14 +616,14 @@ def update_message_flags(request, user_profile,
if stream_name is not None:
stream = get_stream(stream_name, user_profile.realm)
if not stream:
raise JsonableError('No such stream \'%s\'' % (stream_name,))
raise JsonableError(_('No such stream \'%s\'') % (stream_name,))
if topic_name:
topic_exists = UserMessage.objects.filter(user_profile=user_profile,
message__recipient__type_id=stream.id,
message__recipient__type=Recipient.STREAM,
message__subject__iexact=topic_name).exists()
if not topic_exists:
raise JsonableError('No such topic \'%s\'' % (topic_name,))
raise JsonableError(_('No such topic \'%s\'') % (topic_name,))
do_update_message_flags(user_profile, operation, flag, messages, all, stream, topic_name)
return json_success({'result': 'success',
'messages': messages,
@@ -726,17 +727,17 @@ def send_message_backend(request, user_profile,
client = request.client
is_super_user = request.user.is_api_super_user
if forged and not is_super_user:
return json_error("User not authorized for this query")
return json_error(_("User not authorized for this query"))
realm = None
if domain and domain != user_profile.realm.domain:
if not is_super_user:
# The email gateway bot needs to be able to send messages in
# any realm.
return json_error("User not authorized for this query")
return json_error(_("User not authorized for this query"))
realm = get_realm(domain)
if not realm:
return json_error("Unknown domain " + domain)
return json_error(_("Unknown domain %s") % (domain,))
if client.name in ["zephyr_mirror", "irc_mirror", "jabber_mirror", "JabberMirror"]:
# Here's how security works for mirroring:
@@ -756,18 +757,18 @@ def send_message_backend(request, user_profile,
# same-realm constraint) and recipient_for_emails (which
# checks that PMs are received by the forwarding user)
if "sender" not in request.POST:
return json_error("Missing sender")
return json_error(_("Missing sender"))
if message_type_name != "private" and not is_super_user:
return json_error("User not authorized for this query")
return json_error(_("User not authorized for this query"))
(valid_input, mirror_sender) = \
create_mirrored_message_users(request, user_profile, message_to)
if not valid_input:
return json_error("Invalid mirrored message")
return json_error(_("Invalid mirrored message"))
if client.name == "zephyr_mirror" and user_profile.realm.domain != "mit.edu":
return json_error("Invalid mirrored realm")
return json_error(_("Invalid mirrored realm"))
if (client.name == "irc_mirror" and message_type_name != "private" and
not message_to[0].startswith("#")):
return json_error("IRC stream names must start with #")
return json_error(_("IRC stream names must start with #"))
sender = mirror_sender
else:
sender = user_profile
@@ -790,7 +791,7 @@ def update_message_backend(request, user_profile,
propagate_mode=REQ(default="change_one"),
content=REQ(default=None)):
if subject is None and content is None:
return json_error("Nothing to change")
return json_error(_("Nothing to change"))
do_update_message(user_profile, message_id, subject, propagate_mode, content)
return json_success()
@@ -801,10 +802,10 @@ def json_fetch_raw_message(request, user_profile,
try:
message = Message.objects.get(id=message_id)
except Message.DoesNotExist:
return json_error("No such message")
return json_error(_("No such message"))
if message.sender != user_profile:
return json_error("Message was not sent by you")
return json_error(_("Message was not sent by you"))
return json_success({"raw_content": message.content})

View File

@@ -1,6 +1,7 @@
from __future__ import absolute_import
from typing import Any, Optional
from django.utils.translation import ugettext as _
from django.conf import settings
from django.db import transaction
from django.http import HttpRequest, HttpResponse
@@ -56,9 +57,9 @@ def list_to_streams(streams_raw, user_profile, autocreate=False, invite_only=Fal
rejects = []
for stream_name in stream_set:
if len(stream_name) > Stream.MAX_NAME_LENGTH:
raise JsonableError("Stream name (%s) too long." % (stream_name,))
raise JsonableError(_("Stream name (%s) too long.") % (stream_name,))
if not valid_stream_name(stream_name):
raise JsonableError("Invalid stream name (%s)." % (stream_name,))
raise JsonableError(_("Invalid stream name (%s).") % (stream_name,))
existing_stream_map = bulk_get_streams(user_profile.realm, stream_set)
@@ -70,9 +71,9 @@ def list_to_streams(streams_raw, user_profile, autocreate=False, invite_only=Fal
existing_streams.append(stream)
if rejects:
if not user_profile.can_create_streams():
raise JsonableError('User cannot create streams.')
raise JsonableError(_('User cannot create streams.'))
elif not autocreate:
raise JsonableError("Stream(s) (%s) do not exist" % ", ".join(rejects))
raise JsonableError(_("Stream(s) (%s) do not exist") % ", ".join(rejects))
for stream_name in rejects:
stream, created = create_stream_if_needed(user_profile.realm,
@@ -115,10 +116,10 @@ def principal_to_user_profile(agent, principal):
def deactivate_stream_backend(request, user_profile, stream_name):
target = get_stream(stream_name, user_profile.realm)
if not target:
return json_error('No such stream name')
return json_error(_('No such stream name'))
if target.invite_only and not subscribed_to_stream(user_profile, target):
return json_error('Cannot administer invite-only streams this way')
return json_error(_('Cannot administer invite-only streams this way'))
do_deactivate_stream(target)
return json_success({})
@@ -174,7 +175,7 @@ def update_subscriptions_backend(request, user_profile,
delete=REQ(validator=check_list(check_string), default=[]),
add=REQ(validator=check_list(check_dict([['name', check_string]])), default=[])):
if not add and not delete:
return json_error('Nothing to do. Specify at least one of "add" or "delete".')
return json_error(_('Nothing to do. Specify at least one of "add" or "delete".'))
json_dict = {} # type: Dict[str, Any]
for method, items in ((add_subscriptions_backend, add), (remove_subscriptions_backend, delete)):
@@ -199,16 +200,16 @@ def remove_subscriptions_backend(request, user_profile,
if removing_someone_else and not user_profile.is_realm_admin:
# You can only unsubscribe other people from a stream if you are a realm
# admin.
return json_error("This action requires administrative rights")
return json_error(_("This action requires administrative rights"))
streams, _ = list_to_streams(streams_raw, user_profile)
streams, __ = list_to_streams(streams_raw, user_profile)
for stream in streams:
if removing_someone_else and stream.invite_only and \
not subscribed_to_stream(user_profile, stream):
# Even as an admin, you can't remove other people from an
# invite-only stream you're not on.
return json_error("Cannot administer invite-only streams this way")
return json_error(_("Cannot administer invite-only streams this way"))
if principals:
people_to_unsub = set(principal_to_user_profile(
@@ -271,9 +272,9 @@ def add_subscriptions_backend(request, user_profile,
for stream in streams_raw:
stream_name = stream["name"].strip()
if len(stream_name) > Stream.MAX_NAME_LENGTH:
return json_error("Stream name (%s) too long." % (stream_name,))
return json_error(_("Stream name (%s) too long.") % (stream_name,))
if not valid_stream_name(stream_name):
return json_error("Invalid stream name (%s)." % (stream_name,))
return json_error(_("Invalid stream name (%s).") % (stream_name,))
stream_names.append(stream_name)
# Enforcement of can_create_streams policy is inside list_to_streams.
@@ -282,13 +283,13 @@ def add_subscriptions_backend(request, user_profile,
authorized_streams, unauthorized_streams = \
filter_stream_authorization(user_profile, existing_streams)
if len(unauthorized_streams) > 0 and authorization_errors_fatal:
return json_error("Unable to access stream (%s)." % unauthorized_streams[0].name)
return json_error(_("Unable to access stream (%s).") % unauthorized_streams[0].name)
# Newly created streams are also authorized for the creator
streams = authorized_streams + created_streams
if principals is not None:
if user_profile.realm.domain == 'mit.edu' and not all(stream.invite_only for stream in streams):
return json_error("You can only invite other mit.edu users to invite-only streams.")
return json_error(_("You can only invite other mit.edu users to invite-only streams."))
subscribers = set(principal_to_user_profile(user_profile, principal) for principal in principals)
else:
subscribers = set([user_profile])
@@ -380,7 +381,7 @@ def add_subscriptions_backend(request, user_profile,
def get_subscribers_backend(request, user_profile, stream_name=REQ('stream')):
stream = get_stream(stream_name, user_profile.realm)
if stream is None:
raise JsonableError("Stream does not exist: %s" % (stream_name,))
raise JsonableError(_("Stream does not exist: %s") % (stream_name,))
subscribers = get_subscriber_emails(stream, user_profile)
@@ -410,7 +411,7 @@ def json_stream_exists(request, user_profile, stream=REQ(),
def stream_exists_backend(request, user_profile, stream_name, autosubscribe):
if not valid_stream_name(stream_name):
return json_error("Invalid characters in stream name")
return json_error(_("Invalid characters in stream name"))
stream = get_stream(stream_name, user_profile.realm)
result = {"exists": bool(stream)}
if stream is not None:
@@ -426,13 +427,13 @@ def stream_exists_backend(request, user_profile, stream_name, autosubscribe):
def get_subscription_or_die(stream_name, user_profile):
stream = get_stream(stream_name, user_profile.realm)
if not stream:
raise JsonableError("Invalid stream %s" % (stream.name,))
raise JsonableError(_("Invalid stream %s") % (stream.name,))
recipient = get_recipient(Recipient.STREAM, stream.id)
subscription = Subscription.objects.filter(user_profile=user_profile,
recipient=recipient, active=True)
if not subscription.exists():
raise JsonableError("Not subscribed to stream %s" % (stream_name,))
raise JsonableError(_("Not subscribed to stream %s") % (stream_name,))
return subscription
@@ -455,7 +456,7 @@ def json_subscription_property(request, user_profile, subscription_data=REQ(
{"stream": "devel", "property": "color", "value": "#c2c2c2"}]
"""
if request.method != "POST":
return json_error("Invalid verb")
return json_error(_("Invalid verb"))
property_converters = {"color": check_string, "in_home_view": check_bool,
"desktop_notifications": check_bool,
@@ -468,7 +469,7 @@ def json_subscription_property(request, user_profile, subscription_data=REQ(
value = change["value"]
if property not in property_converters:
return json_error("Unknown subscription property: %s" % (property,))
return json_error(_("Unknown subscription property: %s") % (property,))
sub = get_subscription_or_die(stream_name, user_profile)[0]

View File

@@ -1,5 +1,6 @@
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.views.decorators.csrf import csrf_exempt
from zerver.decorator import authenticated_json_post_view, has_request_variables, REQ
@@ -28,7 +29,7 @@ def json_tutorial_send_message(request, user_profile, type=REQ(validator=check_s
realm=user_profile.realm)
return json_success()
# For now, there are no PM cases.
return json_error('Bad data passed in to tutorial_send_message')
return json_error(_('Bad data passed in to tutorial_send_message'))
@authenticated_json_post_view
@has_request_variables

View File

@@ -1,5 +1,6 @@
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.conf import settings
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth import authenticate
@@ -56,9 +57,9 @@ def json_change_settings(request, user_profile,
confirm_password=REQ(default="")):
if new_password != "" or confirm_password != "":
if new_password != confirm_password:
return json_error("New password must match confirmation password!")
return json_error(_("New password must match confirmation password!"))
if not authenticate(username=user_profile.email, password=old_password):
return json_error("Wrong password!")
return json_error(_("Wrong password!"))
do_change_password(user_profile, new_password)
result = {}
@@ -70,7 +71,7 @@ def json_change_settings(request, user_profile,
else:
new_full_name = full_name.strip()
if len(new_full_name) > UserProfile.MAX_NAME_LENGTH:
return json_error("Name too long!")
return json_error(_("Name too long!"))
do_change_full_name(user_profile, new_full_name)
result['full_name'] = new_full_name
@@ -165,7 +166,7 @@ def json_change_notify_settings(request, user_profile,
@authenticated_json_post_view
def json_set_avatar(request, user_profile):
if len(request.FILES) != 1:
return json_error("You must upload exactly one avatar.")
return json_error(_("You must upload exactly one avatar."))
user_file = list(request.FILES.values())[0]
upload_avatar_image(user_file, user_profile, user_profile.email)

View File

@@ -1,5 +1,6 @@
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.shortcuts import redirect
from django.views.decorators.csrf import csrf_exempt
from six.moves import map
@@ -25,23 +26,23 @@ def deactivate_user_backend(request, user_profile, email):
try:
target = get_user_profile_by_email(email)
except UserProfile.DoesNotExist:
return json_error('No such user')
return json_error(_('No such user'))
if target.is_bot:
return json_error('No such user')
return json_error(_('No such user'))
return _deactivate_user_profile_backend(request, user_profile, target)
def deactivate_bot_backend(request, user_profile, email):
try:
target = get_user_profile_by_email(email)
except UserProfile.DoesNotExist:
return json_error('No such bot')
return json_error(_('No such bot'))
if not target.is_bot:
return json_error('No such bot')
return json_error(_('No such bot'))
return _deactivate_user_profile_backend(request, user_profile, target)
def _deactivate_user_profile_backend(request, user_profile, target):
if not user_profile.can_admin_user(target):
return json_error('Insufficient permission')
return json_error(_('Insufficient permission'))
do_deactivate_user(target)
return json_success({})
@@ -50,10 +51,10 @@ def reactivate_user_backend(request, user_profile, email):
try:
target = get_user_profile_by_email(email)
except UserProfile.DoesNotExist:
return json_error('No such user')
return json_error(_('No such user'))
if not user_profile.can_admin_user(target):
return json_error('Insufficient permission')
return json_error(_('Insufficient permission'))
do_reactivate_user(target)
return json_success({})
@@ -64,10 +65,10 @@ def update_user_backend(request, user_profile, email,
try:
target = get_user_profile_by_email(email)
except UserProfile.DoesNotExist:
return json_error('No such user')
return json_error(_('No such user'))
if not user_profile.can_admin_user(target):
return json_error('Insufficient permission')
return json_error(_('Insufficient permission'))
if is_admin is not None:
do_change_is_admin(target, is_admin)
@@ -100,7 +101,7 @@ def stream_or_none(stream_name, realm):
else:
stream = get_stream(stream_name, realm)
if not stream:
raise JsonableError('No such stream \'%s\'' % (stream_name,))
raise JsonableError(_('No such stream \'%s\'') % (stream_name,))
return stream
@has_request_variables
@@ -112,10 +113,10 @@ def patch_bot_backend(request, user_profile, email,
try:
bot = get_user_profile_by_email(email)
except:
return json_error('No such user')
return json_error(_('No such user'))
if not user_profile.can_admin_user(bot):
return json_error('Insufficient permission')
return json_error(_('Insufficient permission'))
if full_name is not None:
do_change_full_name(bot, full_name)
@@ -136,7 +137,7 @@ def patch_bot_backend(request, user_profile, email,
avatar_source = UserProfile.AVATAR_FROM_USER
do_change_avatar_source(bot, avatar_source)
else:
return json_error("You may only upload one file at a time")
return json_error(_("You may only upload one file at a time"))
json_result = dict(
full_name=bot.full_name,
@@ -152,10 +153,10 @@ def regenerate_bot_api_key(request, user_profile, email):
try:
bot = get_user_profile_by_email(email)
except:
return json_error('No such user')
return json_error(_('No such user'))
if not user_profile.can_admin_user(bot):
return json_error('Insufficient permission')
return json_error(_('Insufficient permission'))
do_regenerate_api_key(bot)
json_result = dict(
@@ -173,18 +174,18 @@ def add_bot_backend(request, user_profile, full_name=REQ(), short_name=REQ(),
form = CreateUserForm({'full_name': full_name, 'email': email})
if not form.is_valid():
# We validate client-side as well
return json_error('Bad name or username')
return json_error(_('Bad name or username'))
try:
get_user_profile_by_email(email)
return json_error("Username already in use")
return json_error(_("Username already in use"))
except UserProfile.DoesNotExist:
pass
if len(request.FILES) == 0:
avatar_source = UserProfile.AVATAR_FROM_GRAVATAR
elif len(request.FILES) != 1:
return json_error("You may only upload one file at a time")
return json_error(_("You may only upload one file at a time"))
else:
user_file = list(request.FILES.values())[0]
upload_avatar_image(user_file, user_profile, email)
@@ -194,14 +195,14 @@ def add_bot_backend(request, user_profile, full_name=REQ(), short_name=REQ(),
default_sending_stream = stream_or_none(default_sending_stream, user_profile.realm)
if default_sending_stream and not default_sending_stream.is_public() and not \
subscribed_to_stream(user_profile, default_sending_stream):
return json_error('Insufficient permission')
return json_error(_('Insufficient permission'))
if default_events_register_stream is not None:
default_events_register_stream = stream_or_none(default_events_register_stream,
user_profile.realm)
if default_events_register_stream and not default_events_register_stream.is_public() and not \
subscribed_to_stream(user_profile, default_events_register_stream):
return json_error('Insufficient permission')
return json_error(_('Insufficient permission'))
bot_profile = do_create_user(email=email, password='',
@@ -270,18 +271,19 @@ def create_user_backend(request, user_profile, email=REQ(), password=REQ(),
full_name=REQ(), short_name=REQ()):
form = CreateUserForm({'full_name': full_name, 'email': email})
if not form.is_valid():
return json_error('Bad name or username')
return json_error(_('Bad name or username'))
# Check that the new user's email address belongs to the admin's realm
# (Since this is an admin API, we don't require the user to have been
# invited first.)
realm = user_profile.realm
if not email_allowed_for_realm(email, user_profile.realm):
return json_error("Email '%s' does not belong to domain '%s'" % (email, realm.domain))
return json_error(_("Email '%(email)s' does not belong to domain '%(domain)s'") %
{'email': email, 'domain': realm.domain})
try:
get_user_profile_by_email(email)
return json_error("Email '%s' already in use" % (email,))
return json_error(_("Email '%s' already in use") % (email,))
except UserProfile.DoesNotExist:
pass

View File

@@ -1,5 +1,8 @@
# Webhooks for external integrations.
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
@@ -27,7 +30,7 @@ def api_codeship_webhook(request, user_profile, client, payload=REQ(argument_typ
subject = get_subject_for_http_request(payload)
body = get_body_for_http_request(payload)
except KeyError as e:
return json_error("Missing key {} in JSON".format(e.message))
return json_error(_("Missing key {} in JSON").format(e.message))
check_send_message(user_profile, client, 'stream', [stream], subject, body)
return json_success()

View File

@@ -1,5 +1,8 @@
# Webhooks for external integrations.
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from zerver.models import get_client
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
@@ -106,7 +109,7 @@ def api_freshdesk_webhook(request, user_profile, payload=REQ(argument_type='body
if ticket_data.get(key) is None:
logging.warning("Freshdesk webhook error. Payload was:")
logging.warning(request.body)
return json_error("Missing key %s in JSON" % (key,))
return json_error(_("Missing key %s in JSON") % (key,))
ticket = TicketDict(ticket_data)
@@ -115,7 +118,7 @@ def api_freshdesk_webhook(request, user_profile, payload=REQ(argument_type='body
try:
event_info = parse_freshdesk_event(ticket.triggered_event)
except ValueError:
return json_error("Malformed event %s" % (ticket.triggered_event,))
return json_error(_("Malformed event %s") % (ticket.triggered_event,))
if event_info[1] == "created":
content = format_freshdesk_ticket_creation_message(ticket)

View File

@@ -1,5 +1,7 @@
# Webhooks for external integrations.
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.db.models import Q
from django.conf import settings
@@ -167,7 +169,7 @@ def api_jira_webhook(request, user_profile, client,
logging.warning("Got JIRA event with None event type: %s" % (payload,))
else:
logging.warning("Got JIRA event type we don't understand: %s" % (event,))
return json_error("Unknown JIRA event type")
return json_error(_("Unknown JIRA event type"))
check_send_message(user_profile, client, "stream",
[stream], subject, content)

View File

@@ -1,5 +1,8 @@
# Webhooks for external integrations.
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
from zerver.lib.validator import check_dict
@@ -24,7 +27,7 @@ def api_newrelic_webhook(request, user_profile, client, stream=REQ(),
%(changelog)s""" % (deployment)
else:
return json_error("Unknown webhook request")
return json_error(_("Unknown webhook request"))
check_send_message(user_profile, client, "stream",
[stream], subject, content)

View File

@@ -1,5 +1,8 @@
# Webhooks for external integrations.
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
@@ -35,7 +38,7 @@ def api_pingdom_webhook(request, user_profile, client, payload=REQ(argument_type
subject = get_subject_for_http_request(payload)
body = get_body_for_http_request(payload)
else:
return json_error('Unsupported check_type: {check_type}'.format(check_type=check_type))
return json_error(_('Unsupported check_type: {check_type}').format(check_type=check_type))
check_send_message(user_profile, client, 'stream', [stream], subject, body)
return json_success()

View File

@@ -1,5 +1,8 @@
# Webhooks for external integrations.
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
from zerver.decorator import api_key_only_webhook_view, REQ, has_request_variables
@@ -153,16 +156,16 @@ def api_pivotal_webhook(request, user_profile, client, stream=REQ()):
try:
subject, content = api_pivotal_webhook_v3(request, user_profile, stream)
except AttributeError:
return json_error("Failed to extract data from Pivotal XML response")
return json_error(_("Failed to extract data from Pivotal XML response"))
except:
# Attempt to parse v5 JSON payload
try:
subject, content = api_pivotal_webhook_v5(request, user_profile, stream)
except AttributeError:
return json_error("Failed to extract data from Pivotal V5 JSON response")
return json_error(_("Failed to extract data from Pivotal V5 JSON response"))
if subject is None or content is None:
return json_error("Unable to handle Pivotal payload")
return json_error(_("Unable to handle Pivotal payload"))
check_send_message(user_profile, client, "stream",
[stream], subject, content)

View File

@@ -1,5 +1,8 @@
# Webhooks for external integrations.
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from zerver.models import get_client
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
@@ -23,7 +26,7 @@ def api_stash_webhook(request, user_profile, payload=REQ(argument_type='body'),
entry in commit_entries]
head_ref = commit_entries[-1]["toCommit"]["displayId"]
except KeyError as e:
return json_error("Missing key %s in JSON" % (e.message,))
return json_error(_("Missing key %s in JSON") % (e.message,))
subject = "%s/%s: %s" % (project_name, repo_name, branch_name)

View File

@@ -19,6 +19,9 @@ subject of US/task should be in bold.
"""
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from zerver.lib.actions import check_send_message
from zerver.lib.response import json_success, json_error
from zerver.decorator import REQ, has_request_variables, api_key_only_webhook_view
@@ -239,4 +242,4 @@ def generate_content(data):
try:
return templates[data['type']][data['event']] % data['values']
except KeyError:
return json_error("Unknown message")
return json_error(_("Unknown message"))

View File

@@ -1,4 +1,6 @@
from __future__ import absolute_import
from django.utils.translation import ugettext as _
from django.http import HttpResponse
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.views import login as django_login_page
@@ -83,7 +85,7 @@ def report_error(request, deployment, type=REQ(), report=REQ(validator=check_dic
elif type == 'server':
notify_server_error(report)
else:
return json_error("Invalid type parameter")
return json_error(_("Invalid type parameter"))
return json_success()
def realm_for_email(email):
@@ -102,7 +104,7 @@ def lookup_endpoints_for_user(request, email=REQ()):
try:
return json_response(realm_for_email(email).deployment.endpoints)
except AttributeError:
return json_error("Cannot determine endpoint for user.", status=404)
return json_error(_("Cannot determine endpoint for user."), status=404)
def account_deployment_dispatch(request, **kwargs):
sso_unknown_email = False