15049 add missing gettext to error strings

This commit is contained in:
Arthur 2024-02-14 08:54:49 -08:00
parent 7cc215437f
commit 4416657681
22 changed files with 82 additions and 62 deletions

View File

@ -234,9 +234,9 @@ class CircuitTermination(
# Must define either site *or* provider network # Must define either site *or* provider network
if self.site is None and self.provider_network is None: if self.site is None and self.provider_network is None:
raise ValidationError("A circuit termination must attach to either a site or a provider network.") raise ValidationError(_("A circuit termination must attach to either a site or a provider network."))
if self.site and self.provider_network: if self.site and self.provider_network:
raise ValidationError("A circuit termination cannot attach to both a site and a provider network.") raise ValidationError(_("A circuit termination cannot attach to both a site and a provider network."))
def to_objectchange(self, action): def to_objectchange(self, action):
objectchange = super().to_objectchange(action) objectchange = super().to_objectchange(action)

View File

@ -103,9 +103,9 @@ class ManagedFileForm(SyncedDataMixin, NetBoxModelForm):
super().clean() super().clean()
if self.cleaned_data.get('upload_file') and self.cleaned_data.get('data_file'): if self.cleaned_data.get('upload_file') and self.cleaned_data.get('data_file'):
raise forms.ValidationError("Cannot upload a file and sync from an existing file") raise forms.ValidationError(_("Cannot upload a file and sync from an existing file"))
if not self.cleaned_data.get('upload_file') and not self.cleaned_data.get('data_file'): if not self.cleaned_data.get('upload_file') and not self.cleaned_data.get('data_file'):
raise forms.ValidationError("Must upload a file or select a data file to sync") raise forms.ValidationError(_("Must upload a file or select a data file to sync"))
return self.cleaned_data return self.cleaned_data

View File

@ -177,7 +177,7 @@ class DataSource(JobsMixin, PrimaryModel):
Create/update/delete child DataFiles as necessary to synchronize with the remote source. Create/update/delete child DataFiles as necessary to synchronize with the remote source.
""" """
if self.status == DataSourceStatusChoices.SYNCING: if self.status == DataSourceStatusChoices.SYNCING:
raise SyncError("Cannot initiate sync; syncing already in progress.") raise SyncError(_("Cannot initiate sync; syncing already in progress."))
# Emit the pre_sync signal # Emit the pre_sync signal
pre_sync.send(sender=self.__class__, instance=self) pre_sync.send(sender=self.__class__, instance=self)
@ -190,7 +190,7 @@ class DataSource(JobsMixin, PrimaryModel):
backend = self.get_backend() backend = self.get_backend()
except ModuleNotFoundError as e: except ModuleNotFoundError as e:
raise SyncError( raise SyncError(
f"There was an error initializing the backend. A dependency needs to be installed: {e}" _("There was an error initializing the backend. A dependency needs to be installed: ") + str(e)
) )
with backend.fetch() as local_path: with backend.fetch() as local_path:

View File

@ -160,24 +160,24 @@ class Cable(PrimaryModel):
# Validate length and length_unit # Validate length and length_unit
if self.length is not None and not self.length_unit: if self.length is not None and not self.length_unit:
raise ValidationError("Must specify a unit when setting a cable length") raise ValidationError(_("Must specify a unit when setting a cable length"))
if self.pk is None and (not self.a_terminations or not self.b_terminations): if self.pk is None and (not self.a_terminations or not self.b_terminations):
raise ValidationError("Must define A and B terminations when creating a new cable.") raise ValidationError(_("Must define A and B terminations when creating a new cable."))
if self._terminations_modified: if self._terminations_modified:
# Check that all termination objects for either end are of the same type # Check that all termination objects for either end are of the same type
for terms in (self.a_terminations, self.b_terminations): for terms in (self.a_terminations, self.b_terminations):
if len(terms) > 1 and not all(isinstance(t, type(terms[0])) for t in terms[1:]): if len(terms) > 1 and not all(isinstance(t, type(terms[0])) for t in terms[1:]):
raise ValidationError("Cannot connect different termination types to same end of cable.") raise ValidationError(_("Cannot connect different termination types to same end of cable."))
# Check that termination types are compatible # Check that termination types are compatible
if self.a_terminations and self.b_terminations: if self.a_terminations and self.b_terminations:
a_type = self.a_terminations[0]._meta.model_name a_type = self.a_terminations[0]._meta.model_name
b_type = self.b_terminations[0]._meta.model_name b_type = self.b_terminations[0]._meta.model_name
if b_type not in COMPATIBLE_TERMINATION_TYPES.get(a_type): if b_type not in COMPATIBLE_TERMINATION_TYPES.get(a_type):
raise ValidationError(f"Incompatible termination types: {a_type} and {b_type}") raise ValidationError(_("Incompatible termination types: ") + str(a_type) + _(" and ") + str(b_type))
if a_type == b_type: if a_type == b_type:
# can't directly use self.a_terminations here as possible they # can't directly use self.a_terminations here as possible they
@ -323,17 +323,21 @@ class CableTermination(ChangeLoggedModel):
).first() ).first()
if existing_termination is not None: if existing_termination is not None:
raise ValidationError( raise ValidationError(
f"Duplicate termination found for {self.termination_type.app_label}.{self.termination_type.model} " _("Duplicate termination found for {app_label}.{model} {termination_id}: cable {cable_pk}".format(
f"{self.termination_id}: cable {existing_termination.cable.pk}" app_label=self.termination_type.app_label,
model=self.termination_type.model,
termination_id=self.termination_id,
cable_pk=existing_termination.cable.pk))
) )
# Validate interface type (if applicable) # Validate interface type (if applicable)
if self.termination_type.model == 'interface' and self.termination.type in NONCONNECTABLE_IFACE_TYPES: if self.termination_type.model == 'interface' and self.termination.type in NONCONNECTABLE_IFACE_TYPES:
raise ValidationError(f"Cables cannot be terminated to {self.termination.get_type_display()} interfaces") raise ValidationError(_("Cables cannot be terminated to {type_display} interfaces").format(
type_display=self.termination.get_type_display()))
# A CircuitTermination attached to a ProviderNetwork cannot have a Cable # A CircuitTermination attached to a ProviderNetwork cannot have a Cable
if self.termination_type.model == 'circuittermination' and self.termination.provider_network is not None: if self.termination_type.model == 'circuittermination' and self.termination.provider_network is not None:
raise ValidationError("Circuit terminations attached to a provider network may not be cabled.") raise ValidationError(_("Circuit terminations attached to a provider network may not be cabled."))
def save(self, *args, **kwargs): def save(self, *args, **kwargs):

View File

@ -1,6 +1,7 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.test import override_settings from django.test import override_settings
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext as _
from rest_framework import status from rest_framework import status
from dcim.choices import * from dcim.choices import *
@ -45,7 +46,7 @@ class Mixins:
name='Peer Device' name='Peer Device'
) )
if self.peer_termination_type is None: if self.peer_termination_type is None:
raise NotImplementedError("Test case must set peer_termination_type") raise NotImplementedError(_("Test case must set peer_termination_type"))
peer_obj = self.peer_termination_type.objects.create( peer_obj = self.peer_termination_type.objects.create(
device=peer_device, device=peer_device,
name='Peer Termination' name='Peer Termination'

View File

@ -1,5 +1,6 @@
from django.contrib.auth import get_user_model from django.contrib.auth import get_user_model
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import gettext as _
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from drf_spectacular.utils import extend_schema_field from drf_spectacular.utils import extend_schema_field
from rest_framework import serializers from rest_framework import serializers
@ -150,7 +151,7 @@ class CustomFieldSerializer(ValidatedModelSerializer):
def validate_type(self, value): def validate_type(self, value):
if self.instance and self.instance.type != value: if self.instance and self.instance.type != value:
raise serializers.ValidationError('Changing the type of custom fields is not supported.') raise serializers.ValidationError(_('Changing the type of custom fields is not supported.'))
return value return value
@ -545,12 +546,12 @@ class ReportInputSerializer(serializers.Serializer):
def validate_schedule_at(self, value): def validate_schedule_at(self, value):
if value and not self.context['report'].scheduling_enabled: if value and not self.context['report'].scheduling_enabled:
raise serializers.ValidationError("Scheduling is not enabled for this report.") raise serializers.ValidationError(_("Scheduling is not enabled for this report."))
return value return value
def validate_interval(self, value): def validate_interval(self, value):
if value and not self.context['report'].scheduling_enabled: if value and not self.context['report'].scheduling_enabled:
raise serializers.ValidationError("Scheduling is not enabled for this report.") raise serializers.ValidationError(_("Scheduling is not enabled for this report."))
return value return value
@ -595,12 +596,12 @@ class ScriptInputSerializer(serializers.Serializer):
def validate_schedule_at(self, value): def validate_schedule_at(self, value):
if value and not self.context['script'].scheduling_enabled: if value and not self.context['script'].scheduling_enabled:
raise serializers.ValidationError("Scheduling is not enabled for this script.") raise serializers.ValidationError(_("Scheduling is not enabled for this script."))
return value return value
def validate_interval(self, value): def validate_interval(self, value):
if value and not self.context['script'].scheduling_enabled: if value and not self.context['script'].scheduling_enabled:
raise serializers.ValidationError("Scheduling is not enabled for this script.") raise serializers.ValidationError(_("Scheduling is not enabled for this script."))
return value return value

View File

@ -178,7 +178,7 @@ class ObjectCountsWidget(DashboardWidget):
try: try:
dict(data) dict(data)
except TypeError: except TypeError:
raise forms.ValidationError("Invalid format. Object filters must be passed as a dictionary.") raise forms.ValidationError(_("Invalid format. Object filters must be passed as a dictionary."))
return data return data
def render(self, request): def render(self, request):
@ -232,7 +232,7 @@ class ObjectListWidget(DashboardWidget):
try: try:
urlencode(data) urlencode(data)
except (TypeError, ValueError): except (TypeError, ValueError):
raise forms.ValidationError("Invalid format. URL parameters must be passed as a dictionary.") raise forms.ValidationError(_("Invalid format. URL parameters must be passed as a dictionary."))
return data return data
def render(self, request): def render(self, request):

View File

@ -1,5 +1,6 @@
from django.contrib.contenttypes.models import ContentType from django.contrib.contenttypes.models import ContentType
from django.core.management.base import BaseCommand, CommandError from django.core.management.base import BaseCommand, CommandError
from django.utils.translation import gettext as _
from netbox.registry import registry from netbox.registry import registry
from netbox.search.backends import search_backend from netbox.search.backends import search_backend
@ -62,7 +63,7 @@ class Command(BaseCommand):
# Determine which models to reindex # Determine which models to reindex
indexers = self._get_indexers(*model_labels) indexers = self._get_indexers(*model_labels)
if not indexers: if not indexers:
raise CommandError("No indexers found!") raise CommandError(_("No indexers found!"))
self.stdout.write(f'Reindexing {len(indexers)} models.') self.stdout.write(f'Reindexing {len(indexers)} models.')
# Clear all cached values for the specified models (if not being lazy) # Clear all cached values for the specified models (if not being lazy)

View File

@ -11,6 +11,7 @@ from django.conf import settings
from django.core.validators import RegexValidator from django.core.validators import RegexValidator
from django.db import transaction from django.db import transaction
from django.utils.functional import classproperty from django.utils.functional import classproperty
from django.utils.translation import gettext as _
from core.choices import JobStatusChoices from core.choices import JobStatusChoices
from core.models import Job from core.models import Job
@ -356,7 +357,7 @@ class BaseScript:
return ordered_vars return ordered_vars
def run(self, data, commit): def run(self, data, commit):
raise NotImplementedError("The script must define a run() method.") raise NotImplementedError(_("The script must define a run() method."))
# Form rendering # Form rendering
@ -367,11 +368,11 @@ class BaseScript:
fieldsets.extend(self.fieldsets) fieldsets.extend(self.fieldsets)
else: else:
fields = list(name for name, _ in self._get_vars().items()) fields = list(name for name, _ in self._get_vars().items())
fieldsets.append(('Script Data', fields)) fieldsets.append((_('Script Data'), fields))
# Append the default fieldset if defined in the Meta class # Append the default fieldset if defined in the Meta class
exec_parameters = ('_schedule_at', '_interval', '_commit') if self.scheduling_enabled else ('_commit',) exec_parameters = ('_schedule_at', '_interval', '_commit') if self.scheduling_enabled else ('_commit',)
fieldsets.append(('Script Execution Parameters', exec_parameters)) fieldsets.append((_('Script Execution Parameters'), exec_parameters))
return fieldsets return fieldsets

View File

@ -3,6 +3,7 @@ from copy import deepcopy
from django.core.exceptions import ObjectDoesNotExist, PermissionDenied from django.core.exceptions import ObjectDoesNotExist, PermissionDenied
from django.db import transaction from django.db import transaction
from django.shortcuts import get_object_or_404 from django.shortcuts import get_object_or_404
from django.utils.translation import gettext as _
from django_pglocks import advisory_lock from django_pglocks import advisory_lock
from drf_spectacular.utils import extend_schema from drf_spectacular.utils import extend_schema
from netaddr import IPSet from netaddr import IPSet
@ -379,7 +380,7 @@ class AvailablePrefixesView(AvailableObjectsView):
'vrf': parent.vrf.pk if parent.vrf else None, 'vrf': parent.vrf.pk if parent.vrf else None,
}) })
else: else:
raise ValidationError("Insufficient space is available to accommodate the requested prefix size(s)") raise ValidationError(_("Insufficient space is available to accommodate the requested prefix size(s)"))
return requested_objects return requested_objects

View File

@ -1,6 +1,7 @@
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MinValueValidator, MaxValueValidator from django.core.validators import MinValueValidator, MaxValueValidator
from django.db import models from django.db import models
from django.utils.translation import gettext as _
from netaddr import AddrFormatError, IPNetwork from netaddr import AddrFormatError, IPNetwork
from . import lookups, validators from . import lookups, validators
@ -32,7 +33,7 @@ class BaseIPField(models.Field):
# Always return a netaddr.IPNetwork object. (netaddr.IPAddress does not provide a mask.) # Always return a netaddr.IPNetwork object. (netaddr.IPAddress does not provide a mask.)
return IPNetwork(value) return IPNetwork(value)
except AddrFormatError: except AddrFormatError:
raise ValidationError("Invalid IP address format: {}".format(value)) raise ValidationError(_("Invalid IP address format: {}").format(value))
except (TypeError, ValueError) as e: except (TypeError, ValueError) as e:
raise ValidationError(e) raise ValidationError(e)

View File

@ -1,6 +1,7 @@
from django import forms from django import forms
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import validate_ipv4_address, validate_ipv6_address from django.core.validators import validate_ipv4_address, validate_ipv6_address
from django.utils.translation import gettext_lazy as _
from netaddr import IPAddress, IPNetwork, AddrFormatError from netaddr import IPAddress, IPNetwork, AddrFormatError
@ -10,7 +11,7 @@ from netaddr import IPAddress, IPNetwork, AddrFormatError
class IPAddressFormField(forms.Field): class IPAddressFormField(forms.Field):
default_error_messages = { default_error_messages = {
'invalid': "Enter a valid IPv4 or IPv6 address (without a mask).", 'invalid': _("Enter a valid IPv4 or IPv6 address (without a mask)."),
} }
def to_python(self, value): def to_python(self, value):
@ -28,19 +29,19 @@ class IPAddressFormField(forms.Field):
try: try:
validate_ipv6_address(value) validate_ipv6_address(value)
except ValidationError: except ValidationError:
raise ValidationError("Invalid IPv4/IPv6 address format: {}".format(value)) raise ValidationError(_("Invalid IPv4/IPv6 address format: {}").format(value))
try: try:
return IPAddress(value) return IPAddress(value)
except ValueError: except ValueError:
raise ValidationError('This field requires an IP address without a mask.') raise ValidationError(_('This field requires an IP address without a mask.'))
except AddrFormatError: except AddrFormatError:
raise ValidationError("Please specify a valid IPv4 or IPv6 address.") raise ValidationError(_("Please specify a valid IPv4 or IPv6 address."))
class IPNetworkFormField(forms.Field): class IPNetworkFormField(forms.Field):
default_error_messages = { default_error_messages = {
'invalid': "Enter a valid IPv4 or IPv6 address (with CIDR mask).", 'invalid': _("Enter a valid IPv4 or IPv6 address (with CIDR mask)."),
} }
def to_python(self, value): def to_python(self, value):
@ -52,9 +53,9 @@ class IPNetworkFormField(forms.Field):
# Ensure that a subnet mask has been specified. This prevents IPs from defaulting to a /32 or /128. # Ensure that a subnet mask has been specified. This prevents IPs from defaulting to a /32 or /128.
if len(value.split('/')) != 2: if len(value.split('/')) != 2:
raise ValidationError('CIDR mask (e.g. /24) is required.') raise ValidationError(_('CIDR mask (e.g. /24) is required.'))
try: try:
return IPNetwork(value) return IPNetwork(value)
except AddrFormatError: except AddrFormatError:
raise ValidationError("Please specify a valid IPv4 or IPv6 address.") raise ValidationError(_("Please specify a valid IPv4 or IPv6 address."))

View File

@ -751,4 +751,4 @@ class ServiceCreateForm(ServiceForm):
if not self.cleaned_data['description']: if not self.cleaned_data['description']:
self.cleaned_data['description'] = service_template.description self.cleaned_data['description'] = service_template.description
elif not all(self.cleaned_data[f] for f in ('name', 'protocol', 'ports')): elif not all(self.cleaned_data[f] for f in ('name', 'protocol', 'ports')):
raise forms.ValidationError("Must specify name, protocol, and port(s) if not using a service template.") raise forms.ValidationError(_("Must specify name, protocol, and port(s) if not using a service template."))

View File

@ -1,14 +1,15 @@
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import BaseValidator, RegexValidator from django.core.validators import BaseValidator, RegexValidator
from django.utils.translation import gettext_lazy as _
def prefix_validator(prefix): def prefix_validator(prefix):
if prefix.ip != prefix.cidr.ip: if prefix.ip != prefix.cidr.ip:
raise ValidationError("{} is not a valid prefix. Did you mean {}?".format(prefix, prefix.cidr)) raise ValidationError(_("{} is not a valid prefix. Did you mean {}?").format(prefix, prefix.cidr))
class MaxPrefixLengthValidator(BaseValidator): class MaxPrefixLengthValidator(BaseValidator):
message = 'The prefix length must be less than or equal to %(limit_value)s.' message = _('The prefix length must be less than or equal to %(limit_value)s.')
code = 'max_prefix_length' code = 'max_prefix_length'
def compare(self, a, b): def compare(self, a, b):
@ -16,7 +17,7 @@ class MaxPrefixLengthValidator(BaseValidator):
class MinPrefixLengthValidator(BaseValidator): class MinPrefixLengthValidator(BaseValidator):
message = 'The prefix length must be greater than or equal to %(limit_value)s.' message = _('The prefix length must be greater than or equal to %(limit_value)s.')
code = 'min_prefix_length' code = 'min_prefix_length'
def compare(self, a, b): def compare(self, a, b):
@ -25,6 +26,6 @@ class MinPrefixLengthValidator(BaseValidator):
DNSValidator = RegexValidator( DNSValidator = RegexValidator(
regex=r'^([0-9A-Za-z_-]+|\*)(\.[0-9A-Za-z_-]+)*\.?$', regex=r'^([0-9A-Za-z_-]+|\*)(\.[0-9A-Za-z_-]+)*\.?$',
message='Only alphanumeric characters, asterisks, hyphens, periods, and underscores are allowed in DNS names', message=_('Only alphanumeric characters, asterisks, hyphens, periods, and underscores are allowed in DNS names'),
code='invalid' code='invalid'
) )

View File

@ -1,4 +1,5 @@
from django.core.exceptions import ObjectDoesNotExist from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import gettext as _
from drf_spectacular.utils import extend_schema_field from drf_spectacular.utils import extend_schema_field
from drf_spectacular.types import OpenApiTypes from drf_spectacular.types import OpenApiTypes
from netaddr import IPNetwork from netaddr import IPNetwork
@ -58,11 +59,11 @@ class ChoiceField(serializers.Field):
if data == '': if data == '':
if self.allow_blank: if self.allow_blank:
return data return data
raise ValidationError("This field may not be blank.") raise ValidationError(_("This field may not be blank."))
# Provide an explicit error message if the request is trying to write a dict or list # Provide an explicit error message if the request is trying to write a dict or list
if isinstance(data, (dict, list)): if isinstance(data, (dict, list)):
raise ValidationError('Value must be passed directly (e.g. "foo": 123); do not use a dictionary or list.') raise ValidationError(_('Value must be passed directly (e.g. "foo": 123); do not use a dictionary or list.'))
# Check for string representations of boolean/integer values # Check for string representations of boolean/integer values
if hasattr(data, 'lower'): if hasattr(data, 'lower'):
@ -95,8 +96,8 @@ class ContentTypeField(RelatedField):
Represent a ContentType as '<app_label>.<model>' Represent a ContentType as '<app_label>.<model>'
""" """
default_error_messages = { default_error_messages = {
"does_not_exist": "Invalid content type: {content_type}", "does_not_exist": _("Invalid content type: {content_type}"),
"invalid": "Invalid value. Specify a content type as '<app_label>.<model_name>'.", "invalid": _("Invalid value. Specify a content type as '<app_label>.<model_name>'."),
} }
def to_internal_value(self, data): def to_internal_value(self, data):

View File

@ -1,6 +1,7 @@
from netbox.navigation import MenuGroup from netbox.navigation import MenuGroup
from utilities.choices import ButtonColorChoices from utilities.choices import ButtonColorChoices
from django.utils.text import slugify from django.utils.text import slugify
from django.utils.translation import gettext as _
__all__ = ( __all__ = (
'PluginMenu', 'PluginMenu',
@ -42,11 +43,11 @@ class PluginMenuItem:
self.staff_only = staff_only self.staff_only = staff_only
if permissions is not None: if permissions is not None:
if type(permissions) not in (list, tuple): if type(permissions) not in (list, tuple):
raise TypeError("Permissions must be passed as a tuple or list.") raise TypeError(_("Permissions must be passed as a tuple or list."))
self.permissions = permissions self.permissions = permissions
if buttons is not None: if buttons is not None:
if type(buttons) not in (list, tuple): if type(buttons) not in (list, tuple):
raise TypeError("Buttons must be passed as a tuple or list.") raise TypeError(_("Buttons must be passed as a tuple or list."))
self.buttons = buttons self.buttons = buttons
@ -64,9 +65,9 @@ class PluginMenuButton:
self.icon_class = icon_class self.icon_class = icon_class
if permissions is not None: if permissions is not None:
if type(permissions) not in (list, tuple): if type(permissions) not in (list, tuple):
raise TypeError("Permissions must be passed as a tuple or list.") raise TypeError(_("Permissions must be passed as a tuple or list."))
self.permissions = permissions self.permissions = permissions
if color is not None: if color is not None:
if color not in ButtonColorChoices.values(): if color not in ButtonColorChoices.values():
raise ValueError("Button color must be a choice within ButtonColorChoices.") raise ValueError(_("Button color must be a choice within ButtonColorChoices."))
self.color = color self.color = color

View File

@ -1,4 +1,5 @@
from django.template.loader import get_template from django.template.loader import get_template
from django.utils.translation import gettext as _
__all__ = ( __all__ = (
'PluginTemplateExtension', 'PluginTemplateExtension',
@ -31,7 +32,7 @@ class PluginTemplateExtension:
if extra_context is None: if extra_context is None:
extra_context = {} extra_context = {}
elif not isinstance(extra_context, dict): elif not isinstance(extra_context, dict):
raise TypeError("extra_context must be a dictionary") raise TypeError(_("extra_context must be a dictionary"))
return get_template(template_name).render({**self.context, **extra_context}) return get_template(template_name).render({**self.context, **extra_context})

View File

@ -1,4 +1,5 @@
import collections import collections
from django.utils.translation import gettext as _
class Registry(dict): class Registry(dict):
@ -13,10 +14,10 @@ class Registry(dict):
raise KeyError(f"Invalid store: {key}") raise KeyError(f"Invalid store: {key}")
def __setitem__(self, key, value): def __setitem__(self, key, value):
raise TypeError("Cannot add stores to registry after initialization") raise TypeError(_("Cannot add stores to registry after initialization"))
def __delitem__(self, key): def __delitem__(self, key):
raise TypeError("Cannot delete stores from registry") raise TypeError(_("Cannot delete stores from registry"))
# Initialize the global registry # Initialize the global registry

View File

@ -93,7 +93,7 @@ class RestrictedGenericForeignKey(GenericForeignKey):
if type(queryset) is dict: if type(queryset) is dict:
restrict_params = queryset restrict_params = queryset
elif queryset is not None: elif queryset is not None:
raise ValueError("Custom queryset can't be used for this lookup.") raise ValueError(_("Custom queryset can't be used for this lookup."))
# For efficiency, group the instances by content type and then do one # For efficiency, group the instances by content type and then do one
# query per model # query per model

View File

@ -49,7 +49,7 @@ class BulkImportForm(BootstrapMixin, SyncedDataMixin, forms.Form):
# Determine whether we're reading from form data or an uploaded file # Determine whether we're reading from form data or an uploaded file
if self.cleaned_data['data'] and import_method != ImportMethodChoices.DIRECT: if self.cleaned_data['data'] and import_method != ImportMethodChoices.DIRECT:
raise forms.ValidationError("Form data must be empty when uploading/selecting a file.") raise forms.ValidationError(_("Form data must be empty when uploading/selecting a file."))
if import_method == ImportMethodChoices.UPLOAD: if import_method == ImportMethodChoices.UPLOAD:
self.upload_file = 'upload_file' self.upload_file = 'upload_file'
file = self.files.get('upload_file') file = self.files.get('upload_file')

View File

@ -6,6 +6,7 @@ from django.core.exceptions import ObjectDoesNotExist
from django.db.models import ForeignKey from django.db.models import ForeignKey
from django.test import override_settings from django.test import override_settings
from django.urls import reverse from django.urls import reverse
from django.utils.translation import gettext as _
from extras.choices import ObjectChangeActionChoices from extras.choices import ObjectChangeActionChoices
from extras.models import ObjectChange from extras.models import ObjectChange
@ -621,7 +622,7 @@ class ViewTestCases:
@override_settings(EXEMPT_VIEW_PERMISSIONS=['*']) @override_settings(EXEMPT_VIEW_PERMISSIONS=['*'])
def test_bulk_update_objects_with_permission(self): def test_bulk_update_objects_with_permission(self):
if not hasattr(self, 'csv_update_data'): if not hasattr(self, 'csv_update_data'):
raise NotImplementedError("The test must define csv_update_data.") raise NotImplementedError(_("The test must define csv_update_data."))
initial_count = self._get_queryset().count() initial_count = self._get_queryset().count()
array, csv_data = self._get_update_csv_data() array, csv_data = self._get_update_csv_data()

View File

@ -15,6 +15,7 @@ from django.utils import timezone
from django.utils.datastructures import MultiValueDict from django.utils.datastructures import MultiValueDict
from django.utils.html import escape from django.utils.html import escape
from django.utils.timezone import localtime from django.utils.timezone import localtime
from django.utils.translation import gettext as _
from jinja2.sandbox import SandboxedEnvironment from jinja2.sandbox import SandboxedEnvironment
from mptt.models import MPTTModel from mptt.models import MPTTModel
@ -306,13 +307,14 @@ def to_meters(length, unit):
""" """
try: try:
if length < 0: if length < 0:
raise ValueError("Length must be a positive number") raise ValueError(_("Length must be a positive number"))
except TypeError: except TypeError:
raise TypeError(f"Invalid value '{length}' for length (must be a number)") raise TypeError(_("Invalid value '{length}' for length (must be a number)").format(length=length))
valid_units = CableLengthUnitChoices.values() valid_units = CableLengthUnitChoices.values()
if unit not in valid_units: if unit not in valid_units:
raise ValueError(f"Unknown unit {unit}. Must be one of the following: {', '.join(valid_units)}") raise ValueError(_("Unknown unit {unit}. Must be one of the following: {valid_units}".format(
unit=unit, valid_units=', '.join(valid_units))))
if unit == CableLengthUnitChoices.UNIT_KILOMETER: if unit == CableLengthUnitChoices.UNIT_KILOMETER:
return length * 1000 return length * 1000
@ -326,7 +328,7 @@ def to_meters(length, unit):
return length * Decimal(0.3048) return length * Decimal(0.3048)
if unit == CableLengthUnitChoices.UNIT_INCH: if unit == CableLengthUnitChoices.UNIT_INCH:
return length * Decimal(0.0254) return length * Decimal(0.0254)
raise ValueError(f"Unknown unit {unit}. Must be 'km', 'm', 'cm', 'mi', 'ft', or 'in'.") raise ValueError(_("Unknown unit {unit}. Must be 'km', 'm', 'cm', 'mi', 'ft', or 'in'.").format(unit=unit))
def to_grams(weight, unit): def to_grams(weight, unit):
@ -335,13 +337,14 @@ def to_grams(weight, unit):
""" """
try: try:
if weight < 0: if weight < 0:
raise ValueError("Weight must be a positive number") raise ValueError(_("Weight must be a positive number"))
except TypeError: except TypeError:
raise TypeError(f"Invalid value '{weight}' for weight (must be a number)") raise TypeError(_("Invalid value '{weight}' for weight (must be a number)").format(weight=weight))
valid_units = WeightUnitChoices.values() valid_units = WeightUnitChoices.values()
if unit not in valid_units: if unit not in valid_units:
raise ValueError(f"Unknown unit {unit}. Must be one of the following: {', '.join(valid_units)}") raise ValueError(_("Unknown unit {unit}. Must be one of the following: {valid_units}".format(
unit=unit, valid_units=', '.join(valid_units))))
if unit == WeightUnitChoices.UNIT_KILOGRAM: if unit == WeightUnitChoices.UNIT_KILOGRAM:
return weight * 1000 return weight * 1000
@ -351,7 +354,7 @@ def to_grams(weight, unit):
return weight * Decimal(453.592) return weight * Decimal(453.592)
if unit == WeightUnitChoices.UNIT_OUNCE: if unit == WeightUnitChoices.UNIT_OUNCE:
return weight * Decimal(28.3495) return weight * Decimal(28.3495)
raise ValueError(f"Unknown unit {unit}. Must be 'kg', 'g', 'lb', 'oz'.") raise ValueError(_("Unknown unit {unit}. Must be 'kg', 'g', 'lb', 'oz'.").format(unit=unit))
def render_jinja2(template_code, context): def render_jinja2(template_code, context):