15049 add missing gettext to error strings

This commit is contained in:
Arthur 2024-02-14 10:31:45 -08:00
parent 4416657681
commit 3f305d199d
29 changed files with 124 additions and 68 deletions

View File

@ -102,7 +102,7 @@ class GitBackend(DataBackend):
try:
porcelain.clone(self.url, local_path.name, **clone_args)
except BaseException as e:
raise SyncError(f"Fetching remote data failed ({type(e).__name__}): {e}")
raise SyncError(_("Fetching remote data failed ({name}): {e}").format(name=type(e).__name__, e=e))
yield local_path.name

View File

@ -181,7 +181,7 @@ class Job(models.Model):
"""
valid_statuses = JobStatusChoices.TERMINAL_STATE_CHOICES
if status not in valid_statuses:
raise ValueError(f"Invalid status for job termination. Choices are: {', '.join(valid_statuses)}")
raise ValueError(_("Invalid status for job termination. Choices are: {choices}").format(choices=', '.join(valid_statuses)))
# Mark the job as completed
self.status = status

View File

@ -1,6 +1,7 @@
from django.contrib.postgres.fields import ArrayField
from django.core.exceptions import ValidationError
from django.db import models
from django.utils.translation import gettext as _
from netaddr import AddrFormatError, EUI, eui64_unix_expanded, mac_unix_expanded
from .lookups import PathContains
@ -41,7 +42,7 @@ class MACAddressField(models.Field):
try:
return EUI(value, version=48, dialect=mac_unix_expanded_uppercase)
except AddrFormatError:
raise ValidationError(f"Invalid MAC address format: {value}")
raise ValidationError(_("Invalid MAC address format: {value}").format(value=value))
def db_type(self, connection):
return 'macaddr'
@ -67,7 +68,7 @@ class WWNField(models.Field):
try:
return EUI(value, version=64, dialect=eui64_unix_expanded_uppercase)
except AddrFormatError:
raise ValidationError(f"Invalid WWN format: {value}")
raise ValidationError(_("Invalid WWN format: {value}").format(value=value))
def db_type(self, connection):
return 'macaddr8'

View File

@ -870,7 +870,9 @@ class InterfaceImportForm(NetBoxModelImportForm):
def clean_vdcs(self):
for vdc in self.cleaned_data['vdcs']:
if vdc.device != self.cleaned_data['device']:
raise forms.ValidationError(f"VDC {vdc} is not assigned to device {self.cleaned_data['device']}")
raise forms.ValidationError(
_("VDC {vdc} is not assigned to device {device}").format(
vdc=vdc, device=self.cleaned_data['device']))
return self.cleaned_data['vdcs']
@ -1075,7 +1077,8 @@ class InventoryItemImportForm(NetBoxModelImportForm):
component = model.objects.get(device=device, name=component_name)
self.instance.component = component
except ObjectDoesNotExist:
raise forms.ValidationError(f"Component not found: {device} - {component_name}")
raise forms.ValidationError(_("Component not found: {device} - {component_name}").format(
device=device, component_name=component_name))
#
@ -1193,9 +1196,13 @@ class CableImportForm(NetBoxModelImportForm):
else:
termination_object = model.objects.get(device=device, name=name)
if termination_object.cable is not None and termination_object.cable != self.instance:
raise forms.ValidationError(f"Side {side.upper()}: {device} {termination_object} is already connected")
raise forms.ValidationError(
_("Side {side_upper}: {device} {termination_object} is already connected").format(
side_upper=side.upper(), device=device, termination_object=termination_object))
except ObjectDoesNotExist:
raise forms.ValidationError(f"{side.upper()} side termination not found: {device} {name}")
raise forms.ValidationError(
_("{side_upper} side termination not found: {device} {name}").format(
side_upper=side.upper(), device=device, name=name))
setattr(self.instance, f'{side}_terminations', [termination_object])
return termination_object

View File

@ -1,4 +1,5 @@
from django.contrib.contenttypes.models import ContentType
from django.utils.translation import gettext as _
from drf_spectacular.utils import extend_schema_field
from drf_spectacular.types import OpenApiTypes
from rest_framework.fields import Field
@ -88,7 +89,7 @@ class CustomFieldsDataField(Field):
if serializer.is_valid():
data[cf.name] = [obj['id'] for obj in serializer.data] if many else serializer.data['id']
else:
raise ValidationError(f"Unknown related object(s): {data[cf.name]}")
raise ValidationError(_("Unknown related object(s): {name}").format(name=data[cf.name]))
# If updating an existing instance, start with existing custom_field_data
if self.parent.instance:

View File

@ -1,5 +1,6 @@
import functools
import re
from django.utils.translation import gettext as _
__all__ = (
'Condition',
@ -50,11 +51,12 @@ class Condition:
def __init__(self, attr, value, op=EQ, negate=False):
if op not in self.OPERATORS:
raise ValueError(f"Unknown operator: {op}. Must be one of: {', '.join(self.OPERATORS)}")
raise ValueError(_("Unknown operator: {op}. Must be one of: {operators}").format(
op=op, operators=', '.join(self.OPERATORS)))
if type(value) not in self.TYPES:
raise ValueError(f"Unsupported value type: {type(value)}")
raise ValueError(_("Unsupported value type: {value}").format(value=type(value)))
if op not in self.TYPES[type(value)]:
raise ValueError(f"Invalid type for {op} operation: {type(value)}")
raise ValueError(_("Invalid type for {op} operation: {value}").format(op=op, value=type(value)))
self.attr = attr
self.value = value
@ -131,14 +133,16 @@ class ConditionSet:
"""
def __init__(self, ruleset):
if type(ruleset) is not dict:
raise ValueError(f"Ruleset must be a dictionary, not {type(ruleset)}.")
raise ValueError(_("Ruleset must be a dictionary, not {ruleset}.").format(ruleset=type(ruleset)))
if len(ruleset) != 1:
raise ValueError(f"Ruleset must have exactly one logical operator (found {len(ruleset)})")
raise ValueError(_("Ruleset must have exactly one logical operator (found {ruleset})").format(
ruleset=len(ruleset)))
# Determine the logic type
logic = list(ruleset.keys())[0]
if type(logic) is not str or logic.lower() not in (AND, OR):
raise ValueError(f"Invalid logic type: {logic} (must be '{AND}' or '{OR}')")
raise ValueError(_("Invalid logic type: {logic} (must be '{op_and}' or '{op_or}')").format(
logic=logic, op_and=AND, op_or=OR))
self.logic = logic.lower()
# Compile the set of Conditions

View File

@ -2,6 +2,7 @@ import uuid
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from django.utils.translation import gettext as _
from netbox.registry import registry
from extras.constants import DEFAULT_DASHBOARD
@ -32,7 +33,7 @@ def get_widget_class(name):
try:
return registry['widgets'][name]
except KeyError:
raise ValueError(f"Unregistered widget class: {name}")
raise ValueError(_("Unregistered widget class: {name}").format(name=name))
def get_dashboard(user):

View File

@ -112,7 +112,8 @@ class DashboardWidget:
Params:
request: The current request
"""
raise NotImplementedError(f"{self.__class__} must define a render() method.")
raise NotImplementedError(_("{class_name} must define a render() method.").format(
class_name=self.__class__))
@property
def name(self):

View File

@ -6,6 +6,7 @@ from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ObjectDoesNotExist
from django.utils import timezone
from django.utils.module_loading import import_string
from django.utils.translation import gettext as _
from django_rq import get_queue
from core.models import Job
@ -129,7 +130,8 @@ def process_event_rules(event_rules, model_name, event, data, username=None, sna
)
else:
raise ValueError(f"Unknown action type for an event rule: {event_rule.action_type}")
raise ValueError(_("Unknown action type for an event rule: {action_type}").format(
action_type=event_rule.action_type))
def process_event_queue(events):
@ -175,4 +177,4 @@ def flush_events(queue):
func = import_string(name)
func(queue)
except Exception as e:
logger.error(f"Cannot import events pipeline {name} error: {e}")
logger.error(_("Cannot import events pipeline {name} error: {e}").format(name=name, e=e))

View File

@ -202,7 +202,7 @@ class EventRuleImportForm(NetBoxModelImportForm):
try:
webhook = Webhook.objects.get(name=action_object)
except Webhook.DoesNotExist:
raise forms.ValidationError(f"Webhook {action_object} not found")
raise forms.ValidationError(_("Webhook {action_object} not found").format(action_object=action_object))
self.instance.action_object = webhook
# Script
elif action_type == EventRuleActionChoices.SCRIPT:
@ -211,7 +211,7 @@ class EventRuleImportForm(NetBoxModelImportForm):
try:
module, script = get_module_and_script(module_name, script_name)
except ObjectDoesNotExist:
raise forms.ValidationError(f"Script {action_object} not found")
raise forms.ValidationError(_("Script {action_object} not found").format(action_object=action_object))
self.instance.action_object = module
self.instance.action_object_type = ContentType.objects.get_for_model(module, for_concrete_model=False)
self.instance.action_parameters = {

View File

@ -83,7 +83,7 @@ class ChoiceField(serializers.Field):
except TypeError: # Input is an unhashable type
pass
raise ValidationError(f"{data} is not a valid choice.")
raise ValidationError(_("{data} is not a valid choice.").format(data=data))
@property
def choices(self):

View File

@ -1,4 +1,5 @@
from django.core.exceptions import FieldError, MultipleObjectsReturned, ObjectDoesNotExist
from django.utils.translation import gettext_lazy as _
from rest_framework import serializers
from rest_framework.exceptions import ValidationError
@ -30,9 +31,10 @@ class WritableNestedSerializer(BaseModelSerializer):
try:
return queryset.get(**params)
except ObjectDoesNotExist:
raise ValidationError(f"Related object not found using the provided attributes: {params}")
raise ValidationError(
_("Related object not found using the provided attributes: {params}").format(params=params))
except MultipleObjectsReturned:
raise ValidationError(f"Multiple objects match the provided attributes: {params}")
raise ValidationError(_("Multiple objects match the provided attributes: {params}").format(params=params))
except FieldError as e:
raise ValidationError(e)
@ -42,15 +44,14 @@ class WritableNestedSerializer(BaseModelSerializer):
pk = int(data)
except (TypeError, ValueError):
raise ValidationError(
f"Related objects must be referenced by numeric ID or by dictionary of attributes. Received an "
f"unrecognized value: {data}"
_("Related objects must be referenced by numeric ID or by dictionary of attributes. Received an unrecognized value: {data}").format(data=data)
)
# Look up object by PK
try:
return self.Meta.model.objects.get(pk=pk)
except ObjectDoesNotExist:
raise ValidationError(f"Related object not found using the provided numeric ID: {pk}")
raise ValidationError(_("Related object not found using the provided numeric ID: {pk}").format(pk=pk))
# Declared here for use by PrimaryModelSerializer, but should be imported from extras.api.nested_serializers

View File

@ -7,6 +7,7 @@ from django.contrib.auth.backends import ModelBackend, RemoteUserBackend as _Rem
from django.contrib.auth.models import Group, AnonymousUser
from django.core.exceptions import ImproperlyConfigured
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
from users.constants import CONSTRAINT_TOKEN_USER
from users.models import ObjectPermission
@ -132,7 +133,7 @@ class ObjectPermissionMixin:
# Sanity check: Ensure that the requested permission applies to the specified object
model = obj._meta.concrete_model
if model._meta.label_lower != '.'.join((app_label, model_name)):
raise ValueError(f"Invalid permission {perm} for model {model}")
raise ValueError(_("Invalid permission {perm} for model {model}").format(perm=perm, model=model))
# Compile a QuerySet filter that matches all instances of the specified model
tokens = {

View File

@ -4,6 +4,7 @@ import threading
from django.conf import settings
from django.core.cache import cache
from django.db.utils import DatabaseError
from django.utils.translation import gettext_lazy as _
from .parameters import PARAMS
@ -63,7 +64,7 @@ class Config:
if item in self.defaults:
return self.defaults[item]
raise AttributeError(f"Invalid configuration parameter: {item}")
raise AttributeError(_("Invalid configuration parameter: {item}").format(item=item))
def _populate_from_cache(self):
"""Populate config data from Redis cache"""

View File

@ -35,7 +35,8 @@ class CustomFieldsMixin:
Return the ContentType of the form's model.
"""
if not getattr(self, 'model', None):
raise NotImplementedError(f"{self.__class__.__name__} must specify a model class.")
raise NotImplementedError(_("{class_name} must specify a model class.").format(
class_name=self.__class__.__name__))
return ContentType.objects.get_for_model(self.model)
def _get_custom_fields(self, content_type):

View File

@ -275,16 +275,18 @@ class CustomFieldsMixin(models.Model):
# Validate all field values
for field_name, value in self.custom_field_data.items():
if field_name not in custom_fields:
raise ValidationError(f"Unknown field name '{field_name}' in custom field data.")
raise ValidationError(_("Unknown field name '{field_name}' in custom field data.").format(
field_name=field_name))
try:
custom_fields[field_name].validate(value)
except ValidationError as e:
raise ValidationError(f"Invalid value for custom field '{field_name}': {e.message}")
raise ValidationError(_("Invalid value for custom field '{field_name}': {message}").format(
field_name=field_name, message=e.message))
# Check for missing required values
for cf in custom_fields.values():
if cf.required and cf.name not in self.custom_field_data:
raise ValidationError(f"Missing required custom field '{cf.name}'.")
raise ValidationError(_("Missing required custom field '{name}'.").format(name=cf.name))
class CustomLinksMixin(models.Model):
@ -547,7 +549,8 @@ class SyncedDataMixin(models.Model):
Inheriting models must override this method with specific logic to copy data from the assigned DataFile
to the local instance. This method should *NOT* call save() on the instance.
"""
raise NotImplementedError(f"{self.__class__} must implement a sync_data() method.")
raise NotImplementedError(_("{class_name} must implement a sync_data() method.").format(
class_name=self.__class__))
#

View File

@ -1,5 +1,6 @@
import inspect
from django.utils.translation import gettext_lazy as _
from netbox.registry import registry
from .navigation import PluginMenu, PluginMenuButton, PluginMenuItem
from .templates import PluginTemplateExtension
@ -20,18 +21,24 @@ def register_template_extensions(class_list):
# Validation
for template_extension in class_list:
if not inspect.isclass(template_extension):
raise TypeError(f"PluginTemplateExtension class {template_extension} was passed as an instance!")
raise TypeError(
_("PluginTemplateExtension class {template_extension} was passed as an instance!").format(
template_extension=template_extension))
if not issubclass(template_extension, PluginTemplateExtension):
raise TypeError(f"{template_extension} is not a subclass of netbox.plugins.PluginTemplateExtension!")
raise TypeError(
_("{template_extension} is not a subclass of netbox.plugins.PluginTemplateExtension!").format(
template_extension=template_extension))
if template_extension.model is None:
raise TypeError(f"PluginTemplateExtension class {template_extension} does not define a valid model!")
raise TypeError(
_("PluginTemplateExtension class {template_extension} does not define a valid model!").format(
template_extension=template_extension))
registry['plugins']['template_extensions'][template_extension.model].append(template_extension)
def register_menu(menu):
if not isinstance(menu, PluginMenu):
raise TypeError(f"{menu} must be an instance of netbox.plugins.PluginMenu")
raise TypeError(_("{menu} must be an instance of netbox.plugins.PluginMenu").format(menu=menu))
registry['plugins']['menus'].append(menu)
@ -42,10 +49,12 @@ def register_menu_items(section_name, class_list):
# Validation
for menu_link in class_list:
if not isinstance(menu_link, PluginMenuItem):
raise TypeError(f"{menu_link} must be an instance of netbox.plugins.PluginMenuItem")
raise TypeError(_("{menu_link} must be an instance of netbox.plugins.PluginMenuItem").format(
menu_link=menu_link))
for button in menu_link.buttons:
if not isinstance(button, PluginMenuButton):
raise TypeError(f"{button} must be an instance of netbox.plugins.PluginMenuButton")
raise TypeError(_("{button} must be an instance of netbox.plugins.PluginMenuButton").format(
button=button))
registry['plugins']['menu_items'][section_name] = class_list

View File

@ -11,7 +11,7 @@ class Registry(dict):
try:
return super().__getitem__(key)
except KeyError:
raise KeyError(f"Invalid store: {key}")
raise KeyError(_("Invalid store: {key}").format(key=key))
def __setitem__(self, key, value):
raise TypeError(_("Cannot add stores to registry after initialization"))

View File

@ -14,6 +14,7 @@ from django.http import HttpResponse
from django.shortcuts import get_object_or_404, redirect, render
from django.urls import reverse
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
from django_tables2.export import TableExport
from extras.models import ExportTemplate
@ -390,7 +391,7 @@ class BulkImportView(GetReturnURLMixin, BaseMultiObjectView):
try:
instance = prefetched_objects[object_id]
except KeyError:
form.add_error('data', f"Row {i}: Object with ID {object_id} does not exist")
form.add_error('data', _("Row {i}: Object with ID {object_id} does not exist").format(i=i, object_id=object_id))
raise ValidationError('')
# Take a snapshot for change logging

View File

@ -11,6 +11,7 @@ from django.shortcuts import redirect, render
from django.urls import reverse
from django.utils.html import escape
from django.utils.safestring import mark_safe
from django.utils.translation import gettext as _
from extras.signals import clear_events
from utilities.error_handlers import handle_protectederror
@ -101,7 +102,8 @@ class ObjectChildrenView(ObjectView, ActionsMixin, TableMixin):
request: The current request
parent: The parent object
"""
raise NotImplementedError(f'{self.__class__.__name__} must implement get_children()')
raise NotImplementedError(_('{class_name} must implement get_children()').format(
class_name=self.__class__.__name__))
def prep_table_data(self, request, queryset, parent):
"""

View File

@ -78,7 +78,7 @@ class BulkImportForm(BootstrapMixin, SyncedDataMixin, forms.Form):
elif format == ImportFormatChoices.YAML:
self.cleaned_data['data'] = self._clean_yaml(data)
else:
raise forms.ValidationError(f"Unknown data format: {format}")
raise forms.ValidationError(_("Unknown data format: {format}").format(format=format))
def _detect_format(self, data):
"""

View File

@ -2,6 +2,7 @@ import re
from django import forms
from django.forms.models import fields_for_model
from django.utils.translation import gettext as _
from utilities.choices import unpack_grouped_choices
from utilities.querysets import RestrictedQuerySet
@ -38,7 +39,7 @@ def parse_numeric_range(string, base=10):
try:
begin, end = int(begin.strip(), base=base), int(end.strip(), base=base) + 1
except ValueError:
raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
raise forms.ValidationError(_('Range "{dash_range}" is invalid.').format(dash_range=dash_range))
values.extend(range(begin, end))
return sorted(set(values))
@ -61,7 +62,7 @@ def parse_alphanumeric_range(string):
begin, end = dash_range, dash_range
if begin.isdigit() and end.isdigit():
if int(begin) >= int(end):
raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
raise forms.ValidationError(_('Range "{dash_range}" is invalid.').format(dash_range=dash_range))
for n in list(range(int(begin), int(end) + 1)):
values.append(n)
@ -73,10 +74,10 @@ def parse_alphanumeric_range(string):
else:
# Not a valid range (more than a single character)
if not len(begin) == len(end) == 1:
raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
raise forms.ValidationError(_('Range "{dash_range}" is invalid.').format(dash_range=dash_range))
if ord(begin) >= ord(end):
raise forms.ValidationError(f'Range "{dash_range}" is invalid.')
raise forms.ValidationError(_('Range "{dash_range}" is invalid.').format(dash_range=dash_range))
for n in list(range(ord(begin), ord(end) + 1)):
values.append(chr(n))
@ -221,18 +222,21 @@ def parse_csv(reader):
if '.' in header:
field, to_field = header.split('.', 1)
if field in headers:
raise forms.ValidationError(f'Duplicate or conflicting column header for "{field}"')
raise forms.ValidationError(_('Duplicate or conflicting column header for "{field}"').format(
field=field))
headers[field] = to_field
else:
if header in headers:
raise forms.ValidationError(f'Duplicate or conflicting column header for "{header}"')
raise forms.ValidationError(_('Duplicate or conflicting column header for "{header}"').format(
header=header))
headers[header] = None
# Parse CSV rows into a list of dictionaries mapped from the column headers.
for i, row in enumerate(reader, start=1):
if len(row) != len(headers):
raise forms.ValidationError(
f"Row {i}: Expected {len(headers)} columns but found {len(row)}"
_("Row {i}: Expected {len_headers} columns but found {len_row}").format(
len_headers=len(headers), len_row=len(row))
)
row = [col.strip() for col in row]
record = dict(zip(headers.keys(), row))
@ -253,14 +257,16 @@ def validate_csv(headers, fields, required_fields):
is_update = True
continue
if field not in fields:
raise forms.ValidationError(f'Unexpected column header "{field}" found.')
raise forms.ValidationError(_('Unexpected column header "{field}" found.').format(field=field))
if to_field and not hasattr(fields[field], 'to_field_name'):
raise forms.ValidationError(f'Column "{field}" is not a related object; cannot use dots')
raise forms.ValidationError(_('Column "{field}" is not a related object; cannot use dots').format(
field=field))
if to_field and not hasattr(fields[field].queryset.model, to_field):
raise forms.ValidationError(f'Invalid related object attribute for column "{field}": {to_field}')
raise forms.ValidationError(_('Invalid related object attribute for column "{field}": {to_field}').format(
field=field, to_field=to_field))
# Validate required fields (if not an update)
if not is_update:
for f in required_fields:
if f not in headers:
raise forms.ValidationError(f'Required column header "{f}" not found.')
raise forms.ValidationError(_('Required column header "{f}" not found.').format(f=f))

View File

@ -3,6 +3,7 @@ from typing import Dict, List, Tuple
from django import forms
from django.conf import settings
from django.utils.translation import gettext_lazy as _
__all__ = (
'APISelect',
@ -119,7 +120,9 @@ class APISelect(forms.Select):
update = [{'fieldName': f, 'queryParam': q} for (f, q) in self.dynamic_params.items()]
self._serialize_params(key, update)
except IndexError as error:
raise RuntimeError(f"Missing required value for dynamic query param: '{self.dynamic_params}'") from error
raise RuntimeError(
_("Missing required value for dynamic query param: '{dynamic_params}'").format(
dynamic_params=self.dynamic_params)) from error
def _add_static_params(self):
"""
@ -132,7 +135,9 @@ class APISelect(forms.Select):
update = [{'queryParam': k, 'queryValue': v} for (k, v) in self.static_params.items()]
self._serialize_params(key, update)
except IndexError as error:
raise RuntimeError(f"Missing required value for static query param: '{self.static_params}'") from error
raise RuntimeError(
_("Missing required value for static query param: '{static_params}'").format(
static_params=self.static_params)) from error
def add_query_params(self, query_params):
"""

View File

@ -1,6 +1,7 @@
from django.conf import settings
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
from django.utils.translation import gettext_lazy as _
__all__ = (
'get_permission_for_model',
@ -36,7 +37,7 @@ def resolve_permission(name):
action, model_name = codename.rsplit('_', 1)
except ValueError:
raise ValueError(
f"Invalid permission name: {name}. Must be in the format <app_label>.<action>_<model>"
_("Invalid permission name: {name}. Must be in the format <app_label>.<action>_<model>").format(name=name)
)
return app_label, action, model_name
@ -53,7 +54,7 @@ def resolve_permission_ct(name):
try:
content_type = ContentType.objects.get(app_label=app_label, model=model_name)
except ContentType.DoesNotExist:
raise ValueError(f"Unknown app_label/model_name for {name}")
raise ValueError(_("Unknown app_label/model_name for {name}").format(name=name))
return content_type, action

View File

@ -1,3 +1,4 @@
from django.utils.translation import gettext_lazy as _
from netaddr import AddrFormatError, IPAddress
from urllib.parse import urlparse
@ -29,7 +30,7 @@ def get_client_ip(request, additional_headers=()):
return IPAddress(ip)
except AddrFormatError:
# We did our best
raise ValueError(f"Invalid IP address set for {header}: {ip}")
raise ValueError(_("Invalid IP address set for {header}: {ip}").format(header=header, ip=ip))
# Could not determine the client IP address from request headers
return None

View File

@ -1,3 +1,4 @@
from django.utils.translation import gettext_lazy as _
from netbox.registry import registry
__all__ = (
@ -43,5 +44,6 @@ def register_table_column(column, name, *tables):
for table in tables:
reg = registry['tables'][table]
if name in reg:
raise ValueError(f"A column named {name} is already defined for table {table.__name__}")
raise ValueError(_("A column named {name} is already defined for table {table_name}").format(
name=name, table_name=table.__name__))
reg[name] = column

View File

@ -2,6 +2,7 @@ import re
from django.core.exceptions import ValidationError
from django.core.validators import BaseValidator, RegexValidator, URLValidator, _lazy_re_compile
from django.utils.translation import gettext_lazy as _
from netbox.config import get_config
@ -61,4 +62,4 @@ def validate_regex(value):
try:
re.compile(value)
except re.error:
raise ValidationError(f"{value} is not a valid regular expression.")
raise ValidationError(_("{value} is not a valid regular expression.").format(value=value))

View File

@ -2,6 +2,7 @@ from django.contrib.auth.mixins import AccessMixin
from django.core.exceptions import ImproperlyConfigured
from django.urls import reverse
from django.urls.exceptions import NoReverseMatch
from django.utils.translation import gettext_lazy as _
from netbox.registry import registry
from .permissions import resolve_permission
@ -34,7 +35,8 @@ class ContentTypePermissionRequiredMixin(AccessMixin):
"""
Return the specific permission necessary to perform the requested action on an object.
"""
raise NotImplementedError(f"{self.__class__.__name__} must implement get_required_permission()")
raise NotImplementedError(_("{self.__class__.__name__} must implement get_required_permission()").format(
class_name=self.__class__.__name__))
def has_permission(self):
user = self.request.user
@ -68,7 +70,8 @@ class ObjectPermissionRequiredMixin(AccessMixin):
"""
Return the specific permission necessary to perform the requested action on an object.
"""
raise NotImplementedError(f"{self.__class__.__name__} must implement get_required_permission()")
raise NotImplementedError(_("{class_name} must implement get_required_permission()").format(
class_name=self.__class__.__name__))
def has_permission(self):
user = self.request.user
@ -89,8 +92,8 @@ class ObjectPermissionRequiredMixin(AccessMixin):
if not hasattr(self, 'queryset'):
raise ImproperlyConfigured(
'{} has no queryset defined. ObjectPermissionRequiredMixin may only be used on views which define '
'a base queryset'.format(self.__class__.__name__)
_('{} has no queryset defined. ObjectPermissionRequiredMixin may only be used on views which define a base queryset').format(
self.__class__.__name__)
)
if not self.has_permission():

View File

@ -1,4 +1,5 @@
from decimal import Decimal
from django.utils.translation import gettext_lazy as _
from .choices import WirelessChannelChoices
@ -12,7 +13,7 @@ def get_channel_attr(channel, attr):
Return the specified attribute of a given WirelessChannelChoices value.
"""
if channel not in WirelessChannelChoices.values():
raise ValueError(f"Invalid channel value: {channel}")
raise ValueError(_("Invalid channel value: {channel}").format(channel=channel))
channel_values = channel.split('-')
attrs = {
@ -22,6 +23,6 @@ def get_channel_attr(channel, attr):
'width': Decimal(channel_values[3]),
}
if attr not in attrs:
raise ValueError(f"Invalid channel attribute: {attr}")
raise ValueError(_("Invalid channel attribute: {attr}").format(attr=attr))
return attrs[attr]