python: Convert percent formatting to .format for translated strings.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2020-06-15 14:22:24 -07:00 committed by Tim Abbott
parent eda396376c
commit f364d06fb5
37 changed files with 212 additions and 163 deletions

View File

@ -243,7 +243,7 @@ def get_chart_data(request: HttpRequest, user_profile: UserProfile, chart_name:
labels_sort_function = None
include_empty_subgroups = True
else:
raise JsonableError(_("Unknown chart name: %s") % (chart_name,))
raise JsonableError(_("Unknown chart name: {}").format(chart_name))
# Most likely someone using our API endpoint. The /stats page does not
# pass a start or end in its requests.
@ -252,8 +252,9 @@ def get_chart_data(request: HttpRequest, user_profile: UserProfile, chart_name:
if end is not None:
end = convert_to_UTC(end)
if start is not None and end is not None and start > end:
raise JsonableError(_("Start time is later than end time. Start: %(start)s, End: %(end)s") %
{'start': start, 'end': end})
raise JsonableError(_("Start time is later than end time. Start: {start}, End: {end}").format(
start=start, end=end,
))
if realm is None:
# Note that this value is invalid for Remote tables; be

View File

@ -135,7 +135,9 @@ def renewal_amount(plan: CustomerPlan, event_time: datetime) -> int: # nocovera
class BillingError(Exception):
# error messages
CONTACT_SUPPORT = _("Something went wrong. Please contact %s.") % (settings.ZULIP_ADMINISTRATOR,)
CONTACT_SUPPORT = _("Something went wrong. Please contact {email}.").format(
email=settings.ZULIP_ADMINISTRATOR,
)
TRY_RELOADING = _("Something went wrong. Please reload the page.")
# description is used only for tests

View File

@ -1,6 +1,6 @@
import logging
from decimal import Decimal
from typing import Any, Dict, Optional, Union, cast
from typing import Any, Dict, Optional, Union
import stripe
from django.conf import settings
@ -85,14 +85,17 @@ def payment_method_string(stripe_customer: stripe.Customer) -> str:
if stripe_source is None: # nocoverage
return _("No payment method on file")
if stripe_source.object == "card":
return _("%(brand)s ending in %(last4)s") % {
'brand': cast(stripe.Card, stripe_source).brand,
'last4': cast(stripe.Card, stripe_source).last4}
assert isinstance(stripe_source, stripe.Card)
return _("{brand} ending in {last4}").format(
brand=stripe_source.brand, last4=stripe_source.last4,
)
# There might be one-off stuff we do for a particular customer that
# would land them here. E.g. by default we don't support ACH for
# automatic payments, but in theory we could add it for a customer via
# the Stripe dashboard.
return _("Unknown payment method. Please contact %s.") % (settings.ZULIP_ADMINISTRATOR,) # nocoverage
return _("Unknown payment method. Please contact {email}.").format(
email=settings.ZULIP_ADMINISTRATOR,
) # nocoverage
@has_request_variables
def upgrade(request: HttpRequest, user: UserProfile,

View File

@ -171,7 +171,7 @@ SPLIT_BOUNDARY_REGEX = re.compile(fr'[{SPLIT_BOUNDARY}]')
# Regexes which check capitalization in sentences.
DISALLOWED_REGEXES = [re.compile(regex) for regex in [
r'^[a-z]', # Checks if the sentence starts with a lower case character.
r'^[a-z](?!\})', # Checks if the sentence starts with a lower case character.
r'^[A-Z][a-z]+[\sa-z0-9]+[A-Z]', # Checks if an upper case character exists
# after a lower case character when the first character is in upper case.
]]

View File

@ -81,6 +81,14 @@ rules:
severity: ERROR
message: "Do not write a SQL injection vulnerability please"
- id: translated-format
languages: [python]
pattern-either:
- pattern: django.utils.translation.ugettext(... .format(...))
- pattern: django.utils.translation.ugettext(f"...")
severity: ERROR
message: "Format strings after translation, not before"
- id: mutable-default-type
languages: [python]
pattern-either:
@ -122,5 +130,6 @@ rules:
pattern-either:
- pattern: '"..." % ...'
- pattern: '("...") % ...'
- pattern: django.utils.translation.ugettext(...) % ...
severity: ERROR
message: "Prefer f-strings or .format for string formatting"

View File

@ -1948,7 +1948,7 @@ def validate_recipient_user_profiles(user_profiles: Sequence[UserProfile],
for user_profile in user_profiles:
if (not user_profile.is_active and not user_profile.is_mirror_dummy and
not allow_deactivated) or user_profile.realm.deactivated:
raise ValidationError(_("'%s' is no longer using Zulip.") % (user_profile.email,))
raise ValidationError(_("'{email}' is no longer using Zulip.").format(email=user_profile.email))
recipient_profiles_map[user_profile.id] = user_profile
if not is_cross_realm_bot_email(user_profile.email):
realms.add(user_profile.realm_id)
@ -2132,14 +2132,16 @@ def check_schedule_message(sender: UserProfile, client: Client,
def check_default_stream_group_name(group_name: str) -> None:
if group_name.strip() == "":
raise JsonableError(_("Invalid default stream group name '%s'") % (group_name,))
raise JsonableError(_("Invalid default stream group name '{}'").format(group_name))
if len(group_name) > DefaultStreamGroup.MAX_NAME_LENGTH:
raise JsonableError(_("Default stream group name too long (limit: %s characters)")
% (DefaultStreamGroup.MAX_NAME_LENGTH,))
raise JsonableError(_("Default stream group name too long (limit: {} characters)").format(
DefaultStreamGroup.MAX_NAME_LENGTH,
))
for i in group_name:
if ord(i) == 0:
raise JsonableError(_("Default stream group name '%s' contains NULL (0x00) characters.")
% (group_name,))
raise JsonableError(_("Default stream group name '{}' contains NULL (0x00) characters.").format(
group_name,
))
def send_rate_limited_pm_notification_to_bot_owner(sender: UserProfile,
realm: Realm,
@ -2194,19 +2196,19 @@ def send_pm_if_empty_stream(stream: Optional[Stream],
}
if stream is None:
if stream_id is not None:
content = _("Your bot `%(bot_identity)s` tried to send a message to stream ID "
"%(stream_id)s, but there is no stream with that ID.") % arg_dict
content = _("Your bot `{bot_identity}` tried to send a message to stream ID "
"{stream_id}, but there is no stream with that ID.").format(**arg_dict)
else:
assert(stream_name is not None)
content = _("Your bot `%(bot_identity)s` tried to send a message to stream "
"#**%(stream_name)s**, but that stream does not exist. "
"Click [here](#streams/new) to create it.") % arg_dict
content = _("Your bot `{bot_identity}` tried to send a message to stream "
"#**{stream_name}**, but that stream does not exist. "
"Click [here](#streams/new) to create it.").format(**arg_dict)
else:
if num_subscribers_for_stream_id(stream.id) > 0:
return
content = _("Your bot `%(bot_identity)s` tried to send a message to "
"stream #**%(stream_name)s**. The stream exists but "
"does not have any subscribers.") % arg_dict
content = _("Your bot `{bot_identity}` tried to send a message to "
"stream #**{stream_name}**. The stream exists but "
"does not have any subscribers.").format(**arg_dict)
send_rate_limited_pm_notification_to_bot_owner(sender, realm, content)
@ -2349,7 +2351,9 @@ def check_message(sender: UserProfile, client: Client, addressee: Addressee,
error_msg = check_widget_content(widget_content)
if error_msg:
raise JsonableError(_('Widgets: %s') % (error_msg,))
raise JsonableError(_('Widgets: {error_msg}').format(
error_msg=error_msg,
))
return {'message': message, 'stream': stream, 'local_id': local_id,
'sender_queue_id': sender_queue_id, 'realm': realm,
@ -3583,12 +3587,13 @@ def do_rename_stream(stream: Stream,
sender,
stream,
Realm.STREAM_EVENTS_NOTIFICATION_TOPIC,
_('@_**%(user_name)s|%(user_id)d** renamed stream **%(old_stream_name)s** to '
'**%(new_stream_name)s**.') % {
'user_name': user_profile.full_name,
'user_id': user_profile.id,
'old_stream_name': old_name,
'new_stream_name': new_name},
_('@_**{user_name}|{user_id}** renamed stream **{old_stream_name}** to '
'**{new_stream_name}**.').format(
user_name=user_profile.full_name,
user_id=user_profile.id,
old_stream_name=old_name,
new_stream_name=new_name,
),
)
# Even though the token doesn't change, the web client needs to update the
# email forwarding address to display the correctly-escaped new name.
@ -3734,7 +3739,7 @@ def lookup_default_stream_groups(default_stream_group_names: List[str],
default_stream_group = DefaultStreamGroup.objects.get(
name=group_name, realm=realm)
except DefaultStreamGroup.DoesNotExist:
raise JsonableError(_('Invalid default stream group %s') % (group_name,))
raise JsonableError(_('Invalid default stream group {}').format(group_name))
default_stream_groups.append(default_stream_group)
return default_stream_groups
@ -3771,15 +3776,16 @@ def do_create_default_stream_group(realm: Realm, group_name: str,
for stream in streams:
if stream in default_streams:
raise JsonableError(_(
"'%(stream_name)s' is a default stream and cannot be added to '%(group_name)s'")
% {'stream_name': stream.name, 'group_name': group_name})
"'{stream_name}' is a default stream and cannot be added to '{group_name}'",
).format(stream_name=stream.name, group_name=group_name))
check_default_stream_group_name(group_name)
(group, created) = DefaultStreamGroup.objects.get_or_create(
name=group_name, realm=realm, description=description)
if not created:
raise JsonableError(_("Default stream group '%(group_name)s' already exists")
% {'group_name': group_name})
raise JsonableError(_(
"Default stream group '{group_name}' already exists",
).format(group_name=group_name))
group.streams.set(streams)
notify_default_stream_groups(realm)
@ -3790,12 +3796,12 @@ def do_add_streams_to_default_stream_group(realm: Realm, group: DefaultStreamGro
for stream in streams:
if stream in default_streams:
raise JsonableError(_(
"'%(stream_name)s' is a default stream and cannot be added to '%(group_name)s'")
% {'stream_name': stream.name, 'group_name': group.name})
"'{stream_name}' is a default stream and cannot be added to '{group_name}'",
).format(stream_name=stream.name, group_name=group.name))
if stream in group.streams.all():
raise JsonableError(_(
"Stream '%(stream_name)s' is already present in default stream group '%(group_name)s'")
% {'stream_name': stream.name, 'group_name': group.name})
"Stream '{stream_name}' is already present in default stream group '{group_name}'",
).format(stream_name=stream.name, group_name=group.name))
group.streams.add(stream)
group.save()
@ -3806,8 +3812,8 @@ def do_remove_streams_from_default_stream_group(realm: Realm, group: DefaultStre
for stream in streams:
if stream not in group.streams.all():
raise JsonableError(_(
"Stream '%(stream_name)s' is not present in default stream group '%(group_name)s'")
% {'stream_name': stream.name, 'group_name': group.name})
"Stream '{stream_name}' is not present in default stream group '{group_name}'",
).format(stream_name=stream.name, group_name=group.name))
group.streams.remove(stream)
group.save()
@ -3816,10 +3822,10 @@ def do_remove_streams_from_default_stream_group(realm: Realm, group: DefaultStre
def do_change_default_stream_group_name(realm: Realm, group: DefaultStreamGroup,
new_group_name: str) -> None:
if group.name == new_group_name:
raise JsonableError(_("This default stream group is already named '%s'") % (new_group_name,))
raise JsonableError(_("This default stream group is already named '{}'").format(new_group_name))
if DefaultStreamGroup.objects.filter(name=new_group_name, realm=realm).exists():
raise JsonableError(_("Default stream group '%s' already exists") % (new_group_name,))
raise JsonableError(_("Default stream group '{}' already exists").format(new_group_name))
group.name = new_group_name
group.save()
@ -4172,9 +4178,9 @@ def do_update_message_flags(user_profile: UserProfile,
valid_flags = [item for item in UserMessage.flags
if item not in UserMessage.NON_API_FLAGS]
if flag not in valid_flags:
raise JsonableError(_("Invalid flag: '%s'") % (flag,))
raise JsonableError(_("Invalid flag: '{}'").format(flag))
if flag in UserMessage.NON_EDITABLE_FLAGS:
raise JsonableError(_("Flag not editable: '%s'") % (flag,))
raise JsonableError(_("Flag not editable: '{}'").format(flag))
flagattr = getattr(UserMessage.flags, flag)
msgs = UserMessage.objects.filter(user_profile=user_profile,
@ -4250,15 +4256,19 @@ def notify_topic_moved_streams(user_profile: UserProfile,
if send_notification_to_new_thread:
internal_send_stream_message(
new_stream.realm, sender, new_stream, new_topic,
_("This topic was moved here from %(old_location)s by %(user)s")
% dict(old_location=old_topic_link, user=user_mention))
_("This topic was moved here from {old_location} by {user}").format(
old_location=old_topic_link, user=user_mention,
),
)
if send_notification_to_old_thread:
# Send a notification to the old stream that the topic was moved.
internal_send_stream_message(
old_stream.realm, sender, old_stream, old_topic,
_("This topic was moved by %(user)s to %(new_location)s")
% dict(user=user_mention, new_location=new_topic_link))
_("This topic was moved by {user} to {new_location}").format(
user=user_mention, new_location=new_topic_link,
),
)
def get_user_info_for_message_updates(message_id: int) -> MessageUpdateUserInfoResult:
@ -4992,8 +5002,8 @@ def estimate_recent_invites(realms: Iterable[Realm], *, days: int) -> int:
def check_invite_limit(realm: Realm, num_invitees: int) -> None:
'''Discourage using invitation emails as a vector for carrying spam.'''
msg = _("You do not have enough remaining invites. "
"Please contact %s to have your limit raised. "
"No invitations were sent.") % (settings.ZULIP_ADMINISTRATOR,)
"Please contact {email} to have your limit raised. "
"No invitations were sent.").format(email=settings.ZULIP_ADMINISTRATOR)
if not settings.OPEN_REALM_CREATION:
return
@ -5617,7 +5627,7 @@ def check_add_user_group(realm: Realm, name: str, initial_members: List[UserProf
user_group = create_user_group(name, initial_members, realm, description=description)
do_send_create_user_group_event(user_group, initial_members)
except django.db.utils.IntegrityError:
raise JsonableError(_("User group '%s' already exists.") % (name,))
raise JsonableError(_("User group '{}' already exists.").format(name))
def do_send_user_group_update_event(user_group: UserGroup, data: Dict[str, Any]) -> None:
event = dict(type="user_group", op='update', group_id=user_group.id, data=data)
@ -5628,7 +5638,7 @@ def do_update_user_group_name(user_group: UserGroup, name: str) -> None:
user_group.name = name
user_group.save(update_fields=['name'])
except django.db.utils.IntegrityError:
raise JsonableError(_("User group '%s' already exists.") % (name,))
raise JsonableError(_("User group '{}' already exists.").format(name))
do_send_user_group_update_event(user_group, dict(name=name))
def do_update_user_group_description(user_group: UserGroup, description: str) -> None:

View File

@ -18,7 +18,7 @@ def get_user_profiles(emails: Iterable[str], realm: Realm) -> List[UserProfile]:
try:
user_profile = get_user_including_cross_realm(email, realm)
except UserProfile.DoesNotExist:
raise JsonableError(_("Invalid email '%s'") % (email,))
raise JsonableError(_("Invalid email '{}'").format(email))
user_profiles.append(user_profile)
return user_profiles

View File

@ -174,7 +174,7 @@ def get_existing_user_errors(
if existing_user_profile.is_active:
if verbose:
msg = _('%s already has an account') % (email,)
msg = _('{email} already has an account').format(email=email)
else:
msg = _("Already has an account.")
else:

View File

@ -52,7 +52,7 @@ def emoji_name_to_emoji_code(realm: Realm, emoji_name: str) -> Tuple[str, str]:
return emoji_name, Reaction.ZULIP_EXTRA_EMOJI
if emoji_name in name_to_codepoint:
return name_to_codepoint[emoji_name], Reaction.UNICODE_EMOJI
raise JsonableError(_("Emoji '%s' does not exist") % (emoji_name,))
raise JsonableError(_("Emoji '{}' does not exist").format(emoji_name))
def check_emoji_request(realm: Realm, emoji_name: str, emoji_code: str,
emoji_type: str) -> None:

View File

@ -21,7 +21,7 @@ def check_supported_events_narrow_filter(narrow: Iterable[Sequence[str]]) -> Non
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 {} not supported.").format(operator))
def is_web_public_compatible(narrow: Iterable[Dict[str, str]]) -> bool:
for element in narrow:

View File

@ -238,15 +238,17 @@ def parse_gcm_options(options: Dict[str, Any], data: Dict[str, Any]) -> str:
else: # `'event': 'remove'`, presumably
priority = 'normal'
if priority not in ('normal', 'high'):
raise JsonableError(_("Invalid GCM option to bouncer: priority %r")
% (priority,))
raise JsonableError(_(
"Invalid GCM option to bouncer: priority {!r}",
).format(priority))
if options:
# We're strict about the API; there is no use case for a newer Zulip
# server talking to an older bouncer, so we only need to provide
# one-way compatibility.
raise JsonableError(_("Invalid GCM options to bouncer: %s")
% (ujson.dumps(options),))
raise JsonableError(_(
"Invalid GCM options to bouncer: {}",
).format(ujson.dumps(options)))
return priority # when this grows a second option, can make it a tuple
@ -600,9 +602,9 @@ def get_apns_alert_subtitle(message: Message) -> str:
On an iOS notification, this is the second bolded line.
"""
if message.trigger == "mentioned":
return _("%(full_name)s mentioned you:") % dict(full_name=message.sender.full_name)
return _("{full_name} mentioned you:").format(full_name=message.sender.full_name)
elif message.trigger == "wildcard_mentioned":
return _("%(full_name)s mentioned everyone:") % dict(full_name=message.sender.full_name)
return _("{full_name} mentioned everyone:").format(full_name=message.sender.full_name)
elif message.recipient.type == Recipient.PERSONAL:
return ""
# For group PMs, or regular messages to a stream, just use a colon to indicate this is the sender.

View File

@ -77,7 +77,7 @@ def send_to_push_bouncer(method: str,
if 'code' in result_dict and result_dict['code'] == 'INVALID_ZULIP_SERVER':
# Invalid Zulip server credentials should email this server's admins
raise PushNotificationBouncerException(
_("Push notifications bouncer error: %s") % (msg,))
_("Push notifications bouncer error: {}").format(msg))
else:
# But most other errors coming from the push bouncer
# server are client errors (e.g. never-registered token)

View File

@ -348,7 +348,7 @@ def has_request_variables(view_func: ViewFuncT) -> ViewFuncT:
try:
val = ujson.loads(val)
except Exception:
raise JsonableError(_('Argument "%s" is not valid JSON.') % (post_var_name,))
raise JsonableError(_('Argument "{}" is not valid JSON.').format(post_var_name))
error = param.validator(post_var_name, val)
if error:

View File

@ -115,12 +115,12 @@ def create_streams_if_needed(realm: Realm,
def check_stream_name(stream_name: str) -> None:
if stream_name.strip() == "":
raise JsonableError(_("Invalid stream name '%s'") % (stream_name,))
raise JsonableError(_("Invalid stream name '{}'").format(stream_name))
if len(stream_name) > Stream.MAX_NAME_LENGTH:
raise JsonableError(_("Stream name too long (limit: %s characters).") % (Stream.MAX_NAME_LENGTH,))
raise JsonableError(_("Stream name too long (limit: {} characters).").format(Stream.MAX_NAME_LENGTH))
for i in stream_name:
if ord(i) == 0:
raise JsonableError(_("Stream name '%s' contains NULL (0x00) characters.") % (stream_name,))
raise JsonableError(_("Stream name '{}' contains NULL (0x00) characters.").format(stream_name))
def subscribed_to_stream(user_profile: UserProfile, stream_id: int) -> bool:
return Subscription.objects.filter(
@ -177,7 +177,7 @@ def access_stream_for_send_message(sender: UserProfile,
return
# 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 '{}'").format(stream.name))
def check_for_exactly_one_stream_arg(stream_id: Optional[int], stream: Optional[str]) -> None:
if stream_id is None and stream is None:
@ -276,14 +276,14 @@ def check_stream_name_available(realm: Realm, name: str) -> None:
check_stream_name(name)
try:
get_stream(name, realm)
raise JsonableError(_("Stream name '%s' is already taken.") % (name,))
raise JsonableError(_("Stream name '{}' is already taken.").format(name))
except Stream.DoesNotExist:
pass
def access_stream_by_name(user_profile: UserProfile,
stream_name: str,
allow_realm_admin: bool=False) -> Tuple[Stream, Recipient, Optional[Subscription]]:
error = _("Invalid stream name '%s'") % (stream_name,)
error = _("Invalid stream name '{}'").format(stream_name)
try:
stream = get_realm_stream(stream_name, user_profile.realm_id)
except Stream.DoesNotExist:
@ -345,7 +345,7 @@ def can_access_stream_history(user_profile: UserProfile, stream: Stream) -> bool
if stream.is_history_public_to_subscribers():
# In this case, we check if the user is subscribed.
error = _("Invalid stream name '%s'") % (stream.name,)
error = _("Invalid stream name '{}'").format(stream.name)
try:
(recipient, sub) = access_stream_common(user_profile, stream, error)
except JsonableError:
@ -440,8 +440,9 @@ def list_to_streams(streams_raw: Iterable[Mapping[str, Any]],
if not user_profile.can_create_streams():
raise JsonableError(_('User cannot create streams.'))
elif not autocreate:
raise JsonableError(_("Stream(s) (%s) do not exist") % ", ".join(
stream_dict["name"] for stream_dict in missing_stream_dicts))
raise JsonableError(_("Stream(s) ({}) do not exist").format(
", ".join(stream_dict["name"] for stream_dict in missing_stream_dicts),
))
# We already filtered out existing streams, so dup_streams
# will normally be an empty list below, but we protect against somebody
@ -458,7 +459,7 @@ def access_default_stream_group_by_id(realm: Realm, group_id: int) -> DefaultStr
try:
return DefaultStreamGroup.objects.get(realm=realm, id=group_id)
except DefaultStreamGroup.DoesNotExist:
raise JsonableError(_("Default stream group with id '%s' does not exist.") % (group_id,))
raise JsonableError(_("Default stream group with id '{}' does not exist.").format(group_id))
def get_stream_by_narrow_operand_access_unchecked(operand: Union[str, int], realm: Realm) -> Stream:
"""This is required over access_stream_* in certain cases where

View File

@ -78,12 +78,13 @@ def check_valid_bot_config(bot_type: int, service_name: str,
config_options = {c[1]: c[2] for c in integration.config_options}
break
if not config_options:
raise JsonableError(_("Invalid integration '%s'.") % (service_name,))
raise JsonableError(_("Invalid integration '{}'.").format(service_name))
missing_keys = set(config_options.keys()) - set(config_data.keys())
if missing_keys:
raise JsonableError(_("Missing configuration parameters: %s") % (
missing_keys,))
raise JsonableError(_("Missing configuration parameters: {}").format(
missing_keys,
))
for key, validator in config_options.items():
value = config_data[key]
@ -196,12 +197,12 @@ def user_ids_to_users(user_ids: Sequence[int], realm: Realm) -> List[UserProfile
found_user_ids = user_profiles_by_id.keys()
missed_user_ids = [user_id for user_id in user_ids if user_id not in found_user_ids]
if missed_user_ids:
raise JsonableError(_("Invalid user ID: %s") % (missed_user_ids[0],))
raise JsonableError(_("Invalid user ID: {}").format(missed_user_ids[0]))
user_profiles = list(user_profiles_by_id.values())
for user_profile in user_profiles:
if user_profile.realm != realm:
raise JsonableError(_("Invalid user ID: %s") % (user_profile.id,))
raise JsonableError(_("Invalid user ID: {}").format(user_profile.id))
return user_profiles
def access_bot_by_id(user_profile: UserProfile, user_id: int) -> UserProfile:

View File

@ -56,7 +56,7 @@ def set_type_structure(type_structure: TypeStructure) -> Callable[[FuncT], Any]:
@set_type_structure("str")
def check_string(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, str):
return _('%s is not a string') % (var_name,)
return _('{var_name} is not a string').format(var_name=var_name)
return None
@set_type_structure("str")
@ -78,7 +78,7 @@ def check_string_in(possible_values: Union[Set[str], List[str]]) -> Validator:
if not_str is not None:
return not_str
if val not in possible_values:
return _("Invalid %s") % (var_name,)
return _("Invalid {var_name}").format(var_name=var_name)
return None
return validator
@ -91,7 +91,7 @@ def check_capped_string(max_length: int) -> Validator:
@set_type_structure("str")
def validator(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, str):
return _('%s is not a string') % (var_name,)
return _('{var_name} is not a string').format(var_name=var_name)
if len(val) > max_length:
return _("{var_name} is too long (limit: {max_length} characters)").format(
var_name=var_name, max_length=max_length)
@ -103,7 +103,7 @@ def check_string_fixed_length(length: int) -> Validator:
@set_type_structure("str")
def validator(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, str):
return _('%s is not a string') % (var_name,)
return _('{var_name} is not a string').format(var_name=var_name)
if len(val) != length:
return _("{var_name} has incorrect length {length}; should be {target_length}").format(
var_name=var_name, target_length=length, length=len(val))
@ -117,17 +117,17 @@ def check_long_string(var_name: str, val: object) -> Optional[str]:
@set_type_structure("date")
def check_date(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, str):
return _('%s is not a string') % (var_name,)
return _('{var_name} is not a string').format(var_name=var_name)
try:
datetime.strptime(val, '%Y-%m-%d')
except ValueError:
return _('%s is not a date') % (var_name,)
return _('{var_name} is not a date').format(var_name=var_name)
return None
@set_type_structure("int")
def check_int(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, int):
return _('%s is not an integer') % (var_name,)
return _('{var_name} is not an integer').format(var_name=var_name)
return None
def check_int_in(possible_values: List[int]) -> Validator:
@ -137,7 +137,7 @@ def check_int_in(possible_values: List[int]) -> Validator:
if not_int is not None:
return not_int
if val not in possible_values:
return _("Invalid %s") % (var_name,)
return _("Invalid {var_name}").format(var_name=var_name)
return None
return validator
@ -145,23 +145,23 @@ def check_int_in(possible_values: List[int]) -> Validator:
@set_type_structure("float")
def check_float(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, float):
return _('%s is not a float') % (var_name,)
return _('{var_name} is not a float').format(var_name=var_name)
return None
@set_type_structure("bool")
def check_bool(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, bool):
return _('%s is not a boolean') % (var_name,)
return _('{var_name} is not a boolean').format(var_name=var_name)
return None
@set_type_structure("str")
def check_color(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, str):
return _('%s is not a string') % (var_name,)
return _('{var_name} is not a string').format(var_name=var_name)
valid_color_pattern = re.compile(r'^#([a-fA-F0-9]{3,6})$')
matched_results = valid_color_pattern.match(val)
if not matched_results:
return _('%s is not a valid hex color code') % (var_name,)
return _('{var_name} is not a valid hex color code').format(var_name=var_name)
return None
def check_none_or(sub_validator: Validator) -> Validator:
@ -190,11 +190,12 @@ def check_list(sub_validator: Optional[Validator], length: Optional[int]=None) -
@set_type_structure(type_structure)
def f(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, list):
return _('%s is not a list') % (var_name,)
return _('{var_name} is not a list').format(var_name=var_name)
if length is not None and length != len(val):
return (_('%(container)s should have exactly %(length)s items') %
{'container': var_name, 'length': length})
return (_('{container} should have exactly {length} items').format(
container=var_name, length=length,
))
if sub_validator:
for i, item in enumerate(val):
@ -215,12 +216,13 @@ def check_dict(required_keys: Iterable[Tuple[str, Validator]]=[],
@set_type_structure(type_structure)
def f(var_name: str, val: object) -> Optional[str]:
if not isinstance(val, dict):
return _('%s is not a dict') % (var_name,)
return _('{var_name} is not a dict').format(var_name=var_name)
for k, sub_validator in required_keys:
if k not in val:
return (_('%(key_name)s key is missing from %(var_name)s') %
{'key_name': k, 'var_name': var_name})
return (_('{key_name} key is missing from {var_name}').format(
key_name=k, var_name=var_name,
))
vname = f'{var_name}["{k}"]'
error = sub_validator(vname, val[k])
if error:
@ -251,7 +253,7 @@ def check_dict(required_keys: Iterable[Tuple[str, Validator]]=[],
optional_keys_set = {x[0] for x in optional_keys}
delta_keys = set(val.keys()) - required_keys_set - optional_keys_set
if len(delta_keys) != 0:
return _("Unexpected arguments: %s") % (", ".join(list(delta_keys)),)
return _("Unexpected arguments: {}").format(", ".join(list(delta_keys)))
return None
@ -280,17 +282,16 @@ def check_variable_type(allowed_type_funcs: Iterable[Validator]) -> Validator:
for func in allowed_type_funcs:
if not func(var_name, val):
return None
return _('%s is not an allowed_type') % (var_name,)
return _('{var_name} is not an allowed_type').format(var_name=var_name)
return enumerated_type_check
def equals(expected_val: object) -> Validator:
@set_type_structure(f'equals("{str(expected_val)}")')
def f(var_name: str, val: object) -> Optional[str]:
if val != expected_val:
return (_('%(variable)s != %(expected_value)s (%(value)s is wrong)') %
{'variable': var_name,
'expected_value': expected_val,
'value': val})
return (_('{variable} != {expected_value} ({value} is wrong)').format(
variable=var_name, expected_value=expected_val, value=val,
))
return None
return f
@ -313,7 +314,7 @@ def check_url(var_name: str, val: object) -> Optional[str]:
validate(val)
return None
except ValidationError:
return _('%s is not a URL') % (var_name,)
return _('{var_name} is not a URL').format(var_name=var_name)
@set_type_structure('str')
def check_external_account_url_pattern(var_name: str, val: object) -> Optional[str]:
@ -435,7 +436,7 @@ def check_string_or_int_list(var_name: str, val: object) -> Optional[str]:
return None
if not isinstance(val, list):
return _('%s is not a string or an integer list') % (var_name,)
return _('{var_name} is not a string or an integer list').format(var_name=var_name)
return check_list(check_int)(var_name, val)
@ -444,4 +445,4 @@ def check_string_or_int(var_name: str, val: object) -> Optional[str]:
if isinstance(val, str) or isinstance(val, int):
return None
return _('%s is not a string or integer') % (var_name,)
return _('{var_name} is not a string or integer').format(var_name=var_name)

View File

@ -54,4 +54,4 @@ def process_zcommands(content: str, user_profile: UserProfile) -> Dict[str, Any]
switch_command='fluid-width',
setting='fluid_layout_width',
setting_value=False))
raise JsonableError(_('No such command: %s') % (command,))
raise JsonableError(_('No such command: {}').format(command))

View File

@ -211,7 +211,7 @@ class RealmEmojiTest(ZulipTestCase):
with get_test_image_file('img.png') as fp:
with self.settings(MAX_EMOJI_FILE_SIZE=0):
result = self.client_post('/json/realm/emoji/my_emoji', {'file': fp})
self.assert_json_error(result, 'Uploaded file is larger than the allowed limit of 0 MB')
self.assert_json_error(result, 'Uploaded file is larger than the allowed limit of 0 MiB')
def test_upload_already_existed_emoji(self) -> None:
self.login('iago')

View File

@ -164,7 +164,7 @@ class FileUploadTest(UploadSerializeMixin, ZulipTestCase):
# would be 1MB.
with self.settings(MAX_FILE_UPLOAD_SIZE=0):
result = self.client_post("/json/user_uploads", {'f1': fp})
self.assert_json_error(result, 'Uploaded file is larger than the allowed limit of 0 MB')
self.assert_json_error(result, 'Uploaded file is larger than the allowed limit of 0 MiB')
def test_multiple_upload_failure(self) -> None:
"""
@ -1163,7 +1163,7 @@ class AvatarTest(UploadSerializeMixin, ZulipTestCase):
with get_test_image_file(self.correct_files[0][0]) as fp:
with self.settings(MAX_AVATAR_FILE_SIZE=0):
result = self.client_post("/json/users/me/avatar", {'file': fp})
self.assert_json_error(result, "Uploaded file is larger than the allowed limit of 0 MB")
self.assert_json_error(result, "Uploaded file is larger than the allowed limit of 0 MiB")
def tearDown(self) -> None:
destroy_uploads()
@ -1336,7 +1336,7 @@ class RealmIconTest(UploadSerializeMixin, ZulipTestCase):
with get_test_image_file(self.correct_files[0][0]) as fp:
with self.settings(MAX_ICON_FILE_SIZE=0):
result = self.client_post("/json/realm/icon", {'file': fp})
self.assert_json_error(result, "Uploaded file is larger than the allowed limit of 0 MB")
self.assert_json_error(result, "Uploaded file is larger than the allowed limit of 0 MiB")
def tearDown(self) -> None:
destroy_uploads()
@ -1479,7 +1479,7 @@ class RealmLogoTest(UploadSerializeMixin, ZulipTestCase):
with self.settings(MAX_LOGO_FILE_SIZE=0):
result = self.client_post("/json/realm/logo", {'file': fp, 'night':
ujson.dumps(self.night)})
self.assert_json_error(result, "Uploaded file is larger than the allowed limit of 0 MB")
self.assert_json_error(result, "Uploaded file is larger than the allowed limit of 0 MiB")
def tearDown(self) -> None:
destroy_uploads()

View File

@ -566,13 +566,17 @@ def fetch_events(query: Mapping[str, Any]) -> Dict[str, Any]:
client.event_queue.newest_pruned_id is not None
and last_event_id < client.event_queue.newest_pruned_id
):
raise JsonableError(_("An event newer than %s has already been pruned!") % (last_event_id,))
raise JsonableError(_("An event newer than {event_id} has already been pruned!").format(
event_id=last_event_id,
))
client.event_queue.prune(last_event_id)
if (
client.event_queue.newest_pruned_id is not None
and last_event_id != client.event_queue.newest_pruned_id
):
raise JsonableError(_("Event %s was not in this queue") % (last_event_id,))
raise JsonableError(_("Event {event_id} was not in this queue").format(
event_id=last_event_id,
))
was_connected = client.finish_current_handler()
if not client.event_queue.empty() or dont_block:

View File

@ -15,6 +15,6 @@ from zerver.models import UserProfile
def mark_hotspot_as_read(request: HttpRequest, user: UserProfile,
hotspot: str=REQ(validator=check_string)) -> HttpResponse:
if hotspot not in ALL_HOTSPOTS:
return json_error(_('Unknown hotspot: %s') % (hotspot,))
return json_error(_('Unknown hotspot: {}').format(hotspot))
do_mark_hotspot_as_read(user, hotspot)
return json_success()

View File

@ -852,8 +852,9 @@ def get_messages_backend(request: HttpRequest, user_profile: UserProfile,
apply_markdown: bool=REQ(validator=check_bool, default=True)) -> HttpResponse:
anchor = parse_anchor_value(anchor_val, use_first_unread_anchor_val)
if num_before + num_after > MAX_MESSAGES_PER_FETCH:
return json_error(_("Too many messages requested (maximum %s).")
% (MAX_MESSAGES_PER_FETCH,))
return json_error(_("Too many messages requested (maximum {}).").format(
MAX_MESSAGES_PER_FETCH,
))
if user_profile.realm.email_address_visibility != Realm.EMAIL_ADDRESS_VISIBILITY_EVERYONE:
# If email addresses are only available to administrators,
@ -1218,7 +1219,7 @@ def mark_topic_as_read(request: HttpRequest,
)
if not topic_exists:
raise JsonableError(_('No such topic \'%s\'') % (topic_name,))
raise JsonableError(_('No such topic \'{}\'').format(topic_name))
count = do_mark_stream_messages_as_read(user_profile, request.client, stream, topic_name)
@ -1413,7 +1414,7 @@ def send_message_backend(request: HttpRequest, user_profile: UserProfile,
try:
realm = get_realm(realm_str)
except Realm.DoesNotExist:
return json_error(_("Unknown organization '%s'") % (realm_str,))
return json_error(_("Unknown organization '{}'").format(realm_str))
if client.name in ["zephyr_mirror", "irc_mirror", "jabber_mirror", "JabberMirror"]:
# Here's how security works for mirroring:

View File

@ -30,7 +30,7 @@ def get_presence_backend(request: HttpRequest, user_profile: UserProfile,
presence_dict = get_presence_for_user(target.id)
if len(presence_dict) == 0:
return json_error(_('No presence data for %s') % (email,))
return json_error(_('No presence data for {email}').format(email=email))
# For initial version, we just include the status and timestamp keys
result = dict(presence=presence_dict[target.email])
@ -77,7 +77,7 @@ def update_active_status_backend(request: HttpRequest, user_profile: UserProfile
) -> HttpResponse:
status_val = UserPresence.status_from_string(status)
if status_val is None:
raise JsonableError(_("Invalid status: %s") % (status,))
raise JsonableError(_("Invalid status: {}").format(status))
elif user_profile.presence_enabled:
update_user_presence(user_profile, request.client, timezone_now(),
status_val, new_user_input)

View File

@ -94,7 +94,7 @@ def update_realm(
# Additional validation/error checking beyond types go here, so
# the entire request can succeed or fail atomically.
if default_language is not None and default_language not in get_available_language_codes():
raise JsonableError(_("Invalid language '%s'") % (default_language,))
raise JsonableError(_("Invalid language '{}'").format(default_language))
if description is not None and len(description) > 1000:
return json_error(_("Organization description is too long."))
if name is not None and len(name) > Realm.MAX_REALM_NAME_LENGTH:

View File

@ -26,8 +26,8 @@ def create_realm_domain(request: HttpRequest, user_profile: UserProfile,
except ValidationError as e:
return json_error(_('Invalid domain: {}').format(e.messages[0]))
if RealmDomain.objects.filter(realm=user_profile.realm, domain=domain).exists():
return json_error(_("The domain %(domain)s is already"
" a part of your organization.") % {'domain': domain})
return json_error(_("The domain {domain} is already"
" a part of your organization.").format(domain=domain))
realm_domain = do_add_realm_domain(user_profile.realm, domain, allow_subdomains)
return json_success({'new_domain': [realm_domain.id, realm_domain.domain]})
@ -39,7 +39,7 @@ def patch_realm_domain(request: HttpRequest, user_profile: UserProfile, domain:
realm_domain = RealmDomain.objects.get(realm=user_profile.realm, domain=domain)
do_change_realm_domain(realm_domain, allow_subdomains)
except RealmDomain.DoesNotExist:
return json_error(_('No entry found for domain %(domain)s.') % {'domain': domain})
return json_error(_('No entry found for domain {domain}.').format(domain=domain))
return json_success()
@require_realm_admin
@ -50,5 +50,5 @@ def delete_realm_domain(request: HttpRequest, user_profile: UserProfile,
realm_domain = RealmDomain.objects.get(realm=user_profile.realm, domain=domain)
do_remove_realm_domain(realm_domain)
except RealmDomain.DoesNotExist:
return json_error(_('No entry found for domain %(domain)s.') % {'domain': domain})
return json_error(_('No entry found for domain {domain}.').format(domain=domain))
return json_success()

View File

@ -32,8 +32,9 @@ def upload_emoji(request: HttpRequest, user_profile: UserProfile,
return json_error(_("You must upload exactly one file."))
emoji_file = list(request.FILES.values())[0]
if (settings.MAX_EMOJI_FILE_SIZE * 1024 * 1024) < emoji_file.size:
return json_error(_("Uploaded file is larger than the allowed limit of %s MB") % (
settings.MAX_EMOJI_FILE_SIZE))
return json_error(_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_EMOJI_FILE_SIZE,
))
realm_emoji = check_add_realm_emoji(user_profile.realm,
emoji_name,
@ -49,7 +50,7 @@ def delete_emoji(request: HttpRequest, user_profile: UserProfile,
if not RealmEmoji.objects.filter(realm=user_profile.realm,
name=emoji_name,
deactivated=False).exists():
raise JsonableError(_("Emoji '%s' does not exist") % (emoji_name,))
raise JsonableError(_("Emoji '{}' does not exist").format(emoji_name))
check_emoji_admin(user_profile, emoji_name)
do_remove_realm_emoji(user_profile.realm, emoji_name)
return json_success()

View File

@ -43,8 +43,9 @@ def export_realm(request: HttpRequest, user: UserProfile) -> HttpResponse:
property='messages_sent:client:day'))
if (total_messages > MAX_MESSAGE_HISTORY or
user.realm.currently_used_upload_space_bytes() > MAX_UPLOAD_QUOTA):
return json_error(_('Please request a manual export from %s.') % (
settings.ZULIP_ADMINISTRATOR,))
return json_error(_('Please request a manual export from {email}.').format(
email=settings.ZULIP_ADMINISTRATOR,
))
row = RealmAuditLog.objects.create(realm=realm,
event_type=event_type,

View File

@ -20,8 +20,9 @@ def upload_icon(request: HttpRequest, user_profile: UserProfile) -> HttpResponse
icon_file = list(request.FILES.values())[0]
if ((settings.MAX_ICON_FILE_SIZE * 1024 * 1024) < icon_file.size):
return json_error(_("Uploaded file is larger than the allowed limit of %s MB") % (
settings.MAX_ICON_FILE_SIZE))
return json_error(_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_ICON_FILE_SIZE,
))
upload_icon_image(icon_file, user_profile)
do_change_icon_source(user_profile.realm, user_profile.realm.ICON_UPLOADED)
icon_url = realm_icon_url(user_profile.realm)

View File

@ -24,8 +24,9 @@ def upload_logo(request: HttpRequest, user_profile: UserProfile,
return json_error(_("You must upload exactly one logo."))
logo_file = list(request.FILES.values())[0]
if ((settings.MAX_LOGO_FILE_SIZE * 1024 * 1024) < logo_file.size):
return json_error(_("Uploaded file is larger than the allowed limit of %s MB") % (
settings.MAX_LOGO_FILE_SIZE))
return json_error(_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_LOGO_FILE_SIZE,
))
upload_logo_image(logo_file, user_profile, night)
do_change_logo_source(user_profile.realm, user_profile.realm.LOGO_UPLOADED, night)
return json_success()

View File

@ -356,12 +356,14 @@ def you_were_just_subscribed_message(acting_user: UserProfile,
stream_names: Set[str]) -> str:
subscriptions = sorted(list(stream_names))
if len(subscriptions) == 1:
return _("@**%(full_name)s** subscribed you to the stream #**%(stream_name)s**.") % \
{"full_name": acting_user.full_name,
"stream_name": subscriptions[0]}
return _("@**{full_name}** subscribed you to the stream #**{stream_name}**.").format(
full_name=acting_user.full_name,
stream_name=subscriptions[0],
)
message = _("@**%(full_name)s** subscribed you to the following streams:") % \
{"full_name": acting_user.full_name}
message = _("@**{full_name}** subscribed you to the following streams:").format(
full_name=acting_user.full_name,
)
message += "\n\n"
for stream_name in subscriptions:
message += f"* #**{stream_name}**\n"
@ -416,7 +418,9 @@ def add_subscriptions_backend(
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 ({stream_name}).").format(
stream_name=unauthorized_streams[0].name,
))
# Newly created streams are also authorized for the creator
streams = authorized_streams + created_streams
@ -519,9 +523,10 @@ def add_subscriptions_backend(
sender=sender,
stream=stream,
topic=Realm.STREAM_EVENTS_NOTIFICATION_TOPIC,
content=_('Stream created by @_**%(user_name)s|%(user_id)d**.') % {
'user_name': user_profile.full_name,
'user_id': user_profile.id},
content=_('Stream created by @_**{user_name}|{user_id}**.').format(
user_name=user_profile.full_name,
user_id=user_profile.id,
),
),
)
@ -675,11 +680,11 @@ def update_subscription_properties_backend(
value = change["value"]
if property not in property_converters:
return json_error(_("Unknown subscription property: %s") % (property,))
return json_error(_("Unknown subscription property: {}").format(property))
(stream, recipient, sub) = access_stream_by_id(user_profile, stream_id)
if sub is None:
return json_error(_("Not subscribed to stream id %d") % (stream_id,))
return json_error(_("Not subscribed to stream id {}").format(stream_id))
property_conversion = property_converters[property](property, value)
if property_conversion:

View File

@ -107,8 +107,9 @@ def upload_file_backend(request: HttpRequest, user_profile: UserProfile) -> Http
user_file = list(request.FILES.values())[0]
file_size = user_file.size
if settings.MAX_FILE_UPLOAD_SIZE * 1024 * 1024 < file_size:
return json_error(_("Uploaded file is larger than the allowed limit of %s MB") % (
settings.MAX_FILE_UPLOAD_SIZE))
return json_error(_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_FILE_UPLOAD_SIZE,
))
check_upload_within_quota(user_profile.realm, file_size)
uri = upload_message_image_from_request(request, user_file, user_profile)

View File

@ -99,7 +99,9 @@ def add_members_to_group_backend(request: HttpRequest, user_profile: UserProfile
for user_profile in user_profiles:
if user_profile.id in existing_member_ids:
raise JsonableError(_("User %s is already a member of this group") % (user_profile.id,))
raise JsonableError(_("User {user_id} is already a member of this group").format(
user_id=user_profile.id,
))
bulk_add_members_to_user_group(user_group, user_profiles)
return json_success()
@ -114,7 +116,7 @@ def remove_members_from_group_backend(request: HttpRequest, user_profile: UserPr
group_member_ids = get_user_group_members(user_group)
for member in members:
if (member not in group_member_ids):
raise JsonableError(_("There is no member '%s' in this user group") % (member,))
raise JsonableError(_("There is no member '{}' in this user group").format(member))
remove_members_from_user_group(user_group, user_profiles)
return json_success()

View File

@ -95,7 +95,7 @@ def json_change_settings(request: HttpRequest, user_profile: UserProfile,
except RateLimited as e:
secs_to_freedom = int(float(str(e)))
return json_error(
_("You're making too many attempts! Try again in %s seconds.") % (secs_to_freedom,),
_("You're making too many attempts! Try again in {} seconds.").format(secs_to_freedom),
)
if not check_password_strength(new_password):
@ -221,7 +221,7 @@ def json_change_notify_settings(
if (notification_sound is not None and
notification_sound not in get_available_notification_sounds()):
raise JsonableError(_("Invalid notification sound '%s'") % (notification_sound,))
raise JsonableError(_("Invalid notification sound '{}'").format(notification_sound))
req_vars = {k: v for k, v in list(locals().items()) if k in user_profile.notification_setting_types}
@ -241,8 +241,9 @@ def set_avatar_backend(request: HttpRequest, user_profile: UserProfile) -> HttpR
user_file = list(request.FILES.values())[0]
if ((settings.MAX_AVATAR_FILE_SIZE * 1024 * 1024) < user_file.size):
return json_error(_("Uploaded file is larger than the allowed limit of %s MB") % (
settings.MAX_AVATAR_FILE_SIZE))
return json_error(_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_AVATAR_FILE_SIZE,
))
upload_avatar_image(user_file, user_profile, user_profile)
do_change_avatar_fields(user_profile, UserProfile.AVATAR_FROM_USER)
user_avatar_url = avatar_url(user_profile)

View File

@ -479,8 +479,9 @@ def create_user_backend(request: HttpRequest, user_profile: UserProfile,
try:
email_allowed_for_realm(email, user_profile.realm)
except DomainNotAllowedForRealmError:
return json_error(_("Email '%(email)s' not allowed in this organization") %
{'email': email})
return json_error(_("Email '{email}' not allowed in this organization").format(
email=email,
))
except DisposableEmailError:
return json_error(_("Disposable email addresses are not allowed in this organization"))
except EmailContainsPlusError:
@ -488,7 +489,7 @@ def create_user_backend(request: HttpRequest, user_profile: UserProfile,
try:
get_user_by_delivery_email(email, user_profile.realm)
return json_error(_("Email '%s' already in use") % (email,))
return json_error(_("Email '{}' already in use").format(email))
except UserProfile.DoesNotExist:
pass

View File

@ -146,7 +146,7 @@ def api_freshdesk_webhook(request: HttpRequest, user_profile: UserProfile,
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 {} in JSON").format(key))
ticket = TicketDict(ticket_data)

View File

@ -42,7 +42,7 @@ def api_wordpress_webhook(request: HttpRequest, user_profile: UserProfile,
data = WP_LOGIN_TEMPLATE.format(name=user_login)
else:
return json_error(_("Unknown WordPress webhook action: %s") % (hook,))
return json_error(_("Unknown WordPress webhook action: {}").format(hook))
topic = 'WordPress Notification'

View File

@ -74,7 +74,7 @@ def register_remote_server(
url_validator = URLValidator()
url_validator('http://' + hostname)
except ValidationError:
raise JsonableError(_('%s is not a valid hostname') % (hostname,))
raise JsonableError(_('{} is not a valid hostname').format(hostname))
try:
validate_email(contact_email)
@ -179,7 +179,7 @@ def validate_incoming_table_data(server: RemoteZulipServer, model: Any,
last_id = get_last_id_from_server(server, model)
for row in rows:
if is_count_stat and row['property'] not in COUNT_STATS:
raise JsonableError(_("Invalid property %s") % (row['property'],))
raise JsonableError(_("Invalid property {}").format(row['property']))
if row['id'] <= last_id:
raise JsonableError(_("Data is out of order."))
last_id = row['id']