diff --git a/netbox/circuits/filtersets.py b/netbox/circuits/filtersets.py
index cf250584f..8e4c9ab06 100644
--- a/netbox/circuits/filtersets.py
+++ b/netbox/circuits/filtersets.py
@@ -1,5 +1,6 @@
import django_filters
from django.db.models import Q
+from django.utils.translation import gettext as _
from dcim.filtersets import CabledObjectFilterSet
from dcim.models import Region, Site, SiteGroup
@@ -24,43 +25,43 @@ class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
queryset=Region.objects.all(),
field_name='circuits__terminations__site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='circuits__terminations__site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='circuits__terminations__site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='circuits__terminations__site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='circuits__terminations__site',
queryset=Site.objects.all(),
- label='Site',
+ label=_('Site'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='circuits__terminations__site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
asn_id = django_filters.ModelMultipleChoiceFilter(
field_name='asns',
queryset=ASN.objects.all(),
- label='ASN (ID)',
+ label=_('ASN (ID)'),
)
class Meta:
@@ -80,13 +81,13 @@ class ProviderFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
class ProviderNetworkFilterSet(NetBoxModelFilterSet):
provider_id = django_filters.ModelMultipleChoiceFilter(
queryset=Provider.objects.all(),
- label='Provider (ID)',
+ label=_('Provider (ID)'),
)
provider = django_filters.ModelMultipleChoiceFilter(
field_name='provider__slug',
queryset=Provider.objects.all(),
to_field_name='slug',
- label='Provider (slug)',
+ label=_('Provider (slug)'),
)
class Meta:
@@ -114,28 +115,28 @@ class CircuitTypeFilterSet(OrganizationalModelFilterSet):
class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSet):
provider_id = django_filters.ModelMultipleChoiceFilter(
queryset=Provider.objects.all(),
- label='Provider (ID)',
+ label=_('Provider (ID)'),
)
provider = django_filters.ModelMultipleChoiceFilter(
field_name='provider__slug',
queryset=Provider.objects.all(),
to_field_name='slug',
- label='Provider (slug)',
+ label=_('Provider (slug)'),
)
provider_network_id = django_filters.ModelMultipleChoiceFilter(
field_name='terminations__provider_network',
queryset=ProviderNetwork.objects.all(),
- label='ProviderNetwork (ID)',
+ label=_('ProviderNetwork (ID)'),
)
type_id = django_filters.ModelMultipleChoiceFilter(
queryset=CircuitType.objects.all(),
- label='Circuit type (ID)',
+ label=_('Circuit type (ID)'),
)
type = django_filters.ModelMultipleChoiceFilter(
field_name='type__slug',
queryset=CircuitType.objects.all(),
to_field_name='slug',
- label='Circuit type (slug)',
+ label=_('Circuit type (slug)'),
)
status = django_filters.MultipleChoiceFilter(
choices=CircuitStatusChoices,
@@ -145,38 +146,38 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
queryset=Region.objects.all(),
field_name='terminations__site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='terminations__site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='terminations__site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='terminations__site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='terminations__site',
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='terminations__site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
class Meta:
@@ -199,25 +200,25 @@ class CircuitFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
class CircuitTerminationFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
circuit_id = django_filters.ModelMultipleChoiceFilter(
queryset=Circuit.objects.all(),
- label='Circuit',
+ label=_('Circuit'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
provider_network_id = django_filters.ModelMultipleChoiceFilter(
queryset=ProviderNetwork.objects.all(),
- label='ProviderNetwork (ID)',
+ label=_('ProviderNetwork (ID)'),
)
class Meta:
diff --git a/netbox/circuits/forms/bulk_edit.py b/netbox/circuits/forms/bulk_edit.py
index 6e9ae516c..e1fe6338d 100644
--- a/netbox/circuits/forms/bulk_edit.py
+++ b/netbox/circuits/forms/bulk_edit.py
@@ -28,7 +28,7 @@ class ProviderBulkEditForm(NetBoxModelBulkEditForm):
account = forms.CharField(
max_length=30,
required=False,
- label='Account number'
+ label=_('Account number')
)
description = forms.CharField(
max_length=200,
@@ -36,7 +36,7 @@ class ProviderBulkEditForm(NetBoxModelBulkEditForm):
)
comments = CommentField(
widget=SmallTextarea,
- label='Comments'
+ label=_('Comments')
)
model = Provider
@@ -56,7 +56,7 @@ class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm):
service_id = forms.CharField(
max_length=100,
required=False,
- label='Service ID'
+ label=_('Service ID')
)
description = forms.CharField(
max_length=200,
@@ -64,7 +64,7 @@ class ProviderNetworkBulkEditForm(NetBoxModelBulkEditForm):
)
comments = CommentField(
widget=SmallTextarea,
- label='Comments'
+ label=_('Comments')
)
model = ProviderNetwork
@@ -118,7 +118,7 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm):
)
commit_rate = forms.IntegerField(
required=False,
- label='Commit rate (Kbps)'
+ label=_('Commit rate (Kbps)')
)
description = forms.CharField(
max_length=100,
@@ -126,7 +126,7 @@ class CircuitBulkEditForm(NetBoxModelBulkEditForm):
)
comments = CommentField(
widget=SmallTextarea,
- label='Comments'
+ label=_('Comments')
)
model = Circuit
diff --git a/netbox/circuits/forms/bulk_import.py b/netbox/circuits/forms/bulk_import.py
index 4976e2d9b..97b6af428 100644
--- a/netbox/circuits/forms/bulk_import.py
+++ b/netbox/circuits/forms/bulk_import.py
@@ -1,5 +1,6 @@
from circuits.choices import CircuitStatusChoices
from circuits.models import *
+from django.utils.translation import gettext as _
from netbox.forms import NetBoxModelCSVForm
from tenancy.models import Tenant
from utilities.forms import CSVChoiceField, CSVModelChoiceField, SlugField
@@ -26,7 +27,7 @@ class ProviderNetworkCSVForm(NetBoxModelCSVForm):
provider = CSVModelChoiceField(
queryset=Provider.objects.all(),
to_field_name='name',
- help_text='Assigned provider'
+ help_text=_('Assigned provider')
)
class Meta:
@@ -43,7 +44,7 @@ class CircuitTypeCSVForm(NetBoxModelCSVForm):
model = CircuitType
fields = ('name', 'slug', 'description', 'tags')
help_texts = {
- 'name': 'Name of circuit type',
+ 'name': _('Name of circuit type'),
}
@@ -51,22 +52,22 @@ class CircuitCSVForm(NetBoxModelCSVForm):
provider = CSVModelChoiceField(
queryset=Provider.objects.all(),
to_field_name='name',
- help_text='Assigned provider'
+ help_text=_('Assigned provider')
)
type = CSVModelChoiceField(
queryset=CircuitType.objects.all(),
to_field_name='name',
- help_text='Type of circuit'
+ help_text=_('Type of circuit')
)
status = CSVChoiceField(
choices=CircuitStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
diff --git a/netbox/circuits/forms/model_forms.py b/netbox/circuits/forms/model_forms.py
index ab1b6bca2..890462aaa 100644
--- a/netbox/circuits/forms/model_forms.py
+++ b/netbox/circuits/forms/model_forms.py
@@ -39,7 +39,7 @@ class ProviderForm(NetBoxModelForm):
'name', 'slug', 'account', 'asns', 'description', 'comments', 'tags',
]
help_texts = {
- 'name': "Full name of the provider",
+ 'name': _("Full name of the provider"),
}
@@ -98,8 +98,8 @@ class CircuitForm(TenancyForm, NetBoxModelForm):
'tenant_group', 'tenant', 'comments', 'tags',
]
help_texts = {
- 'cid': "Unique circuit ID",
- 'commit_rate': "Committed rate",
+ 'cid': _("Unique circuit ID"),
+ 'commit_rate': _("Committed rate"),
}
widgets = {
'status': StaticSelect(),
@@ -157,9 +157,9 @@ class CircuitTerminationForm(NetBoxModelForm):
'port_speed', 'upstream_speed', 'xconnect_id', 'pp_info', 'description', 'tags',
]
help_texts = {
- 'port_speed': "Physical circuit speed",
- 'xconnect_id': "ID of the local cross-connect",
- 'pp_info': "Patch panel ID and port number(s)"
+ 'port_speed': _("Physical circuit speed"),
+ 'xconnect_id': _("ID of the local cross-connect"),
+ 'pp_info': _("Patch panel ID and port number(s)")
}
widgets = {
'term_side': StaticSelect(),
diff --git a/netbox/circuits/models/circuits.py b/netbox/circuits/models/circuits.py
index 9d302bb8e..ebba74738 100644
--- a/netbox/circuits/models/circuits.py
+++ b/netbox/circuits/models/circuits.py
@@ -3,6 +3,7 @@ from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.db import models
from django.urls import reverse
+from django.utils.translation import gettext as _
from circuits.choices import *
from dcim.models import CabledObjectModel
@@ -168,7 +169,7 @@ class CircuitTermination(
blank=True,
null=True,
verbose_name='Upstream speed (Kbps)',
- help_text='Upstream speed, if different from port speed'
+ help_text=_('Upstream speed, if different from port speed')
)
xconnect_id = models.CharField(
max_length=50,
diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py
index 33d79612a..4b8c95a73 100644
--- a/netbox/dcim/api/serializers.py
+++ b/netbox/dcim/api/serializers.py
@@ -1,6 +1,7 @@
import decimal
from django.contrib.contenttypes.models import ContentType
+from django.utils.translation import gettext as _
from drf_yasg.utils import swagger_serializer_method
from rest_framework import serializers
from timezone_field.rest_framework import TimeZoneSerializerField
@@ -197,7 +198,7 @@ class RackSerializer(NetBoxModelSerializer):
status = ChoiceField(choices=RackStatusChoices, required=False)
role = NestedRackRoleSerializer(required=False, allow_null=True)
type = ChoiceField(choices=RackTypeChoices, allow_blank=True, required=False)
- facility_id = serializers.CharField(max_length=50, allow_blank=True, allow_null=True, label='Facility ID',
+ facility_id = serializers.CharField(max_length=50, allow_blank=True, allow_null=True, label=_('Facility ID'),
default=None)
width = ChoiceField(choices=RackWidthChoices, required=False)
outer_unit = ChoiceField(choices=RackDimensionUnitChoices, allow_blank=True, required=False)
@@ -311,7 +312,7 @@ class DeviceTypeSerializer(NetBoxModelSerializer):
u_height = serializers.DecimalField(
max_digits=4,
decimal_places=1,
- label='Position (U)',
+ label=_('Position (U)'),
min_value=0,
default=1.0
)
@@ -636,7 +637,7 @@ class DeviceSerializer(NetBoxModelSerializer):
max_digits=4,
decimal_places=1,
allow_null=True,
- label='Position (U)',
+ label=_('Position (U)'),
min_value=decimal.Decimal(0.5),
default=None
)
diff --git a/netbox/dcim/filtersets.py b/netbox/dcim/filtersets.py
index 88d84a7ab..53576d017 100644
--- a/netbox/dcim/filtersets.py
+++ b/netbox/dcim/filtersets.py
@@ -1,5 +1,6 @@
import django_filters
from django.contrib.auth.models import User
+from django.utils.translation import gettext as _
from extras.filtersets import LocalConfigContextFilterSet
from ipam.models import ASN, VRF
@@ -72,13 +73,13 @@ __all__ = (
class RegionFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
parent_id = django_filters.ModelMultipleChoiceFilter(
queryset=Region.objects.all(),
- label='Parent region (ID)',
+ label=_('Parent region (ID)'),
)
parent = django_filters.ModelMultipleChoiceFilter(
field_name='parent__slug',
queryset=Region.objects.all(),
to_field_name='slug',
- label='Parent region (slug)',
+ label=_('Parent region (slug)'),
)
class Meta:
@@ -89,13 +90,13 @@ class RegionFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
class SiteGroupFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet):
parent_id = django_filters.ModelMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
- label='Parent site group (ID)',
+ label=_('Parent site group (ID)'),
)
parent = django_filters.ModelMultipleChoiceFilter(
field_name='parent__slug',
queryset=SiteGroup.objects.all(),
to_field_name='slug',
- label='Parent site group (slug)',
+ label=_('Parent site group (slug)'),
)
class Meta:
@@ -112,36 +113,36 @@ class SiteFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
queryset=Region.objects.all(),
field_name='region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='group',
lookup_expr='in',
- label='Group (ID)',
+ label=_('Group (ID)'),
)
group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
lookup_expr='in',
to_field_name='slug',
- label='Group (slug)',
+ label=_('Group (slug)'),
)
asn = django_filters.ModelMultipleChoiceFilter(
field_name='asns__asn',
queryset=ASN.objects.all(),
to_field_name='asn',
- label='AS (ID)',
+ label=_('AS (ID)'),
)
asn_id = django_filters.ModelMultipleChoiceFilter(
field_name='asns',
queryset=ASN.objects.all(),
- label='AS (ID)',
+ label=_('AS (ID)'),
)
class Meta:
@@ -173,50 +174,50 @@ class LocationFilterSet(TenancyFilterSet, ContactModelFilterSet, OrganizationalM
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
parent_id = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='parent',
lookup_expr='in',
- label='Location (ID)',
+ label=_('Location (ID)'),
)
parent = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='parent',
lookup_expr='in',
to_field_name='slug',
- label='Location (slug)',
+ label=_('Location (slug)'),
)
status = django_filters.MultipleChoiceFilter(
choices=LocationStatusChoices,
@@ -248,50 +249,50 @@ class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
location_id = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='location',
lookup_expr='in',
- label='Location (ID)',
+ label=_('Location (ID)'),
)
location = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='location',
lookup_expr='in',
to_field_name='slug',
- label='Location (slug)',
+ label=_('Location (slug)'),
)
status = django_filters.MultipleChoiceFilter(
choices=RackStatusChoices,
@@ -305,13 +306,13 @@ class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=RackRole.objects.all(),
- label='Role (ID)',
+ label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=RackRole.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
serial = MultiValueCharFilter(
lookup_expr='iexact'
@@ -339,67 +340,67 @@ class RackFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilterSe
class RackReservationFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
rack_id = django_filters.ModelMultipleChoiceFilter(
queryset=Rack.objects.all(),
- label='Rack (ID)',
+ label=_('Rack (ID)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='rack__site',
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='rack__site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='rack__site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='rack__site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='rack__site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='rack__site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
location_id = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='rack__location',
lookup_expr='in',
- label='Location (ID)',
+ label=_('Location (ID)'),
)
location = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='rack__location',
lookup_expr='in',
to_field_name='slug',
- label='Location (slug)',
+ label=_('Location (slug)'),
)
user_id = django_filters.ModelMultipleChoiceFilter(
queryset=User.objects.all(),
- label='User (ID)',
+ label=_('User (ID)'),
)
user = django_filters.ModelMultipleChoiceFilter(
field_name='user__username',
queryset=User.objects.all(),
to_field_name='username',
- label='User (name)',
+ label=_('User (name)'),
)
class Meta:
@@ -427,57 +428,57 @@ class ManufacturerFilterSet(OrganizationalModelFilterSet, ContactModelFilterSet)
class DeviceTypeFilterSet(NetBoxModelFilterSet):
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
queryset=Manufacturer.objects.all(),
- label='Manufacturer (ID)',
+ label=_('Manufacturer (ID)'),
)
manufacturer = django_filters.ModelMultipleChoiceFilter(
field_name='manufacturer__slug',
queryset=Manufacturer.objects.all(),
to_field_name='slug',
- label='Manufacturer (slug)',
+ label=_('Manufacturer (slug)'),
)
has_front_image = django_filters.BooleanFilter(
- label='Has a front image',
+ label=_('Has a front image'),
method='_has_front_image'
)
has_rear_image = django_filters.BooleanFilter(
- label='Has a rear image',
+ label=_('Has a rear image'),
method='_has_rear_image'
)
console_ports = django_filters.BooleanFilter(
method='_console_ports',
- label='Has console ports',
+ label=_('Has console ports'),
)
console_server_ports = django_filters.BooleanFilter(
method='_console_server_ports',
- label='Has console server ports',
+ label=_('Has console server ports'),
)
power_ports = django_filters.BooleanFilter(
method='_power_ports',
- label='Has power ports',
+ label=_('Has power ports'),
)
power_outlets = django_filters.BooleanFilter(
method='_power_outlets',
- label='Has power outlets',
+ label=_('Has power outlets'),
)
interfaces = django_filters.BooleanFilter(
method='_interfaces',
- label='Has interfaces',
+ label=_('Has interfaces'),
)
pass_through_ports = django_filters.BooleanFilter(
method='_pass_through_ports',
- label='Has pass-through ports',
+ label=_('Has pass-through ports'),
)
module_bays = django_filters.BooleanFilter(
method='_module_bays',
- label='Has module bays',
+ label=_('Has module bays'),
)
device_bays = django_filters.BooleanFilter(
method='_device_bays',
- label='Has device bays',
+ label=_('Has device bays'),
)
inventory_items = django_filters.BooleanFilter(
method='_inventory_items',
- label='Has inventory items',
+ label=_('Has inventory items'),
)
class Meta:
@@ -542,37 +543,37 @@ class DeviceTypeFilterSet(NetBoxModelFilterSet):
class ModuleTypeFilterSet(NetBoxModelFilterSet):
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
queryset=Manufacturer.objects.all(),
- label='Manufacturer (ID)',
+ label=_('Manufacturer (ID)'),
)
manufacturer = django_filters.ModelMultipleChoiceFilter(
field_name='manufacturer__slug',
queryset=Manufacturer.objects.all(),
to_field_name='slug',
- label='Manufacturer (slug)',
+ label=_('Manufacturer (slug)'),
)
console_ports = django_filters.BooleanFilter(
method='_console_ports',
- label='Has console ports',
+ label=_('Has console ports'),
)
console_server_ports = django_filters.BooleanFilter(
method='_console_server_ports',
- label='Has console server ports',
+ label=_('Has console server ports'),
)
power_ports = django_filters.BooleanFilter(
method='_power_ports',
- label='Has power ports',
+ label=_('Has power ports'),
)
power_outlets = django_filters.BooleanFilter(
method='_power_outlets',
- label='Has power outlets',
+ label=_('Has power outlets'),
)
interfaces = django_filters.BooleanFilter(
method='_interfaces',
- label='Has interfaces',
+ label=_('Has interfaces'),
)
pass_through_ports = django_filters.BooleanFilter(
method='_pass_through_ports',
- label='Has pass-through ports',
+ label=_('Has pass-through ports'),
)
class Meta:
@@ -614,12 +615,12 @@ class ModuleTypeFilterSet(NetBoxModelFilterSet):
class DeviceTypeComponentFilterSet(django_filters.FilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
devicetype_id = django_filters.ModelMultipleChoiceFilter(
queryset=DeviceType.objects.all(),
field_name='device_type_id',
- label='Device type (ID)',
+ label=_('Device type (ID)'),
)
def search(self, queryset, name, value):
@@ -632,7 +633,7 @@ class ModularDeviceTypeComponentFilterSet(DeviceTypeComponentFilterSet):
moduletype_id = django_filters.ModelMultipleChoiceFilter(
queryset=ModuleType.objects.all(),
field_name='module_type_id',
- label='Module type (ID)',
+ label=_('Module type (ID)'),
)
@@ -724,27 +725,27 @@ class DeviceBayTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponent
class InventoryItemTemplateFilterSet(ChangeLoggedModelFilterSet, DeviceTypeComponentFilterSet):
parent_id = django_filters.ModelMultipleChoiceFilter(
queryset=InventoryItemTemplate.objects.all(),
- label='Parent inventory item (ID)',
+ label=_('Parent inventory item (ID)'),
)
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
queryset=Manufacturer.objects.all(),
- label='Manufacturer (ID)',
+ label=_('Manufacturer (ID)'),
)
manufacturer = django_filters.ModelMultipleChoiceFilter(
field_name='manufacturer__slug',
queryset=Manufacturer.objects.all(),
to_field_name='slug',
- label='Manufacturer (slug)',
+ label=_('Manufacturer (slug)'),
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=InventoryItemRole.objects.all(),
- label='Role (ID)',
+ label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=InventoryItemRole.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
component_type = ContentTypeFilter()
component_id = MultiValueNumberFilter()
@@ -775,13 +776,13 @@ class PlatformFilterSet(OrganizationalModelFilterSet):
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
field_name='manufacturer',
queryset=Manufacturer.objects.all(),
- label='Manufacturer (ID)',
+ label=_('Manufacturer (ID)'),
)
manufacturer = django_filters.ModelMultipleChoiceFilter(
field_name='manufacturer__slug',
queryset=Manufacturer.objects.all(),
to_field_name='slug',
- label='Manufacturer (slug)',
+ label=_('Manufacturer (slug)'),
)
class Meta:
@@ -793,106 +794,106 @@ class DeviceFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilter
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
field_name='device_type__manufacturer',
queryset=Manufacturer.objects.all(),
- label='Manufacturer (ID)',
+ label=_('Manufacturer (ID)'),
)
manufacturer = django_filters.ModelMultipleChoiceFilter(
field_name='device_type__manufacturer__slug',
queryset=Manufacturer.objects.all(),
to_field_name='slug',
- label='Manufacturer (slug)',
+ label=_('Manufacturer (slug)'),
)
device_type = django_filters.ModelMultipleChoiceFilter(
field_name='device_type__slug',
queryset=DeviceType.objects.all(),
to_field_name='slug',
- label='Device type (slug)',
+ label=_('Device type (slug)'),
)
device_type_id = django_filters.ModelMultipleChoiceFilter(
queryset=DeviceType.objects.all(),
- label='Device type (ID)',
+ label=_('Device type (ID)'),
)
role_id = django_filters.ModelMultipleChoiceFilter(
field_name='device_role_id',
queryset=DeviceRole.objects.all(),
- label='Role (ID)',
+ label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='device_role__slug',
queryset=DeviceRole.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
parent_device_id = django_filters.ModelMultipleChoiceFilter(
field_name='parent_bay__device',
queryset=Device.objects.all(),
- label='Parent Device (ID)',
+ label=_('Parent Device (ID)'),
)
platform_id = django_filters.ModelMultipleChoiceFilter(
queryset=Platform.objects.all(),
- label='Platform (ID)',
+ label=_('Platform (ID)'),
)
platform = django_filters.ModelMultipleChoiceFilter(
field_name='platform__slug',
queryset=Platform.objects.all(),
to_field_name='slug',
- label='Platform (slug)',
+ label=_('Platform (slug)'),
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site name (slug)',
+ label=_('Site name (slug)'),
)
location_id = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='location',
lookup_expr='in',
- label='Location (ID)',
+ label=_('Location (ID)'),
)
rack_id = django_filters.ModelMultipleChoiceFilter(
field_name='rack',
queryset=Rack.objects.all(),
- label='Rack (ID)',
+ label=_('Rack (ID)'),
)
cluster_id = django_filters.ModelMultipleChoiceFilter(
queryset=Cluster.objects.all(),
- label='VM cluster (ID)',
+ label=_('VM cluster (ID)'),
)
model = django_filters.ModelMultipleChoiceFilter(
field_name='device_type__slug',
queryset=DeviceType.objects.all(),
to_field_name='slug',
- label='Device model (slug)',
+ label=_('Device model (slug)'),
)
name = MultiValueCharFilter(
lookup_expr='iexact'
@@ -903,59 +904,59 @@ class DeviceFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilter
)
is_full_depth = django_filters.BooleanFilter(
field_name='device_type__is_full_depth',
- label='Is full depth',
+ label=_('Is full depth'),
)
mac_address = MultiValueMACAddressFilter(
field_name='interfaces__mac_address',
- label='MAC address',
+ label=_('MAC address'),
)
serial = MultiValueCharFilter(
lookup_expr='iexact'
)
has_primary_ip = django_filters.BooleanFilter(
method='_has_primary_ip',
- label='Has a primary IP',
+ label=_('Has a primary IP'),
)
virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_chassis',
queryset=VirtualChassis.objects.all(),
- label='Virtual chassis (ID)',
+ label=_('Virtual chassis (ID)'),
)
virtual_chassis_member = django_filters.BooleanFilter(
method='_virtual_chassis_member',
- label='Is a virtual chassis member'
+ label=_('Is a virtual chassis member')
)
console_ports = django_filters.BooleanFilter(
method='_console_ports',
- label='Has console ports',
+ label=_('Has console ports'),
)
console_server_ports = django_filters.BooleanFilter(
method='_console_server_ports',
- label='Has console server ports',
+ label=_('Has console server ports'),
)
power_ports = django_filters.BooleanFilter(
method='_power_ports',
- label='Has power ports',
+ label=_('Has power ports'),
)
power_outlets = django_filters.BooleanFilter(
method='_power_outlets',
- label='Has power outlets',
+ label=_('Has power outlets'),
)
interfaces = django_filters.BooleanFilter(
method='_interfaces',
- label='Has interfaces',
+ label=_('Has interfaces'),
)
pass_through_ports = django_filters.BooleanFilter(
method='_pass_through_ports',
- label='Has pass-through ports',
+ label=_('Has pass-through ports'),
)
module_bays = django_filters.BooleanFilter(
method='_module_bays',
- label='Has module bays',
+ label=_('Has module bays'),
)
device_bays = django_filters.BooleanFilter(
method='_device_bays',
- label='Has device bays',
+ label=_('Has device bays'),
)
class Meta:
@@ -1052,34 +1053,34 @@ class ModuleFilterSet(NetBoxModelFilterSet):
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
field_name='module_type__manufacturer',
queryset=Manufacturer.objects.all(),
- label='Manufacturer (ID)',
+ label=_('Manufacturer (ID)'),
)
manufacturer = django_filters.ModelMultipleChoiceFilter(
field_name='module_type__manufacturer__slug',
queryset=Manufacturer.objects.all(),
to_field_name='slug',
- label='Manufacturer (slug)',
+ label=_('Manufacturer (slug)'),
)
module_type_id = django_filters.ModelMultipleChoiceFilter(
field_name='module_type',
queryset=ModuleType.objects.all(),
- label='Module type (ID)',
+ label=_('Module type (ID)'),
)
module_type = django_filters.ModelMultipleChoiceFilter(
field_name='module_type__model',
queryset=ModuleType.objects.all(),
to_field_name='model',
- label='Module type (model)',
+ label=_('Module type (model)'),
)
module_bay_id = django_filters.ModelMultipleChoiceFilter(
field_name='module_bay',
queryset=ModuleBay.objects.all(),
to_field_name='id',
- label='Module Bay (ID)'
+ label=_('Module Bay (ID)')
)
device_id = django_filters.ModelMultipleChoiceFilter(
queryset=Device.objects.all(),
- label='Device (ID)',
+ label=_('Device (ID)'),
)
serial = MultiValueCharFilter(
lookup_expr='iexact'
@@ -1102,87 +1103,87 @@ class ModuleFilterSet(NetBoxModelFilterSet):
class DeviceComponentFilterSet(django_filters.FilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='device__site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='device__site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='device__site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='device__site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='device__site',
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='device__site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site name (slug)',
+ label=_('Site name (slug)'),
)
location_id = django_filters.ModelMultipleChoiceFilter(
field_name='device__location',
queryset=Location.objects.all(),
- label='Location (ID)',
+ label=_('Location (ID)'),
)
location = django_filters.ModelMultipleChoiceFilter(
field_name='device__location__slug',
queryset=Location.objects.all(),
to_field_name='slug',
- label='Location (slug)',
+ label=_('Location (slug)'),
)
rack_id = django_filters.ModelMultipleChoiceFilter(
field_name='device__rack',
queryset=Rack.objects.all(),
- label='Rack (ID)',
+ label=_('Rack (ID)'),
)
rack = django_filters.ModelMultipleChoiceFilter(
field_name='device__rack__name',
queryset=Rack.objects.all(),
to_field_name='name',
- label='Rack (name)',
+ label=_('Rack (name)'),
)
device_id = django_filters.ModelMultipleChoiceFilter(
queryset=Device.objects.all(),
- label='Device (ID)',
+ label=_('Device (ID)'),
)
device = django_filters.ModelMultipleChoiceFilter(
field_name='device__name',
queryset=Device.objects.all(),
to_field_name='name',
- label='Device (name)',
+ label=_('Device (name)'),
)
virtual_chassis_id = django_filters.ModelMultipleChoiceFilter(
field_name='device__virtual_chassis',
queryset=VirtualChassis.objects.all(),
- label='Virtual Chassis (ID)'
+ label=_('Virtual Chassis (ID)')
)
virtual_chassis = django_filters.ModelMultipleChoiceFilter(
field_name='device__virtual_chassis__name',
queryset=VirtualChassis.objects.all(),
to_field_name='name',
- label='Virtual Chassis',
+ label=_('Virtual Chassis'),
)
def search(self, queryset, name, value):
@@ -1202,7 +1203,7 @@ class ModularDeviceComponentFilterSet(DeviceComponentFilterSet):
"""
module_id = django_filters.ModelMultipleChoiceFilter(
queryset=Module.objects.all(),
- label='Module (ID)',
+ label=_('Module (ID)'),
)
@@ -1314,31 +1315,31 @@ class InterfaceFilterSet(
device = MultiValueCharFilter(
method='filter_device',
field_name='name',
- label='Device',
+ label=_('Device'),
)
device_id = MultiValueNumberFilter(
method='filter_device_id',
field_name='pk',
- label='Device (ID)',
+ label=_('Device (ID)'),
)
kind = django_filters.CharFilter(
method='filter_kind',
- label='Kind of interface',
+ label=_('Kind of interface'),
)
parent_id = django_filters.ModelMultipleChoiceFilter(
field_name='parent',
queryset=Interface.objects.all(),
- label='Parent interface (ID)',
+ label=_('Parent interface (ID)'),
)
bridge_id = django_filters.ModelMultipleChoiceFilter(
field_name='bridge',
queryset=Interface.objects.all(),
- label='Bridged interface (ID)',
+ label=_('Bridged interface (ID)'),
)
lag_id = django_filters.ModelMultipleChoiceFilter(
field_name='lag',
queryset=Interface.objects.all(),
- label='LAG interface (ID)',
+ label=_('LAG interface (ID)'),
)
speed = MultiValueNumberFilter()
duplex = django_filters.MultipleChoiceFilter(
@@ -1354,11 +1355,11 @@ class InterfaceFilterSet(
)
vlan_id = django_filters.CharFilter(
method='filter_vlan_id',
- label='Assigned VLAN'
+ label=_('Assigned VLAN')
)
vlan = django_filters.CharFilter(
method='filter_vlan',
- label='Assigned VID'
+ label=_('Assigned VID')
)
type = django_filters.MultipleChoiceFilter(
choices=InterfaceTypeChoices,
@@ -1373,13 +1374,13 @@ class InterfaceFilterSet(
vrf_id = django_filters.ModelMultipleChoiceFilter(
field_name='vrf',
queryset=VRF.objects.all(),
- label='VRF',
+ label=_('VRF'),
)
vrf = django_filters.ModelMultipleChoiceFilter(
field_name='vrf__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
- label='VRF (RD)',
+ label=_('VRF (RD)'),
)
vdc_id = django_filters.ModelMultipleChoiceFilter(
field_name='vdcs',
@@ -1501,27 +1502,27 @@ class DeviceBayFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
class InventoryItemFilterSet(DeviceComponentFilterSet, NetBoxModelFilterSet):
parent_id = django_filters.ModelMultipleChoiceFilter(
queryset=InventoryItem.objects.all(),
- label='Parent inventory item (ID)',
+ label=_('Parent inventory item (ID)'),
)
manufacturer_id = django_filters.ModelMultipleChoiceFilter(
queryset=Manufacturer.objects.all(),
- label='Manufacturer (ID)',
+ label=_('Manufacturer (ID)'),
)
manufacturer = django_filters.ModelMultipleChoiceFilter(
field_name='manufacturer__slug',
queryset=Manufacturer.objects.all(),
to_field_name='slug',
- label='Manufacturer (slug)',
+ label=_('Manufacturer (slug)'),
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=InventoryItemRole.objects.all(),
- label='Role (ID)',
+ label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=InventoryItemRole.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
component_type = ContentTypeFilter()
component_id = MultiValueNumberFilter()
@@ -1556,61 +1557,61 @@ class InventoryItemRoleFilterSet(OrganizationalModelFilterSet):
class VirtualChassisFilterSet(NetBoxModelFilterSet):
master_id = django_filters.ModelMultipleChoiceFilter(
queryset=Device.objects.all(),
- label='Master (ID)',
+ label=_('Master (ID)'),
)
master = django_filters.ModelMultipleChoiceFilter(
field_name='master__name',
queryset=Device.objects.all(),
to_field_name='name',
- label='Master (name)',
+ label=_('Master (name)'),
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='master__site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='master__site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='master__site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='master__site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='master__site',
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='master__site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site name (slug)',
+ label=_('Site name (slug)'),
)
tenant_id = django_filters.ModelMultipleChoiceFilter(
field_name='master__tenant',
queryset=Tenant.objects.all(),
- label='Tenant (ID)',
+ label=_('Tenant (ID)'),
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='master__tenant__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
- label='Tenant (slug)',
+ label=_('Tenant (slug)'),
)
class Meta:
@@ -1709,43 +1710,43 @@ class PowerPanelFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site name (slug)',
+ label=_('Site name (slug)'),
)
location_id = TreeNodeMultipleChoiceFilter(
queryset=Location.objects.all(),
field_name='location',
lookup_expr='in',
- label='Location (ID)',
+ label=_('Location (ID)'),
)
class Meta:
@@ -1766,47 +1767,47 @@ class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpoi
queryset=Region.objects.all(),
field_name='power_panel__site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='power_panel__site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='power_panel__site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='power_panel__site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='power_panel__site',
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='power_panel__site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site name (slug)',
+ label=_('Site name (slug)'),
)
power_panel_id = django_filters.ModelMultipleChoiceFilter(
queryset=PowerPanel.objects.all(),
- label='Power panel (ID)',
+ label=_('Power panel (ID)'),
)
rack_id = django_filters.ModelMultipleChoiceFilter(
field_name='rack',
queryset=Rack.objects.all(),
- label='Rack (ID)',
+ label=_('Rack (ID)'),
)
status = django_filters.MultipleChoiceFilter(
choices=PowerFeedStatusChoices,
@@ -1836,7 +1837,7 @@ class PowerFeedFilterSet(NetBoxModelFilterSet, CabledObjectFilterSet, PathEndpoi
class ConnectionFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
site_id = MultiValueNumberFilter(
method='filter_connections',
diff --git a/netbox/dcim/forms/bulk_create.py b/netbox/dcim/forms/bulk_create.py
index f6bc27079..11fdfa6d2 100644
--- a/netbox/dcim/forms/bulk_create.py
+++ b/netbox/dcim/forms/bulk_create.py
@@ -1,6 +1,7 @@
from django import forms
from dcim.models import *
+from django.utils.translation import gettext as _
from extras.forms import CustomFieldsMixin
from extras.models import Tag
from utilities.forms import BootstrapMixin, DynamicModelMultipleChoiceField, ExpandableNameField, form_from_model
@@ -105,9 +106,9 @@ class ModuleBayBulkCreateForm(DeviceBulkAddComponentForm):
field_order = ('name', 'label', 'position_pattern', 'description', 'tags')
replication_fields = ('name', 'label', 'position')
position_pattern = ExpandableNameField(
- label='Position',
+ label=_('Position'),
required=False,
- help_text='Alphanumeric ranges are supported. (Must match the number of names being created.)'
+ help_text=_('Alphanumeric ranges are supported. (Must match the number of names being created.)')
)
diff --git a/netbox/dcim/forms/bulk_edit.py b/netbox/dcim/forms/bulk_edit.py
index 7a81ae7fb..c21988b45 100644
--- a/netbox/dcim/forms/bulk_edit.py
+++ b/netbox/dcim/forms/bulk_edit.py
@@ -1,6 +1,6 @@
from django import forms
-from django.utils.translation import gettext as _
from django.contrib.auth.models import User
+from django.utils.translation import gettext as _
from timezone_field import TimeZoneFormField
from dcim.choices import *
@@ -126,7 +126,7 @@ class SiteBulkEditForm(NetBoxModelBulkEditForm):
)
contact_email = forms.EmailField(
required=False,
- label='Contact E-mail'
+ label=_('Contact E-mail')
)
time_zone = TimeZoneFormField(
choices=add_blank_choice(TimeZoneFormField().choices),
@@ -248,7 +248,7 @@ class RackBulkEditForm(NetBoxModelBulkEditForm):
serial = forms.CharField(
max_length=50,
required=False,
- label='Serial Number'
+ label=_('Serial Number')
)
asset_tag = forms.CharField(
max_length=50,
@@ -266,12 +266,12 @@ class RackBulkEditForm(NetBoxModelBulkEditForm):
)
u_height = forms.IntegerField(
required=False,
- label='Height (U)'
+ label=_('Height (U)')
)
desc_units = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect,
- label='Descending units'
+ label=_('Descending units')
)
outer_width = forms.IntegerField(
required=False,
@@ -380,7 +380,7 @@ class DeviceTypeBulkEditForm(NetBoxModelBulkEditForm):
is_full_depth = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect(),
- label='Is full depth'
+ label=_('Is full depth')
)
airflow = forms.ChoiceField(
choices=add_blank_choice(DeviceAirflowChoices),
@@ -456,7 +456,7 @@ class DeviceRoleBulkEditForm(NetBoxModelBulkEditForm):
vm_role = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect,
- label='VM role'
+ label=_('VM role')
)
description = forms.CharField(
max_length=200,
@@ -540,7 +540,7 @@ class DeviceBulkEditForm(NetBoxModelBulkEditForm):
serial = forms.CharField(
max_length=50,
required=False,
- label='Serial Number'
+ label=_('Serial Number')
)
description = forms.CharField(
max_length=200,
@@ -577,7 +577,7 @@ class ModuleBulkEditForm(NetBoxModelBulkEditForm):
serial = forms.CharField(
max_length=50,
required=False,
- label='Serial Number'
+ label=_('Serial Number')
)
description = forms.CharField(
max_length=200,
@@ -767,7 +767,7 @@ class PowerFeedBulkEditForm(NetBoxModelBulkEditForm):
)
comments = CommentField(
widget=SmallTextarea,
- label='Comments'
+ label=_('Comments')
)
model = PowerFeed
@@ -838,12 +838,12 @@ class PowerPortTemplateBulkEditForm(BulkEditForm):
maximum_draw = forms.IntegerField(
min_value=1,
required=False,
- help_text="Maximum power draw (watts)"
+ help_text=_("Maximum power draw (watts)")
)
allocated_draw = forms.IntegerField(
min_value=1,
required=False,
- help_text="Allocated power draw (watts)"
+ help_text=_("Allocated power draw (watts)")
)
description = forms.CharField(
required=False
@@ -916,7 +916,7 @@ class InterfaceTemplateBulkEditForm(BulkEditForm):
mgmt_only = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect,
- label='Management only'
+ label=_('Management only')
)
description = forms.CharField(
required=False
@@ -926,14 +926,14 @@ class InterfaceTemplateBulkEditForm(BulkEditForm):
required=False,
initial='',
widget=StaticSelect(),
- label='PoE mode'
+ label=_('PoE mode')
)
poe_type = forms.ChoiceField(
choices=add_blank_choice(InterfacePoETypeChoices),
required=False,
initial='',
widget=StaticSelect(),
- label='PoE type'
+ label=_('PoE type')
)
nullable_fields = ('label', 'description', 'poe_mode', 'poe_type')
@@ -1174,31 +1174,31 @@ class InterfaceBulkEditForm(
query_params={
'type': 'lag',
},
- label='LAG'
+ label=_('LAG')
)
speed = forms.IntegerField(
required=False,
widget=SelectSpeedWidget(),
- label='Speed'
+ label=_('Speed')
)
mgmt_only = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect,
- label='Management only'
+ label=_('Management only')
)
poe_mode = forms.ChoiceField(
choices=add_blank_choice(InterfacePoEModeChoices),
required=False,
initial='',
widget=StaticSelect(),
- label='PoE mode'
+ label=_('PoE mode')
)
poe_type = forms.ChoiceField(
choices=add_blank_choice(InterfacePoETypeChoices),
required=False,
initial='',
widget=StaticSelect(),
- label='PoE type'
+ label=_('PoE type')
)
mark_connected = forms.NullBooleanField(
required=False,
@@ -1213,7 +1213,7 @@ class InterfaceBulkEditForm(
vlan_group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
- label='VLAN group'
+ label=_('VLAN group')
)
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
@@ -1221,7 +1221,7 @@ class InterfaceBulkEditForm(
query_params={
'group_id': '$vlan_group',
},
- label='Untagged VLAN'
+ label=_('Untagged VLAN')
)
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
@@ -1229,12 +1229,12 @@ class InterfaceBulkEditForm(
query_params={
'group_id': '$vlan_group',
},
- label='Tagged VLANs'
+ label=_('Tagged VLANs')
)
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
model = Interface
diff --git a/netbox/dcim/forms/bulk_import.py b/netbox/dcim/forms/bulk_import.py
index 6073ee6fc..c7dbfcb17 100644
--- a/netbox/dcim/forms/bulk_import.py
+++ b/netbox/dcim/forms/bulk_import.py
@@ -3,6 +3,7 @@ from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.forms.array import SimpleArrayField
from django.core.exceptions import ObjectDoesNotExist
from django.utils.safestring import mark_safe
+from django.utils.translation import gettext as _
from dcim.choices import *
from dcim.constants import *
@@ -52,7 +53,7 @@ class RegionCSVForm(NetBoxModelCSVForm):
queryset=Region.objects.all(),
required=False,
to_field_name='name',
- help_text='Name of parent region'
+ help_text=_('Name of parent region')
)
class Meta:
@@ -65,7 +66,7 @@ class SiteGroupCSVForm(NetBoxModelCSVForm):
queryset=SiteGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Name of parent site group'
+ help_text=_('Name of parent site group')
)
class Meta:
@@ -76,25 +77,25 @@ class SiteGroupCSVForm(NetBoxModelCSVForm):
class SiteCSVForm(NetBoxModelCSVForm):
status = CSVChoiceField(
choices=SiteStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
region = CSVModelChoiceField(
queryset=Region.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned region'
+ help_text=_('Assigned region')
)
group = CSVModelChoiceField(
queryset=SiteGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned group'
+ help_text=_('Assigned group')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
@@ -105,7 +106,7 @@ class SiteCSVForm(NetBoxModelCSVForm):
)
help_texts = {
'time_zone': mark_safe(
- 'Time zone (available options)'
+ _('Time zone (available options)')
)
}
@@ -114,26 +115,26 @@ class LocationCSVForm(NetBoxModelCSVForm):
site = CSVModelChoiceField(
queryset=Site.objects.all(),
to_field_name='name',
- help_text='Assigned site'
+ help_text=_('Assigned site')
)
parent = CSVModelChoiceField(
queryset=Location.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent location',
+ help_text=_('Parent location'),
error_messages={
- 'invalid_choice': 'Location not found.',
+ 'invalid_choice': _('Location not found.'),
}
)
status = CSVChoiceField(
choices=LocationStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
@@ -148,7 +149,7 @@ class RackRoleCSVForm(NetBoxModelCSVForm):
model = RackRole
fields = ('name', 'slug', 'color', 'description', 'tags')
help_texts = {
- 'color': mark_safe('RGB color in hexadecimal (e.g. 00ff00
)'),
+ 'color': mark_safe(_('RGB color in hexadecimal (e.g. 00ff00
)')),
}
@@ -166,31 +167,31 @@ class RackCSVForm(NetBoxModelCSVForm):
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Name of assigned tenant'
+ help_text=_('Name of assigned tenant')
)
status = CSVChoiceField(
choices=RackStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
role = CSVModelChoiceField(
queryset=RackRole.objects.all(),
required=False,
to_field_name='name',
- help_text='Name of assigned role'
+ help_text=_('Name of assigned role')
)
type = CSVChoiceField(
choices=RackTypeChoices,
required=False,
- help_text='Rack type'
+ help_text=_('Rack type')
)
width = forms.ChoiceField(
choices=RackWidthChoices,
- help_text='Rail-to-rail width (in inches)'
+ help_text=_('Rail-to-rail width (in inches)')
)
outer_unit = CSVChoiceField(
choices=RackDimensionUnitChoices,
required=False,
- help_text='Unit for outer dimensions'
+ help_text=_('Unit for outer dimensions')
)
class Meta:
@@ -215,29 +216,29 @@ class RackReservationCSVForm(NetBoxModelCSVForm):
site = CSVModelChoiceField(
queryset=Site.objects.all(),
to_field_name='name',
- help_text='Parent site'
+ help_text=_('Parent site')
)
location = CSVModelChoiceField(
queryset=Location.objects.all(),
to_field_name='name',
required=False,
- help_text="Rack's location (if any)"
+ help_text=_("Rack's location (if any)")
)
rack = CSVModelChoiceField(
queryset=Rack.objects.all(),
to_field_name='name',
- help_text='Rack'
+ help_text=_('Rack')
)
units = SimpleArrayField(
base_field=forms.IntegerField(),
required=True,
- help_text='Comma-separated list of individual unit numbers'
+ help_text=_('Comma-separated list of individual unit numbers')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
@@ -275,7 +276,7 @@ class DeviceRoleCSVForm(NetBoxModelCSVForm):
model = DeviceRole
fields = ('name', 'slug', 'color', 'vm_role', 'description', 'tags')
help_texts = {
- 'color': mark_safe('RGB color in hexadecimal (e.g. 00ff00
)'),
+ 'color': mark_safe(_('RGB color in hexadecimal (e.g. 00ff00
)')),
}
@@ -285,7 +286,7 @@ class PlatformCSVForm(NetBoxModelCSVForm):
queryset=Manufacturer.objects.all(),
required=False,
to_field_name='name',
- help_text='Limit platform assignments to this manufacturer'
+ help_text=_('Limit platform assignments to this manufacturer')
)
class Meta:
@@ -297,45 +298,45 @@ class BaseDeviceCSVForm(NetBoxModelCSVForm):
device_role = CSVModelChoiceField(
queryset=DeviceRole.objects.all(),
to_field_name='name',
- help_text='Assigned role'
+ help_text=_('Assigned role')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
manufacturer = CSVModelChoiceField(
queryset=Manufacturer.objects.all(),
to_field_name='name',
- help_text='Device type manufacturer'
+ help_text=_('Device type manufacturer')
)
device_type = CSVModelChoiceField(
queryset=DeviceType.objects.all(),
to_field_name='model',
- help_text='Device type model'
+ help_text=_('Device type model')
)
platform = CSVModelChoiceField(
queryset=Platform.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned platform'
+ help_text=_('Assigned platform')
)
status = CSVChoiceField(
choices=DeviceStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
virtual_chassis = CSVModelChoiceField(
queryset=VirtualChassis.objects.all(),
to_field_name='name',
required=False,
- help_text='Virtual chassis'
+ help_text=_('Virtual chassis')
)
cluster = CSVModelChoiceField(
queryset=Cluster.objects.all(),
to_field_name='name',
required=False,
- help_text='Virtualization cluster'
+ help_text=_('Virtualization cluster')
)
class Meta:
@@ -360,29 +361,29 @@ class DeviceCSVForm(BaseDeviceCSVForm):
site = CSVModelChoiceField(
queryset=Site.objects.all(),
to_field_name='name',
- help_text='Assigned site'
+ help_text=_('Assigned site')
)
location = CSVModelChoiceField(
queryset=Location.objects.all(),
to_field_name='name',
required=False,
- help_text="Assigned location (if any)"
+ help_text=_("Assigned location (if any)")
)
rack = CSVModelChoiceField(
queryset=Rack.objects.all(),
to_field_name='name',
required=False,
- help_text="Assigned rack (if any)"
+ help_text=_("Assigned rack (if any)")
)
face = CSVChoiceField(
choices=DeviceFaceChoices,
required=False,
- help_text='Mounted rack face'
+ help_text=_('Mounted rack face')
)
airflow = CSVChoiceField(
choices=DeviceAirflowChoices,
required=False,
- help_text='Airflow direction'
+ help_text=_('Airflow direction')
)
class Meta(BaseDeviceCSVForm.Meta):
@@ -442,12 +443,12 @@ class ChildDeviceCSVForm(BaseDeviceCSVForm):
parent = CSVModelChoiceField(
queryset=Device.objects.all(),
to_field_name='name',
- help_text='Parent device'
+ help_text=_('Parent device')
)
device_bay = CSVModelChoiceField(
queryset=DeviceBay.objects.all(),
to_field_name='name',
- help_text='Device bay in which this device is installed'
+ help_text=_('Device bay in which this device is installed')
)
class Meta(BaseDeviceCSVForm.Meta):
@@ -492,14 +493,14 @@ class ConsolePortCSVForm(NetBoxModelCSVForm):
type = CSVChoiceField(
choices=ConsolePortTypeChoices,
required=False,
- help_text='Port type'
+ help_text=_('Port type')
)
speed = CSVTypedChoiceField(
choices=ConsolePortSpeedChoices,
coerce=int,
empty_value=None,
required=False,
- help_text='Port speed in bps'
+ help_text=_('Port speed in bps')
)
class Meta:
@@ -515,14 +516,14 @@ class ConsoleServerPortCSVForm(NetBoxModelCSVForm):
type = CSVChoiceField(
choices=ConsolePortTypeChoices,
required=False,
- help_text='Port type'
+ help_text=_('Port type')
)
speed = CSVTypedChoiceField(
choices=ConsolePortSpeedChoices,
coerce=int,
empty_value=None,
required=False,
- help_text='Port speed in bps'
+ help_text=_('Port speed in bps')
)
class Meta:
@@ -538,7 +539,7 @@ class PowerPortCSVForm(NetBoxModelCSVForm):
type = CSVChoiceField(
choices=PowerPortTypeChoices,
required=False,
- help_text='Port type'
+ help_text=_('Port type')
)
class Meta:
@@ -556,18 +557,18 @@ class PowerOutletCSVForm(NetBoxModelCSVForm):
type = CSVChoiceField(
choices=PowerOutletTypeChoices,
required=False,
- help_text='Outlet type'
+ help_text=_('Outlet type')
)
power_port = CSVModelChoiceField(
queryset=PowerPort.objects.all(),
required=False,
to_field_name='name',
- help_text='Local power port which feeds this outlet'
+ help_text=_('Local power port which feeds this outlet')
)
feed_leg = CSVChoiceField(
choices=PowerOutletFeedLegChoices,
required=False,
- help_text='Electrical phase (for three-phase circuits)'
+ help_text=_('Electrical phase (for three-phase circuits)')
)
class Meta:
@@ -606,23 +607,23 @@ class InterfaceCSVForm(NetBoxModelCSVForm):
queryset=Interface.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent interface'
+ help_text=_('Parent interface')
)
bridge = CSVModelChoiceField(
queryset=Interface.objects.all(),
required=False,
to_field_name='name',
- help_text='Bridged interface'
+ help_text=_('Bridged interface')
)
lag = CSVModelChoiceField(
queryset=Interface.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent LAG interface'
+ help_text=_('Parent LAG interface')
)
type = CSVChoiceField(
choices=InterfaceTypeChoices,
- help_text='Physical medium'
+ help_text=_('Physical medium')
)
duplex = CSVChoiceField(
choices=InterfaceDuplexChoices,
@@ -631,28 +632,28 @@ class InterfaceCSVForm(NetBoxModelCSVForm):
poe_mode = CSVChoiceField(
choices=InterfacePoEModeChoices,
required=False,
- help_text='PoE mode'
+ help_text=_('PoE mode')
)
poe_type = CSVChoiceField(
choices=InterfacePoETypeChoices,
required=False,
- help_text='PoE type'
+ help_text=_('PoE type')
)
mode = CSVChoiceField(
choices=InterfaceModeChoices,
required=False,
- help_text='IEEE 802.1Q operational mode (for L2 interfaces)'
+ help_text=_('IEEE 802.1Q operational mode (for L2 interfaces)')
)
vrf = CSVModelChoiceField(
queryset=VRF.objects.all(),
required=False,
to_field_name='rd',
- help_text='Assigned VRF'
+ help_text=_('Assigned VRF')
)
rf_role = CSVChoiceField(
choices=WirelessRoleChoices,
required=False,
- help_text='Wireless role (AP/station)'
+ help_text=_('Wireless role (AP/station)')
)
class Meta:
@@ -692,11 +693,11 @@ class FrontPortCSVForm(NetBoxModelCSVForm):
rear_port = CSVModelChoiceField(
queryset=RearPort.objects.all(),
to_field_name='name',
- help_text='Corresponding rear port'
+ help_text=_('Corresponding rear port')
)
type = CSVChoiceField(
choices=PortTypeChoices,
- help_text='Physical medium classification'
+ help_text=_('Physical medium classification')
)
class Meta:
@@ -706,7 +707,7 @@ class FrontPortCSVForm(NetBoxModelCSVForm):
'description', 'tags'
)
help_texts = {
- 'rear_port_position': 'Mapped position on corresponding rear port',
+ 'rear_port_position': _('Mapped position on corresponding rear port'),
}
def __init__(self, *args, **kwargs):
@@ -738,7 +739,7 @@ class RearPortCSVForm(NetBoxModelCSVForm):
to_field_name='name'
)
type = CSVChoiceField(
- help_text='Physical medium classification',
+ help_text=_('Physical medium classification'),
choices=PortTypeChoices,
)
@@ -746,7 +747,7 @@ class RearPortCSVForm(NetBoxModelCSVForm):
model = RearPort
fields = ('device', 'name', 'label', 'type', 'color', 'mark_connected', 'positions', 'description', 'tags')
help_texts = {
- 'positions': 'Number of front ports which may be mapped'
+ 'positions': _('Number of front ports which may be mapped')
}
@@ -770,9 +771,9 @@ class DeviceBayCSVForm(NetBoxModelCSVForm):
queryset=Device.objects.all(),
required=False,
to_field_name='name',
- help_text='Child device installed within this bay',
+ help_text=_('Child device installed within this bay'),
error_messages={
- 'invalid_choice': 'Child device not found.',
+ 'invalid_choice': _('Child device not found.'),
}
)
@@ -826,7 +827,7 @@ class InventoryItemCSVForm(NetBoxModelCSVForm):
queryset=Device.objects.all(),
to_field_name='name',
required=False,
- help_text='Parent inventory item'
+ help_text=_('Parent inventory item')
)
class Meta:
@@ -863,7 +864,7 @@ class InventoryItemRoleCSVForm(NetBoxModelCSVForm):
model = InventoryItemRole
fields = ('name', 'slug', 'color', 'description')
help_texts = {
- 'color': mark_safe('RGB color in hexadecimal (e.g. 00ff00
)'),
+ 'color': mark_safe(_('RGB color in hexadecimal (e.g. 00ff00
)')),
}
@@ -876,53 +877,53 @@ class CableCSVForm(NetBoxModelCSVForm):
side_a_device = CSVModelChoiceField(
queryset=Device.objects.all(),
to_field_name='name',
- help_text='Side A device'
+ help_text=_('Side A device')
)
side_a_type = CSVContentTypeField(
queryset=ContentType.objects.all(),
limit_choices_to=CABLE_TERMINATION_MODELS,
- help_text='Side A type'
+ help_text=_('Side A type')
)
side_a_name = forms.CharField(
- help_text='Side A component name'
+ help_text=_('Side A component name')
)
# Termination B
side_b_device = CSVModelChoiceField(
queryset=Device.objects.all(),
to_field_name='name',
- help_text='Side B device'
+ help_text=_('Side B device')
)
side_b_type = CSVContentTypeField(
queryset=ContentType.objects.all(),
limit_choices_to=CABLE_TERMINATION_MODELS,
- help_text='Side B type'
+ help_text=_('Side B type')
)
side_b_name = forms.CharField(
- help_text='Side B component name'
+ help_text=_('Side B component name')
)
# Cable attributes
status = CSVChoiceField(
choices=LinkStatusChoices,
required=False,
- help_text='Connection status'
+ help_text=_('Connection status')
)
type = CSVChoiceField(
choices=CableTypeChoices,
required=False,
- help_text='Physical medium classification'
+ help_text=_('Physical medium classification')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
length_unit = CSVChoiceField(
choices=CableLengthUnitChoices,
required=False,
- help_text='Length unit'
+ help_text=_('Length unit')
)
class Meta:
@@ -932,7 +933,7 @@ class CableCSVForm(NetBoxModelCSVForm):
'status', 'tenant', 'label', 'color', 'length', 'length_unit', 'description', 'comments', 'tags',
]
help_texts = {
- 'color': mark_safe('RGB color in hexadecimal (e.g. 00ff00
)'),
+ 'color': mark_safe(_('RGB color in hexadecimal (e.g. 00ff00
)')),
}
def _clean_side(self, side):
@@ -981,7 +982,7 @@ class VirtualChassisCSVForm(NetBoxModelCSVForm):
queryset=Device.objects.all(),
to_field_name='name',
required=False,
- help_text='Master device'
+ help_text=_('Master device')
)
class Meta:
@@ -997,7 +998,7 @@ class PowerPanelCSVForm(NetBoxModelCSVForm):
site = CSVModelChoiceField(
queryset=Site.objects.all(),
to_field_name='name',
- help_text='Name of parent site'
+ help_text=_('Name of parent site')
)
location = CSVModelChoiceField(
queryset=Location.objects.all(),
@@ -1023,40 +1024,40 @@ class PowerFeedCSVForm(NetBoxModelCSVForm):
site = CSVModelChoiceField(
queryset=Site.objects.all(),
to_field_name='name',
- help_text='Assigned site'
+ help_text=_('Assigned site')
)
power_panel = CSVModelChoiceField(
queryset=PowerPanel.objects.all(),
to_field_name='name',
- help_text='Upstream power panel'
+ help_text=_('Upstream power panel')
)
location = CSVModelChoiceField(
queryset=Location.objects.all(),
to_field_name='name',
required=False,
- help_text="Rack's location (if any)"
+ help_text=_("Rack's location (if any)")
)
rack = CSVModelChoiceField(
queryset=Rack.objects.all(),
to_field_name='name',
required=False,
- help_text='Rack'
+ help_text=_('Rack')
)
status = CSVChoiceField(
choices=PowerFeedStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
type = CSVChoiceField(
choices=PowerFeedTypeChoices,
- help_text='Primary or redundant'
+ help_text=_('Primary or redundant')
)
supply = CSVChoiceField(
choices=PowerFeedSupplyChoices,
- help_text='Supply type (AC/DC)'
+ help_text=_('Supply type (AC/DC)')
)
phase = CSVChoiceField(
choices=PowerFeedPhaseChoices,
- help_text='Single or three-phase'
+ help_text=_('Single or three-phase')
)
class Meta:
diff --git a/netbox/dcim/forms/common.py b/netbox/dcim/forms/common.py
index f484b48e1..9d5232ddf 100644
--- a/netbox/dcim/forms/common.py
+++ b/netbox/dcim/forms/common.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from dcim.choices import *
from dcim.constants import *
@@ -12,13 +13,13 @@ class InterfaceCommonForm(forms.Form):
mac_address = forms.CharField(
empty_value=None,
required=False,
- label='MAC address'
+ label=_('MAC address')
)
mtu = forms.IntegerField(
required=False,
min_value=INTERFACE_MTU_MIN,
max_value=INTERFACE_MTU_MAX,
- label='MTU'
+ label=_('MTU')
)
def clean(self):
diff --git a/netbox/dcim/forms/connections.py b/netbox/dcim/forms/connections.py
index 537a89bad..ba5e51c41 100644
--- a/netbox/dcim/forms/connections.py
+++ b/netbox/dcim/forms/connections.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from circuits.models import Circuit, CircuitTermination, Provider
from dcim.models import *
@@ -16,7 +17,7 @@ def get_cable_form(a_type, b_type):
attrs[f'termination_{cable_end}_region'] = DynamicModelChoiceField(
queryset=Region.objects.all(),
- label='Region',
+ label=_('Region'),
required=False,
initial_params={
'sites': f'$termination_{cable_end}_site'
@@ -24,7 +25,7 @@ def get_cable_form(a_type, b_type):
)
attrs[f'termination_{cable_end}_sitegroup'] = DynamicModelChoiceField(
queryset=SiteGroup.objects.all(),
- label='Site group',
+ label=_('Site group'),
required=False,
initial_params={
'sites': f'$termination_{cable_end}_site'
@@ -32,7 +33,7 @@ def get_cable_form(a_type, b_type):
)
attrs[f'termination_{cable_end}_site'] = DynamicModelChoiceField(
queryset=Site.objects.all(),
- label='Site',
+ label=_('Site'),
required=False,
query_params={
'region_id': f'$termination_{cable_end}_region',
@@ -41,7 +42,7 @@ def get_cable_form(a_type, b_type):
)
attrs[f'termination_{cable_end}_location'] = DynamicModelChoiceField(
queryset=Location.objects.all(),
- label='Location',
+ label=_('Location'),
required=False,
null_option='None',
query_params={
@@ -54,7 +55,7 @@ def get_cable_form(a_type, b_type):
attrs[f'termination_{cable_end}_rack'] = DynamicModelChoiceField(
queryset=Rack.objects.all(),
- label='Rack',
+ label=_('Rack'),
required=False,
null_option='None',
initial_params={
@@ -67,7 +68,7 @@ def get_cable_form(a_type, b_type):
)
attrs[f'termination_{cable_end}_device'] = DynamicModelChoiceField(
queryset=Device.objects.all(),
- label='Device',
+ label=_('Device'),
required=False,
initial_params={
f'{term_cls._meta.model_name}s__in': f'${cable_end}_terminations'
@@ -93,7 +94,7 @@ def get_cable_form(a_type, b_type):
attrs[f'termination_{cable_end}_powerpanel'] = DynamicModelChoiceField(
queryset=PowerPanel.objects.all(),
- label='Power Panel',
+ label=_('Power Panel'),
required=False,
initial_params={
'powerfeeds__in': f'${cable_end}_terminations'
@@ -105,7 +106,7 @@ def get_cable_form(a_type, b_type):
)
attrs[f'{cable_end}_terminations'] = DynamicModelMultipleChoiceField(
queryset=term_cls.objects.all(),
- label='Power Feed',
+ label=_('Power Feed'),
disabled_indicator='_occupied',
query_params={
'power_panel_id': f'$termination_{cable_end}_powerpanel',
@@ -117,7 +118,7 @@ def get_cable_form(a_type, b_type):
attrs[f'termination_{cable_end}_provider'] = DynamicModelChoiceField(
queryset=Provider.objects.all(),
- label='Provider',
+ label=_('Provider'),
initial_params={
'circuits': f'$termination_{cable_end}_circuit'
},
@@ -125,7 +126,7 @@ def get_cable_form(a_type, b_type):
)
attrs[f'termination_{cable_end}_circuit'] = DynamicModelChoiceField(
queryset=Circuit.objects.all(),
- label='Circuit',
+ label=_('Circuit'),
initial_params={
'terminations__in': f'${cable_end}_terminations'
},
@@ -136,7 +137,7 @@ def get_cable_form(a_type, b_type):
)
attrs[f'{cable_end}_terminations'] = DynamicModelMultipleChoiceField(
queryset=term_cls.objects.all(),
- label='Side',
+ label=_('Side'),
disabled_indicator='_occupied',
query_params={
'circuit_id': f'$termination_{cable_end}_circuit',
diff --git a/netbox/dcim/forms/model_forms.py b/netbox/dcim/forms/model_forms.py
index da0148784..76d2d9204 100644
--- a/netbox/dcim/forms/model_forms.py
+++ b/netbox/dcim/forms/model_forms.py
@@ -1,7 +1,7 @@
from django import forms
-from django.utils.translation import gettext as _
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
+from django.utils.translation import gettext as _
from timezone_field import TimeZoneFormField
from dcim.choices import *
@@ -163,14 +163,14 @@ class SiteForm(TenancyForm, NetBoxModelForm):
'time_zone': StaticSelect(),
}
help_texts = {
- 'name': "Full name of the site",
- 'facility': "Data center provider and facility (e.g. Equinix NY7)",
- 'time_zone': "Local time zone",
- 'description': "Short description (will appear in sites list)",
- 'physical_address': "Physical location of the building (e.g. for GPS)",
- 'shipping_address': "If different from the physical address",
- 'latitude': "Latitude in decimal format (xx.yyyyyy)",
- 'longitude': "Longitude in decimal format (xx.yyyyyy)"
+ 'name': _("Full name of the site"),
+ 'facility': _("Data center provider and facility (e.g. Equinix NY7)"),
+ 'time_zone': _("Local time zone"),
+ 'description': _("Short description (will appear in sites list)"),
+ 'physical_address': _("Physical location of the building (e.g. for GPS)"),
+ 'shipping_address': _("If different from the physical address"),
+ 'latitude': _("Latitude in decimal format (xx.yyyyyy)"),
+ 'longitude': _("Longitude in decimal format (xx.yyyyyy)")
}
@@ -282,10 +282,10 @@ class RackForm(TenancyForm, NetBoxModelForm):
'outer_unit', 'mounting_depth', 'weight', 'weight_unit', 'description', 'comments', 'tags',
]
help_texts = {
- 'site': "The site at which the rack exists",
- 'name': "Organizational rack name",
- 'facility_id': "The unique rack ID assigned by the facility",
- 'u_height': "Height in rack units",
+ 'site': _("The site at which the rack exists"),
+ 'name': _("Organizational rack name"),
+ 'facility_id': _("The unique rack ID assigned by the facility"),
+ 'u_height': _("Height in rack units"),
}
widgets = {
'status': StaticSelect(),
@@ -335,7 +335,7 @@ class RackReservationForm(TenancyForm, NetBoxModelForm):
)
units = NumericArrayField(
base_field=forms.IntegerField(),
- help_text="Comma-separated list of numeric unit IDs. A range may be specified using a hyphen."
+ help_text=_("Comma-separated list of numeric unit IDs. A range may be specified using a hyphen.")
)
user = forms.ModelChoiceField(
queryset=User.objects.order_by(
@@ -519,7 +519,7 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
)
position = forms.DecimalField(
required=False,
- help_text="The lowest-numbered unit occupied by the device",
+ help_text=_("The lowest-numbered unit occupied by the device"),
widget=APISelect(
api_url='/api/dcim/racks/{{rack}}/elevation/',
attrs={
@@ -577,13 +577,13 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
)
vc_position = forms.IntegerField(
required=False,
- label='Position',
- help_text="The position in the virtual chassis this device is identified by"
+ label=_('Position'),
+ help_text=_("The position in the virtual chassis this device is identified by")
)
vc_priority = forms.IntegerField(
required=False,
- label='Priority',
- help_text="The priority of the device in the virtual chassis"
+ label=_('Priority'),
+ help_text=_("The priority of the device in the virtual chassis")
)
class Meta:
@@ -595,10 +595,10 @@ class DeviceForm(TenancyForm, NetBoxModelForm):
'description', 'comments', 'tags', 'local_context_data'
]
help_texts = {
- 'device_role': "The function this device serves",
- 'serial': "Chassis serial number",
- 'local_context_data': "Local config context data overwrites all source contexts in the final rendered "
- "config context",
+ 'device_role': _("The function this device serves"),
+ 'serial': _("Chassis serial number"),
+ 'local_context_data': _("Local config context data overwrites all source contexts in the final rendered "
+ "config context"),
}
widgets = {
'face': StaticSelect(),
@@ -695,13 +695,13 @@ class ModuleForm(NetBoxModelForm):
replicate_components = forms.BooleanField(
required=False,
initial=True,
- help_text="Automatically populate components associated with this module type"
+ help_text=_("Automatically populate components associated with this module type")
)
adopt_components = forms.BooleanField(
required=False,
initial=False,
- help_text="Adopt already existing components"
+ help_text=_("Adopt already existing components")
)
fieldsets = (
@@ -1390,7 +1390,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
parent = DynamicModelChoiceField(
queryset=Interface.objects.all(),
required=False,
- label='Parent interface',
+ label=_('Parent interface'),
query_params={
'device_id': '$device',
}
@@ -1398,7 +1398,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
bridge = DynamicModelChoiceField(
queryset=Interface.objects.all(),
required=False,
- label='Bridged interface',
+ label=_('Bridged interface'),
query_params={
'device_id': '$device',
}
@@ -1406,7 +1406,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
lag = DynamicModelChoiceField(
queryset=Interface.objects.all(),
required=False,
- label='LAG interface',
+ label=_('LAG interface'),
query_params={
'device_id': '$device',
'type': 'lag',
@@ -1415,12 +1415,12 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
wireless_lan_group = DynamicModelChoiceField(
queryset=WirelessLANGroup.objects.all(),
required=False,
- label='Wireless LAN group'
+ label=_('Wireless LAN group')
)
wireless_lans = DynamicModelMultipleChoiceField(
queryset=WirelessLAN.objects.all(),
required=False,
- label='Wireless LANs',
+ label=_('Wireless LANs'),
query_params={
'group_id': '$wireless_lan_group',
}
@@ -1428,12 +1428,12 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
vlan_group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
- label='VLAN group'
+ label=_('VLAN group')
)
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
- label='Untagged VLAN',
+ label=_('Untagged VLAN'),
query_params={
'group_id': '$vlan_group',
'available_on_device': '$device',
@@ -1442,7 +1442,7 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
required=False,
- label='Tagged VLANs',
+ label=_('Tagged VLANs'),
query_params={
'group_id': '$vlan_group',
'available_on_device': '$device',
@@ -1451,13 +1451,13 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
wwn = forms.CharField(
empty_value=None,
required=False,
- label='WWN'
+ label=_('WWN')
)
fieldsets = (
@@ -1495,8 +1495,8 @@ class InterfaceForm(InterfaceCommonForm, ModularDeviceComponentForm):
}
help_texts = {
'mode': INTERFACE_MODE_HELP_TEXT,
- 'rf_channel_frequency': "Populated by selected channel (if set)",
- 'rf_channel_width': "Populated by selected channel (if set)",
+ 'rf_channel_frequency': _("Populated by selected channel (if set)"),
+ 'rf_channel_width': _("Populated by selected channel (if set)"),
}
@@ -1570,8 +1570,8 @@ class DeviceBayForm(DeviceComponentForm):
class PopulateDeviceBayForm(BootstrapMixin, forms.Form):
installed_device = forms.ModelChoiceField(
queryset=Device.objects.all(),
- label='Child Device',
- help_text="Child devices must first be created and assigned to the site/rack of the parent device.",
+ label=_('Child Device'),
+ help_text=_("Child devices must first be created and assigned to the site/rack of the parent device."),
widget=StaticSelect(),
)
diff --git a/netbox/dcim/forms/object_create.py b/netbox/dcim/forms/object_create.py
index afdaa4fcc..6de193043 100644
--- a/netbox/dcim/forms/object_create.py
+++ b/netbox/dcim/forms/object_create.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from dcim.models import *
from netbox.forms import NetBoxModelForm
@@ -39,7 +40,7 @@ class ComponentCreateForm(forms.Form):
name = ExpandableNameField()
label = ExpandableNameField(
required=False,
- help_text='Alphanumeric ranges are supported. (Must match the number of objects being created.)'
+ help_text=_('Alphanumeric ranges are supported. (Must match the number of objects being created.)')
)
# Identify the fields which support replication (i.e. ExpandableNameFields). This is referenced by
@@ -97,8 +98,8 @@ class InterfaceTemplateCreateForm(ComponentCreateForm, model_forms.InterfaceTemp
class FrontPortTemplateCreateForm(ComponentCreateForm, model_forms.FrontPortTemplateForm):
rear_port = forms.MultipleChoiceField(
choices=[],
- label='Rear ports',
- help_text='Select one rear port assignment for each front port being created.',
+ label=_('Rear ports'),
+ help_text=_('Select one rear port assignment for each front port being created.'),
)
# Override fieldsets from FrontPortTemplateForm to omit rear_port_position
@@ -166,9 +167,9 @@ class DeviceBayTemplateCreateForm(ComponentCreateForm, model_forms.DeviceBayTemp
class ModuleBayTemplateCreateForm(ComponentCreateForm, model_forms.ModuleBayTemplateForm):
position = ExpandableNameField(
- label='Position',
+ label=_('Position'),
required=False,
- help_text='Alphanumeric ranges are supported. (Must match the number of objects being created.)'
+ help_text=_('Alphanumeric ranges are supported. (Must match the number of objects being created.)')
)
replication_fields = ('name', 'label', 'position')
@@ -226,8 +227,8 @@ class InterfaceCreateForm(ComponentCreateForm, model_forms.InterfaceForm):
class FrontPortCreateForm(ComponentCreateForm, model_forms.FrontPortForm):
rear_port = forms.MultipleChoiceField(
choices=[],
- label='Rear ports',
- help_text='Select one rear port assignment for each front port being created.',
+ label=_('Rear ports'),
+ help_text=_('Select one rear port assignment for each front port being created.'),
)
# Override fieldsets from FrontPortForm to omit rear_port_position
@@ -290,9 +291,9 @@ class DeviceBayCreateForm(ComponentCreateForm, model_forms.DeviceBayForm):
class ModuleBayCreateForm(ComponentCreateForm, model_forms.ModuleBayForm):
position = ExpandableNameField(
- label='Position',
+ label=_('Position'),
required=False,
- help_text='Alphanumeric ranges are supported. (Must match the number of objects being created.)'
+ help_text=_('Alphanumeric ranges are supported. (Must match the number of objects being created.)')
)
replication_fields = ('name', 'label', 'position')
@@ -352,7 +353,7 @@ class VirtualChassisCreateForm(NetBoxModelForm):
initial_position = forms.IntegerField(
initial=1,
required=False,
- help_text='Position of the first member device. Increases by one for each additional member.'
+ help_text=_('Position of the first member device. Increases by one for each additional member.')
)
class Meta:
diff --git a/netbox/dcim/forms/object_import.py b/netbox/dcim/forms/object_import.py
index 82ee093dd..920c0081f 100644
--- a/netbox/dcim/forms/object_import.py
+++ b/netbox/dcim/forms/object_import.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from dcim.choices import InterfacePoEModeChoices, InterfacePoETypeChoices, InterfaceTypeChoices, PortTypeChoices
from dcim.models import *
@@ -115,12 +116,12 @@ class InterfaceTemplateImportForm(ComponentTemplateImportForm):
poe_mode = forms.ChoiceField(
choices=InterfacePoEModeChoices,
required=False,
- label='PoE mode'
+ label=_('PoE mode')
)
poe_type = forms.ChoiceField(
choices=InterfacePoETypeChoices,
required=False,
- label='PoE type'
+ label=_('PoE type')
)
class Meta:
diff --git a/netbox/dcim/models/device_component_templates.py b/netbox/dcim/models/device_component_templates.py
index 15389a2c0..3b136987d 100644
--- a/netbox/dcim/models/device_component_templates.py
+++ b/netbox/dcim/models/device_component_templates.py
@@ -3,6 +3,7 @@ from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
+from django.utils.translation import gettext as _
from mptt.models import MPTTModel, TreeForeignKey
from dcim.choices import *
@@ -52,7 +53,7 @@ class ComponentTemplateModel(WebhooksMixin, ChangeLoggedModel):
label = models.CharField(
max_length=64,
blank=True,
- help_text="Physical label"
+ help_text=_("Physical label")
)
description = models.CharField(
max_length=200,
@@ -222,13 +223,13 @@ class PowerPortTemplate(ModularComponentTemplateModel):
blank=True,
null=True,
validators=[MinValueValidator(1)],
- help_text="Maximum power draw (watts)"
+ help_text=_("Maximum power draw (watts)")
)
allocated_draw = models.PositiveSmallIntegerField(
blank=True,
null=True,
validators=[MinValueValidator(1)],
- help_text="Allocated power draw (watts)"
+ help_text=_("Allocated power draw (watts)")
)
component_model = PowerPort
@@ -283,7 +284,7 @@ class PowerOutletTemplate(ModularComponentTemplateModel):
max_length=50,
choices=PowerOutletFeedLegChoices,
blank=True,
- help_text="Phase (for three-phase feeds)"
+ help_text=_("Phase (for three-phase feeds)")
)
component_model = PowerOutlet
@@ -526,7 +527,7 @@ class ModuleBayTemplate(ComponentTemplateModel):
position = models.CharField(
max_length=30,
blank=True,
- help_text='Identifier to reference when renaming installed components'
+ help_text=_('Identifier to reference when renaming installed components')
)
component_model = ModuleBay
@@ -621,7 +622,7 @@ class InventoryItemTemplate(MPTTModel, ComponentTemplateModel):
max_length=50,
verbose_name='Part ID',
blank=True,
- help_text='Manufacturer-assigned part identifier'
+ help_text=_('Manufacturer-assigned part identifier')
)
objects = TreeManager()
diff --git a/netbox/dcim/models/device_components.py b/netbox/dcim/models/device_components.py
index 23c820571..7b3534a4e 100644
--- a/netbox/dcim/models/device_components.py
+++ b/netbox/dcim/models/device_components.py
@@ -7,6 +7,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models import Sum
from django.urls import reverse
+from django.utils.translation import gettext as _
from mptt.models import MPTTModel, TreeForeignKey
from dcim.choices import *
@@ -60,7 +61,7 @@ class ComponentModel(NetBoxModel):
label = models.CharField(
max_length=64,
blank=True,
- help_text="Physical label"
+ help_text=_("Physical label")
)
description = models.CharField(
max_length=200,
@@ -129,7 +130,7 @@ class CabledObjectModel(models.Model):
)
mark_connected = models.BooleanField(
default=False,
- help_text="Treat as if a cable is connected"
+ help_text=_("Treat as if a cable is connected")
)
cable_terminations = GenericRelation(
@@ -261,13 +262,13 @@ class ConsolePort(ModularComponentModel, CabledObjectModel, PathEndpoint):
max_length=50,
choices=ConsolePortTypeChoices,
blank=True,
- help_text='Physical port type'
+ help_text=_('Physical port type')
)
speed = models.PositiveIntegerField(
choices=ConsolePortSpeedChoices,
blank=True,
null=True,
- help_text='Port speed in bits per second'
+ help_text=_('Port speed in bits per second')
)
clone_fields = ('device', 'module', 'type', 'speed')
@@ -284,13 +285,13 @@ class ConsoleServerPort(ModularComponentModel, CabledObjectModel, PathEndpoint):
max_length=50,
choices=ConsolePortTypeChoices,
blank=True,
- help_text='Physical port type'
+ help_text=_('Physical port type')
)
speed = models.PositiveIntegerField(
choices=ConsolePortSpeedChoices,
blank=True,
null=True,
- help_text='Port speed in bits per second'
+ help_text=_('Port speed in bits per second')
)
clone_fields = ('device', 'module', 'type', 'speed')
@@ -311,19 +312,19 @@ class PowerPort(ModularComponentModel, CabledObjectModel, PathEndpoint):
max_length=50,
choices=PowerPortTypeChoices,
blank=True,
- help_text='Physical port type'
+ help_text=_('Physical port type')
)
maximum_draw = models.PositiveSmallIntegerField(
blank=True,
null=True,
validators=[MinValueValidator(1)],
- help_text="Maximum power draw (watts)"
+ help_text=_("Maximum power draw (watts)")
)
allocated_draw = models.PositiveSmallIntegerField(
blank=True,
null=True,
validators=[MinValueValidator(1)],
- help_text="Allocated power draw (watts)"
+ help_text=_("Allocated power draw (watts)")
)
clone_fields = ('device', 'module', 'maximum_draw', 'allocated_draw')
@@ -420,7 +421,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint):
max_length=50,
choices=PowerOutletTypeChoices,
blank=True,
- help_text='Physical port type'
+ help_text=_('Physical port type')
)
power_port = models.ForeignKey(
to='dcim.PowerPort',
@@ -433,7 +434,7 @@ class PowerOutlet(ModularComponentModel, CabledObjectModel, PathEndpoint):
max_length=50,
choices=PowerOutletFeedLegChoices,
blank=True,
- help_text="Phase (for three-phase feeds)"
+ help_text=_("Phase (for three-phase feeds)")
)
clone_fields = ('device', 'module', 'type', 'power_port', 'feed_leg')
@@ -550,7 +551,7 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
mgmt_only = models.BooleanField(
default=False,
verbose_name='Management only',
- help_text='This interface is used only for out-of-band management'
+ help_text=_('This interface is used only for out-of-band management')
)
speed = models.PositiveIntegerField(
blank=True,
@@ -567,7 +568,7 @@ class Interface(ModularComponentModel, BaseInterface, CabledObjectModel, PathEnd
null=True,
blank=True,
verbose_name='WWN',
- help_text='64-bit World Wide Name'
+ help_text=_('64-bit World Wide Name')
)
rf_role = models.CharField(
max_length=30,
@@ -970,7 +971,7 @@ class ModuleBay(ComponentModel):
position = models.CharField(
max_length=30,
blank=True,
- help_text='Identifier to reference when renaming installed components'
+ help_text=_('Identifier to reference when renaming installed components')
)
clone_fields = ('device',)
@@ -1084,7 +1085,7 @@ class InventoryItem(MPTTModel, ComponentModel):
max_length=50,
verbose_name='Part ID',
blank=True,
- help_text='Manufacturer-assigned part identifier'
+ help_text=_('Manufacturer-assigned part identifier')
)
serial = models.CharField(
max_length=50,
@@ -1097,11 +1098,11 @@ class InventoryItem(MPTTModel, ComponentModel):
blank=True,
null=True,
verbose_name='Asset tag',
- help_text='A unique tag used to identify this item'
+ help_text=_('A unique tag used to identify this item')
)
discovered = models.BooleanField(
default=False,
- help_text='This item was automatically discovered'
+ help_text=_('This item was automatically discovered')
)
objects = TreeManager()
diff --git a/netbox/dcim/models/devices.py b/netbox/dcim/models/devices.py
index afa792ffb..b71a185b7 100644
--- a/netbox/dcim/models/devices.py
+++ b/netbox/dcim/models/devices.py
@@ -12,6 +12,7 @@ from django.db.models import F, ProtectedError
from django.db.models.functions import Lower
from django.urls import reverse
from django.utils.safestring import mark_safe
+from django.utils.translation import gettext as _
from dcim.choices import *
from dcim.constants import *
@@ -84,7 +85,7 @@ class DeviceType(PrimaryModel, WeightMixin):
part_number = models.CharField(
max_length=50,
blank=True,
- help_text='Discrete part number (optional)'
+ help_text=_('Discrete part number (optional)')
)
u_height = models.DecimalField(
max_digits=4,
@@ -95,15 +96,15 @@ class DeviceType(PrimaryModel, WeightMixin):
is_full_depth = models.BooleanField(
default=True,
verbose_name='Is full depth',
- help_text='Device consumes both front and rear rack faces'
+ help_text=_('Device consumes both front and rear rack faces')
)
subdevice_role = models.CharField(
max_length=50,
choices=SubdeviceRoleChoices,
blank=True,
verbose_name='Parent/child status',
- help_text='Parent devices house child devices in device bays. Leave blank '
- 'if this device type is neither a parent nor a child.'
+ help_text=_('Parent devices house child devices in device bays. Leave blank '
+ 'if this device type is neither a parent nor a child.')
)
airflow = models.CharField(
max_length=50,
@@ -314,7 +315,7 @@ class ModuleType(PrimaryModel, WeightMixin):
part_number = models.CharField(
max_length=50,
blank=True,
- help_text='Discrete part number (optional)'
+ help_text=_('Discrete part number (optional)')
)
# Generic relations
@@ -400,7 +401,7 @@ class DeviceRole(OrganizationalModel):
vm_role = models.BooleanField(
default=True,
verbose_name='VM Role',
- help_text='Virtual machines may be assigned to this role'
+ help_text=_('Virtual machines may be assigned to this role')
)
def get_absolute_url(self):
@@ -419,19 +420,19 @@ class Platform(OrganizationalModel):
related_name='platforms',
blank=True,
null=True,
- help_text='Optionally limit this platform to devices of a certain manufacturer'
+ help_text=_('Optionally limit this platform to devices of a certain manufacturer')
)
napalm_driver = models.CharField(
max_length=50,
blank=True,
verbose_name='NAPALM driver',
- help_text='The name of the NAPALM driver to use when interacting with devices'
+ help_text=_('The name of the NAPALM driver to use when interacting with devices')
)
napalm_args = models.JSONField(
blank=True,
null=True,
verbose_name='NAPALM arguments',
- help_text='Additional arguments to pass when initiating the NAPALM driver (JSON format)'
+ help_text=_('Additional arguments to pass when initiating the NAPALM driver (JSON format)')
)
def get_absolute_url(self):
@@ -496,7 +497,7 @@ class Device(PrimaryModel, ConfigContextModel):
null=True,
unique=True,
verbose_name='Asset tag',
- help_text='A unique tag used to identify this device'
+ help_text=_('A unique tag used to identify this device')
)
site = models.ForeignKey(
to='dcim.Site',
@@ -524,7 +525,7 @@ class Device(PrimaryModel, ConfigContextModel):
null=True,
validators=[MinValueValidator(1), MaxValueValidator(99.5)],
verbose_name='Position (U)',
- help_text='The lowest-numbered unit occupied by the device'
+ help_text=_('The lowest-numbered unit occupied by the device')
)
face = models.CharField(
max_length=50,
@@ -929,7 +930,7 @@ class Module(PrimaryModel, ConfigContextModel):
null=True,
unique=True,
verbose_name='Asset tag',
- help_text='A unique tag used to identify this device'
+ help_text=_('A unique tag used to identify this device')
)
clone_fields = ('device', 'module_type')
diff --git a/netbox/dcim/models/power.py b/netbox/dcim/models/power.py
index e79cf4c44..a910b1437 100644
--- a/netbox/dcim/models/power.py
+++ b/netbox/dcim/models/power.py
@@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.urls import reverse
+from django.utils.translation import gettext as _
from dcim.choices import *
from netbox.config import ConfigItem
@@ -125,7 +126,7 @@ class PowerFeed(PrimaryModel, PathEndpoint, CabledObjectModel):
max_utilization = models.PositiveSmallIntegerField(
validators=[MinValueValidator(1), MaxValueValidator(100)],
default=ConfigItem('POWERFEED_DEFAULT_MAX_UTILIZATION'),
- help_text="Maximum permissible draw (percentage)"
+ help_text=_("Maximum permissible draw (percentage)")
)
available_power = models.PositiveIntegerField(
default=0,
diff --git a/netbox/dcim/models/racks.py b/netbox/dcim/models/racks.py
index e37fc8dc3..ff37aff5a 100644
--- a/netbox/dcim/models/racks.py
+++ b/netbox/dcim/models/racks.py
@@ -10,6 +10,7 @@ from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.db.models import Count
from django.urls import reverse
+from django.utils.translation import gettext as _
from dcim.choices import *
from dcim.constants import *
@@ -64,7 +65,7 @@ class Rack(PrimaryModel, WeightMixin):
blank=True,
null=True,
verbose_name='Facility ID',
- help_text='Locally-assigned identifier'
+ help_text=_('Locally-assigned identifier')
)
site = models.ForeignKey(
to='dcim.Site',
@@ -96,7 +97,7 @@ class Rack(PrimaryModel, WeightMixin):
related_name='racks',
blank=True,
null=True,
- help_text='Functional role'
+ help_text=_('Functional role')
)
serial = models.CharField(
max_length=50,
@@ -109,7 +110,7 @@ class Rack(PrimaryModel, WeightMixin):
null=True,
unique=True,
verbose_name='Asset tag',
- help_text='A unique tag used to identify this rack'
+ help_text=_('A unique tag used to identify this rack')
)
type = models.CharField(
choices=RackTypeChoices,
@@ -121,28 +122,28 @@ class Rack(PrimaryModel, WeightMixin):
choices=RackWidthChoices,
default=RackWidthChoices.WIDTH_19IN,
verbose_name='Width',
- help_text='Rail-to-rail width'
+ help_text=_('Rail-to-rail width')
)
u_height = models.PositiveSmallIntegerField(
default=RACK_U_HEIGHT_DEFAULT,
verbose_name='Height (U)',
validators=[MinValueValidator(1), MaxValueValidator(100)],
- help_text='Height in rack units'
+ help_text=_('Height in rack units')
)
desc_units = models.BooleanField(
default=False,
verbose_name='Descending units',
- help_text='Units are numbered top-to-bottom'
+ help_text=_('Units are numbered top-to-bottom')
)
outer_width = models.PositiveSmallIntegerField(
blank=True,
null=True,
- help_text='Outer dimension of rack (width)'
+ help_text=_('Outer dimension of rack (width)')
)
outer_depth = models.PositiveSmallIntegerField(
blank=True,
null=True,
- help_text='Outer dimension of rack (depth)'
+ help_text=_('Outer dimension of rack (depth)')
)
outer_unit = models.CharField(
max_length=50,
@@ -153,8 +154,8 @@ class Rack(PrimaryModel, WeightMixin):
blank=True,
null=True,
help_text=(
- 'Maximum depth of a mounted device, in millimeters. For four-post racks, this is the '
- 'distance between the front and rear rails.'
+ _('Maximum depth of a mounted device, in millimeters. For four-post racks, this is the '
+ 'distance between the front and rear rails.')
)
)
diff --git a/netbox/dcim/models/sites.py b/netbox/dcim/models/sites.py
index c760119fb..33f695e70 100644
--- a/netbox/dcim/models/sites.py
+++ b/netbox/dcim/models/sites.py
@@ -2,6 +2,7 @@ from django.contrib.contenttypes.fields import GenericRelation
from django.core.exceptions import ValidationError
from django.db import models
from django.urls import reverse
+from django.utils.translation import gettext as _
from timezone_field import TimeZoneField
from dcim.choices import *
@@ -178,7 +179,7 @@ class Site(PrimaryModel):
facility = models.CharField(
max_length=50,
blank=True,
- help_text='Local facility ID or description'
+ help_text=_('Local facility ID or description')
)
asns = models.ManyToManyField(
to='ipam.ASN',
@@ -201,14 +202,14 @@ class Site(PrimaryModel):
decimal_places=6,
blank=True,
null=True,
- help_text='GPS coordinate (latitude)'
+ help_text=_('GPS coordinate (latitude)')
)
longitude = models.DecimalField(
max_digits=9,
decimal_places=6,
blank=True,
null=True,
- help_text='GPS coordinate (longitude)'
+ help_text=_('GPS coordinate (longitude)')
)
# Generic relations
diff --git a/netbox/extras/filtersets.py b/netbox/extras/filtersets.py
index 6010c733a..824ba90cb 100644
--- a/netbox/extras/filtersets.py
+++ b/netbox/extras/filtersets.py
@@ -2,6 +2,7 @@ import django_filters
from django.contrib.auth.models import User
from django.contrib.contenttypes.models import ContentType
from django.db.models import Q
+from django.utils.translation import gettext as _
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
from netbox.filtersets import BaseFilterSet, ChangeLoggedModelFilterSet, NetBoxModelFilterSet
@@ -32,7 +33,7 @@ __all__ = (
class WebhookFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
content_type_id = MultiValueNumberFilter(
field_name='content_types__id'
@@ -61,7 +62,7 @@ class WebhookFilterSet(BaseFilterSet):
class CustomFieldFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
type = django_filters.MultipleChoiceFilter(
choices=CustomFieldTypeChoices
@@ -92,7 +93,7 @@ class CustomFieldFilterSet(BaseFilterSet):
class CustomLinkFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
content_type_id = MultiValueNumberFilter(
field_name='content_types__id'
@@ -119,7 +120,7 @@ class CustomLinkFilterSet(BaseFilterSet):
class ExportTemplateFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
content_type_id = MultiValueNumberFilter(
field_name='content_types__id'
@@ -142,7 +143,7 @@ class ExportTemplateFilterSet(BaseFilterSet):
class SavedFilterFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
content_type_id = MultiValueNumberFilter(
field_name='content_types__id'
@@ -150,13 +151,13 @@ class SavedFilterFilterSet(BaseFilterSet):
content_types = ContentTypeFilter()
user_id = django_filters.ModelMultipleChoiceFilter(
queryset=User.objects.all(),
- label='User (ID)',
+ label=_('User (ID)'),
)
user = django_filters.ModelMultipleChoiceFilter(
field_name='user__username',
queryset=User.objects.all(),
to_field_name='username',
- label='User (name)',
+ label=_('User (name)'),
)
usable = django_filters.BooleanFilter(
method='_usable'
@@ -191,7 +192,7 @@ class SavedFilterFilterSet(BaseFilterSet):
class ImageAttachmentFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
created = django_filters.DateTimeFilter()
content_type = ContentTypeFilter()
@@ -211,13 +212,13 @@ class JournalEntryFilterSet(NetBoxModelFilterSet):
assigned_object_type = ContentTypeFilter()
created_by_id = django_filters.ModelMultipleChoiceFilter(
queryset=User.objects.all(),
- label='User (ID)',
+ label=_('User (ID)'),
)
created_by = django_filters.ModelMultipleChoiceFilter(
field_name='created_by__username',
queryset=User.objects.all(),
to_field_name='username',
- label='User (name)',
+ label=_('User (name)'),
)
kind = django_filters.MultipleChoiceFilter(
choices=JournalEntryKindChoices
@@ -236,7 +237,7 @@ class JournalEntryFilterSet(NetBoxModelFilterSet):
class TagFilterSet(ChangeLoggedModelFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
content_type = MultiValueCharFilter(
method='_content_type'
@@ -288,138 +289,138 @@ class TagFilterSet(ChangeLoggedModelFilterSet):
class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
region_id = django_filters.ModelMultipleChoiceFilter(
field_name='regions',
queryset=Region.objects.all(),
- label='Region',
+ label=_('Region'),
)
region = django_filters.ModelMultipleChoiceFilter(
field_name='regions__slug',
queryset=Region.objects.all(),
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group = django_filters.ModelMultipleChoiceFilter(
field_name='site_groups__slug',
queryset=SiteGroup.objects.all(),
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_group_id = django_filters.ModelMultipleChoiceFilter(
field_name='site_groups',
queryset=SiteGroup.objects.all(),
- label='Site group',
+ label=_('Site group'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='sites',
queryset=Site.objects.all(),
- label='Site',
+ label=_('Site'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='sites__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
location_id = django_filters.ModelMultipleChoiceFilter(
field_name='locations',
queryset=Location.objects.all(),
- label='Location',
+ label=_('Location'),
)
location = django_filters.ModelMultipleChoiceFilter(
field_name='locations__slug',
queryset=Location.objects.all(),
to_field_name='slug',
- label='Location (slug)',
+ label=_('Location (slug)'),
)
device_type_id = django_filters.ModelMultipleChoiceFilter(
field_name='device_types',
queryset=DeviceType.objects.all(),
- label='Device type',
+ label=_('Device type'),
)
role_id = django_filters.ModelMultipleChoiceFilter(
field_name='roles',
queryset=DeviceRole.objects.all(),
- label='Role',
+ label=_('Role'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='roles__slug',
queryset=DeviceRole.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
platform_id = django_filters.ModelMultipleChoiceFilter(
field_name='platforms',
queryset=Platform.objects.all(),
- label='Platform',
+ label=_('Platform'),
)
platform = django_filters.ModelMultipleChoiceFilter(
field_name='platforms__slug',
queryset=Platform.objects.all(),
to_field_name='slug',
- label='Platform (slug)',
+ label=_('Platform (slug)'),
)
cluster_type_id = django_filters.ModelMultipleChoiceFilter(
field_name='cluster_types',
queryset=ClusterType.objects.all(),
- label='Cluster type',
+ label=_('Cluster type'),
)
cluster_type = django_filters.ModelMultipleChoiceFilter(
field_name='cluster_types__slug',
queryset=ClusterType.objects.all(),
to_field_name='slug',
- label='Cluster type (slug)',
+ label=_('Cluster type (slug)'),
)
cluster_group_id = django_filters.ModelMultipleChoiceFilter(
field_name='cluster_groups',
queryset=ClusterGroup.objects.all(),
- label='Cluster group',
+ label=_('Cluster group'),
)
cluster_group = django_filters.ModelMultipleChoiceFilter(
field_name='cluster_groups__slug',
queryset=ClusterGroup.objects.all(),
to_field_name='slug',
- label='Cluster group (slug)',
+ label=_('Cluster group (slug)'),
)
cluster_id = django_filters.ModelMultipleChoiceFilter(
field_name='clusters',
queryset=Cluster.objects.all(),
- label='Cluster',
+ label=_('Cluster'),
)
tenant_group_id = django_filters.ModelMultipleChoiceFilter(
field_name='tenant_groups',
queryset=TenantGroup.objects.all(),
- label='Tenant group',
+ label=_('Tenant group'),
)
tenant_group = django_filters.ModelMultipleChoiceFilter(
field_name='tenant_groups__slug',
queryset=TenantGroup.objects.all(),
to_field_name='slug',
- label='Tenant group (slug)',
+ label=_('Tenant group (slug)'),
)
tenant_id = django_filters.ModelMultipleChoiceFilter(
field_name='tenants',
queryset=Tenant.objects.all(),
- label='Tenant',
+ label=_('Tenant'),
)
tenant = django_filters.ModelMultipleChoiceFilter(
field_name='tenants__slug',
queryset=Tenant.objects.all(),
to_field_name='slug',
- label='Tenant (slug)',
+ label=_('Tenant (slug)'),
)
tag_id = django_filters.ModelMultipleChoiceFilter(
field_name='tags',
queryset=Tag.objects.all(),
- label='Tag',
+ label=_('Tag'),
)
tag = django_filters.ModelMultipleChoiceFilter(
field_name='tags__slug',
queryset=Tag.objects.all(),
to_field_name='slug',
- label='Tag (slug)',
+ label=_('Tag (slug)'),
)
class Meta:
@@ -443,7 +444,7 @@ class ConfigContextFilterSet(ChangeLoggedModelFilterSet):
class LocalConfigContextFilterSet(django_filters.FilterSet):
local_context_data = django_filters.BooleanFilter(
method='_local_context_data',
- label='Has local config context data',
+ label=_('Has local config context data'),
)
def _local_context_data(self, queryset, name, value):
@@ -453,19 +454,19 @@ class LocalConfigContextFilterSet(django_filters.FilterSet):
class ObjectChangeFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
time = django_filters.DateTimeFromToRangeFilter()
changed_object_type = ContentTypeFilter()
user_id = django_filters.ModelMultipleChoiceFilter(
queryset=User.objects.all(),
- label='User (ID)',
+ label=_('User (ID)'),
)
user = django_filters.ModelMultipleChoiceFilter(
field_name='user__username',
queryset=User.objects.all(),
to_field_name='username',
- label='User name',
+ label=_('User name'),
)
class Meta:
@@ -491,7 +492,7 @@ class ObjectChangeFilterSet(BaseFilterSet):
class JobResultFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
created = django_filters.DateTimeFilter()
created__before = django_filters.DateTimeFilter(
@@ -547,7 +548,7 @@ class JobResultFilterSet(BaseFilterSet):
class ContentTypeFilterSet(django_filters.FilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
class Meta:
diff --git a/netbox/extras/forms/bulk_edit.py b/netbox/extras/forms/bulk_edit.py
index a061d9784..6e245bcaf 100644
--- a/netbox/extras/forms/bulk_edit.py
+++ b/netbox/extras/forms/bulk_edit.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from extras.choices import *
from extras.models import *
@@ -37,7 +38,7 @@ class CustomFieldBulkEditForm(BulkEditForm):
required=False
)
ui_visibility = forms.ChoiceField(
- label="UI visibility",
+ label=_("UI visibility"),
choices=add_blank_choice(CustomFieldVisibilityChoices),
required=False,
initial='',
@@ -143,23 +144,23 @@ class WebhookBulkEditForm(BulkEditForm):
http_method = forms.ChoiceField(
choices=add_blank_choice(WebhookHttpMethodChoices),
required=False,
- label='HTTP method'
+ label=_('HTTP method')
)
payload_url = forms.CharField(
required=False,
- label='Payload URL'
+ label=_('Payload URL')
)
ssl_verification = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect(),
- label='SSL verification'
+ label=_('SSL verification')
)
secret = forms.CharField(
required=False
)
ca_file_path = forms.CharField(
required=False,
- label='CA file path'
+ label=_('CA file path')
)
nullable_fields = ('secret', 'conditions', 'ca_file_path')
diff --git a/netbox/extras/forms/bulk_import.py b/netbox/extras/forms/bulk_import.py
index 0f5974698..9def8fda6 100644
--- a/netbox/extras/forms/bulk_import.py
+++ b/netbox/extras/forms/bulk_import.py
@@ -2,6 +2,7 @@ from django import forms
from django.contrib.contenttypes.models import ContentType
from django.contrib.postgres.forms import SimpleArrayField
from django.utils.safestring import mark_safe
+from django.utils.translation import gettext as _
from extras.choices import CustomFieldVisibilityChoices, CustomFieldTypeChoices
from extras.models import *
@@ -22,26 +23,26 @@ class CustomFieldCSVForm(CSVModelForm):
content_types = CSVMultipleContentTypeField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields'),
- help_text="One or more assigned object types"
+ help_text=_("One or more assigned object types")
)
type = CSVChoiceField(
choices=CustomFieldTypeChoices,
- help_text='Field data type (e.g. text, integer, etc.)'
+ help_text=_('Field data type (e.g. text, integer, etc.)')
)
object_type = CSVContentTypeField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields'),
required=False,
- help_text="Object type (for object or multi-object fields)"
+ help_text=_("Object type (for object or multi-object fields)")
)
choices = SimpleArrayField(
base_field=forms.CharField(),
required=False,
- help_text='Comma-separated list of field choices'
+ help_text=_('Comma-separated list of field choices')
)
ui_visibility = CSVChoiceField(
choices=CustomFieldVisibilityChoices,
- help_text='How the custom field is displayed in the user interface'
+ help_text=_('How the custom field is displayed in the user interface')
)
class Meta:
@@ -57,7 +58,7 @@ class CustomLinkCSVForm(CSVModelForm):
content_types = CSVMultipleContentTypeField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_links'),
- help_text="One or more assigned object types"
+ help_text=_("One or more assigned object types")
)
class Meta:
@@ -72,7 +73,7 @@ class ExportTemplateCSVForm(CSVModelForm):
content_types = CSVMultipleContentTypeField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('export_templates'),
- help_text="One or more assigned object types"
+ help_text=_("One or more assigned object types")
)
class Meta:
@@ -85,7 +86,7 @@ class ExportTemplateCSVForm(CSVModelForm):
class SavedFilterCSVForm(CSVModelForm):
content_types = CSVMultipleContentTypeField(
queryset=ContentType.objects.all(),
- help_text="One or more assigned object types"
+ help_text=_("One or more assigned object types")
)
class Meta:
@@ -99,7 +100,7 @@ class WebhookCSVForm(CSVModelForm):
content_types = CSVMultipleContentTypeField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('webhooks'),
- help_text="One or more assigned object types"
+ help_text=_("One or more assigned object types")
)
class Meta:
@@ -118,5 +119,5 @@ class TagCSVForm(CSVModelForm):
model = Tag
fields = ('name', 'slug', 'color', 'description')
help_texts = {
- 'color': mark_safe('RGB color in hexadecimal (e.g. 00ff00
)'),
+ 'color': mark_safe(_('RGB color in hexadecimal (e.g. 00ff00
)')),
}
diff --git a/netbox/extras/forms/filtersets.py b/netbox/extras/forms/filtersets.py
index 479367ff0..0421cab22 100644
--- a/netbox/extras/forms/filtersets.py
+++ b/netbox/extras/forms/filtersets.py
@@ -41,7 +41,7 @@ class CustomFieldFilterForm(SavedFiltersMixin, FilterForm):
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields'),
required=False,
- label='Object type'
+ label=_('Object type')
)
type = MultipleChoiceField(
choices=CustomFieldTypeChoices,
@@ -209,7 +209,7 @@ class WebhookFilterForm(SavedFiltersMixin, FilterForm):
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('webhooks'),
required=False,
- label='Object type'
+ label=_('Object type')
)
http_method = MultipleChoiceField(
choices=WebhookHttpMethodChoices,
diff --git a/netbox/extras/forms/mixins.py b/netbox/extras/forms/mixins.py
index 2b64d1a74..0a7dbdbcf 100644
--- a/netbox/extras/forms/mixins.py
+++ b/netbox/extras/forms/mixins.py
@@ -1,5 +1,6 @@
from django.contrib.contenttypes.models import ContentType
from django import forms
+from django.utils.translation import gettext as _
from extras.models import *
from extras.choices import CustomFieldVisibilityChoices
@@ -66,7 +67,7 @@ class SavedFiltersMixin(forms.Form):
filter = DynamicModelMultipleChoiceField(
queryset=SavedFilter.objects.all(),
required=False,
- label='Saved Filter',
+ label=_('Saved Filter'),
query_params={
'usable': True,
}
diff --git a/netbox/extras/forms/model_forms.py b/netbox/extras/forms/model_forms.py
index 97e80100a..192cdeeec 100644
--- a/netbox/extras/forms/model_forms.py
+++ b/netbox/extras/forms/model_forms.py
@@ -1,6 +1,7 @@
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.http import QueryDict
+from django.utils.translation import gettext as _
from dcim.models import DeviceRole, DeviceType, Location, Platform, Region, Site, SiteGroup
from extras.choices import *
@@ -31,14 +32,14 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm):
content_types = ContentTypeMultipleChoiceField(
queryset=ContentType.objects.all(),
limit_choices_to=FeatureQuery('custom_fields'),
- label='Model(s)'
+ label=_('Model(s)')
)
object_type = ContentTypeChoiceField(
queryset=ContentType.objects.all(),
# TODO: Come up with a canonical way to register suitable models
limit_choices_to=FeatureQuery('webhooks'),
required=False,
- help_text="Type of the related object (for object/multi-object fields only)"
+ help_text=_("Type of the related object (for object/multi-object fields only)")
)
fieldsets = (
@@ -54,8 +55,8 @@ class CustomFieldForm(BootstrapMixin, forms.ModelForm):
model = CustomField
fields = '__all__'
help_texts = {
- 'type': "The type of data stored in this field. For object/multi-object fields, select the related object "
- "type below."
+ 'type': _("The type of data stored in this field. For object/multi-object fields, select the related object "
+ "type below.")
}
widgets = {
'type': StaticSelect(),
@@ -84,9 +85,9 @@ class CustomLinkForm(BootstrapMixin, forms.ModelForm):
'link_url': forms.Textarea(attrs={'class': 'font-monospace'}),
}
help_texts = {
- 'link_text': 'Jinja2 template code for the link text. Reference the object as {{ object }}
. '
- 'Links which render as empty text will not be displayed.',
- 'link_url': 'Jinja2 template code for the link URL. Reference the object as {{ object }}
.',
+ 'link_text': _('Jinja2 template code for the link text. Reference the object as {{ object }}
. '
+ 'Links which render as empty text will not be displayed.'),
+ 'link_url': _('Jinja2 template code for the link URL. Reference the object as {{ object }}
.'),
}
diff --git a/netbox/extras/forms/reports.py b/netbox/extras/forms/reports.py
index aa4f6223b..863cf29c1 100644
--- a/netbox/extras/forms/reports.py
+++ b/netbox/extras/forms/reports.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from utilities.forms import BootstrapMixin, DateTimePicker
@@ -11,6 +12,6 @@ class ReportForm(BootstrapMixin, forms.Form):
schedule_at = forms.DateTimeField(
required=False,
widget=DateTimePicker(),
- label="Schedule at",
- help_text="Schedule execution of report to a set time",
+ label=_("Schedule at"),
+ help_text=_("Schedule execution of report to a set time"),
)
diff --git a/netbox/extras/forms/scripts.py b/netbox/extras/forms/scripts.py
index de55a3ee6..74c865c8d 100644
--- a/netbox/extras/forms/scripts.py
+++ b/netbox/extras/forms/scripts.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from utilities.forms import BootstrapMixin, DateTimePicker
@@ -11,14 +12,14 @@ class ScriptForm(BootstrapMixin, forms.Form):
_commit = forms.BooleanField(
required=False,
initial=True,
- label="Commit changes",
- help_text="Commit changes to the database (uncheck for a dry-run)"
+ label=_("Commit changes"),
+ help_text=_("Commit changes to the database (uncheck for a dry-run)")
)
_schedule_at = forms.DateTimeField(
required=False,
widget=DateTimePicker(),
- label="Schedule at",
- help_text="Schedule execution of script to a set time",
+ label=_("Schedule at"),
+ help_text=_("Schedule execution of script to a set time"),
)
def __init__(self, *args, **kwargs):
diff --git a/netbox/extras/models/customfields.py b/netbox/extras/models/customfields.py
index 2de806ca6..b03149698 100644
--- a/netbox/extras/models/customfields.py
+++ b/netbox/extras/models/customfields.py
@@ -11,6 +11,7 @@ from django.db import models
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.choices import *
from extras.utils import FeatureQuery
@@ -57,25 +58,25 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
to=ContentType,
related_name='custom_fields',
limit_choices_to=FeatureQuery('custom_fields'),
- help_text='The object(s) to which this field applies.'
+ help_text=_('The object(s) to which this field applies.')
)
type = models.CharField(
max_length=50,
choices=CustomFieldTypeChoices,
default=CustomFieldTypeChoices.TYPE_TEXT,
- help_text='The type of data this custom field holds'
+ help_text=_('The type of data this custom field holds')
)
object_type = models.ForeignKey(
to=ContentType,
on_delete=models.PROTECT,
blank=True,
null=True,
- help_text='The type of NetBox object this field maps to (for object fields)'
+ help_text=_('The type of NetBox object this field maps to (for object fields)')
)
name = models.CharField(
max_length=50,
unique=True,
- help_text='Internal field name',
+ help_text=_('Internal field name'),
validators=(
RegexValidator(
regex=r'^[a-z0-9_]+$',
@@ -87,13 +88,13 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
label = models.CharField(
max_length=50,
blank=True,
- help_text='Name of the field as displayed to users (if not provided, '
- 'the field\'s name will be used)'
+ help_text=_('Name of the field as displayed to users (if not provided, '
+ 'the field\'s name will be used)')
)
group_name = models.CharField(
max_length=50,
blank=True,
- help_text="Custom fields within the same group will be displayed together"
+ help_text=_("Custom fields within the same group will be displayed together")
)
description = models.CharField(
max_length=200,
@@ -101,64 +102,64 @@ class CustomField(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
)
required = models.BooleanField(
default=False,
- help_text='If true, this field is required when creating new objects '
- 'or editing an existing object.'
+ help_text=_('If true, this field is required when creating new objects '
+ 'or editing an existing object.')
)
search_weight = models.PositiveSmallIntegerField(
default=1000,
- help_text='Weighting for search. Lower values are considered more important. '
- 'Fields with a search weight of zero will be ignored.'
+ help_text=_('Weighting for search. Lower values are considered more important. '
+ 'Fields with a search weight of zero will be ignored.')
)
filter_logic = models.CharField(
max_length=50,
choices=CustomFieldFilterLogicChoices,
default=CustomFieldFilterLogicChoices.FILTER_LOOSE,
- help_text='Loose matches any instance of a given string; exact '
- 'matches the entire field.'
+ help_text=_('Loose matches any instance of a given string; exact '
+ 'matches the entire field.')
)
default = models.JSONField(
blank=True,
null=True,
- help_text='Default value for the field (must be a JSON value). Encapsulate '
- 'strings with double quotes (e.g. "Foo").'
+ help_text=_('Default value for the field (must be a JSON value). Encapsulate '
+ 'strings with double quotes (e.g. "Foo").')
)
weight = models.PositiveSmallIntegerField(
default=100,
verbose_name='Display weight',
- help_text='Fields with higher weights appear lower in a form.'
+ help_text=_('Fields with higher weights appear lower in a form.')
)
validation_minimum = models.IntegerField(
blank=True,
null=True,
verbose_name='Minimum value',
- help_text='Minimum allowed value (for numeric fields)'
+ help_text=_('Minimum allowed value (for numeric fields)')
)
validation_maximum = models.IntegerField(
blank=True,
null=True,
verbose_name='Maximum value',
- help_text='Maximum allowed value (for numeric fields)'
+ help_text=_('Maximum allowed value (for numeric fields)')
)
validation_regex = models.CharField(
blank=True,
validators=[validate_regex],
max_length=500,
verbose_name='Validation regex',
- help_text='Regular expression to enforce on text field values. Use ^ and $ to force matching of entire string. '
- 'For example, ^[A-Z]{3}$
will limit values to exactly three uppercase letters.'
+ help_text=_('Regular expression to enforce on text field values. Use ^ and $ to force matching of entire string. '
+ 'For example, ^[A-Z]{3}$
will limit values to exactly three uppercase letters.')
)
choices = ArrayField(
base_field=models.CharField(max_length=100),
blank=True,
null=True,
- help_text='Comma-separated list of available choices (for selection fields)'
+ help_text=_('Comma-separated list of available choices (for selection fields)')
)
ui_visibility = models.CharField(
max_length=50,
choices=CustomFieldVisibilityChoices,
default=CustomFieldVisibilityChoices.VISIBILITY_READ_WRITE,
verbose_name='UI visibility',
- help_text='Specifies the visibility of custom field in the UI'
+ help_text=_('Specifies the visibility of custom field in the UI')
)
objects = CustomFieldManager()
diff --git a/netbox/extras/models/models.py b/netbox/extras/models/models.py
index 4b4e7c0cf..c33245f99 100644
--- a/netbox/extras/models/models.py
+++ b/netbox/extras/models/models.py
@@ -12,6 +12,7 @@ from django.http import HttpResponse, QueryDict
from django.urls import reverse
from django.utils import timezone
from django.utils.formats import date_format
+from django.utils.translation import gettext as _
from rest_framework.utils.encoders import JSONEncoder
import django_rq
@@ -51,7 +52,7 @@ class Webhook(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
related_name='webhooks',
verbose_name='Object types',
limit_choices_to=FeatureQuery('webhooks'),
- help_text="The object(s) to which this Webhook applies."
+ help_text=_("The object(s) to which this Webhook applies.")
)
name = models.CharField(
max_length=150,
@@ -59,21 +60,21 @@ class Webhook(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
)
type_create = models.BooleanField(
default=False,
- help_text="Call this webhook when a matching object is created."
+ help_text=_("Call this webhook when a matching object is created.")
)
type_update = models.BooleanField(
default=False,
- help_text="Call this webhook when a matching object is updated."
+ help_text=_("Call this webhook when a matching object is updated.")
)
type_delete = models.BooleanField(
default=False,
- help_text="Call this webhook when a matching object is deleted."
+ help_text=_("Call this webhook when a matching object is deleted.")
)
payload_url = models.CharField(
max_length=500,
verbose_name='URL',
- help_text='This URL will be called using the HTTP method defined when the webhook is called. '
- 'Jinja2 template processing is supported with the same context as the request body.'
+ help_text=_('This URL will be called using the HTTP method defined when the webhook is called. '
+ 'Jinja2 template processing is supported with the same context as the request body.')
)
enabled = models.BooleanField(
default=True
@@ -88,46 +89,46 @@ class Webhook(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
max_length=100,
default=HTTP_CONTENT_TYPE_JSON,
verbose_name='HTTP content type',
- help_text='The complete list of official content types is available '
- 'here.'
+ help_text=_('The complete list of official content types is available '
+ 'here.')
)
additional_headers = models.TextField(
blank=True,
- help_text="User-supplied HTTP headers to be sent with the request in addition to the HTTP content type. "
- "Headers should be defined in the format Name: Value
. Jinja2 template processing is "
- "supported with the same context as the request body (below)."
+ help_text=_("User-supplied HTTP headers to be sent with the request in addition to the HTTP content type. "
+ "Headers should be defined in the format Name: Value
. Jinja2 template processing is "
+ "supported with the same context as the request body (below).")
)
body_template = models.TextField(
blank=True,
- help_text='Jinja2 template for a custom request body. If blank, a JSON object representing the change will be '
- 'included. Available context data includes: event
, model
, '
- 'timestamp
, username
, request_id
, and data
.'
+ help_text=_('Jinja2 template for a custom request body. If blank, a JSON object representing the change will be '
+ 'included. Available context data includes: event
, model
, '
+ 'timestamp
, username
, request_id
, and data
.')
)
secret = models.CharField(
max_length=255,
blank=True,
- help_text="When provided, the request will include a 'X-Hook-Signature' "
- "header containing a HMAC hex digest of the payload body using "
- "the secret as the key. The secret is not transmitted in "
- "the request."
+ help_text=_("When provided, the request will include a 'X-Hook-Signature' "
+ "header containing a HMAC hex digest of the payload body using "
+ "the secret as the key. The secret is not transmitted in "
+ "the request.")
)
conditions = models.JSONField(
blank=True,
null=True,
- help_text="A set of conditions which determine whether the webhook will be generated."
+ help_text=_("A set of conditions which determine whether the webhook will be generated.")
)
ssl_verification = models.BooleanField(
default=True,
verbose_name='SSL verification',
- help_text="Enable SSL certificate verification. Disable with caution!"
+ help_text=_("Enable SSL certificate verification. Disable with caution!")
)
ca_file_path = models.CharField(
max_length=4096,
null=True,
blank=True,
verbose_name='CA File Path',
- help_text='The specific CA certificate file to use for SSL verification. '
- 'Leave blank to use the system defaults.'
+ help_text=_('The specific CA certificate file to use for SSL verification. '
+ 'Leave blank to use the system defaults.')
)
class Meta:
@@ -201,7 +202,7 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogged
content_types = models.ManyToManyField(
to=ContentType,
related_name='custom_links',
- help_text='The object type(s) to which this link applies.'
+ help_text=_('The object type(s) to which this link applies.')
)
name = models.CharField(
max_length=100,
@@ -211,11 +212,11 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogged
default=True
)
link_text = models.TextField(
- help_text="Jinja2 template code for link text"
+ help_text=_("Jinja2 template code for link text")
)
link_url = models.TextField(
verbose_name='Link URL',
- help_text="Jinja2 template code for link URL"
+ help_text=_("Jinja2 template code for link URL")
)
weight = models.PositiveSmallIntegerField(
default=100
@@ -223,17 +224,17 @@ class CustomLink(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogged
group_name = models.CharField(
max_length=50,
blank=True,
- help_text="Links with the same group will appear as a dropdown menu"
+ help_text=_("Links with the same group will appear as a dropdown menu")
)
button_class = models.CharField(
max_length=30,
choices=CustomLinkButtonClassChoices,
default=CustomLinkButtonClassChoices.DEFAULT,
- help_text="The class of the first link in a group will be used for the dropdown button"
+ help_text=_("The class of the first link in a group will be used for the dropdown button")
)
new_window = models.BooleanField(
default=False,
- help_text="Force link to open in a new window"
+ help_text=_("Force link to open in a new window")
)
clone_fields = (
@@ -272,7 +273,7 @@ class ExportTemplate(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
content_types = models.ManyToManyField(
to=ContentType,
related_name='export_templates',
- help_text='The object type(s) to which this template applies.'
+ help_text=_('The object type(s) to which this template applies.')
)
name = models.CharField(
max_length=100
@@ -282,23 +283,23 @@ class ExportTemplate(ExportTemplatesMixin, WebhooksMixin, ChangeLoggedModel):
blank=True
)
template_code = models.TextField(
- help_text='Jinja2 template code. The list of objects being exported is passed as a context variable named '
- 'queryset
.'
+ help_text=_('Jinja2 template code. The list of objects being exported is passed as a context variable named '
+ 'queryset
.')
)
mime_type = models.CharField(
max_length=50,
blank=True,
verbose_name='MIME type',
- help_text='Defaults to text/plain
'
+ help_text=_('Defaults to text/plain
')
)
file_extension = models.CharField(
max_length=15,
blank=True,
- help_text='Extension to append to the rendered filename'
+ help_text=_('Extension to append to the rendered filename')
)
as_attachment = models.BooleanField(
default=True,
- help_text="Download file as attachment"
+ help_text=_("Download file as attachment")
)
class Meta:
@@ -358,7 +359,7 @@ class SavedFilter(CloningMixin, ExportTemplatesMixin, WebhooksMixin, ChangeLogge
content_types = models.ManyToManyField(
to=ContentType,
related_name='saved_filters',
- help_text='The object type(s) to which this filter applies.'
+ help_text=_('The object type(s) to which this filter applies.')
)
name = models.CharField(
max_length=100,
@@ -553,7 +554,7 @@ class JobResult(models.Model):
related_name='job_results',
verbose_name='Object types',
limit_choices_to=FeatureQuery('job_results'),
- help_text="The object type to which this job result applies",
+ help_text=_("The object type to which this job result applies"),
on_delete=models.CASCADE,
)
created = models.DateTimeField(
diff --git a/netbox/extras/tests/dummy_plugin/navigation.py b/netbox/extras/tests/dummy_plugin/navigation.py
index a475b1cde..8aa161520 100644
--- a/netbox/extras/tests/dummy_plugin/navigation.py
+++ b/netbox/extras/tests/dummy_plugin/navigation.py
@@ -1,3 +1,4 @@
+from django.utils.translation import gettext as _
from extras.plugins import PluginMenu, PluginMenuButton, PluginMenuItem
@@ -25,7 +26,7 @@ items = (
)
menu = PluginMenu(
- label='Dummy',
+ label=_('Dummy'),
groups=(('Group 1', items),),
)
menu_items = items
diff --git a/netbox/ipam/filtersets.py b/netbox/ipam/filtersets.py
index 360cf2a56..b5478b7a0 100644
--- a/netbox/ipam/filtersets.py
+++ b/netbox/ipam/filtersets.py
@@ -3,6 +3,7 @@ import netaddr
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db.models import Q
+from django.utils.translation import gettext as _
from netaddr.core import AddrFormatError
from dcim.models import Device, Interface, Region, Site, SiteGroup
@@ -41,24 +42,24 @@ class VRFFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
import_target_id = django_filters.ModelMultipleChoiceFilter(
field_name='import_targets',
queryset=RouteTarget.objects.all(),
- label='Import target',
+ label=_('Import target'),
)
import_target = django_filters.ModelMultipleChoiceFilter(
field_name='import_targets__name',
queryset=RouteTarget.objects.all(),
to_field_name='name',
- label='Import target (name)',
+ label=_('Import target (name)'),
)
export_target_id = django_filters.ModelMultipleChoiceFilter(
field_name='export_targets',
queryset=RouteTarget.objects.all(),
- label='Export target',
+ label=_('Export target'),
)
export_target = django_filters.ModelMultipleChoiceFilter(
field_name='export_targets__name',
queryset=RouteTarget.objects.all(),
to_field_name='name',
- label='Export target (name)',
+ label=_('Export target (name)'),
)
def search(self, queryset, name, value):
@@ -79,24 +80,24 @@ class RouteTargetFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
importing_vrf_id = django_filters.ModelMultipleChoiceFilter(
field_name='importing_vrfs',
queryset=VRF.objects.all(),
- label='Importing VRF',
+ label=_('Importing VRF'),
)
importing_vrf = django_filters.ModelMultipleChoiceFilter(
field_name='importing_vrfs__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
- label='Import VRF (RD)',
+ label=_('Import VRF (RD)'),
)
exporting_vrf_id = django_filters.ModelMultipleChoiceFilter(
field_name='exporting_vrfs',
queryset=VRF.objects.all(),
- label='Exporting VRF',
+ label=_('Exporting VRF'),
)
exporting_vrf = django_filters.ModelMultipleChoiceFilter(
field_name='exporting_vrfs__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
- label='Export VRF (RD)',
+ label=_('Export VRF (RD)'),
)
def search(self, queryset, name, value):
@@ -126,17 +127,17 @@ class AggregateFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
)
prefix = django_filters.CharFilter(
method='filter_prefix',
- label='Prefix',
+ label=_('Prefix'),
)
rir_id = django_filters.ModelMultipleChoiceFilter(
queryset=RIR.objects.all(),
- label='RIR (ID)',
+ label=_('RIR (ID)'),
)
rir = django_filters.ModelMultipleChoiceFilter(
field_name='rir__slug',
queryset=RIR.objects.all(),
to_field_name='slug',
- label='RIR (slug)',
+ label=_('RIR (slug)'),
)
class Meta:
@@ -169,24 +170,24 @@ class AggregateFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
class ASNFilterSet(OrganizationalModelFilterSet, TenancyFilterSet):
rir_id = django_filters.ModelMultipleChoiceFilter(
queryset=RIR.objects.all(),
- label='RIR (ID)',
+ label=_('RIR (ID)'),
)
rir = django_filters.ModelMultipleChoiceFilter(
field_name='rir__slug',
queryset=RIR.objects.all(),
to_field_name='slug',
- label='RIR (slug)',
+ label=_('RIR (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
field_name='sites',
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='sites__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
class Meta:
@@ -218,19 +219,19 @@ class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
)
prefix = MultiValueCharFilter(
method='filter_prefix',
- label='Prefix',
+ label=_('Prefix'),
)
within = django_filters.CharFilter(
method='search_within',
- label='Within prefix',
+ label=_('Within prefix'),
)
within_include = django_filters.CharFilter(
method='search_within_include',
- label='Within and including prefix',
+ label=_('Within and including prefix'),
)
contains = django_filters.CharFilter(
method='search_contains',
- label='Prefixes which contain this prefix or IP',
+ label=_('Prefixes which contain this prefix or IP'),
)
depth = MultiValueNumberFilter(
field_name='_depth'
@@ -252,78 +253,78 @@ class PrefixFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
)
vrf_id = django_filters.ModelMultipleChoiceFilter(
queryset=VRF.objects.all(),
- label='VRF',
+ label=_('VRF'),
)
vrf = django_filters.ModelMultipleChoiceFilter(
field_name='vrf__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
- label='VRF (RD)',
+ label=_('VRF (RD)'),
)
present_in_vrf_id = django_filters.ModelChoiceFilter(
queryset=VRF.objects.all(),
method='filter_present_in_vrf',
- label='VRF'
+ label=_('VRF')
)
present_in_vrf = django_filters.ModelChoiceFilter(
queryset=VRF.objects.all(),
method='filter_present_in_vrf',
to_field_name='rd',
- label='VRF (RD)',
+ label=_('VRF (RD)'),
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
vlan_id = django_filters.ModelMultipleChoiceFilter(
queryset=VLAN.objects.all(),
- label='VLAN (ID)',
+ label=_('VLAN (ID)'),
)
vlan_vid = django_filters.NumberFilter(
field_name='vlan__vid',
- label='VLAN number (1-4094)',
+ label=_('VLAN number (1-4094)'),
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=Role.objects.all(),
- label='Role (ID)',
+ label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=Role.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
status = django_filters.MultipleChoiceFilter(
choices=PrefixStatusChoices,
@@ -406,27 +407,27 @@ class IPRangeFilterSet(TenancyFilterSet, NetBoxModelFilterSet):
)
contains = django_filters.CharFilter(
method='search_contains',
- label='Ranges which contain this prefix or IP',
+ label=_('Ranges which contain this prefix or IP'),
)
vrf_id = django_filters.ModelMultipleChoiceFilter(
queryset=VRF.objects.all(),
- label='VRF',
+ label=_('VRF'),
)
vrf = django_filters.ModelMultipleChoiceFilter(
field_name='vrf__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
- label='VRF (RD)',
+ label=_('VRF (RD)'),
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=Role.objects.all(),
- label='Role (ID)',
+ label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=Role.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
status = django_filters.MultipleChoiceFilter(
choices=IPRangeStatusChoices,
@@ -468,87 +469,87 @@ class IPAddressFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
)
parent = MultiValueCharFilter(
method='search_by_parent',
- label='Parent prefix',
+ label=_('Parent prefix'),
)
address = MultiValueCharFilter(
method='filter_address',
- label='Address',
+ label=_('Address'),
)
mask_length = django_filters.NumberFilter(
method='filter_mask_length',
- label='Mask length',
+ label=_('Mask length'),
)
vrf_id = django_filters.ModelMultipleChoiceFilter(
queryset=VRF.objects.all(),
- label='VRF',
+ label=_('VRF'),
)
vrf = django_filters.ModelMultipleChoiceFilter(
field_name='vrf__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
- label='VRF (RD)',
+ label=_('VRF (RD)'),
)
present_in_vrf_id = django_filters.ModelChoiceFilter(
queryset=VRF.objects.all(),
method='filter_present_in_vrf',
- label='VRF'
+ label=_('VRF')
)
present_in_vrf = django_filters.ModelChoiceFilter(
queryset=VRF.objects.all(),
method='filter_present_in_vrf',
to_field_name='rd',
- label='VRF (RD)',
+ label=_('VRF (RD)'),
)
device = MultiValueCharFilter(
method='filter_device',
field_name='name',
- label='Device (name)',
+ label=_('Device (name)'),
)
device_id = MultiValueNumberFilter(
method='filter_device',
field_name='pk',
- label='Device (ID)',
+ label=_('Device (ID)'),
)
virtual_machine = MultiValueCharFilter(
method='filter_virtual_machine',
field_name='name',
- label='Virtual machine (name)',
+ label=_('Virtual machine (name)'),
)
virtual_machine_id = MultiValueNumberFilter(
method='filter_virtual_machine',
field_name='pk',
- label='Virtual machine (ID)',
+ label=_('Virtual machine (ID)'),
)
interface = django_filters.ModelMultipleChoiceFilter(
field_name='interface__name',
queryset=Interface.objects.all(),
to_field_name='name',
- label='Interface (name)',
+ label=_('Interface (name)'),
)
interface_id = django_filters.ModelMultipleChoiceFilter(
field_name='interface',
queryset=Interface.objects.all(),
- label='Interface (ID)',
+ label=_('Interface (ID)'),
)
vminterface = django_filters.ModelMultipleChoiceFilter(
field_name='vminterface__name',
queryset=VMInterface.objects.all(),
to_field_name='name',
- label='VM interface (name)',
+ label=_('VM interface (name)'),
)
vminterface_id = django_filters.ModelMultipleChoiceFilter(
field_name='vminterface',
queryset=VMInterface.objects.all(),
- label='VM interface (ID)',
+ label=_('VM interface (ID)'),
)
fhrpgroup_id = django_filters.ModelMultipleChoiceFilter(
field_name='fhrpgroup',
queryset=FHRPGroup.objects.all(),
- label='FHRP group (ID)',
+ label=_('FHRP group (ID)'),
)
assigned_to_interface = django_filters.BooleanFilter(
method='_assigned_to_interface',
- label='Is assigned to an interface',
+ label=_('Is assigned to an interface'),
)
status = django_filters.MultipleChoiceFilter(
choices=IPAddressStatusChoices,
@@ -688,27 +689,27 @@ class FHRPGroupAssignmentFilterSet(ChangeLoggedModelFilterSet):
interface_type = ContentTypeFilter()
group_id = django_filters.ModelMultipleChoiceFilter(
queryset=FHRPGroup.objects.all(),
- label='Group (ID)',
+ label=_('Group (ID)'),
)
device = MultiValueCharFilter(
method='filter_device',
field_name='name',
- label='Device (name)',
+ label=_('Device (name)'),
)
device_id = MultiValueNumberFilter(
method='filter_device',
field_name='pk',
- label='Device (ID)',
+ label=_('Device (ID)'),
)
virtual_machine = MultiValueCharFilter(
method='filter_virtual_machine',
field_name='name',
- label='Virtual machine (name)',
+ label=_('Virtual machine (name)'),
)
virtual_machine_id = MultiValueNumberFilter(
method='filter_virtual_machine',
field_name='pk',
- label='Virtual machine (ID)',
+ label=_('Virtual machine (ID)'),
)
class Meta:
@@ -787,57 +788,57 @@ class VLANFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
group_id = django_filters.ModelMultipleChoiceFilter(
queryset=VLANGroup.objects.all(),
- label='Group (ID)',
+ label=_('Group (ID)'),
)
group = django_filters.ModelMultipleChoiceFilter(
field_name='group__slug',
queryset=VLANGroup.objects.all(),
to_field_name='slug',
- label='Group',
+ label=_('Group'),
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=Role.objects.all(),
- label='Role (ID)',
+ label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=Role.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
status = django_filters.MultipleChoiceFilter(
choices=VLANStatusChoices,
@@ -893,23 +894,23 @@ class ServiceTemplateFilterSet(NetBoxModelFilterSet):
class ServiceFilterSet(NetBoxModelFilterSet):
device_id = django_filters.ModelMultipleChoiceFilter(
queryset=Device.objects.all(),
- label='Device (ID)',
+ label=_('Device (ID)'),
)
device = django_filters.ModelMultipleChoiceFilter(
field_name='device__name',
queryset=Device.objects.all(),
to_field_name='name',
- label='Device (name)',
+ label=_('Device (name)'),
)
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
queryset=VirtualMachine.objects.all(),
- label='Virtual machine (ID)',
+ label=_('Virtual machine (ID)'),
)
virtual_machine = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine__name',
queryset=VirtualMachine.objects.all(),
to_field_name='name',
- label='Virtual machine (name)',
+ label=_('Virtual machine (name)'),
)
port = NumericArrayFilter(
field_name='ports',
@@ -939,24 +940,24 @@ class L2VPNFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
import_target_id = django_filters.ModelMultipleChoiceFilter(
field_name='import_targets',
queryset=RouteTarget.objects.all(),
- label='Import target',
+ label=_('Import target'),
)
import_target = django_filters.ModelMultipleChoiceFilter(
field_name='import_targets__name',
queryset=RouteTarget.objects.all(),
to_field_name='name',
- label='Import target (name)',
+ label=_('Import target (name)'),
)
export_target_id = django_filters.ModelMultipleChoiceFilter(
field_name='export_targets',
queryset=RouteTarget.objects.all(),
- label='Export target',
+ label=_('Export target'),
)
export_target = django_filters.ModelMultipleChoiceFilter(
field_name='export_targets__name',
queryset=RouteTarget.objects.all(),
to_field_name='name',
- label='Export target (name)',
+ label=_('Export target (name)'),
)
class Meta:
@@ -977,92 +978,92 @@ class L2VPNFilterSet(NetBoxModelFilterSet, TenancyFilterSet):
class L2VPNTerminationFilterSet(NetBoxModelFilterSet):
l2vpn_id = django_filters.ModelMultipleChoiceFilter(
queryset=L2VPN.objects.all(),
- label='L2VPN (ID)',
+ label=_('L2VPN (ID)'),
)
l2vpn = django_filters.ModelMultipleChoiceFilter(
field_name='l2vpn__slug',
queryset=L2VPN.objects.all(),
to_field_name='slug',
- label='L2VPN (slug)',
+ label=_('L2VPN (slug)'),
)
region = MultiValueCharFilter(
method='filter_region',
field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
region_id = MultiValueNumberFilter(
method='filter_region',
field_name='pk',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
site = MultiValueCharFilter(
method='filter_site',
field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
site_id = MultiValueNumberFilter(
method='filter_site',
field_name='pk',
- label='Site (ID)',
+ label=_('Site (ID)'),
)
device = django_filters.ModelMultipleChoiceFilter(
field_name='interface__device__name',
queryset=Device.objects.all(),
to_field_name='name',
- label='Device (name)',
+ label=_('Device (name)'),
)
device_id = django_filters.ModelMultipleChoiceFilter(
field_name='interface__device',
queryset=Device.objects.all(),
- label='Device (ID)',
+ label=_('Device (ID)'),
)
virtual_machine = django_filters.ModelMultipleChoiceFilter(
field_name='vminterface__virtual_machine__name',
queryset=VirtualMachine.objects.all(),
to_field_name='name',
- label='Virtual machine (name)',
+ label=_('Virtual machine (name)'),
)
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
field_name='vminterface__virtual_machine',
queryset=VirtualMachine.objects.all(),
- label='Virtual machine (ID)',
+ label=_('Virtual machine (ID)'),
)
interface = django_filters.ModelMultipleChoiceFilter(
field_name='interface__name',
queryset=Interface.objects.all(),
to_field_name='name',
- label='Interface (name)',
+ label=_('Interface (name)'),
)
interface_id = django_filters.ModelMultipleChoiceFilter(
field_name='interface',
queryset=Interface.objects.all(),
- label='Interface (ID)',
+ label=_('Interface (ID)'),
)
vminterface = django_filters.ModelMultipleChoiceFilter(
field_name='vminterface__name',
queryset=VMInterface.objects.all(),
to_field_name='name',
- label='VM interface (name)',
+ label=_('VM interface (name)'),
)
vminterface_id = django_filters.ModelMultipleChoiceFilter(
field_name='vminterface',
queryset=VMInterface.objects.all(),
- label='VM Interface (ID)',
+ label=_('VM Interface (ID)'),
)
vlan = django_filters.ModelMultipleChoiceFilter(
field_name='vlan__name',
queryset=VLAN.objects.all(),
to_field_name='name',
- label='VLAN (name)',
+ label=_('VLAN (name)'),
)
vlan_vid = django_filters.NumberFilter(
field_name='vlan__vid',
- label='VLAN number (1-4094)',
+ label=_('VLAN number (1-4094)'),
)
vlan_id = django_filters.ModelMultipleChoiceFilter(
field_name='vlan',
queryset=VLAN.objects.all(),
- label='VLAN (ID)',
+ label=_('VLAN (ID)'),
)
assigned_object_type = ContentTypeFilter()
diff --git a/netbox/ipam/forms/bulk_create.py b/netbox/ipam/forms/bulk_create.py
index 790474c6e..6d07951a3 100644
--- a/netbox/ipam/forms/bulk_create.py
+++ b/netbox/ipam/forms/bulk_create.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from utilities.forms import BootstrapMixin, ExpandableIPAddressField
@@ -9,5 +10,5 @@ __all__ = (
class IPAddressBulkCreateForm(BootstrapMixin, forms.Form):
pattern = ExpandableIPAddressField(
- label='Address pattern'
+ label=_('Address pattern')
)
diff --git a/netbox/ipam/forms/bulk_edit.py b/netbox/ipam/forms/bulk_edit.py
index ed1d1d9e9..d0af43975 100644
--- a/netbox/ipam/forms/bulk_edit.py
+++ b/netbox/ipam/forms/bulk_edit.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from dcim.models import Region, Site, SiteGroup
from ipam.choices import *
@@ -40,7 +41,7 @@ class VRFBulkEditForm(NetBoxModelBulkEditForm):
enforce_unique = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect(),
- label='Enforce unique space'
+ label=_('Enforce unique space')
)
description = forms.CharField(
max_length=200,
@@ -104,7 +105,7 @@ class ASNBulkEditForm(NetBoxModelBulkEditForm):
rir = DynamicModelChoiceField(
queryset=RIR.objects.all(),
required=False,
- label='RIR'
+ label=_('RIR')
)
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
@@ -130,7 +131,7 @@ class AggregateBulkEditForm(NetBoxModelBulkEditForm):
rir = DynamicModelChoiceField(
queryset=RIR.objects.all(),
required=False,
- label='RIR'
+ label=_('RIR')
)
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
@@ -191,7 +192,7 @@ class PrefixBulkEditForm(NetBoxModelBulkEditForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
prefix_length = forms.IntegerField(
min_value=PREFIX_LENGTH_MIN,
@@ -214,12 +215,12 @@ class PrefixBulkEditForm(NetBoxModelBulkEditForm):
is_pool = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect(),
- label='Is a pool'
+ label=_('Is a pool')
)
mark_utilized = forms.NullBooleanField(
required=False,
widget=BulkEditNullBooleanSelect(),
- label='Treat as 100% utilized'
+ label=_('Treat as 100% utilized')
)
description = forms.CharField(
max_length=200,
@@ -245,7 +246,7 @@ class IPRangeBulkEditForm(NetBoxModelBulkEditForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
@@ -282,7 +283,7 @@ class IPAddressBulkEditForm(NetBoxModelBulkEditForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
mask_length = forms.IntegerField(
min_value=IPADDRESS_MASK_LENGTH_MIN,
@@ -306,7 +307,7 @@ class IPAddressBulkEditForm(NetBoxModelBulkEditForm):
dns_name = forms.CharField(
max_length=255,
required=False,
- label='DNS name'
+ label=_('DNS name')
)
description = forms.CharField(
max_length=200,
@@ -336,18 +337,18 @@ class FHRPGroupBulkEditForm(NetBoxModelBulkEditForm):
group_id = forms.IntegerField(
min_value=0,
required=False,
- label='Group ID'
+ label=_('Group ID')
)
auth_type = forms.ChoiceField(
choices=add_blank_choice(FHRPGroupAuthTypeChoices),
required=False,
widget=StaticSelect(),
- label='Authentication type'
+ label=_('Authentication type')
)
auth_key = forms.CharField(
max_length=255,
required=False,
- label='Authentication key'
+ label=_('Authentication key')
)
name = forms.CharField(
max_length=100,
@@ -379,13 +380,13 @@ class VLANGroupBulkEditForm(NetBoxModelBulkEditForm):
min_value=VLAN_VID_MIN,
max_value=VLAN_VID_MAX,
required=False,
- label='Minimum child VLAN VID'
+ label=_('Minimum child VLAN VID')
)
max_vid = forms.IntegerField(
min_value=VLAN_VID_MIN,
max_value=VLAN_VID_MAX,
required=False,
- label='Maximum child VLAN VID'
+ label=_('Maximum child VLAN VID')
)
description = forms.CharField(
max_length=200,
diff --git a/netbox/ipam/forms/bulk_import.py b/netbox/ipam/forms/bulk_import.py
index 4cd0bb69f..177233717 100644
--- a/netbox/ipam/forms/bulk_import.py
+++ b/netbox/ipam/forms/bulk_import.py
@@ -1,6 +1,7 @@
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
+from django.utils.translation import gettext as _
from dcim.models import Device, Interface, Site
from ipam.choices import *
@@ -36,7 +37,7 @@ class VRFCSVForm(NetBoxModelCSVForm):
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
@@ -49,7 +50,7 @@ class RouteTargetCSVForm(NetBoxModelCSVForm):
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
@@ -64,7 +65,7 @@ class RIRCSVForm(NetBoxModelCSVForm):
model = RIR
fields = ('name', 'slug', 'is_private', 'description', 'tags')
help_texts = {
- 'name': 'RIR name',
+ 'name': _('RIR name'),
}
@@ -72,13 +73,13 @@ class AggregateCSVForm(NetBoxModelCSVForm):
rir = CSVModelChoiceField(
queryset=RIR.objects.all(),
to_field_name='name',
- help_text='Assigned RIR'
+ help_text=_('Assigned RIR')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
@@ -90,13 +91,13 @@ class ASNCSVForm(NetBoxModelCSVForm):
rir = CSVModelChoiceField(
queryset=RIR.objects.all(),
to_field_name='name',
- help_text='Assigned RIR'
+ help_text=_('Assigned RIR')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
@@ -117,41 +118,41 @@ class PrefixCSVForm(NetBoxModelCSVForm):
queryset=VRF.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned VRF'
+ help_text=_('Assigned VRF')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
site = CSVModelChoiceField(
queryset=Site.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned site'
+ help_text=_('Assigned site')
)
vlan_group = CSVModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
to_field_name='name',
- help_text="VLAN's group (if any)"
+ help_text=_("VLAN's group (if any)")
)
vlan = CSVModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
to_field_name='vid',
- help_text="Assigned VLAN"
+ help_text=_("Assigned VLAN")
)
status = CSVChoiceField(
choices=PrefixStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
role = CSVModelChoiceField(
queryset=Role.objects.all(),
required=False,
to_field_name='name',
- help_text='Functional role'
+ help_text=_('Functional role')
)
class Meta:
@@ -181,23 +182,23 @@ class IPRangeCSVForm(NetBoxModelCSVForm):
queryset=VRF.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned VRF'
+ help_text=_('Assigned VRF')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
status = CSVChoiceField(
choices=IPRangeStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
role = CSVModelChoiceField(
queryset=Role.objects.all(),
required=False,
to_field_name='name',
- help_text='Functional role'
+ help_text=_('Functional role')
)
class Meta:
@@ -212,43 +213,43 @@ class IPAddressCSVForm(NetBoxModelCSVForm):
queryset=VRF.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned VRF'
+ help_text=_('Assigned VRF')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
status = CSVChoiceField(
choices=IPAddressStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
role = CSVChoiceField(
choices=IPAddressRoleChoices,
required=False,
- help_text='Functional role'
+ help_text=_('Functional role')
)
device = CSVModelChoiceField(
queryset=Device.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent device of assigned interface (if any)'
+ help_text=_('Parent device of assigned interface (if any)')
)
virtual_machine = CSVModelChoiceField(
queryset=VirtualMachine.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent VM of assigned interface (if any)'
+ help_text=_('Parent VM of assigned interface (if any)')
)
interface = CSVModelChoiceField(
queryset=Interface.objects.none(), # Can also refer to VMInterface
required=False,
to_field_name='name',
- help_text='Assigned interface'
+ help_text=_('Assigned interface')
)
is_primary = forms.BooleanField(
- help_text='Make this the primary IP for the assigned device',
+ help_text=_('Make this the primary IP for the assigned device'),
required=False
)
@@ -333,7 +334,7 @@ class VLANGroupCSVForm(NetBoxModelCSVForm):
scope_type = CSVContentTypeField(
queryset=ContentType.objects.filter(model__in=VLANGROUP_SCOPE_TYPES),
required=False,
- label='Scope type (app & model)'
+ label=_('Scope type (app & model)')
)
min_vid = forms.IntegerField(
min_value=VLAN_VID_MIN,
@@ -361,29 +362,29 @@ class VLANCSVForm(NetBoxModelCSVForm):
queryset=Site.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned site'
+ help_text=_('Assigned site')
)
group = CSVModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned VLAN group'
+ help_text=_('Assigned VLAN group')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
status = CSVChoiceField(
choices=VLANStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
role = CSVModelChoiceField(
queryset=Role.objects.all(),
required=False,
to_field_name='name',
- help_text='Functional role'
+ help_text=_('Functional role')
)
class Meta:
@@ -398,7 +399,7 @@ class VLANCSVForm(NetBoxModelCSVForm):
class ServiceTemplateCSVForm(NetBoxModelCSVForm):
protocol = CSVChoiceField(
choices=ServiceProtocolChoices,
- help_text='IP protocol'
+ help_text=_('IP protocol')
)
class Meta:
@@ -411,17 +412,17 @@ class ServiceCSVForm(NetBoxModelCSVForm):
queryset=Device.objects.all(),
required=False,
to_field_name='name',
- help_text='Required if not assigned to a VM'
+ help_text=_('Required if not assigned to a VM')
)
virtual_machine = CSVModelChoiceField(
queryset=VirtualMachine.objects.all(),
required=False,
to_field_name='name',
- help_text='Required if not assigned to a device'
+ help_text=_('Required if not assigned to a device')
)
protocol = CSVChoiceField(
choices=ServiceProtocolChoices,
- help_text='IP protocol'
+ help_text=_('IP protocol')
)
class Meta:
@@ -437,7 +438,7 @@ class L2VPNCSVForm(NetBoxModelCSVForm):
)
type = CSVChoiceField(
choices=L2VPNTypeChoices,
- help_text='L2VPN type'
+ help_text=_('L2VPN type')
)
class Meta:
@@ -450,31 +451,31 @@ class L2VPNTerminationCSVForm(NetBoxModelCSVForm):
queryset=L2VPN.objects.all(),
required=True,
to_field_name='name',
- label='L2VPN',
+ label=_('L2VPN'),
)
device = CSVModelChoiceField(
queryset=Device.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent device (for interface)'
+ help_text=_('Parent device (for interface)')
)
virtual_machine = CSVModelChoiceField(
queryset=VirtualMachine.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent virtual machine (for interface)'
+ help_text=_('Parent virtual machine (for interface)')
)
interface = CSVModelChoiceField(
queryset=Interface.objects.none(), # Can also refer to VMInterface
required=False,
to_field_name='name',
- help_text='Assigned interface (device or VM)'
+ help_text=_('Assigned interface (device or VM)')
)
vlan = CSVModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned VLAN'
+ help_text=_('Assigned VLAN')
)
class Meta:
diff --git a/netbox/ipam/forms/filtersets.py b/netbox/ipam/forms/filtersets.py
index 7d277b33b..1a1496d7b 100644
--- a/netbox/ipam/forms/filtersets.py
+++ b/netbox/ipam/forms/filtersets.py
@@ -397,13 +397,13 @@ class VLANGroupFilterForm(NetBoxModelFilterSetForm):
required=False,
min_value=VLAN_VID_MIN,
max_value=VLAN_VID_MAX,
- label='Minimum VID'
+ label=_('Minimum VID')
)
max_vid = forms.IntegerField(
required=False,
min_value=VLAN_VID_MIN,
max_value=VLAN_VID_MAX,
- label='Maximum VID'
+ label=_('Maximum VID')
)
tag = TagFilterField(model)
diff --git a/netbox/ipam/forms/model_forms.py b/netbox/ipam/forms/model_forms.py
index 9a5abc082..56c0631f4 100644
--- a/netbox/ipam/forms/model_forms.py
+++ b/netbox/ipam/forms/model_forms.py
@@ -1,6 +1,7 @@
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
+from django.utils.translation import gettext as _
from dcim.models import Device, Interface, Location, Rack, Region, Site, SiteGroup
from ipam.choices import *
@@ -67,7 +68,7 @@ class VRFForm(TenancyForm, NetBoxModelForm):
'rd': "RD",
}
help_texts = {
- 'rd': "Route distinguisher in any format",
+ 'rd': _("Route distinguisher in any format"),
}
@@ -104,7 +105,7 @@ class RIRForm(NetBoxModelForm):
class AggregateForm(TenancyForm, NetBoxModelForm):
rir = DynamicModelChoiceField(
queryset=RIR.objects.all(),
- label='RIR'
+ label=_('RIR')
)
comments = CommentField()
@@ -119,8 +120,8 @@ class AggregateForm(TenancyForm, NetBoxModelForm):
'prefix', 'rir', 'date_added', 'tenant_group', 'tenant', 'description', 'comments', 'tags',
]
help_texts = {
- 'prefix': "IPv4 or IPv6 network",
- 'rir': "Regional Internet Registry responsible for this prefix",
+ 'prefix': _("IPv4 or IPv6 network"),
+ 'rir': _("Regional Internet Registry responsible for this prefix"),
}
widgets = {
'date_added': DatePicker(),
@@ -130,11 +131,11 @@ class AggregateForm(TenancyForm, NetBoxModelForm):
class ASNForm(TenancyForm, NetBoxModelForm):
rir = DynamicModelChoiceField(
queryset=RIR.objects.all(),
- label='RIR',
+ label=_('RIR'),
)
sites = DynamicModelMultipleChoiceField(
queryset=Site.objects.all(),
- label='Sites',
+ label=_('Sites'),
required=False
)
comments = CommentField()
@@ -150,8 +151,8 @@ class ASNForm(TenancyForm, NetBoxModelForm):
'asn', 'rir', 'sites', 'tenant_group', 'tenant', 'description', 'comments', 'tags'
]
help_texts = {
- 'asn': "AS number",
- 'rir': "Regional Internet Registry responsible for this prefix",
+ 'asn': _("AS number"),
+ 'rir': _("Regional Internet Registry responsible for this prefix"),
}
widgets = {
'date_added': DatePicker(),
@@ -189,7 +190,7 @@ class PrefixForm(TenancyForm, NetBoxModelForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
region = DynamicModelChoiceField(
queryset=Region.objects.all(),
@@ -217,7 +218,7 @@ class PrefixForm(TenancyForm, NetBoxModelForm):
vlan_group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
- label='VLAN group',
+ label=_('VLAN group'),
null_option='None',
query_params={
'site': '$site'
@@ -229,7 +230,7 @@ class PrefixForm(TenancyForm, NetBoxModelForm):
vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
- label='VLAN',
+ label=_('VLAN'),
query_params={
'site_id': '$site',
'group_id': '$vlan_group',
@@ -262,7 +263,7 @@ class IPRangeForm(TenancyForm, NetBoxModelForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
role = DynamicModelChoiceField(
queryset=Role.objects.all(),
@@ -311,7 +312,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
vminterface = DynamicModelChoiceField(
queryset=VMInterface.objects.all(),
required=False,
- label='Interface',
+ label=_('Interface'),
query_params={
'virtual_machine_id': '$virtual_machine'
}
@@ -319,17 +320,17 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
fhrpgroup = DynamicModelChoiceField(
queryset=FHRPGroup.objects.all(),
required=False,
- label='FHRP Group'
+ label=_('FHRP Group')
)
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
nat_region = DynamicModelChoiceField(
queryset=Region.objects.all(),
required=False,
- label='Region',
+ label=_('Region'),
initial_params={
'sites': '$nat_site'
}
@@ -337,7 +338,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
nat_site_group = DynamicModelChoiceField(
queryset=SiteGroup.objects.all(),
required=False,
- label='Site group',
+ label=_('Site group'),
initial_params={
'sites': '$nat_site'
}
@@ -345,7 +346,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
nat_site = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
- label='Site',
+ label=_('Site'),
query_params={
'region_id': '$nat_region',
'group_id': '$nat_site_group',
@@ -354,7 +355,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
nat_rack = DynamicModelChoiceField(
queryset=Rack.objects.all(),
required=False,
- label='Rack',
+ label=_('Rack'),
null_option='None',
query_params={
'site_id': '$site'
@@ -363,7 +364,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
nat_device = DynamicModelChoiceField(
queryset=Device.objects.all(),
required=False,
- label='Device',
+ label=_('Device'),
query_params={
'site_id': '$site',
'rack_id': '$nat_rack',
@@ -372,12 +373,12 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
nat_cluster = DynamicModelChoiceField(
queryset=Cluster.objects.all(),
required=False,
- label='Cluster'
+ label=_('Cluster')
)
nat_virtual_machine = DynamicModelChoiceField(
queryset=VirtualMachine.objects.all(),
required=False,
- label='Virtual Machine',
+ label=_('Virtual Machine'),
query_params={
'cluster_id': '$nat_cluster',
}
@@ -385,12 +386,12 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
nat_vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
nat_inside = DynamicModelChoiceField(
queryset=IPAddress.objects.all(),
required=False,
- label='IP Address',
+ label=_('IP Address'),
query_params={
'device_id': '$nat_device',
'virtual_machine_id': '$nat_virtual_machine',
@@ -399,7 +400,7 @@ class IPAddressForm(TenancyForm, NetBoxModelForm):
)
primary_for_parent = forms.BooleanField(
required=False,
- label='Make this the primary IP for the device/VM'
+ label=_('Make this the primary IP for the device/VM')
)
comments = CommentField()
@@ -500,7 +501,7 @@ class IPAddressBulkAddForm(TenancyForm, NetBoxModelForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
class Meta:
@@ -518,11 +519,11 @@ class IPAddressAssignForm(BootstrapMixin, forms.Form):
vrf_id = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
q = forms.CharField(
required=False,
- label='Search',
+ label=_('Search'),
)
@@ -532,16 +533,16 @@ class FHRPGroupForm(NetBoxModelForm):
ip_vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
ip_address = IPNetworkFormField(
required=False,
- label='Address'
+ label=_('Address')
)
ip_status = forms.ChoiceField(
choices=add_blank_choice(IPAddressStatusChoices),
required=False,
- label='Status'
+ label=_('Status')
)
comments = CommentField()
@@ -633,7 +634,7 @@ class VLANGroupForm(NetBoxModelForm):
initial_params={
'sites': '$site'
},
- label='Site group'
+ label=_('Site group')
)
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
@@ -670,7 +671,7 @@ class VLANGroupForm(NetBoxModelForm):
initial_params={
'clusters': '$cluster'
},
- label='Cluster group'
+ label=_('Cluster group')
)
cluster = DynamicModelChoiceField(
queryset=Cluster.objects.all(),
@@ -734,7 +735,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
),
required=False,
widget=StaticSelect,
- label='Group scope'
+ label=_('Group scope')
)
group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
@@ -742,7 +743,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
query_params={
'scope_type': '$scope_type',
},
- label='VLAN Group'
+ label=_('VLAN Group')
)
# Site assignment fields
@@ -752,7 +753,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
initial_params={
'sites': '$site'
},
- label='Region'
+ label=_('Region')
)
sitegroup = DynamicModelChoiceField(
queryset=SiteGroup.objects.all(),
@@ -760,7 +761,7 @@ class VLANForm(TenancyForm, NetBoxModelForm):
initial_params={
'sites': '$site'
},
- label='Site group'
+ label=_('Site group')
)
site = DynamicModelChoiceField(
queryset=Site.objects.all(),
@@ -786,12 +787,12 @@ class VLANForm(TenancyForm, NetBoxModelForm):
'tags',
]
help_texts = {
- 'site': "Leave blank if this VLAN spans multiple sites",
- 'group': "VLAN group (optional)",
- 'vid': "Configured VLAN ID",
- 'name': "Configured VLAN name",
- 'status': "Operational status of this VLAN",
- 'role': "The primary function of this VLAN",
+ 'site': _("Leave blank if this VLAN spans multiple sites"),
+ 'group': _("VLAN group (optional)"),
+ 'vid': _("Configured VLAN ID"),
+ 'name': _("Configured VLAN name"),
+ 'status': _("Operational status of this VLAN"),
+ 'role': _("The primary function of this VLAN"),
}
widgets = {
'status': StaticSelect(),
@@ -804,7 +805,7 @@ class ServiceTemplateForm(NetBoxModelForm):
min_value=SERVICE_PORT_MIN,
max_value=SERVICE_PORT_MAX
),
- help_text="Comma-separated list of one or more port numbers. A range may be specified using a hyphen."
+ help_text=_("Comma-separated list of one or more port numbers. A range may be specified using a hyphen.")
)
comments = CommentField()
@@ -836,12 +837,12 @@ class ServiceForm(NetBoxModelForm):
min_value=SERVICE_PORT_MIN,
max_value=SERVICE_PORT_MAX
),
- help_text="Comma-separated list of one or more port numbers. A range may be specified using a hyphen."
+ help_text=_("Comma-separated list of one or more port numbers. A range may be specified using a hyphen.")
)
ipaddresses = DynamicModelMultipleChoiceField(
queryset=IPAddress.objects.all(),
required=False,
- label='IP Addresses',
+ label=_('IP Addresses'),
query_params={
'device_id': '$device',
'virtual_machine_id': '$virtual_machine',
@@ -855,8 +856,8 @@ class ServiceForm(NetBoxModelForm):
'device', 'virtual_machine', 'name', 'protocol', 'ports', 'ipaddresses', 'description', 'comments', 'tags',
]
help_texts = {
- 'ipaddresses': "IP address assignment is optional. If no IPs are selected, the service is assumed to be "
- "reachable via all IPs assigned to the device.",
+ 'ipaddresses': _("IP address assignment is optional. If no IPs are selected, the service is assumed to be "
+ "reachable via all IPs assigned to the device."),
}
widgets = {
'protocol': StaticSelect(),
@@ -937,12 +938,12 @@ class L2VPNTerminationForm(NetBoxModelForm):
queryset=L2VPN.objects.all(),
required=True,
query_params={},
- label='L2VPN',
+ label=_('L2VPN'),
fetch_trigger='open'
)
device_vlan = DynamicModelChoiceField(
queryset=Device.objects.all(),
- label="Available on Device",
+ label=_("Available on Device"),
required=False,
query_params={}
)
@@ -952,7 +953,7 @@ class L2VPNTerminationForm(NetBoxModelForm):
query_params={
'available_on_device': '$device_vlan'
},
- label='VLAN'
+ label=_('VLAN')
)
device = DynamicModelChoiceField(
queryset=Device.objects.all(),
@@ -977,7 +978,7 @@ class L2VPNTerminationForm(NetBoxModelForm):
query_params={
'virtual_machine_id': '$virtual_machine'
},
- label='Interface'
+ label=_('Interface')
)
class Meta:
diff --git a/netbox/ipam/models/ip.py b/netbox/ipam/models/ip.py
index bf9bd6d7f..dd92f97cc 100644
--- a/netbox/ipam/models/ip.py
+++ b/netbox/ipam/models/ip.py
@@ -6,6 +6,7 @@ from django.db import models
from django.db.models import F
from django.urls import reverse
from django.utils.functional import cached_property
+from django.utils.translation import gettext as _
from dcim.fields import ASNField
from dcim.models import Device
@@ -64,7 +65,7 @@ class RIR(OrganizationalModel):
is_private = models.BooleanField(
default=False,
verbose_name='Private',
- help_text='IP space managed by this RIR is considered private'
+ help_text=_('IP space managed by this RIR is considered private')
)
class Meta:
@@ -84,7 +85,7 @@ class ASN(PrimaryModel):
asn = ASNField(
unique=True,
verbose_name='ASN',
- help_text='32-bit autonomous system number'
+ help_text=_('32-bit autonomous system number')
)
rir = models.ForeignKey(
to='ipam.RIR',
@@ -263,7 +264,7 @@ class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
assigned to a VLAN where appropriate.
"""
prefix = IPNetworkField(
- help_text='IPv4 or IPv6 network with mask'
+ help_text=_('IPv4 or IPv6 network with mask')
)
site = models.ForeignKey(
to='dcim.Site',
@@ -300,7 +301,7 @@ class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
choices=PrefixStatusChoices,
default=PrefixStatusChoices.STATUS_ACTIVE,
verbose_name='Status',
- help_text='Operational status of this prefix'
+ help_text=_('Operational status of this prefix')
)
role = models.ForeignKey(
to='ipam.Role',
@@ -308,16 +309,16 @@ class Prefix(GetAvailablePrefixesMixin, PrimaryModel):
related_name='prefixes',
blank=True,
null=True,
- help_text='The primary function of this prefix'
+ help_text=_('The primary function of this prefix')
)
is_pool = models.BooleanField(
verbose_name='Is a pool',
default=False,
- help_text='All IP addresses within this prefix are considered usable'
+ help_text=_('All IP addresses within this prefix are considered usable')
)
mark_utilized = models.BooleanField(
default=False,
- help_text="Treat as 100% utilized"
+ help_text=_("Treat as 100% utilized")
)
# Cached depth & child counts
@@ -538,10 +539,10 @@ class IPRange(PrimaryModel):
A range of IP addresses, defined by start and end addresses.
"""
start_address = IPAddressField(
- help_text='IPv4 or IPv6 address (with mask)'
+ help_text=_('IPv4 or IPv6 address (with mask)')
)
end_address = IPAddressField(
- help_text='IPv4 or IPv6 address (with mask)'
+ help_text=_('IPv4 or IPv6 address (with mask)')
)
size = models.PositiveIntegerField(
editable=False
@@ -565,7 +566,7 @@ class IPRange(PrimaryModel):
max_length=50,
choices=IPRangeStatusChoices,
default=IPRangeStatusChoices.STATUS_ACTIVE,
- help_text='Operational status of this range'
+ help_text=_('Operational status of this range')
)
role = models.ForeignKey(
to='ipam.Role',
@@ -573,7 +574,7 @@ class IPRange(PrimaryModel):
related_name='ip_ranges',
blank=True,
null=True,
- help_text='The primary function of this range'
+ help_text=_('The primary function of this range')
)
clone_fields = (
@@ -736,7 +737,7 @@ class IPAddress(PrimaryModel):
which has a NAT outside IP, that Interface's Device can use either the inside or outside IP as its primary IP.
"""
address = IPAddressField(
- help_text='IPv4 or IPv6 address (with mask)'
+ help_text=_('IPv4 or IPv6 address (with mask)')
)
vrf = models.ForeignKey(
to='ipam.VRF',
@@ -757,13 +758,13 @@ class IPAddress(PrimaryModel):
max_length=50,
choices=IPAddressStatusChoices,
default=IPAddressStatusChoices.STATUS_ACTIVE,
- help_text='The operational status of this IP'
+ help_text=_('The operational status of this IP')
)
role = models.CharField(
max_length=50,
choices=IPAddressRoleChoices,
blank=True,
- help_text='The functional role of this IP'
+ help_text=_('The functional role of this IP')
)
assigned_object_type = models.ForeignKey(
to=ContentType,
@@ -788,14 +789,14 @@ class IPAddress(PrimaryModel):
blank=True,
null=True,
verbose_name='NAT (Inside)',
- help_text='The IP for which this address is the "outside" IP'
+ help_text=_('The IP for which this address is the "outside" IP')
)
dns_name = models.CharField(
max_length=255,
blank=True,
validators=[DNSValidator],
verbose_name='DNS Name',
- help_text='Hostname or FQDN (not case-sensitive)'
+ help_text=_('Hostname or FQDN (not case-sensitive)')
)
objects = IPAddressManager()
diff --git a/netbox/ipam/models/vlans.py b/netbox/ipam/models/vlans.py
index 4f5d513cf..bf6c6a52e 100644
--- a/netbox/ipam/models/vlans.py
+++ b/netbox/ipam/models/vlans.py
@@ -4,6 +4,7 @@ from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator
from django.db import models
from django.urls import reverse
+from django.utils.translation import gettext as _
from dcim.models import Interface
from ipam.choices import *
@@ -50,7 +51,7 @@ class VLANGroup(OrganizationalModel):
MinValueValidator(VLAN_VID_MIN),
MaxValueValidator(VLAN_VID_MAX)
),
- help_text='Lowest permissible ID of a child VLAN'
+ help_text=_('Lowest permissible ID of a child VLAN')
)
max_vid = models.PositiveSmallIntegerField(
verbose_name='Maximum VLAN ID',
@@ -59,7 +60,7 @@ class VLANGroup(OrganizationalModel):
MinValueValidator(VLAN_VID_MIN),
MaxValueValidator(VLAN_VID_MAX)
),
- help_text='Highest permissible ID of a child VLAN'
+ help_text=_('Highest permissible ID of a child VLAN')
)
class Meta:
diff --git a/netbox/ipam/models/vrfs.py b/netbox/ipam/models/vrfs.py
index 0f3c9793c..a1a53b3a7 100644
--- a/netbox/ipam/models/vrfs.py
+++ b/netbox/ipam/models/vrfs.py
@@ -1,5 +1,6 @@
from django.db import models
from django.urls import reverse
+from django.utils.translation import gettext as _
from ipam.constants import *
from netbox.models import PrimaryModel
@@ -26,7 +27,7 @@ class VRF(PrimaryModel):
blank=True,
null=True,
verbose_name='Route distinguisher',
- help_text='Unique route distinguisher (as defined in RFC 4364)'
+ help_text=_('Unique route distinguisher (as defined in RFC 4364)')
)
tenant = models.ForeignKey(
to='tenancy.Tenant',
@@ -38,7 +39,7 @@ class VRF(PrimaryModel):
enforce_unique = models.BooleanField(
default=True,
verbose_name='Enforce unique space',
- help_text='Prevent duplicate prefixes/IP addresses within this VRF'
+ help_text=_('Prevent duplicate prefixes/IP addresses within this VRF')
)
import_targets = models.ManyToManyField(
to='ipam.RouteTarget',
@@ -76,7 +77,7 @@ class RouteTarget(PrimaryModel):
name = models.CharField(
max_length=VRF_RD_MAX_LENGTH, # Same format options as VRF RD (RFC 4360 section 4)
unique=True,
- help_text='Route target value (formatted in accordance with RFC 4360)'
+ help_text=_('Route target value (formatted in accordance with RFC 4360)')
)
tenant = models.ForeignKey(
to='tenancy.Tenant',
diff --git a/netbox/netbox/config/parameters.py b/netbox/netbox/config/parameters.py
index e2295888f..8efb0a033 100644
--- a/netbox/netbox/config/parameters.py
+++ b/netbox/netbox/config/parameters.py
@@ -1,5 +1,6 @@
from django import forms
from django.contrib.postgres.forms import SimpleArrayField
+from django.utils.translation import gettext_lazy as _
class ConfigParam:
@@ -18,9 +19,9 @@ PARAMS = (
# Banners
ConfigParam(
name='BANNER_LOGIN',
- label='Login banner',
+ label=_('Login banner'),
default='',
- description="Additional content to display on the login page",
+ description=_("Additional content to display on the login page"),
field_kwargs={
'widget': forms.Textarea(
attrs={'class': 'vLargeTextField'}
@@ -29,9 +30,9 @@ PARAMS = (
),
ConfigParam(
name='BANNER_TOP',
- label='Top banner',
+ label=_('Top banner'),
default='',
- description="Additional content to display at the top of every page",
+ description=_("Additional content to display at the top of every page"),
field_kwargs={
'widget': forms.Textarea(
attrs={'class': 'vLargeTextField'}
@@ -40,9 +41,9 @@ PARAMS = (
),
ConfigParam(
name='BANNER_BOTTOM',
- label='Bottom banner',
+ label=_('Bottom banner'),
default='',
- description="Additional content to display at the bottom of every page",
+ description=_("Additional content to display at the bottom of every page"),
field_kwargs={
'widget': forms.Textarea(
attrs={'class': 'vLargeTextField'}
@@ -53,69 +54,69 @@ PARAMS = (
# IPAM
ConfigParam(
name='ENFORCE_GLOBAL_UNIQUE',
- label='Globally unique IP space',
+ label=_('Globally unique IP space'),
default=False,
- description="Enforce unique IP addressing within the global table",
+ description=_("Enforce unique IP addressing within the global table"),
field=forms.BooleanField
),
ConfigParam(
name='PREFER_IPV4',
- label='Prefer IPv4',
+ label=_('Prefer IPv4'),
default=False,
- description="Prefer IPv4 addresses over IPv6",
+ description=_("Prefer IPv4 addresses over IPv6"),
field=forms.BooleanField
),
# Racks
ConfigParam(
name='RACK_ELEVATION_DEFAULT_UNIT_HEIGHT',
- label='Rack unit height',
+ label=_('Rack unit height'),
default=22,
- description="Default unit height for rendered rack elevations",
+ description=_("Default unit height for rendered rack elevations"),
field=forms.IntegerField
),
ConfigParam(
name='RACK_ELEVATION_DEFAULT_UNIT_WIDTH',
- label='Rack unit width',
+ label=_('Rack unit width'),
default=220,
- description="Default unit width for rendered rack elevations",
+ description=_("Default unit width for rendered rack elevations"),
field=forms.IntegerField
),
# Power
ConfigParam(
name='POWERFEED_DEFAULT_VOLTAGE',
- label='Powerfeed voltage',
+ label=_('Powerfeed voltage'),
default=120,
- description="Default voltage for powerfeeds",
+ description=_("Default voltage for powerfeeds"),
field=forms.IntegerField
),
ConfigParam(
name='POWERFEED_DEFAULT_AMPERAGE',
- label='Powerfeed amperage',
+ label=_('Powerfeed amperage'),
default=15,
- description="Default amperage for powerfeeds",
+ description=_("Default amperage for powerfeeds"),
field=forms.IntegerField
),
ConfigParam(
name='POWERFEED_DEFAULT_MAX_UTILIZATION',
- label='Powerfeed max utilization',
+ label=_('Powerfeed max utilization'),
default=80,
- description="Default max utilization for powerfeeds",
+ description=_("Default max utilization for powerfeeds"),
field=forms.IntegerField
),
# Security
ConfigParam(
name='ALLOWED_URL_SCHEMES',
- label='Allowed URL schemes',
+ label=_('Allowed URL schemes'),
default=(
'file', 'ftp', 'ftps', 'http', 'https', 'irc', 'mailto', 'sftp', 'ssh', 'tel', 'telnet', 'tftp', 'vnc',
'xmpp',
),
- description="Permitted schemes for URLs in user-provided content",
+ description=_("Permitted schemes for URLs in user-provided content"),
field=SimpleArrayField,
field_kwargs={'base_field': forms.CharField()}
),
@@ -123,13 +124,13 @@ PARAMS = (
# Pagination
ConfigParam(
name='PAGINATE_COUNT',
- label='Default page size',
+ label=_('Default page size'),
default=50,
field=forms.IntegerField
),
ConfigParam(
name='MAX_PAGE_SIZE',
- label='Maximum page size',
+ label=_('Maximum page size'),
default=1000,
field=forms.IntegerField
),
@@ -137,9 +138,9 @@ PARAMS = (
# Validation
ConfigParam(
name='CUSTOM_VALIDATORS',
- label='Custom validators',
+ label=_('Custom validators'),
default={},
- description="Custom validation rules (JSON)",
+ description=_("Custom validation rules (JSON)"),
field=forms.JSONField,
field_kwargs={
'widget': forms.Textarea(
@@ -151,28 +152,28 @@ PARAMS = (
# NAPALM
ConfigParam(
name='NAPALM_USERNAME',
- label='NAPALM username',
+ label=_('NAPALM username'),
default='',
- description="Username to use when connecting to devices via NAPALM"
+ description=_("Username to use when connecting to devices via NAPALM")
),
ConfigParam(
name='NAPALM_PASSWORD',
- label='NAPALM password',
+ label=_('NAPALM password'),
default='',
- description="Password to use when connecting to devices via NAPALM"
+ description=_("Password to use when connecting to devices via NAPALM")
),
ConfigParam(
name='NAPALM_TIMEOUT',
- label='NAPALM timeout',
+ label=_('NAPALM timeout'),
default=30,
- description="NAPALM connection timeout (in seconds)",
+ description=_("NAPALM connection timeout (in seconds)"),
field=forms.IntegerField
),
ConfigParam(
name='NAPALM_ARGS',
- label='NAPALM arguments',
+ label=_('NAPALM arguments'),
default={},
- description="Additional arguments to pass when invoking a NAPALM driver (as JSON data)",
+ description=_("Additional arguments to pass when invoking a NAPALM driver (as JSON data)"),
field=forms.JSONField,
field_kwargs={
'widget': forms.Textarea(
@@ -184,46 +185,46 @@ PARAMS = (
# User preferences
ConfigParam(
name='DEFAULT_USER_PREFERENCES',
- label='Default preferences',
+ label=_('Default preferences'),
default={},
- description="Default preferences for new users",
+ description=_("Default preferences for new users"),
field=forms.JSONField
),
# Miscellaneous
ConfigParam(
name='MAINTENANCE_MODE',
- label='Maintenance mode',
+ label=_('Maintenance mode'),
default=False,
- description="Enable maintenance mode",
+ description=_("Enable maintenance mode"),
field=forms.BooleanField
),
ConfigParam(
name='GRAPHQL_ENABLED',
- label='GraphQL enabled',
+ label=_('GraphQL enabled'),
default=True,
- description="Enable the GraphQL API",
+ description=_("Enable the GraphQL API"),
field=forms.BooleanField
),
ConfigParam(
name='CHANGELOG_RETENTION',
- label='Changelog retention',
+ label=_('Changelog retention'),
default=90,
- description="Days to retain changelog history (set to zero for unlimited)",
+ description=_("Days to retain changelog history (set to zero for unlimited)"),
field=forms.IntegerField
),
ConfigParam(
name='JOBRESULT_RETENTION',
- label='Job result retention',
+ label=_('Job result retention'),
default=90,
- description="Days to retain job result history (set to zero for unlimited)",
+ description=_("Days to retain job result history (set to zero for unlimited)"),
field=forms.IntegerField
),
ConfigParam(
name='MAPS_URL',
- label='Maps URL',
+ label=_('Maps URL'),
default='https://maps.google.com/?q=',
- description="Base URL for mapping geographic locations"
+ description=_("Base URL for mapping geographic locations")
),
)
diff --git a/netbox/netbox/filtersets.py b/netbox/netbox/filtersets.py
index 02ccdca50..8c39db287 100644
--- a/netbox/netbox/filtersets.py
+++ b/netbox/netbox/filtersets.py
@@ -5,6 +5,7 @@ from django.db import models
from django_filters.exceptions import FieldLookupError
from django_filters.utils import get_model_field, resolve_field
from django.shortcuts import get_object_or_404
+from django.utils.translation import gettext as _
from extras.choices import CustomFieldFilterLogicChoices
from extras.filters import TagFilter
@@ -235,7 +236,7 @@ class NetBoxModelFilterSet(ChangeLoggedModelFilterSet):
"""
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
tag = TagFilter()
diff --git a/netbox/netbox/forms/__init__.py b/netbox/netbox/forms/__init__.py
index dd1fb7726..fd4998274 100644
--- a/netbox/netbox/forms/__init__.py
+++ b/netbox/netbox/forms/__init__.py
@@ -17,7 +17,7 @@ LOOKUP_CHOICES = (
class SearchForm(BootstrapMixin, forms.Form):
q = forms.CharField(
- label='Search',
+ label=_('Search'),
widget=forms.TextInput(
attrs={
'hx-get': '',
@@ -29,7 +29,7 @@ class SearchForm(BootstrapMixin, forms.Form):
obj_types = forms.MultipleChoiceField(
choices=[],
required=False,
- label='Object type(s)',
+ label=_('Object type(s)'),
widget=StaticSelectMultiple()
)
lookup = forms.ChoiceField(
diff --git a/netbox/netbox/forms/base.py b/netbox/netbox/forms/base.py
index 4a4368a65..2d785400c 100644
--- a/netbox/netbox/forms/base.py
+++ b/netbox/netbox/forms/base.py
@@ -2,6 +2,7 @@ from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
from django.db.models import Q
+from django.utils.translation import gettext as _
from extras.choices import CustomFieldFilterLogicChoices, CustomFieldTypeChoices, CustomFieldVisibilityChoices
from extras.forms.mixins import CustomFieldsMixin, SavedFiltersMixin
@@ -132,7 +133,7 @@ class NetBoxModelFilterSetForm(BootstrapMixin, CustomFieldsMixin, SavedFiltersMi
"""
q = forms.CharField(
required=False,
- label='Search'
+ label=_('Search')
)
def __init__(self, *args, **kwargs):
diff --git a/netbox/netbox/navigation/menu.py b/netbox/netbox/navigation/menu.py
index dcec76d91..a912c84d5 100644
--- a/netbox/netbox/navigation/menu.py
+++ b/netbox/netbox/navigation/menu.py
@@ -1,119 +1,120 @@
+from django.utils.translation import gettext as _
+
from netbox.registry import registry
from . import *
-
#
# Nav menus
#
ORGANIZATION_MENU = Menu(
- label='Organization',
+ label=_('Organization'),
icon_class='mdi mdi-domain',
groups=(
MenuGroup(
- label='Sites',
+ label=_('Sites'),
items=(
- get_model_item('dcim', 'site', 'Sites'),
- get_model_item('dcim', 'region', 'Regions'),
- get_model_item('dcim', 'sitegroup', 'Site Groups'),
- get_model_item('dcim', 'location', 'Locations'),
+ get_model_item('dcim', 'site', _('Sites')),
+ get_model_item('dcim', 'region', _('Regions')),
+ get_model_item('dcim', 'sitegroup', _('Site Groups')),
+ get_model_item('dcim', 'location', _('Locations')),
),
),
MenuGroup(
- label='Racks',
+ label=_('Racks'),
items=(
- get_model_item('dcim', 'rack', 'Racks'),
- get_model_item('dcim', 'rackrole', 'Rack Roles'),
- get_model_item('dcim', 'rackreservation', 'Reservations'),
+ get_model_item('dcim', 'rack', _('Racks')),
+ get_model_item('dcim', 'rackrole', _('Rack Roles')),
+ get_model_item('dcim', 'rackreservation', _('Reservations')),
MenuItem(
link='dcim:rack_elevation_list',
- link_text='Elevations',
+ link_text=_('Elevations'),
permissions=['dcim.view_rack']
),
),
),
MenuGroup(
- label='Tenancy',
+ label=_('Tenancy'),
items=(
- get_model_item('tenancy', 'tenant', 'Tenants'),
- get_model_item('tenancy', 'tenantgroup', 'Tenant Groups'),
+ get_model_item('tenancy', 'tenant', _('Tenants')),
+ get_model_item('tenancy', 'tenantgroup', _('Tenant Groups')),
),
),
MenuGroup(
- label='Contacts',
+ label=_('Contacts'),
items=(
- get_model_item('tenancy', 'contact', 'Contacts'),
- get_model_item('tenancy', 'contactgroup', 'Contact Groups'),
- get_model_item('tenancy', 'contactrole', 'Contact Roles'),
+ get_model_item('tenancy', 'contact', _('Contacts')),
+ get_model_item('tenancy', 'contactgroup', _('Contact Groups')),
+ get_model_item('tenancy', 'contactrole', _('Contact Roles')),
),
),
),
)
DEVICES_MENU = Menu(
- label='Devices',
+ label=_('Devices'),
icon_class='mdi mdi-server',
groups=(
MenuGroup(
- label='Devices',
+ label=_('Devices'),
items=(
- get_model_item('dcim', 'device', 'Devices'),
- get_model_item('dcim', 'module', 'Modules'),
- get_model_item('dcim', 'devicerole', 'Device Roles'),
- get_model_item('dcim', 'platform', 'Platforms'),
- get_model_item('dcim', 'virtualchassis', 'Virtual Chassis'),
- get_model_item('dcim', 'virtualdevicecontext', 'Virtual Device Contexts'),
+ get_model_item('dcim', 'device', _('Devices')),
+ get_model_item('dcim', 'module', _('Modules')),
+ get_model_item('dcim', 'devicerole', _('Device Roles')),
+ get_model_item('dcim', 'platform', _('Platforms')),
+ get_model_item('dcim', 'virtualchassis', _('Virtual Chassis')),
+ get_model_item('dcim', 'virtualdevicecontext', _('Virtual Device Contexts')),
),
),
MenuGroup(
- label='Device Types',
+ label=_('Device Types'),
items=(
- get_model_item('dcim', 'devicetype', 'Device Types'),
- get_model_item('dcim', 'moduletype', 'Module Types'),
- get_model_item('dcim', 'manufacturer', 'Manufacturers'),
+ get_model_item('dcim', 'devicetype', _('Device Types')),
+ get_model_item('dcim', 'moduletype', _('Module Types')),
+ get_model_item('dcim', 'manufacturer', _('Manufacturers')),
),
),
MenuGroup(
- label='Device Components',
+ label=_('Device Components'),
items=(
- get_model_item('dcim', 'interface', 'Interfaces', actions=['import']),
- get_model_item('dcim', 'frontport', 'Front Ports', actions=['import']),
- get_model_item('dcim', 'rearport', 'Rear Ports', actions=['import']),
- get_model_item('dcim', 'consoleport', 'Console Ports', actions=['import']),
- get_model_item('dcim', 'consoleserverport', 'Console Server Ports', actions=['import']),
- get_model_item('dcim', 'powerport', 'Power Ports', actions=['import']),
- get_model_item('dcim', 'poweroutlet', 'Power Outlets', actions=['import']),
- get_model_item('dcim', 'modulebay', 'Module Bays', actions=['import']),
- get_model_item('dcim', 'devicebay', 'Device Bays', actions=['import']),
- get_model_item('dcim', 'inventoryitem', 'Inventory Items', actions=['import']),
- get_model_item('dcim', 'inventoryitemrole', 'Inventory Item Roles'),
+ get_model_item('dcim', 'interface', _('Interfaces'), actions=['import']),
+ get_model_item('dcim', 'frontport', _('Front Ports'), actions=['import']),
+ get_model_item('dcim', 'rearport', _('Rear Ports'), actions=['import']),
+ get_model_item('dcim', 'consoleport', _('Console Ports'), actions=['import']),
+ get_model_item('dcim', 'consoleserverport', _('Console Server Ports'), actions=['import']),
+ get_model_item('dcim', 'powerport', _('Power Ports'), actions=['import']),
+ get_model_item('dcim', 'poweroutlet', _('Power Outlets'), actions=['import']),
+ get_model_item('dcim', 'modulebay', _('Module Bays'), actions=['import']),
+ get_model_item('dcim', 'devicebay', _('Device Bays'), actions=['import']),
+ get_model_item('dcim', 'inventoryitem', _('Inventory Items'), actions=['import']),
+ get_model_item('dcim', 'inventoryitemrole', _('Inventory Item Roles')),
),
),
),
)
CONNECTIONS_MENU = Menu(
- label='Connections',
+ label=_('Connections'),
icon_class='mdi mdi-connection',
groups=(
MenuGroup(
- label='Connections',
+ label=_('Connections'),
items=(
- get_model_item('dcim', 'cable', 'Cables', actions=['import']),
- get_model_item('wireless', 'wirelesslink', 'Wireless Links', actions=['import']),
+ get_model_item('dcim', 'cable', _('Cables'), actions=['import']),
+ get_model_item('wireless', 'wirelesslink', _('Wireless Links'), actions=['import']),
MenuItem(
link='dcim:interface_connections_list',
- link_text='Interface Connections',
+ link_text=_('Interface Connections'),
permissions=['dcim.view_interface']
),
MenuItem(
link='dcim:console_connections_list',
- link_text='Console Connections',
+ link_text=_('Console Connections'),
permissions=['dcim.view_consoleport']
),
MenuItem(
link='dcim:power_connections_list',
- link_text='Power Connections',
+ link_text=_('Power Connections'),
permissions=['dcim.view_powerport']
),
),
@@ -122,192 +123,192 @@ CONNECTIONS_MENU = Menu(
)
WIRELESS_MENU = Menu(
- label='Wireless',
+ label=_('Wireless'),
icon_class='mdi mdi-wifi',
groups=(
MenuGroup(
- label='Wireless',
+ label=_('Wireless'),
items=(
- get_model_item('wireless', 'wirelesslan', 'Wireless LANs'),
- get_model_item('wireless', 'wirelesslangroup', 'Wireless LAN Groups'),
+ get_model_item('wireless', 'wirelesslan', _('Wireless LANs')),
+ get_model_item('wireless', 'wirelesslangroup', _('Wireless LAN Groups')),
),
),
),
)
IPAM_MENU = Menu(
- label='IPAM',
+ label=_('IPAM'),
icon_class='mdi mdi-counter',
groups=(
MenuGroup(
- label='IP Addresses',
+ label=_('IP Addresses'),
items=(
- get_model_item('ipam', 'ipaddress', 'IP Addresses'),
- get_model_item('ipam', 'iprange', 'IP Ranges'),
+ get_model_item('ipam', 'ipaddress', _('IP Addresses')),
+ get_model_item('ipam', 'iprange', _('IP Ranges')),
),
),
MenuGroup(
- label='Prefixes',
+ label=_('Prefixes'),
items=(
- get_model_item('ipam', 'prefix', 'Prefixes'),
- get_model_item('ipam', 'role', 'Prefix & VLAN Roles'),
+ get_model_item('ipam', 'prefix', _('Prefixes')),
+ get_model_item('ipam', 'role', _('Prefix & VLAN Roles')),
),
),
MenuGroup(
- label='ASNs',
+ label=_('ASNs'),
items=(
- get_model_item('ipam', 'asn', 'ASNs'),
+ get_model_item('ipam', 'asn', _('ASNs')),
),
),
MenuGroup(
- label='Aggregates',
+ label=_('Aggregates'),
items=(
- get_model_item('ipam', 'aggregate', 'Aggregates'),
- get_model_item('ipam', 'rir', 'RIRs'),
+ get_model_item('ipam', 'aggregate', _('Aggregates')),
+ get_model_item('ipam', 'rir', _('RIRs')),
),
),
MenuGroup(
- label='VRFs',
+ label=_('VRFs'),
items=(
- get_model_item('ipam', 'vrf', 'VRFs'),
- get_model_item('ipam', 'routetarget', 'Route Targets'),
+ get_model_item('ipam', 'vrf', _('VRFs')),
+ get_model_item('ipam', 'routetarget', _('Route Targets')),
),
),
MenuGroup(
- label='VLANs',
+ label=_('VLANs'),
items=(
- get_model_item('ipam', 'vlan', 'VLANs'),
- get_model_item('ipam', 'vlangroup', 'VLAN Groups'),
+ get_model_item('ipam', 'vlan', _('VLANs')),
+ get_model_item('ipam', 'vlangroup', _('VLAN Groups')),
),
),
MenuGroup(
- label='Other',
+ label=_('Other'),
items=(
- get_model_item('ipam', 'fhrpgroup', 'FHRP Groups'),
- get_model_item('ipam', 'servicetemplate', 'Service Templates'),
- get_model_item('ipam', 'service', 'Services'),
+ get_model_item('ipam', 'fhrpgroup', _('FHRP Groups')),
+ get_model_item('ipam', 'servicetemplate', _('Service Templates')),
+ get_model_item('ipam', 'service', _('Services')),
),
),
),
)
OVERLAY_MENU = Menu(
- label='Overlay',
+ label=_('Overlay'),
icon_class='mdi mdi-graph-outline',
groups=(
MenuGroup(
label='L2VPNs',
items=(
- get_model_item('ipam', 'l2vpn', 'L2VPNs'),
- get_model_item('ipam', 'l2vpntermination', 'Terminations'),
+ get_model_item('ipam', 'l2vpn', _('L2VPNs')),
+ get_model_item('ipam', 'l2vpntermination', _('Terminations')),
),
),
),
)
VIRTUALIZATION_MENU = Menu(
- label='Virtualization',
+ label=_('Virtualization'),
icon_class='mdi mdi-monitor',
groups=(
MenuGroup(
- label='Virtual Machines',
+ label=_('Virtual Machines'),
items=(
- get_model_item('virtualization', 'virtualmachine', 'Virtual Machines'),
- get_model_item('virtualization', 'vminterface', 'Interfaces', actions=['import']),
+ get_model_item('virtualization', 'virtualmachine', _('Virtual Machines')),
+ get_model_item('virtualization', 'vminterface', _('Interfaces'), actions=['import']),
),
),
MenuGroup(
- label='Clusters',
+ label=_('Clusters'),
items=(
- get_model_item('virtualization', 'cluster', 'Clusters'),
- get_model_item('virtualization', 'clustertype', 'Cluster Types'),
- get_model_item('virtualization', 'clustergroup', 'Cluster Groups'),
+ get_model_item('virtualization', 'cluster', _('Clusters')),
+ get_model_item('virtualization', 'clustertype', _('Cluster Types')),
+ get_model_item('virtualization', 'clustergroup', _('Cluster Groups')),
),
),
),
)
CIRCUITS_MENU = Menu(
- label='Circuits',
+ label=_('Circuits'),
icon_class='mdi mdi-transit-connection-variant',
groups=(
MenuGroup(
- label='Circuits',
+ label=_('Circuits'),
items=(
- get_model_item('circuits', 'circuit', 'Circuits'),
- get_model_item('circuits', 'circuittype', 'Circuit Types'),
+ get_model_item('circuits', 'circuit', _('Circuits')),
+ get_model_item('circuits', 'circuittype', _('Circuit Types')),
),
),
MenuGroup(
- label='Providers',
+ label=_('Providers'),
items=(
- get_model_item('circuits', 'provider', 'Providers'),
- get_model_item('circuits', 'providernetwork', 'Provider Networks'),
+ get_model_item('circuits', 'provider', _('Providers')),
+ get_model_item('circuits', 'providernetwork', _('Provider Networks')),
),
),
),
)
POWER_MENU = Menu(
- label='Power',
+ label=_('Power'),
icon_class='mdi mdi-flash',
groups=(
MenuGroup(
- label='Power',
+ label=_('Power'),
items=(
- get_model_item('dcim', 'powerfeed', 'Power Feeds'),
- get_model_item('dcim', 'powerpanel', 'Power Panels'),
+ get_model_item('dcim', 'powerfeed', _('Power Feeds')),
+ get_model_item('dcim', 'powerpanel', _('Power Panels')),
),
),
),
)
OTHER_MENU = Menu(
- label='Other',
+ label=_('Other'),
icon_class='mdi mdi-notification-clear-all',
groups=(
MenuGroup(
- label='Logging',
+ label=_('Logging'),
items=(
- get_model_item('extras', 'journalentry', 'Journal Entries', actions=[]),
- get_model_item('extras', 'objectchange', 'Change Log', actions=[]),
+ get_model_item('extras', 'journalentry', _('Journal Entries'), actions=[]),
+ get_model_item('extras', 'objectchange', _('Change Log'), actions=[]),
),
),
MenuGroup(
- label='Customization',
+ label=_('Customization'),
items=(
- get_model_item('extras', 'customfield', 'Custom Fields'),
- get_model_item('extras', 'customlink', 'Custom Links'),
- get_model_item('extras', 'exporttemplate', 'Export Templates'),
- get_model_item('extras', 'savedfilter', 'Saved Filters'),
+ get_model_item('extras', 'customfield', _('Custom Fields')),
+ get_model_item('extras', 'customlink', _('Custom Links')),
+ get_model_item('extras', 'exporttemplate', _('Export Templates')),
+ get_model_item('extras', 'savedfilter', _('Saved Filters')),
),
),
MenuGroup(
- label='Integrations',
+ label=_('Integrations'),
items=(
- get_model_item('extras', 'webhook', 'Webhooks'),
+ get_model_item('extras', 'webhook', _('Webhooks')),
MenuItem(
link='extras:report_list',
- link_text='Reports',
+ link_text=_('Reports'),
permissions=['extras.view_report']
),
MenuItem(
link='extras:script_list',
- link_text='Scripts',
+ link_text=_('Scripts'),
permissions=['extras.view_script']
),
MenuItem(
link='extras:jobresult_list',
- link_text='Job Results',
+ link_text=_('Job Results'),
permissions=['extras.view_jobresult'],
),
),
),
MenuGroup(
- label='Other',
+ label=_('Other'),
items=(
get_model_item('extras', 'tag', 'Tags'),
- get_model_item('extras', 'configcontext', 'Config Contexts', actions=['add']),
+ get_model_item('extras', 'configcontext', _('Config Contexts'), actions=['add']),
),
),
),
@@ -342,7 +343,7 @@ if registry['plugins']['menu_items']:
for label, items in registry['plugins']['menu_items'].items()
]
plugins_menu = Menu(
- label="Plugins",
+ label=_("Plugins"),
icon_class="mdi mdi-puzzle",
groups=groups
)
diff --git a/netbox/netbox/preferences.py b/netbox/netbox/preferences.py
index 95fd101c3..c88b56072 100644
--- a/netbox/netbox/preferences.py
+++ b/netbox/netbox/preferences.py
@@ -1,3 +1,4 @@
+from django.utils.translation import gettext as _
from netbox.registry import registry
from users.preferences import UserPreference
from utilities.paginator import EnhancedPaginator
@@ -13,7 +14,7 @@ PREFERENCES = {
# User interface
'ui.colormode': UserPreference(
- label='Color mode',
+ label=_('Color mode'),
choices=(
('light', 'Light'),
('dark', 'Dark'),
@@ -21,25 +22,25 @@ PREFERENCES = {
default='light',
),
'pagination.per_page': UserPreference(
- label='Page length',
+ label=_('Page length'),
choices=get_page_lengths(),
- description='The number of objects to display per page',
+ description=_('The number of objects to display per page'),
coerce=lambda x: int(x)
),
'pagination.placement': UserPreference(
- label='Paginator placement',
+ label=_('Paginator placement'),
choices=(
('bottom', 'Bottom'),
('top', 'Top'),
('both', 'Both'),
),
- description='Where the paginator controls will be displayed relative to a table',
+ description=_('Where the paginator controls will be displayed relative to a table'),
default='bottom'
),
# Miscellaneous
'data_format': UserPreference(
- label='Data format',
+ label=_('Data format'),
choices=(
('json', 'JSON'),
('yaml', 'YAML'),
diff --git a/netbox/tenancy/filtersets.py b/netbox/tenancy/filtersets.py
index dd14a412b..ab74949ff 100644
--- a/netbox/tenancy/filtersets.py
+++ b/netbox/tenancy/filtersets.py
@@ -1,5 +1,6 @@
import django_filters
from django.db.models import Q
+from django.utils.translation import gettext as _
from netbox.filtersets import ChangeLoggedModelFilterSet, OrganizationalModelFilterSet, NetBoxModelFilterSet
from utilities.filters import ContentTypeFilter, TreeNodeMultipleChoiceFilter
@@ -25,13 +26,13 @@ __all__ = (
class ContactGroupFilterSet(OrganizationalModelFilterSet):
parent_id = django_filters.ModelMultipleChoiceFilter(
queryset=ContactGroup.objects.all(),
- label='Contact group (ID)',
+ label=_('Contact group (ID)'),
)
parent = django_filters.ModelMultipleChoiceFilter(
field_name='parent__slug',
queryset=ContactGroup.objects.all(),
to_field_name='slug',
- label='Contact group (slug)',
+ label=_('Contact group (slug)'),
)
class Meta:
@@ -51,14 +52,14 @@ class ContactFilterSet(NetBoxModelFilterSet):
queryset=ContactGroup.objects.all(),
field_name='group',
lookup_expr='in',
- label='Contact group (ID)',
+ label=_('Contact group (ID)'),
)
group = TreeNodeMultipleChoiceFilter(
queryset=ContactGroup.objects.all(),
field_name='group',
lookup_expr='in',
to_field_name='slug',
- label='Contact group (slug)',
+ label=_('Contact group (slug)'),
)
class Meta:
@@ -83,17 +84,17 @@ class ContactAssignmentFilterSet(ChangeLoggedModelFilterSet):
content_type = ContentTypeFilter()
contact_id = django_filters.ModelMultipleChoiceFilter(
queryset=Contact.objects.all(),
- label='Contact (ID)',
+ label=_('Contact (ID)'),
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=ContactRole.objects.all(),
- label='Contact role (ID)',
+ label=_('Contact role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=ContactRole.objects.all(),
to_field_name='slug',
- label='Contact role (slug)',
+ label=_('Contact role (slug)'),
)
class Meta:
@@ -105,18 +106,18 @@ class ContactModelFilterSet(django_filters.FilterSet):
contact = django_filters.ModelMultipleChoiceFilter(
field_name='contacts__contact',
queryset=Contact.objects.all(),
- label='Contact',
+ label=_('Contact'),
)
contact_role = django_filters.ModelMultipleChoiceFilter(
field_name='contacts__role',
queryset=ContactRole.objects.all(),
- label='Contact Role'
+ label=_('Contact Role')
)
contact_group = TreeNodeMultipleChoiceFilter(
queryset=ContactGroup.objects.all(),
field_name='contacts__contact__group',
lookup_expr='in',
- label='Contact group',
+ label=_('Contact group'),
)
@@ -127,13 +128,13 @@ class ContactModelFilterSet(django_filters.FilterSet):
class TenantGroupFilterSet(OrganizationalModelFilterSet):
parent_id = django_filters.ModelMultipleChoiceFilter(
queryset=TenantGroup.objects.all(),
- label='Tenant group (ID)',
+ label=_('Tenant group (ID)'),
)
parent = django_filters.ModelMultipleChoiceFilter(
field_name='parent__slug',
queryset=TenantGroup.objects.all(),
to_field_name='slug',
- label='Tenant group (slug)',
+ label=_('Tenant group (slug)'),
)
class Meta:
@@ -146,14 +147,14 @@ class TenantFilterSet(NetBoxModelFilterSet, ContactModelFilterSet):
queryset=TenantGroup.objects.all(),
field_name='group',
lookup_expr='in',
- label='Tenant group (ID)',
+ label=_('Tenant group (ID)'),
)
group = TreeNodeMultipleChoiceFilter(
queryset=TenantGroup.objects.all(),
field_name='group',
lookup_expr='in',
to_field_name='slug',
- label='Tenant group (slug)',
+ label=_('Tenant group (slug)'),
)
class Meta:
@@ -179,22 +180,22 @@ class TenancyFilterSet(django_filters.FilterSet):
queryset=TenantGroup.objects.all(),
field_name='tenant__group',
lookup_expr='in',
- label='Tenant Group (ID)',
+ label=_('Tenant Group (ID)'),
)
tenant_group = TreeNodeMultipleChoiceFilter(
queryset=TenantGroup.objects.all(),
field_name='tenant__group',
to_field_name='slug',
lookup_expr='in',
- label='Tenant Group (slug)',
+ label=_('Tenant Group (slug)'),
)
tenant_id = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
- label='Tenant (ID)',
+ label=_('Tenant (ID)'),
)
tenant = django_filters.ModelMultipleChoiceFilter(
queryset=Tenant.objects.all(),
field_name='tenant__slug',
to_field_name='slug',
- label='Tenant (slug)',
+ label=_('Tenant (slug)'),
)
diff --git a/netbox/tenancy/forms/bulk_import.py b/netbox/tenancy/forms/bulk_import.py
index 137f79d42..27092f9e8 100644
--- a/netbox/tenancy/forms/bulk_import.py
+++ b/netbox/tenancy/forms/bulk_import.py
@@ -1,3 +1,4 @@
+from django.utils.translation import gettext as _
from netbox.forms import NetBoxModelCSVForm
from tenancy.models import *
from utilities.forms import CSVModelChoiceField, SlugField
@@ -20,7 +21,7 @@ class TenantGroupCSVForm(NetBoxModelCSVForm):
queryset=TenantGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent group'
+ help_text=_('Parent group')
)
slug = SlugField()
@@ -35,7 +36,7 @@ class TenantCSVForm(NetBoxModelCSVForm):
queryset=TenantGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned group'
+ help_text=_('Assigned group')
)
class Meta:
@@ -52,7 +53,7 @@ class ContactGroupCSVForm(NetBoxModelCSVForm):
queryset=ContactGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent group'
+ help_text=_('Parent group')
)
slug = SlugField()
@@ -74,7 +75,7 @@ class ContactCSVForm(NetBoxModelCSVForm):
queryset=ContactGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned group'
+ help_text=_('Assigned group')
)
class Meta:
diff --git a/netbox/users/admin/forms.py b/netbox/users/admin/forms.py
index 540735ecc..986ddd0aa 100644
--- a/netbox/users/admin/forms.py
+++ b/netbox/users/admin/forms.py
@@ -3,6 +3,7 @@ from django.contrib.auth.models import Group, User
from django.contrib.admin.widgets import FilteredSelectMultiple
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import FieldError, ValidationError
+from django.utils.translation import gettext as _
from users.constants import CONSTRAINT_TOKEN_USER, OBJECTPERMISSION_OBJECT_TYPES
from users.models import ObjectPermission, Token
@@ -46,7 +47,7 @@ class GroupAdminForm(forms.ModelForm):
class TokenAdminForm(forms.ModelForm):
key = forms.CharField(
required=False,
- help_text="If no key is provided, one will be generated automatically."
+ help_text=_("If no key is provided, one will be generated automatically.")
)
class Meta:
@@ -70,10 +71,10 @@ class ObjectPermissionForm(forms.ModelForm):
model = ObjectPermission
exclude = []
help_texts = {
- 'actions': 'Actions granted in addition to those listed above',
- 'constraints': 'JSON expression of a queryset filter that will return only permitted objects. Leave null '
- 'to match all objects of this type. A list of multiple objects will result in a logical OR '
- 'operation.'
+ 'actions': _('Actions granted in addition to those listed above'),
+ 'constraints': _('JSON expression of a queryset filter that will return only permitted objects. Leave null '
+ 'to match all objects of this type. A list of multiple objects will result in a logical OR '
+ 'operation.')
}
labels = {
'actions': 'Additional actions'
diff --git a/netbox/users/filtersets.py b/netbox/users/filtersets.py
index 71246956b..4ae9df89a 100644
--- a/netbox/users/filtersets.py
+++ b/netbox/users/filtersets.py
@@ -1,6 +1,7 @@
import django_filters
from django.contrib.auth.models import Group, User
from django.db.models import Q
+from django.utils.translation import gettext as _
from netbox.filtersets import BaseFilterSet
from users.models import ObjectPermission, Token
@@ -15,7 +16,7 @@ __all__ = (
class GroupFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
class Meta:
@@ -31,18 +32,18 @@ class GroupFilterSet(BaseFilterSet):
class UserFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
group_id = django_filters.ModelMultipleChoiceFilter(
field_name='groups',
queryset=Group.objects.all(),
- label='Group',
+ label=_('Group'),
)
group = django_filters.ModelMultipleChoiceFilter(
field_name='groups__name',
queryset=Group.objects.all(),
to_field_name='name',
- label='Group (name)',
+ label=_('Group (name)'),
)
class Meta:
@@ -63,18 +64,18 @@ class UserFilterSet(BaseFilterSet):
class TokenFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
user_id = django_filters.ModelMultipleChoiceFilter(
field_name='user',
queryset=User.objects.all(),
- label='User',
+ label=_('User'),
)
user = django_filters.ModelMultipleChoiceFilter(
field_name='user__username',
queryset=User.objects.all(),
to_field_name='username',
- label='User (name)',
+ label=_('User (name)'),
)
created = django_filters.DateTimeFilter()
created__gte = django_filters.DateTimeFilter(
@@ -111,29 +112,29 @@ class TokenFilterSet(BaseFilterSet):
class ObjectPermissionFilterSet(BaseFilterSet):
q = django_filters.CharFilter(
method='search',
- label='Search',
+ label=_('Search'),
)
user_id = django_filters.ModelMultipleChoiceFilter(
field_name='users',
queryset=User.objects.all(),
- label='User',
+ label=_('User'),
)
user = django_filters.ModelMultipleChoiceFilter(
field_name='users__username',
queryset=User.objects.all(),
to_field_name='username',
- label='User (name)',
+ label=_('User (name)'),
)
group_id = django_filters.ModelMultipleChoiceFilter(
field_name='groups',
queryset=Group.objects.all(),
- label='Group',
+ label=_('Group'),
)
group = django_filters.ModelMultipleChoiceFilter(
field_name='groups__name',
queryset=Group.objects.all(),
to_field_name='name',
- label='Group (name)',
+ label=_('Group (name)'),
)
class Meta:
diff --git a/netbox/users/forms.py b/netbox/users/forms.py
index 048005f13..e8647aa5f 100644
--- a/netbox/users/forms.py
+++ b/netbox/users/forms.py
@@ -3,6 +3,7 @@ from django.conf import settings
from django.contrib.auth.forms import AuthenticationForm, PasswordChangeForm as DjangoPasswordChangeForm
from django.contrib.postgres.forms import SimpleArrayField
from django.utils.html import mark_safe
+from django.utils.translation import gettext as _
from ipam.formfields import IPNetworkFormField
from netbox.preferences import PREFERENCES
@@ -100,14 +101,14 @@ class UserConfigForm(BootstrapMixin, forms.ModelForm, metaclass=UserConfigFormMe
class TokenForm(BootstrapMixin, forms.ModelForm):
key = forms.CharField(
required=False,
- help_text="If no key is provided, one will be generated automatically."
+ help_text=_("If no key is provided, one will be generated automatically.")
)
allowed_ips = SimpleArrayField(
base_field=IPNetworkFormField(),
required=False,
- label='Allowed IPs',
- help_text='Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
- 'Example: 10.1.1.0/24,192.168.10.16/32,2001:db8:1::/64
',
+ label=_('Allowed IPs'),
+ help_text=_('Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
+ 'Example: 10.1.1.0/24,192.168.10.16/32,2001:db8:1::/64
'),
)
class Meta:
diff --git a/netbox/users/models.py b/netbox/users/models.py
index 441ed2eee..07e903569 100644
--- a/netbox/users/models.py
+++ b/netbox/users/models.py
@@ -10,6 +10,7 @@ from django.db import models
from django.db.models.signals import post_save
from django.dispatch import receiver
from django.utils import timezone
+from django.utils.translation import gettext as _
from netaddr import IPNetwork
from ipam.fields import IPNetworkField
@@ -216,7 +217,7 @@ class Token(models.Model):
)
write_enabled = models.BooleanField(
default=True,
- help_text='Permit create/update/delete operations using this key'
+ help_text=_('Permit create/update/delete operations using this key')
)
description = models.CharField(
max_length=200,
@@ -227,8 +228,8 @@ class Token(models.Model):
blank=True,
null=True,
verbose_name='Allowed IPs',
- help_text='Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
- 'Ex: "10.1.1.0/24, 192.168.10.16/32, 2001:DB8:1::/64"',
+ help_text=_('Allowed IPv4/IPv6 networks from where the token can be used. Leave blank for no restrictions. '
+ 'Ex: "10.1.1.0/24, 192.168.10.16/32, 2001:DB8:1::/64"'),
)
def __str__(self):
@@ -304,12 +305,12 @@ class ObjectPermission(models.Model):
)
actions = ArrayField(
base_field=models.CharField(max_length=30),
- help_text="The list of actions granted by this permission"
+ help_text=_("The list of actions granted by this permission")
)
constraints = models.JSONField(
blank=True,
null=True,
- help_text="Queryset filter matching the applicable objects of the selected type(s)"
+ help_text=_("Queryset filter matching the applicable objects of the selected type(s)")
)
objects = RestrictedQuerySet.as_manager()
diff --git a/netbox/utilities/forms/fields/csv.py b/netbox/utilities/forms/fields/csv.py
index 59765cae8..f964d0db0 100644
--- a/netbox/utilities/forms/fields/csv.py
+++ b/netbox/utilities/forms/fields/csv.py
@@ -5,6 +5,7 @@ from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import MultipleObjectsReturned, ObjectDoesNotExist
from django.db.models import Q
+from django.utils.translation import gettext as _
from utilities.choices import unpack_grouped_choices
from utilities.forms.utils import parse_csv, validate_csv
@@ -50,9 +51,9 @@ class CSVDataField(forms.CharField):
if not self.initial:
self.initial = ','.join(self.required_fields) + '\n'
if not self.help_text:
- self.help_text = 'Enter the list of column headers followed by one line per record to be imported, using ' \
- 'commas to separate values. Multi-line data and values containing commas may be wrapped ' \
- 'in double quotes.'
+ self.help_text = _('Enter the list of column headers followed by one line per record to be imported, using '
+ 'commas to separate values. Multi-line data and values containing commas may be wrapped '
+ 'in double quotes.')
def to_python(self, value):
reader = csv.reader(StringIO(value.strip()))
diff --git a/netbox/utilities/forms/fields/expandable.py b/netbox/utilities/forms/fields/expandable.py
index fca370c26..781de9f76 100644
--- a/netbox/utilities/forms/fields/expandable.py
+++ b/netbox/utilities/forms/fields/expandable.py
@@ -1,6 +1,7 @@
import re
from django import forms
+from django.utils.translation import gettext as _
from utilities.forms.constants import *
from utilities.forms.utils import expand_alphanumeric_pattern, expand_ipaddress_pattern
@@ -42,8 +43,8 @@ class ExpandableIPAddressField(forms.CharField):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.help_text:
- self.help_text = 'Specify a numeric range to create multiple IPs.
'\
- 'Example: 192.0.2.[1,5,100-254]/24
'
+ self.help_text = _('Specify a numeric range to create multiple IPs.
'
+ 'Example: 192.0.2.[1,5,100-254]/24
')
def to_python(self, value):
# Hackish address family detection but it's all we have to work with
diff --git a/netbox/utilities/forms/fields/fields.py b/netbox/utilities/forms/fields/fields.py
index df69339e5..bb6c3f73b 100644
--- a/netbox/utilities/forms/fields/fields.py
+++ b/netbox/utilities/forms/fields/fields.py
@@ -4,6 +4,7 @@ from django import forms
from django.db.models import Count
from django.forms.fields import JSONField as _JSONField, InvalidJSONInput
from django.templatetags.static import static
+from django.utils.translation import gettext as _
from netaddr import AddrFormatError, EUI
from utilities.forms import widgets
@@ -45,7 +46,7 @@ class SlugField(forms.SlugField):
slug_source: Name of the form field from which the slug value will be derived
"""
widget = widgets.SlugWidget
- help_text = "URL-friendly unique shorthand"
+ help_text = _("URL-friendly unique shorthand")
def __init__(self, *, slug_source='name', help_text=help_text, **kwargs):
super().__init__(help_text=help_text, **kwargs)
@@ -97,7 +98,7 @@ class JSONField(_JSONField):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
if not self.help_text:
- self.help_text = 'Enter context data in JSON format.'
+ self.help_text = _('Enter context data in JSON format.')
self.widget.attrs['placeholder'] = ''
self.widget.attrs['class'] = 'font-monospace'
diff --git a/netbox/utilities/forms/forms.py b/netbox/utilities/forms/forms.py
index 0569853b8..5756cf0e3 100644
--- a/netbox/utilities/forms/forms.py
+++ b/netbox/utilities/forms/forms.py
@@ -5,8 +5,9 @@ from io import StringIO
import yaml
from django import forms
-from utilities.forms.utils import parse_csv
+from django.utils.translation import gettext as _
+from utilities.forms.utils import parse_csv
from .choices import ImportFormatChoices
from .widgets import APISelect, APISelectMultiple, ClearableFileInput, StaticSelect
@@ -103,7 +104,7 @@ class BulkRenameForm(BootstrapMixin, forms.Form):
use_regex = forms.BooleanField(
required=False,
initial=True,
- label='Use regular expressions'
+ label=_('Use regular expressions')
)
def clean(self):
@@ -145,7 +146,7 @@ class ImportForm(BootstrapMixin, forms.Form):
data = forms.CharField(
required=False,
widget=forms.Textarea(attrs={'class': 'font-monospace'}),
- help_text="Enter object data in CSV, JSON or YAML format."
+ help_text=_("Enter object data in CSV, JSON or YAML format.")
)
data_file = forms.FileField(
label="Data file",
@@ -219,7 +220,7 @@ class FilterForm(BootstrapMixin, forms.Form):
"""
q = forms.CharField(
required=False,
- label='Search'
+ label=_('Search')
)
@@ -233,7 +234,7 @@ class TableConfigForm(BootstrapMixin, forms.Form):
widget=forms.SelectMultiple(
attrs={'size': 10, 'class': 'form-select'}
),
- label='Available Columns'
+ label=_('Available Columns')
)
columns = forms.MultipleChoiceField(
choices=[],
@@ -241,7 +242,7 @@ class TableConfigForm(BootstrapMixin, forms.Form):
widget=forms.SelectMultiple(
attrs={'size': 10, 'class': 'form-select'}
),
- label='Selected Columns'
+ label=_('Selected Columns')
)
def __init__(self, table, *args, **kwargs):
diff --git a/netbox/virtualization/filtersets.py b/netbox/virtualization/filtersets.py
index 1b9c5bc78..ef33ebddc 100644
--- a/netbox/virtualization/filtersets.py
+++ b/netbox/virtualization/filtersets.py
@@ -1,5 +1,6 @@
import django_filters
from django.db.models import Q
+from django.utils.translation import gettext as _
from dcim.models import Device, DeviceRole, Platform, Region, Site, SiteGroup
from extras.filtersets import LocalConfigContextFilterSet
@@ -38,57 +39,57 @@ class ClusterFilterSet(NetBoxModelFilterSet, TenancyFilterSet, ContactModelFilte
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
group_id = django_filters.ModelMultipleChoiceFilter(
queryset=ClusterGroup.objects.all(),
- label='Parent group (ID)',
+ label=_('Parent group (ID)'),
)
group = django_filters.ModelMultipleChoiceFilter(
field_name='group__slug',
queryset=ClusterGroup.objects.all(),
to_field_name='slug',
- label='Parent group (slug)',
+ label=_('Parent group (slug)'),
)
type_id = django_filters.ModelMultipleChoiceFilter(
queryset=ClusterType.objects.all(),
- label='Cluster type (ID)',
+ label=_('Cluster type (ID)'),
)
type = django_filters.ModelMultipleChoiceFilter(
field_name='type__slug',
queryset=ClusterType.objects.all(),
to_field_name='slug',
- label='Cluster type (slug)',
+ label=_('Cluster type (slug)'),
)
status = django_filters.MultipleChoiceFilter(
choices=ClusterStatusChoices,
@@ -121,111 +122,111 @@ class VirtualMachineFilterSet(
cluster_group_id = django_filters.ModelMultipleChoiceFilter(
field_name='cluster__group',
queryset=ClusterGroup.objects.all(),
- label='Cluster group (ID)',
+ label=_('Cluster group (ID)'),
)
cluster_group = django_filters.ModelMultipleChoiceFilter(
field_name='cluster__group__slug',
queryset=ClusterGroup.objects.all(),
to_field_name='slug',
- label='Cluster group (slug)',
+ label=_('Cluster group (slug)'),
)
cluster_type_id = django_filters.ModelMultipleChoiceFilter(
field_name='cluster__type',
queryset=ClusterType.objects.all(),
- label='Cluster type (ID)',
+ label=_('Cluster type (ID)'),
)
cluster_type = django_filters.ModelMultipleChoiceFilter(
field_name='cluster__type__slug',
queryset=ClusterType.objects.all(),
to_field_name='slug',
- label='Cluster type (slug)',
+ label=_('Cluster type (slug)'),
)
cluster_id = django_filters.ModelMultipleChoiceFilter(
queryset=Cluster.objects.all(),
- label='Cluster (ID)',
+ label=_('Cluster (ID)'),
)
cluster = django_filters.ModelMultipleChoiceFilter(
field_name='cluster__name',
queryset=Cluster.objects.all(),
to_field_name='name',
- label='Cluster',
+ label=_('Cluster'),
)
device_id = django_filters.ModelMultipleChoiceFilter(
queryset=Device.objects.all(),
- label='Device (ID)',
+ label=_('Device (ID)'),
)
device = django_filters.ModelMultipleChoiceFilter(
field_name='device__name',
queryset=Device.objects.all(),
to_field_name='name',
- label='Device',
+ label=_('Device'),
)
region_id = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
- label='Region (ID)',
+ label=_('Region (ID)'),
)
region = TreeNodeMultipleChoiceFilter(
queryset=Region.objects.all(),
field_name='site__region',
lookup_expr='in',
to_field_name='slug',
- label='Region (slug)',
+ label=_('Region (slug)'),
)
site_group_id = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
- label='Site group (ID)',
+ label=_('Site group (ID)'),
)
site_group = TreeNodeMultipleChoiceFilter(
queryset=SiteGroup.objects.all(),
field_name='site__group',
lookup_expr='in',
to_field_name='slug',
- label='Site group (slug)',
+ label=_('Site group (slug)'),
)
site_id = django_filters.ModelMultipleChoiceFilter(
queryset=Site.objects.all(),
- label='Site (ID)',
+ label=_('Site (ID)'),
)
site = django_filters.ModelMultipleChoiceFilter(
field_name='site__slug',
queryset=Site.objects.all(),
to_field_name='slug',
- label='Site (slug)',
+ label=_('Site (slug)'),
)
name = MultiValueCharFilter(
lookup_expr='iexact'
)
role_id = django_filters.ModelMultipleChoiceFilter(
queryset=DeviceRole.objects.all(),
- label='Role (ID)',
+ label=_('Role (ID)'),
)
role = django_filters.ModelMultipleChoiceFilter(
field_name='role__slug',
queryset=DeviceRole.objects.all(),
to_field_name='slug',
- label='Role (slug)',
+ label=_('Role (slug)'),
)
platform_id = django_filters.ModelMultipleChoiceFilter(
queryset=Platform.objects.all(),
- label='Platform (ID)',
+ label=_('Platform (ID)'),
)
platform = django_filters.ModelMultipleChoiceFilter(
field_name='platform__slug',
queryset=Platform.objects.all(),
to_field_name='slug',
- label='Platform (slug)',
+ label=_('Platform (slug)'),
)
mac_address = MultiValueMACAddressFilter(
field_name='interfaces__mac_address',
- label='MAC address',
+ label=_('MAC address'),
)
has_primary_ip = django_filters.BooleanFilter(
method='_has_primary_ip',
- label='Has a primary IP',
+ label=_('Has a primary IP'),
)
class Meta:
@@ -251,48 +252,48 @@ class VMInterfaceFilterSet(NetBoxModelFilterSet):
cluster_id = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine__cluster',
queryset=Cluster.objects.all(),
- label='Cluster (ID)',
+ label=_('Cluster (ID)'),
)
cluster = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine__cluster__name',
queryset=Cluster.objects.all(),
to_field_name='name',
- label='Cluster',
+ label=_('Cluster'),
)
virtual_machine_id = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine',
queryset=VirtualMachine.objects.all(),
- label='Virtual machine (ID)',
+ label=_('Virtual machine (ID)'),
)
virtual_machine = django_filters.ModelMultipleChoiceFilter(
field_name='virtual_machine__name',
queryset=VirtualMachine.objects.all(),
to_field_name='name',
- label='Virtual machine',
+ label=_('Virtual machine'),
)
parent_id = django_filters.ModelMultipleChoiceFilter(
field_name='parent',
queryset=VMInterface.objects.all(),
- label='Parent interface (ID)',
+ label=_('Parent interface (ID)'),
)
bridge_id = django_filters.ModelMultipleChoiceFilter(
field_name='bridge',
queryset=VMInterface.objects.all(),
- label='Bridged interface (ID)',
+ label=_('Bridged interface (ID)'),
)
mac_address = MultiValueMACAddressFilter(
- label='MAC address',
+ label=_('MAC address'),
)
vrf_id = django_filters.ModelMultipleChoiceFilter(
field_name='vrf',
queryset=VRF.objects.all(),
- label='VRF',
+ label=_('VRF'),
)
vrf = django_filters.ModelMultipleChoiceFilter(
field_name='vrf__rd',
queryset=VRF.objects.all(),
to_field_name='rd',
- label='VRF (RD)',
+ label=_('VRF (RD)'),
)
class Meta:
diff --git a/netbox/virtualization/forms/bulk_create.py b/netbox/virtualization/forms/bulk_create.py
index 03997f88d..54722c7b1 100644
--- a/netbox/virtualization/forms/bulk_create.py
+++ b/netbox/virtualization/forms/bulk_create.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from utilities.forms import BootstrapMixin, ExpandableNameField, form_from_model
from virtualization.models import VMInterface, VirtualMachine
@@ -14,7 +15,7 @@ class VirtualMachineBulkAddComponentForm(BootstrapMixin, forms.Form):
widget=forms.MultipleHiddenInput()
)
name = ExpandableNameField(
- label='Name'
+ label=_('Name')
)
def clean_tags(self):
diff --git a/netbox/virtualization/forms/bulk_edit.py b/netbox/virtualization/forms/bulk_edit.py
index a94b2da1c..14ae89c37 100644
--- a/netbox/virtualization/forms/bulk_edit.py
+++ b/netbox/virtualization/forms/bulk_edit.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from dcim.choices import InterfaceModeChoices
from dcim.constants import INTERFACE_MTU_MAX, INTERFACE_MTU_MIN
@@ -90,7 +91,7 @@ class ClusterBulkEditForm(NetBoxModelBulkEditForm):
)
comments = CommentField(
widget=SmallTextarea,
- label='Comments'
+ label=_('Comments')
)
model = Cluster
@@ -147,15 +148,15 @@ class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm):
)
vcpus = forms.IntegerField(
required=False,
- label='vCPUs'
+ label=_('vCPUs')
)
memory = forms.IntegerField(
required=False,
- label='Memory (MB)'
+ label=_('Memory (MB)')
)
disk = forms.IntegerField(
required=False,
- label='Disk (GB)'
+ label=_('Disk (GB)')
)
description = forms.CharField(
max_length=200,
@@ -163,7 +164,7 @@ class VirtualMachineBulkEditForm(NetBoxModelBulkEditForm):
)
comments = CommentField(
widget=SmallTextarea,
- label='Comments'
+ label=_('Comments')
)
model = VirtualMachine
@@ -199,7 +200,7 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
required=False,
min_value=INTERFACE_MTU_MIN,
max_value=INTERFACE_MTU_MAX,
- label='MTU'
+ label=_('MTU')
)
description = forms.CharField(
max_length=100,
@@ -213,7 +214,7 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
vlan_group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
- label='VLAN group'
+ label=_('VLAN group')
)
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
@@ -221,7 +222,7 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
query_params={
'group_id': '$vlan_group',
},
- label='Untagged VLAN'
+ label=_('Untagged VLAN')
)
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
@@ -229,12 +230,12 @@ class VMInterfaceBulkEditForm(NetBoxModelBulkEditForm):
query_params={
'group_id': '$vlan_group',
},
- label='Tagged VLANs'
+ label=_('Tagged VLANs')
)
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
model = VMInterface
diff --git a/netbox/virtualization/forms/bulk_import.py b/netbox/virtualization/forms/bulk_import.py
index 6fc704ae4..154c21328 100644
--- a/netbox/virtualization/forms/bulk_import.py
+++ b/netbox/virtualization/forms/bulk_import.py
@@ -1,5 +1,6 @@
from dcim.choices import InterfaceModeChoices
from dcim.models import Device, DeviceRole, Platform, Site
+from django.utils.translation import gettext as _
from ipam.models import VRF
from netbox.forms import NetBoxModelCSVForm
from tenancy.models import Tenant
@@ -36,29 +37,29 @@ class ClusterCSVForm(NetBoxModelCSVForm):
type = CSVModelChoiceField(
queryset=ClusterType.objects.all(),
to_field_name='name',
- help_text='Type of cluster'
+ help_text=_('Type of cluster')
)
group = CSVModelChoiceField(
queryset=ClusterGroup.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned cluster group'
+ help_text=_('Assigned cluster group')
)
status = CSVChoiceField(
choices=ClusterStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
site = CSVModelChoiceField(
queryset=Site.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned site'
+ help_text=_('Assigned site')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
class Meta:
@@ -69,25 +70,25 @@ class ClusterCSVForm(NetBoxModelCSVForm):
class VirtualMachineCSVForm(NetBoxModelCSVForm):
status = CSVChoiceField(
choices=VirtualMachineStatusChoices,
- help_text='Operational status'
+ help_text=_('Operational status')
)
site = CSVModelChoiceField(
queryset=Site.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned site'
+ help_text=_('Assigned site')
)
cluster = CSVModelChoiceField(
queryset=Cluster.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned cluster'
+ help_text=_('Assigned cluster')
)
device = CSVModelChoiceField(
queryset=Device.objects.all(),
to_field_name='name',
required=False,
- help_text='Assigned device within cluster'
+ help_text=_('Assigned device within cluster')
)
role = CSVModelChoiceField(
queryset=DeviceRole.objects.filter(
@@ -95,19 +96,19 @@ class VirtualMachineCSVForm(NetBoxModelCSVForm):
),
required=False,
to_field_name='name',
- help_text='Functional role'
+ help_text=_('Functional role')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
platform = CSVModelChoiceField(
queryset=Platform.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned platform'
+ help_text=_('Assigned platform')
)
class Meta:
@@ -127,24 +128,24 @@ class VMInterfaceCSVForm(NetBoxModelCSVForm):
queryset=VMInterface.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent interface'
+ help_text=_('Parent interface')
)
bridge = CSVModelChoiceField(
queryset=VMInterface.objects.all(),
required=False,
to_field_name='name',
- help_text='Bridged interface'
+ help_text=_('Bridged interface')
)
mode = CSVChoiceField(
choices=InterfaceModeChoices,
required=False,
- help_text='IEEE 802.1Q operational mode (for L2 interfaces)'
+ help_text=_('IEEE 802.1Q operational mode (for L2 interfaces)')
)
vrf = CSVModelChoiceField(
queryset=VRF.objects.all(),
required=False,
to_field_name='rd',
- help_text='Assigned VRF'
+ help_text=_('Assigned VRF')
)
class Meta:
diff --git a/netbox/virtualization/forms/filtersets.py b/netbox/virtualization/forms/filtersets.py
index 62fa4002e..c4fdf033a 100644
--- a/netbox/virtualization/forms/filtersets.py
+++ b/netbox/virtualization/forms/filtersets.py
@@ -160,11 +160,11 @@ class VirtualMachineFilterForm(
)
mac_address = forms.CharField(
required=False,
- label='MAC address'
+ label=_('MAC address')
)
has_primary_ip = forms.NullBooleanField(
required=False,
- label='Has a primary IP',
+ label=_('Has a primary IP'),
widget=StaticSelect(
choices=BOOLEAN_WITH_BLANK_CHOICES
)
diff --git a/netbox/virtualization/forms/model_forms.py b/netbox/virtualization/forms/model_forms.py
index 3f598d061..037af0b5c 100644
--- a/netbox/virtualization/forms/model_forms.py
+++ b/netbox/virtualization/forms/model_forms.py
@@ -1,6 +1,7 @@
from django import forms
from django.contrib.contenttypes.models import ContentType
from django.core.exceptions import ValidationError
+from django.utils.translation import gettext as _
from dcim.forms.common import InterfaceCommonForm
from dcim.forms.model_forms import INTERFACE_MODE_HELP_TEXT
@@ -204,7 +205,7 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
'cluster_id': '$cluster',
'site_id': '$site',
},
- help_text="Optionally pin this VM to a specific host device within the cluster"
+ help_text=_("Optionally pin this VM to a specific host device within the cluster")
)
role = DynamicModelChoiceField(
queryset=DeviceRole.objects.all(),
@@ -240,8 +241,8 @@ class VirtualMachineForm(TenancyForm, NetBoxModelForm):
'local_context_data',
]
help_texts = {
- 'local_context_data': "Local config context data overwrites all sources contexts in the final rendered "
- "config context",
+ 'local_context_data': _("Local config context data overwrites all sources contexts in the final rendered "
+ "config context"),
}
widgets = {
"status": StaticSelect(),
@@ -297,7 +298,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
parent = DynamicModelChoiceField(
queryset=VMInterface.objects.all(),
required=False,
- label='Parent interface',
+ label=_('Parent interface'),
query_params={
'virtual_machine_id': '$virtual_machine',
}
@@ -305,7 +306,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
bridge = DynamicModelChoiceField(
queryset=VMInterface.objects.all(),
required=False,
- label='Bridged interface',
+ label=_('Bridged interface'),
query_params={
'virtual_machine_id': '$virtual_machine',
}
@@ -313,12 +314,12 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
vlan_group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
- label='VLAN group'
+ label=_('VLAN group')
)
untagged_vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
- label='Untagged VLAN',
+ label=_('Untagged VLAN'),
query_params={
'group_id': '$vlan_group',
'available_on_virtualmachine': '$virtual_machine',
@@ -327,7 +328,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
tagged_vlans = DynamicModelMultipleChoiceField(
queryset=VLAN.objects.all(),
required=False,
- label='Tagged VLANs',
+ label=_('Tagged VLANs'),
query_params={
'group_id': '$vlan_group',
'available_on_virtualmachine': '$virtual_machine',
@@ -336,7 +337,7 @@ class VMInterfaceForm(InterfaceCommonForm, NetBoxModelForm):
vrf = DynamicModelChoiceField(
queryset=VRF.objects.all(),
required=False,
- label='VRF'
+ label=_('VRF')
)
fieldsets = (
diff --git a/netbox/wireless/forms/bulk_edit.py b/netbox/wireless/forms/bulk_edit.py
index 7544327a5..be54faf9e 100644
--- a/netbox/wireless/forms/bulk_edit.py
+++ b/netbox/wireless/forms/bulk_edit.py
@@ -1,4 +1,5 @@
from django import forms
+from django.utils.translation import gettext as _
from dcim.choices import LinkStatusChoices
from ipam.models import VLAN
@@ -45,12 +46,12 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm):
vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
- label='VLAN'
+ label=_('VLAN')
)
ssid = forms.CharField(
max_length=SSID_MAX_LENGTH,
required=False,
- label='SSID'
+ label=_('SSID')
)
tenant = DynamicModelChoiceField(
queryset=Tenant.objects.all(),
@@ -66,7 +67,7 @@ class WirelessLANBulkEditForm(NetBoxModelBulkEditForm):
)
auth_psk = forms.CharField(
required=False,
- label='Pre-shared key'
+ label=_('Pre-shared key')
)
description = forms.CharField(
max_length=200,
@@ -91,7 +92,7 @@ class WirelessLinkBulkEditForm(NetBoxModelBulkEditForm):
ssid = forms.CharField(
max_length=SSID_MAX_LENGTH,
required=False,
- label='SSID'
+ label=_('SSID')
)
status = forms.ChoiceField(
choices=add_blank_choice(LinkStatusChoices),
@@ -111,7 +112,7 @@ class WirelessLinkBulkEditForm(NetBoxModelBulkEditForm):
)
auth_psk = forms.CharField(
required=False,
- label='Pre-shared key'
+ label=_('Pre-shared key')
)
description = forms.CharField(
max_length=200,
diff --git a/netbox/wireless/forms/bulk_import.py b/netbox/wireless/forms/bulk_import.py
index 4d96f60ad..adf2a2b6c 100644
--- a/netbox/wireless/forms/bulk_import.py
+++ b/netbox/wireless/forms/bulk_import.py
@@ -1,3 +1,4 @@
+from django.utils.translation import gettext as _
from dcim.choices import LinkStatusChoices
from dcim.models import Interface
from ipam.models import VLAN
@@ -19,7 +20,7 @@ class WirelessLANGroupCSVForm(NetBoxModelCSVForm):
queryset=WirelessLANGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Parent group'
+ help_text=_('Parent group')
)
slug = SlugField()
@@ -33,7 +34,7 @@ class WirelessLANCSVForm(NetBoxModelCSVForm):
queryset=WirelessLANGroup.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned group'
+ help_text=_('Assigned group')
)
status = CSVChoiceField(
choices=WirelessLANStatusChoices,
@@ -43,23 +44,23 @@ class WirelessLANCSVForm(NetBoxModelCSVForm):
queryset=VLAN.objects.all(),
required=False,
to_field_name='name',
- help_text='Bridged VLAN'
+ help_text=_('Bridged VLAN')
)
tenant = CSVModelChoiceField(
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
auth_type = CSVChoiceField(
choices=WirelessAuthTypeChoices,
required=False,
- help_text='Authentication type'
+ help_text=_('Authentication type')
)
auth_cipher = CSVChoiceField(
choices=WirelessAuthCipherChoices,
required=False,
- help_text='Authentication cipher'
+ help_text=_('Authentication cipher')
)
class Meta:
@@ -73,7 +74,7 @@ class WirelessLANCSVForm(NetBoxModelCSVForm):
class WirelessLinkCSVForm(NetBoxModelCSVForm):
status = CSVChoiceField(
choices=LinkStatusChoices,
- help_text='Connection status'
+ help_text=_('Connection status')
)
interface_a = CSVModelChoiceField(
queryset=Interface.objects.all()
@@ -85,17 +86,17 @@ class WirelessLinkCSVForm(NetBoxModelCSVForm):
queryset=Tenant.objects.all(),
required=False,
to_field_name='name',
- help_text='Assigned tenant'
+ help_text=_('Assigned tenant')
)
auth_type = CSVChoiceField(
choices=WirelessAuthTypeChoices,
required=False,
- help_text='Authentication type'
+ help_text=_('Authentication type')
)
auth_cipher = CSVChoiceField(
choices=WirelessAuthCipherChoices,
required=False,
- help_text='Authentication cipher'
+ help_text=_('Authentication cipher')
)
class Meta:
diff --git a/netbox/wireless/forms/filtersets.py b/netbox/wireless/forms/filtersets.py
index c3e63687d..287ef779c 100644
--- a/netbox/wireless/forms/filtersets.py
+++ b/netbox/wireless/forms/filtersets.py
@@ -35,7 +35,7 @@ class WirelessLANFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
)
ssid = forms.CharField(
required=False,
- label='SSID'
+ label=_('SSID')
)
group_id = DynamicModelMultipleChoiceField(
queryset=WirelessLANGroup.objects.all(),
@@ -74,7 +74,7 @@ class WirelessLinkFilterForm(TenancyFilterForm, NetBoxModelFilterSetForm):
)
ssid = forms.CharField(
required=False,
- label='SSID'
+ label=_('SSID')
)
status = forms.ChoiceField(
required=False,
diff --git a/netbox/wireless/forms/model_forms.py b/netbox/wireless/forms/model_forms.py
index e59c36696..8b45b0116 100644
--- a/netbox/wireless/forms/model_forms.py
+++ b/netbox/wireless/forms/model_forms.py
@@ -1,3 +1,4 @@
+from django.utils.translation import gettext as _
from dcim.models import Device, Interface, Location, Region, Site, SiteGroup
from ipam.models import VLAN, VLANGroup
from netbox.forms import NetBoxModelForm
@@ -63,7 +64,7 @@ class WirelessLANForm(TenancyForm, NetBoxModelForm):
vlan_group = DynamicModelChoiceField(
queryset=VLANGroup.objects.all(),
required=False,
- label='VLAN group',
+ label=_('VLAN group'),
null_option='None',
query_params={
'site': '$site'
@@ -75,7 +76,7 @@ class WirelessLANForm(TenancyForm, NetBoxModelForm):
vlan = DynamicModelChoiceField(
queryset=VLAN.objects.all(),
required=False,
- label='VLAN',
+ label=_('VLAN'),
query_params={
'site_id': '$site',
'group_id': '$vlan_group',
@@ -107,7 +108,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
site_a = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
- label='Site',
+ label=_('Site'),
initial_params={
'devices': '$device_a',
}
@@ -118,7 +119,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
'site_id': '$site_a',
},
required=False,
- label='Location',
+ label=_('Location'),
initial_params={
'devices': '$device_a',
}
@@ -130,7 +131,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
'location_id': '$location_a',
},
required=False,
- label='Device',
+ label=_('Device'),
initial_params={
'interfaces': '$interface_a'
}
@@ -142,12 +143,12 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
'device_id': '$device_a',
},
disabled_indicator='_occupied',
- label='Interface'
+ label=_('Interface')
)
site_b = DynamicModelChoiceField(
queryset=Site.objects.all(),
required=False,
- label='Site',
+ label=_('Site'),
initial_params={
'devices': '$device_b',
}
@@ -158,7 +159,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
'site_id': '$site_b',
},
required=False,
- label='Location',
+ label=_('Location'),
initial_params={
'devices': '$device_b',
}
@@ -170,7 +171,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
'location_id': '$location_b',
},
required=False,
- label='Device',
+ label=_('Device'),
initial_params={
'interfaces': '$interface_b'
}
@@ -182,7 +183,7 @@ class WirelessLinkForm(TenancyForm, NetBoxModelForm):
'device_id': '$device_b',
},
disabled_indicator='_occupied',
- label='Interface'
+ label=_('Interface')
)
comments = CommentField()