mirror of
https://github.com/netbox-community/netbox.git
synced 2025-08-17 21:18:16 -06:00
15049 add missing gettext to error strings
This commit is contained in:
parent
7cc215437f
commit
4416657681
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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:
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
|
||||||
|
@ -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'
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
|
||||||
|
@ -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):
|
||||||
|
@ -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)
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
@ -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."))
|
||||||
|
@ -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."))
|
||||||
|
@ -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'
|
||||||
)
|
)
|
||||||
|
@ -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):
|
||||||
|
@ -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
|
||||||
|
@ -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})
|
||||||
|
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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')
|
||||||
|
@ -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()
|
||||||
|
@ -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):
|
||||||
|
Loading…
Reference in New Issue
Block a user