python: Convert translated positional {} fields to {named} fields.

Translators benefit from the extra information in the field names, and
need the reordering freedom that isn’t available with multiple
positional fields.

Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
Anders Kaseorg 2023-07-17 13:40:33 -07:00 committed by Tim Abbott
parent db6323b2c4
commit 143baa4243
40 changed files with 199 additions and 98 deletions

View File

@ -315,7 +315,7 @@ def get_chart_data(
labels_sort_function = None
include_empty_subgroups = True
else:
raise JsonableError(_("Unknown chart name: {}").format(chart_name))
raise JsonableError(_("Unknown chart name: {chart_name}").format(chart_name=chart_name))
# Most likely someone using our API endpoint. The /stats page does not
# pass a start or end in its requests.

View File

@ -109,14 +109,17 @@ def validate_licenses(
if licenses is None or (not exempt_from_license_number_check and licenses < min_licenses):
raise BillingError(
"not enough licenses", _("You must invoice for at least {} users.").format(min_licenses)
"not enough licenses",
_("You must invoice for at least {min_licenses} users.").format(
min_licenses=min_licenses
),
)
if max_licenses is not None and licenses > max_licenses:
message = _(
"Invoices with more than {} licenses can't be processed from this page. To complete "
"the upgrade, please contact {}."
).format(max_licenses, settings.ZULIP_ADMINISTRATOR)
"Invoices with more than {max_licenses} licenses can't be processed from this page. To"
" complete the upgrade, please contact {email}."
).format(max_licenses=max_licenses, email=settings.ZULIP_ADMINISTRATOR)
raise BillingError("too many licenses", message)

View File

@ -76,6 +76,20 @@ rules:
severity: ERROR
message: "Immediately formatting a lazily translated string destroys its laziness"
- id: translated-positional-field
languages: [python]
patterns:
- pattern-either:
- pattern: django.utils.translation.gettext("$MESSAGE")
- pattern: django.utils.translation.pgettext($CONTEXT, "$MESSAGE")
- pattern: django.utils.translation.gettext_lazy("$MESSAGE")
- pattern: django.utils.translation.pgettext_lazy($CONTEXT, "$MESSAGE")
- metavariable-regex:
metavariable: $MESSAGE
regex: (^|.*[^{])(\{\{)*\{[:!}].*
severity: ERROR
message: "Prefer {named} fields over positional {} in translated strings"
- id: mutable-default-type
languages: [python]
pattern-either:
@ -99,7 +113,9 @@ rules:
pattern-either:
- pattern: '"..." % ...'
- pattern: django.utils.translation.gettext(...) % ...
- pattern: django.utils.translation.pgettext(...) % ...
- pattern: django.utils.translation.gettext_lazy(...) % ...
- pattern: django.utils.translation.pgettext_lazy(...) % ...
severity: ERROR
message: "Prefer f-strings or .format for string formatting"

View File

@ -21,18 +21,22 @@ from zerver.tornado.django_api import send_event_on_commit
def check_default_stream_group_name(group_name: str) -> None:
if group_name.strip() == "":
raise JsonableError(_("Invalid default stream group name '{}'").format(group_name))
raise JsonableError(
_("Invalid default stream group name '{group_name}'").format(group_name=group_name)
)
if len(group_name) > DefaultStreamGroup.MAX_NAME_LENGTH:
raise JsonableError(
_("Default stream group name too long (limit: {} characters)").format(
DefaultStreamGroup.MAX_NAME_LENGTH,
_("Default stream group name too long (limit: {max_length} characters)").format(
max_length=DefaultStreamGroup.MAX_NAME_LENGTH,
)
)
for i in group_name:
if ord(i) == 0:
raise JsonableError(
_("Default stream group name '{}' contains NULL (0x00) characters.").format(
group_name,
_(
"Default stream group name '{group_name}' contains NULL (0x00) characters."
).format(
group_name=group_name,
)
)
@ -45,7 +49,9 @@ def lookup_default_stream_groups(
try:
default_stream_group = DefaultStreamGroup.objects.get(name=group_name, realm=realm)
except DefaultStreamGroup.DoesNotExist:
raise JsonableError(_("Invalid default stream group {}").format(group_name))
raise JsonableError(
_("Invalid default stream group {group_name}").format(group_name=group_name)
)
default_stream_groups.append(default_stream_group)
return default_stream_groups
@ -157,11 +163,17 @@ def do_change_default_stream_group_name(
) -> None:
if group.name == new_group_name:
raise JsonableError(
_("This default stream group is already named '{}'").format(new_group_name)
_("This default stream group is already named '{group_name}'").format(
group_name=new_group_name
)
)
if DefaultStreamGroup.objects.filter(name=new_group_name, realm=realm).exists():
raise JsonableError(_("Default stream group '{}' already exists").format(new_group_name))
raise JsonableError(
_("Default stream group '{group_name}' already exists").format(
group_name=new_group_name
)
)
group.name = new_group_name
group.save()

View File

@ -254,11 +254,13 @@ def do_update_message_flags(
) -> int:
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: '{}'").format(flag))
raise JsonableError(_("Invalid flag: '{flag}'").format(flag=flag))
if flag in UserMessage.NON_EDITABLE_FLAGS:
raise JsonableError(_("Flag not editable: '{}'").format(flag))
raise JsonableError(_("Flag not editable: '{flag}'").format(flag=flag))
if operation not in ("add", "remove"):
raise JsonableError(_("Invalid message flag operation: '{}'").format(operation))
raise JsonableError(
_("Invalid message flag operation: '{operation}'").format(operation=operation)
)
is_adding = operation == "add"
flagattr = getattr(UserMessage.flags, flag)
flag_target = flagattr if is_adding else 0

View File

@ -52,7 +52,7 @@ def check_send_typing_notification(sender: UserProfile, user_ids: List[int], ope
# is relevant here.
user_profile = get_user_by_id_in_realm_including_cross_realm(user_id, sender.realm)
except UserProfile.DoesNotExist:
raise JsonableError(_("Invalid user ID {}").format(user_id))
raise JsonableError(_("Invalid user ID {user_id}").format(user_id=user_id))
user_profiles.append(user_profile)
do_send_typing_notification(

View File

@ -210,7 +210,7 @@ def check_add_user_group(
do_send_create_user_group_event(user_group, initial_members)
return user_group
except django.db.utils.IntegrityError:
raise JsonableError(_("User group '{}' already exists.").format(name))
raise JsonableError(_("User group '{group_name}' already exists.").format(group_name=name))
def do_send_user_group_update_event(
@ -242,7 +242,7 @@ def do_update_user_group_name(
).decode(),
)
except django.db.utils.IntegrityError:
raise JsonableError(_("User group '{}' already exists.").format(name))
raise JsonableError(_("User group '{group_name}' already exists.").format(group_name=name))
do_send_user_group_update_event(user_group, dict(name=name))

View File

@ -494,10 +494,10 @@ class OurAuthenticationForm(AuthenticationForm):
secs_to_freedom = int(e.secs_to_freedom)
error_message = _(
"You're making too many attempts to sign in."
" Try again in {} seconds or contact your organization administrator"
" Try again in {seconds} seconds or contact your organization administrator"
" for help."
)
raise ValidationError(error_message.format(secs_to_freedom))
raise ValidationError(error_message.format(seconds=secs_to_freedom))
if return_data.get("inactive_realm"):
raise AssertionError("Programming error: inactive realm in authentication form")

View File

@ -19,7 +19,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 '{}'").format(email))
raise JsonableError(_("Invalid email '{email}'").format(email=email))
user_profiles.append(user_profile)
return user_profiles
@ -30,7 +30,7 @@ def get_user_profiles_by_ids(user_ids: Iterable[int], realm: Realm) -> List[User
try:
user_profile = get_user_by_id_in_realm_including_cross_realm(user_id, realm)
except UserProfile.DoesNotExist:
raise JsonableError(_("Invalid user ID {}").format(user_id))
raise JsonableError(_("Invalid user ID {user_id}").format(user_id=user_id))
user_profiles.append(user_profile)
return user_profiles

View File

@ -85,7 +85,7 @@ def get_emoji_data(realm_id: int, emoji_name: str) -> EmojiData:
emoji_code = name_to_codepoint[emoji_name]
return EmojiData(emoji_code=emoji_code, reaction_type=Reaction.UNICODE_EMOJI)
raise JsonableError(_("Emoji '{}' does not exist").format(emoji_name))
raise JsonableError(_("Emoji '{emoji_name}' does not exist").format(emoji_name=emoji_name))
def check_emoji_request(realm: Realm, emoji_name: str, emoji_code: str, emoji_type: str) -> None:

View File

@ -105,7 +105,7 @@ def check_narrow_for_events(narrow: Collection[NarrowTerm]) -> None:
for narrow_term in narrow:
operator = narrow_term.operator
if operator not in ["stream", "topic", "sender", "is"]:
raise JsonableError(_("Operator {} not supported.").format(operator))
raise JsonableError(_("Operator {operator} not supported.").format(operator=operator))
def is_spectator_compatible(narrow: Iterable[Dict[str, Any]]) -> bool:

View File

@ -338,8 +338,8 @@ def parse_gcm_options(options: Dict[str, Any], data: Dict[str, Any]) -> str:
if priority not in ("normal", "high"):
raise JsonableError(
_(
"Invalid GCM option to bouncer: priority {!r}",
).format(priority)
"Invalid GCM option to bouncer: priority {priority!r}",
).format(priority=priority)
)
if options:
@ -348,8 +348,8 @@ def parse_gcm_options(options: Dict[str, Any], data: Dict[str, Any]) -> str:
# one-way compatibility.
raise JsonableError(
_(
"Invalid GCM options to bouncer: {}",
).format(orjson.dumps(options).decode())
"Invalid GCM options to bouncer: {options}",
).format(options=orjson.dumps(options).decode())
)
return priority # when this grows a second option, can make it a tuple

View File

@ -90,7 +90,7 @@ def send_to_push_bouncer(
if "code" in result_dict and result_dict["code"] == "INVALID_ZULIP_SERVER":
# Invalid Zulip server credentials should email this server's admins
raise PushNotificationBouncerError(
_("Push notifications bouncer error: {}").format(msg)
_("Push notifications bouncer error: {error}").format(error=msg)
)
else:
# But most other errors coming from the push bouncer

View File

@ -439,7 +439,9 @@ def has_request_variables(
except orjson.JSONDecodeError:
if param.argument_type == "body":
raise InvalidJSONError(_("Malformed JSON"))
raise JsonableError(_('Argument "{}" is not valid JSON.').format(post_var_name))
raise JsonableError(
_('Argument "{name}" is not valid JSON.').format(name=post_var_name)
)
try:
val = param.json_validator(post_var_name, val)

View File

@ -298,7 +298,9 @@ def access_stream_for_send_message(
return
# All other cases are an error.
raise JsonableError(_("Not authorized to send to stream '{}'").format(stream.name))
raise JsonableError(
_("Not authorized to send to stream '{stream_name}'").format(stream_name=stream.name)
)
def check_for_exactly_one_stream_arg(stream_id: Optional[int], stream: Optional[str]) -> None:
@ -456,7 +458,9 @@ def check_stream_name_available(realm: Realm, name: str) -> None:
check_stream_name(name)
try:
get_stream(name, realm)
raise JsonableError(_("Stream name '{}' is already taken.").format(name))
raise JsonableError(
_("Stream name '{stream_name}' is already taken.").format(stream_name=name)
)
except Stream.DoesNotExist:
pass
@ -464,7 +468,7 @@ def check_stream_name_available(realm: Realm, name: str) -> None:
def access_stream_by_name(
user_profile: UserProfile, stream_name: str, allow_realm_admin: bool = False
) -> Tuple[Stream, Optional[Subscription]]:
error = _("Invalid stream name '{}'").format(stream_name)
error = _("Invalid stream name '{stream_name}'").format(stream_name=stream_name)
try:
stream = get_realm_stream(stream_name, user_profile.realm_id)
except Stream.DoesNotExist:
@ -584,7 +588,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 '{}'").format(stream.name)
error = _("Invalid stream name '{stream_name}'").format(stream_name=stream.name)
try:
access_stream_common(user_profile, stream, error)
except JsonableError:
@ -728,8 +732,10 @@ def list_to_streams(
if not autocreate:
raise JsonableError(
_("Stream(s) ({}) do not exist").format(
", ".join(stream_dict["name"] for stream_dict in missing_stream_dicts),
_("Stream(s) ({stream_names}) do not exist").format(
stream_names=", ".join(
stream_dict["name"] for stream_dict in missing_stream_dicts
),
)
)
@ -764,7 +770,9 @@ 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 '{}' does not exist.").format(group_id))
raise JsonableError(
_("Default stream group with id '{group_id}' does not exist.").format(group_id=group_id)
)
def get_stream_by_narrow_operand_access_unchecked(operand: Union[str, int], realm: Realm) -> Stream:

View File

@ -39,13 +39,17 @@ def check_stream_name(stream_name: str) -> None:
if len(stream_name) > Stream.MAX_NAME_LENGTH:
raise JsonableError(
_("Stream name too long (limit: {} characters).").format(Stream.MAX_NAME_LENGTH)
_("Stream name too long (limit: {max_length} characters).").format(
max_length=Stream.MAX_NAME_LENGTH
)
)
invalid_character_pos = check_string_is_printable(stream_name)
if invalid_character_pos is not None:
raise JsonableError(
_("Invalid character in stream name, at position {}!").format(invalid_character_pos)
_("Invalid character in stream name, at position {position}!").format(
position=invalid_character_pos
)
)
@ -56,5 +60,7 @@ def check_stream_topic(topic: str) -> None:
invalid_character_pos = check_string_is_printable(topic)
if invalid_character_pos is not None:
raise JsonableError(
_("Invalid character in topic, at position {}!").format(invalid_character_pos)
_("Invalid character in topic, at position {position}!").format(
position=invalid_character_pos
)
)

View File

@ -63,7 +63,9 @@ def access_user_groups_as_potential_subgroups(
valid_group_ids = [group.id for group in user_groups]
invalid_group_ids = [group_id for group_id in user_group_ids if group_id not in valid_group_ids]
if invalid_group_ids:
raise JsonableError(_("Invalid user group ID: {}").format(invalid_group_ids[0]))
raise JsonableError(
_("Invalid user group ID: {group_id}").format(group_id=invalid_group_ids[0])
)
return list(user_groups)
@ -81,21 +83,29 @@ def access_user_group_for_setting(
user_group = access_user_group_by_id(user_group_id, user_profile, for_read=True)
if require_system_group and not user_group.is_system_group:
raise JsonableError(_("'{}' must be a system user group.").format(setting_name))
raise JsonableError(
_("'{setting_name}' must be a system user group.").format(setting_name=setting_name)
)
if not allow_internet_group and user_group.name == UserGroup.EVERYONE_ON_INTERNET_GROUP_NAME:
raise JsonableError(
_("'{}' setting cannot be set to 'role:internet' group.").format(setting_name)
_("'{setting_name}' setting cannot be set to 'role:internet' group.").format(
setting_name=setting_name
)
)
if not allow_owners_group and user_group.name == UserGroup.OWNERS_GROUP_NAME:
raise JsonableError(
_("'{}' setting cannot be set to 'role:owners' group.").format(setting_name)
_("'{setting_name}' setting cannot be set to 'role:owners' group.").format(
setting_name=setting_name
)
)
if not allow_nobody_group and user_group.name == UserGroup.NOBODY_GROUP_NAME:
raise JsonableError(
_("'{}' setting cannot be set to 'role:nobody' group.").format(setting_name)
_("'{setting_name}' setting cannot be set to 'role:nobody' group.").format(
setting_name=setting_name
)
)
return user_group
@ -104,12 +114,16 @@ def access_user_group_for_setting(
def check_user_group_name(group_name: str) -> str:
if len(group_name) > UserGroup.MAX_NAME_LENGTH:
raise JsonableError(
_("User group name cannot exceed {} characters.").format(UserGroup.MAX_NAME_LENGTH)
_("User group name cannot exceed {max_length} characters.").format(
max_length=UserGroup.MAX_NAME_LENGTH
)
)
for invalid_prefix in UserGroup.INVALID_NAME_PREFIXES:
if group_name.startswith(invalid_prefix):
raise JsonableError(_("User group name cannot start with '{}'.").format(invalid_prefix))
raise JsonableError(
_("User group name cannot start with '{prefix}'.").format(prefix=invalid_prefix)
)
return group_name

View File

@ -92,13 +92,15 @@ def check_valid_bot_config(
config_options = {c[1]: c[2] for c in integration.config_options}
break
if not config_options:
raise JsonableError(_("Invalid integration '{}'.").format(service_name))
raise JsonableError(
_("Invalid integration '{integration_name}'.").format(integration_name=service_name)
)
missing_keys = set(config_options.keys()) - set(config_data.keys())
if missing_keys:
raise JsonableError(
_("Missing configuration parameters: {}").format(
missing_keys,
_("Missing configuration parameters: {keys}").format(
keys=missing_keys,
)
)
@ -106,7 +108,11 @@ def check_valid_bot_config(
value = config_data[key]
error = validator(key, value)
if error is not None:
raise JsonableError(_("Invalid {} value {} ({})").format(key, value, error))
raise JsonableError(
_("Invalid {key} value {value} ({error})").format(
key=key, value=value, error=error
)
)
elif bot_type == UserProfile.EMBEDDED_BOT:
try:
@ -229,12 +235,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: {}").format(missed_user_ids[0]))
raise JsonableError(_("Invalid user ID: {user_id}").format(user_id=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: {}").format(user_profile.id))
raise JsonableError(_("Invalid user ID: {user_id}").format(user_id=user_profile.id))
return user_profiles

View File

@ -314,7 +314,7 @@ def check_dict(
delta_keys = set(val.keys()) - required_keys_set - optional_keys_set
if len(delta_keys) != 0:
raise ValidationError(
_("Unexpected arguments: {}").format(", ".join(list(delta_keys)))
_("Unexpected arguments: {keys}").format(keys=", ".join(list(delta_keys)))
)
return cast(Dict[str, ResultT], val)

View File

@ -228,4 +228,6 @@ def unix_milliseconds_to_timestamp(milliseconds: Any, webhook: str) -> datetime:
seconds = milliseconds / 1000
return timestamp_to_datetime(seconds)
except (ValueError, TypeError):
raise JsonableError(_("The {} webhook expects time in milliseconds.").format(webhook))
raise JsonableError(
_("The {webhook} webhook expects time in milliseconds.").format(webhook=webhook)
)

View File

@ -76,4 +76,4 @@ def process_zcommands(content: str, user_profile: UserProfile) -> Dict[str, Any]
setting_value=False,
)
)
raise JsonableError(_("No such command: {}").format(command))
raise JsonableError(_("No such command: {command}").format(command=command))

View File

@ -1230,9 +1230,11 @@ def filter_pattern_validator(value: str) -> Pattern[str]:
except re2.error as e:
if len(e.args) >= 1:
if isinstance(e.args[0], str): # nocoverage
raise ValidationError(_("Bad regular expression: {}").format(e.args[0]))
raise ValidationError(_("Bad regular expression: {regex}").format(regex=e.args[0]))
if isinstance(e.args[0], bytes):
raise ValidationError(_("Bad regular expression: {}").format(e.args[0].decode()))
raise ValidationError(
_("Bad regular expression: {regex}").format(regex=e.args[0].decode())
)
raise ValidationError(_("Unknown regular expression error")) # nocoverage
return regex
@ -4697,13 +4699,15 @@ def check_valid_user_ids(realm_id: int, val: object, allow_deactivated: bool = F
try:
user_profile = get_user_profile_by_id_in_realm(user_id, realm)
except UserProfile.DoesNotExist:
raise ValidationError(_("Invalid user ID: {}").format(user_id))
raise ValidationError(_("Invalid user ID: {user_id}").format(user_id=user_id))
if not allow_deactivated and not user_profile.is_active:
raise ValidationError(_("User with ID {} is deactivated").format(user_id))
raise ValidationError(
_("User with ID {user_id} is deactivated").format(user_id=user_id)
)
if user_profile.is_bot:
raise ValidationError(_("User with ID {} is a bot").format(user_id))
raise ValidationError(_("User with ID {user_id} is a bot").format(user_id=user_id))
return user_ids

View File

@ -105,11 +105,13 @@ def events_register_backend(
# These parameters must be false for anonymous requests.
if client_gravatar:
raise JsonableError(
_("Invalid '{}' parameter for anonymous request").format("client_gravatar")
_("Invalid '{key}' parameter for anonymous request").format(key="client_gravatar")
)
if include_subscribers:
raise JsonableError(
_("Invalid '{}' parameter for anonymous request").format("include_subscribers")
_("Invalid '{key}' parameter for anonymous request").format(
key="include_subscribers"
)
)
# Language set by spectator to be passed down to clients as user_settings.

View File

@ -16,6 +16,6 @@ def mark_hotspot_as_read(
request: HttpRequest, user: UserProfile, hotspot: str = REQ()
) -> HttpResponse:
if hotspot not in ALL_HOTSPOTS:
raise JsonableError(_("Unknown hotspot: {}").format(hotspot))
raise JsonableError(_("Unknown hotspot: {hotspot}").format(hotspot=hotspot))
do_mark_hotspot_as_read(user, hotspot)
return json_success(request)

View File

@ -79,7 +79,9 @@ def invite_users_backend(
(stream, sub) = access_stream_by_id(user_profile, stream_id)
except JsonableError:
raise JsonableError(
_("Stream does not exist with id: {}. No invites were sent.").format(stream_id)
_("Stream does not exist with id: {stream_id}. No invites were sent.").format(
stream_id=stream_id
)
)
streams.append(stream)
@ -204,7 +206,11 @@ def generate_multiuse_invite_backend(
try:
(stream, sub) = access_stream_by_id(user_profile, stream_id)
except JsonableError:
raise JsonableError(_("Invalid stream ID {}. No invites were sent.").format(stream_id))
raise JsonableError(
_("Invalid stream ID {stream_id}. No invites were sent.").format(
stream_id=stream_id
)
)
streams.append(stream)
invite_link = do_create_multiuse_invite_link(

View File

@ -96,8 +96,8 @@ def get_messages_backend(
anchor = parse_anchor_value(anchor_val, use_first_unread_anchor_val)
if num_before + num_after > MAX_MESSAGES_PER_FETCH:
raise JsonableError(
_("Too many messages requested (maximum {}).").format(
MAX_MESSAGES_PER_FETCH,
_("Too many messages requested (maximum {max_messages}).").format(
max_messages=MAX_MESSAGES_PER_FETCH,
)
)
if num_before > 0 and num_after > 0 and not include_anchor:

View File

@ -166,7 +166,7 @@ def mark_topic_as_read(
)
if not topic_exists:
raise JsonableError(_("No such topic '{}'").format(topic_name))
raise JsonableError(_("No such topic '{topic}'").format(topic=topic_name))
count = do_mark_stream_messages_as_read(user_profile, stream.recipient_id, topic_name)

View File

@ -143,7 +143,7 @@ def update_active_status_backend(
) -> HttpResponse:
status_val = UserPresence.status_from_string(status)
if status_val is None:
raise JsonableError(_("Invalid status: {}").format(status))
raise JsonableError(_("Invalid status: {status}").format(status=status))
elif user_profile.presence_enabled:
client = RequestNotes.get_notes(request).client
assert client is not None

View File

@ -157,7 +157,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 '{}'").format(default_language))
raise JsonableError(_("Invalid language '{language}'").format(language=default_language))
if authentication_methods is not None:
if not user_profile.is_realm_owner:
raise OrganizationOwnerRequiredError
@ -166,11 +166,17 @@ def update_realm(
if video_chat_provider is not None and video_chat_provider not in {
p["id"] for p in Realm.VIDEO_CHAT_PROVIDERS.values()
}:
raise JsonableError(_("Invalid video_chat_provider {}").format(video_chat_provider))
raise JsonableError(
_("Invalid video_chat_provider {video_chat_provider}").format(
video_chat_provider=video_chat_provider
)
)
if giphy_rating is not None and giphy_rating not in {
p["id"] for p in Realm.GIPHY_RATING_OPTIONS.values()
}:
raise JsonableError(_("Invalid giphy_rating {}").format(giphy_rating))
raise JsonableError(
_("Invalid giphy_rating {giphy_rating}").format(giphy_rating=giphy_rating)
)
message_retention_days: Optional[int] = None
if message_retention_days_raw is not None:

View File

@ -33,7 +33,7 @@ def create_realm_domain(
try:
validate_domain(domain)
except ValidationError as e:
raise JsonableError(_("Invalid domain: {}").format(e.messages[0]))
raise JsonableError(_("Invalid domain: {error}").format(error=e.messages[0]))
if RealmDomain.objects.filter(realm=user_profile.realm, domain=domain).exists():
raise JsonableError(
_("The domain {domain} is already a part of your organization.").format(domain=domain)

View File

@ -45,8 +45,8 @@ def upload_emoji(
assert emoji_file.size is not None
if (settings.MAX_EMOJI_FILE_SIZE_MIB * 1024 * 1024) < emoji_file.size:
raise JsonableError(
_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_EMOJI_FILE_SIZE_MIB,
_("Uploaded file is larger than the allowed limit of {max_size} MiB").format(
max_size=settings.MAX_EMOJI_FILE_SIZE_MIB,
)
)
@ -58,7 +58,9 @@ def delete_emoji(request: HttpRequest, user_profile: UserProfile, emoji_name: st
if not RealmEmoji.objects.filter(
realm=user_profile.realm, name=emoji_name, deactivated=False
).exists():
raise ResourceNotFoundError(_("Emoji '{}' does not exist").format(emoji_name))
raise ResourceNotFoundError(
_("Emoji '{emoji_name}' does not exist").format(emoji_name=emoji_name)
)
check_remove_custom_emoji(user_profile, emoji_name)
do_remove_realm_emoji(user_profile.realm, emoji_name, acting_user=user_profile)
return json_success(request)

View File

@ -24,8 +24,8 @@ def upload_icon(request: HttpRequest, user_profile: UserProfile) -> HttpResponse
assert icon_file.size is not None
if (settings.MAX_ICON_FILE_SIZE_MIB * 1024 * 1024) < icon_file.size:
raise JsonableError(
_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_ICON_FILE_SIZE_MIB,
_("Uploaded file is larger than the allowed limit of {max_size} MiB").format(
max_size=settings.MAX_ICON_FILE_SIZE_MIB,
)
)
upload_icon_image(icon_file, user_profile)

View File

@ -30,8 +30,8 @@ def upload_logo(
assert logo_file.size is not None
if (settings.MAX_LOGO_FILE_SIZE_MIB * 1024 * 1024) < logo_file.size:
raise JsonableError(
_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_LOGO_FILE_SIZE_MIB,
_("Uploaded file is larger than the allowed limit of {max_size} MiB").format(
max_size=settings.MAX_LOGO_FILE_SIZE_MIB,
)
)
upload_logo_image(logo_file, user_profile, night)

View File

@ -1052,11 +1052,15 @@ def update_subscription_properties_backend(
value = change["value"]
if property not in property_converters:
raise JsonableError(_("Unknown subscription property: {}").format(property))
raise JsonableError(
_("Unknown subscription property: {property}").format(property=property)
)
(stream, sub) = access_stream_by_id(user_profile, stream_id)
if sub is None:
raise JsonableError(_("Not subscribed to stream id {}").format(stream_id))
raise JsonableError(
_("Not subscribed to stream id {stream_id}").format(stream_id=stream_id)
)
try:
value = property_converters[property](property, value)

View File

@ -275,8 +275,8 @@ def upload_file_backend(request: HttpRequest, user_profile: UserProfile) -> Http
assert file_size is not None
if settings.MAX_FILE_UPLOAD_SIZE * 1024 * 1024 < file_size:
raise JsonableError(
_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_FILE_UPLOAD_SIZE,
_("Uploaded file is larger than the allowed limit of {max_size} MiB").format(
max_size=settings.MAX_FILE_UPLOAD_SIZE,
)
)
check_upload_within_quota(user_profile.realm, file_size)

View File

@ -265,7 +265,9 @@ def remove_members_from_group_backend(
group_member_ids = get_user_group_direct_member_ids(user_group)
for member in members:
if member not in group_member_ids:
raise JsonableError(_("There is no member '{}' in this user group").format(member))
raise JsonableError(
_("There is no member '{user_id}' in this user group").format(user_id=member)
)
user_profile_ids = [user.id for user in user_profiles]
remove_members_from_user_group(user_group, user_profile_ids, acting_user=user_profile)

View File

@ -130,7 +130,11 @@ def check_settings_values(
and notification_sound not in get_available_notification_sounds()
and notification_sound != "none"
):
raise JsonableError(_("Invalid notification sound '{}'").format(notification_sound))
raise JsonableError(
_("Invalid notification sound '{notification_sound}'").format(
notification_sound=notification_sound
)
)
if email_notifications_batching_period_seconds is not None and (
email_notifications_batching_period_seconds <= 0
@ -138,8 +142,8 @@ def check_settings_values(
):
# We set a limit of one week for the batching period
raise JsonableError(
_("Invalid email batching period: {} seconds").format(
email_notifications_batching_period_seconds
_("Invalid email batching period: {seconds} seconds").format(
seconds=email_notifications_batching_period_seconds
)
)
@ -275,8 +279,8 @@ def json_change_settings(
assert e.secs_to_freedom is not None
secs_to_freedom = int(e.secs_to_freedom)
raise JsonableError(
_("You're making too many attempts! Try again in {} seconds.").format(
secs_to_freedom
_("You're making too many attempts! Try again in {seconds} seconds.").format(
seconds=secs_to_freedom
),
)
@ -364,8 +368,8 @@ def set_avatar_backend(request: HttpRequest, user_profile: UserProfile) -> HttpR
assert user_file.size is not None
if (settings.MAX_AVATAR_FILE_SIZE_MIB * 1024 * 1024) < user_file.size:
raise JsonableError(
_("Uploaded file is larger than the allowed limit of {} MiB").format(
settings.MAX_AVATAR_FILE_SIZE_MIB,
_("Uploaded file is larger than the allowed limit of {max_size} MiB").format(
max_size=settings.MAX_AVATAR_FILE_SIZE_MIB,
)
)
upload_avatar_image(user_file, user_profile, user_profile)

View File

@ -709,7 +709,7 @@ def create_user_backend(
try:
get_user_by_delivery_email(email, user_profile.realm)
raise JsonableError(_("Email '{}' already in use").format(email))
raise JsonableError(_("Email '{email}' already in use").format(email=email))
except UserProfile.DoesNotExist:
pass

View File

@ -53,7 +53,7 @@ def api_wordpress_webhook(
data = WP_LOGIN_TEMPLATE.format(name=user_login)
else:
raise JsonableError(_("Unknown WordPress webhook action: {}").format(hook))
raise JsonableError(_("Unknown WordPress webhook action: {hook}").format(hook=hook))
topic = "WordPress notification"

View File

@ -106,7 +106,7 @@ def register_remote_server(
url_validator = URLValidator()
url_validator("http://" + hostname)
except ValidationError:
raise JsonableError(_("{} is not a valid hostname").format(hostname))
raise JsonableError(_("{hostname} is not a valid hostname").format(hostname=hostname))
try:
validate_email(contact_email)
@ -370,7 +370,7 @@ def validate_incoming_table_data(
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 {}").format(row["property"]))
raise JsonableError(_("Invalid property {property}").format(property=row["property"]))
if row["id"] <= last_id:
raise JsonableError(_("Data is out of order."))
last_id = row["id"]