From 5887129546a4901a2688cc913cb97a223a0e8a80 Mon Sep 17 00:00:00 2001 From: Louis Date: Fri, 24 Jul 2026 15:41:35 +0200 Subject: [PATCH] feat: add German localization Internationalize plugin navigation, forms, tables, model labels, detail templates, choices, and validation messages. Ship a compiled German Django message catalog and bump the plugin version to 1.10.0. --- CHANGELOG.md | 1 + README.md | 5 +- netbox_slm/__init__.py | 7 +- netbox_slm/api/serializers.py | 3 +- netbox_slm/filtersets.py | 15 +- netbox_slm/forms/software_license.py | 41 +-- netbox_slm/forms/software_product.py | 3 +- .../forms/software_product_installation.py | 23 +- netbox_slm/forms/software_product_version.py | 13 +- netbox_slm/locale/de/LC_MESSAGES/django.mo | Bin 0 -> 4593 bytes netbox_slm/locale/de/LC_MESSAGES/django.po | 263 ++++++++++++++++++ netbox_slm/models.py | 133 ++++++--- netbox_slm/navigation.py | 27 +- netbox_slm/tables.py | 11 +- .../installations_card_include.html | 5 +- .../templates/netbox_slm/softwarelicense.html | 31 ++- .../templates/netbox_slm/softwareproduct.html | 21 +- .../softwareproductinstallation.html | 17 +- .../netbox_slm/softwareproductversion.html | 31 ++- netbox_slm/tests/test_models.py | 7 + 20 files changed, 499 insertions(+), 158 deletions(-) create mode 100644 netbox_slm/locale/de/LC_MESSAGES/django.mo create mode 100644 netbox_slm/locale/de/LC_MESSAGES/django.po diff --git a/CHANGELOG.md b/CHANGELOG.md index 9191db7..a4bbfef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,7 @@ ### Added * Optional tenant group and tenant assignments for software licenses +* German translation for navigation, forms, tables, detail views, choices, and validation messages ### Changed diff --git a/README.md b/README.md index a75e532..a3c838e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,9 @@ Lizenzen können optional einer NetBox-Mandantengruppe und einem Mandanten zugeo Diese Variante ist für **NetBox 4.6.5** vorgesehen. +Die Oberfläche ist auf Englisch und Deutsch verfügbar. Die Sprache richtet sich nach der in NetBox für den +Benutzer ausgewählten Sprache. + ## Funktionen - Softwareprodukte und Hersteller verwalten @@ -54,7 +57,7 @@ Die installierte Version kann anschließend geprüft werden: /opt/netbox/venv/bin/pip show netbox-slm ``` -Für diese Variante muss dort mindestens Version `1.9.1` stehen. +Für diese Variante muss dort mindestens Version `1.10.0` stehen. ### 3. Plugin in NetBox aktivieren diff --git a/netbox_slm/__init__.py b/netbox_slm/__init__.py index c6e0b71..9f6a914 100644 --- a/netbox_slm/__init__.py +++ b/netbox_slm/__init__.py @@ -15,15 +15,16 @@ limitations under the License. """ from netbox.plugins import PluginConfig +from django.utils.translation import gettext_lazy as _ -__version__ = "1.9.1" +__version__ = "1.10.0" class SLMConfig(PluginConfig): name = "netbox_slm" - verbose_name = "Software Lifecycle Management" + verbose_name = _("Software Lifecycle Management") version = __version__ - description = "Software Lifecycle Management Netbox Plugin." + description = _("Software Lifecycle Management NetBox Plugin.") author = "ICTU" author_email = "open-source-projects@ictu.nl" base_url = "slm" diff --git a/netbox_slm/api/serializers.py b/netbox_slm/api/serializers.py index 23c2d9c..393ad69 100644 --- a/netbox_slm/api/serializers.py +++ b/netbox_slm/api/serializers.py @@ -1,5 +1,6 @@ from rest_framework import serializers from rest_framework.serializers import SerializerMethodField, HyperlinkedIdentityField +from django.utils.translation import gettext_lazy as _ from netbox.api.serializers import NetBoxModelSerializer from netbox_slm.models import SoftwareProduct, SoftwareProductVersion, SoftwareProductInstallation, SoftwareLicense @@ -46,7 +47,7 @@ class SoftwareLicenseSerializer(NetBoxModelSerializer): tenant = attrs.get("tenant", getattr(self.instance, "tenant", None)) if tenant_group and tenant and tenant.group_id != tenant_group.pk: raise serializers.ValidationError( - {"tenant": "The selected tenant does not belong to the selected tenant group."} + {"tenant": _("The selected tenant does not belong to the selected tenant group.")} ) return attrs diff --git a/netbox_slm/filtersets.py b/netbox_slm/filtersets.py index 311e111..3fdd089 100644 --- a/netbox_slm/filtersets.py +++ b/netbox_slm/filtersets.py @@ -1,4 +1,5 @@ from django.db.models import Q +from django.utils.translation import gettext_lazy as _ from django_filters import CharFilter, ModelMultipleChoiceFilter, MultipleChoiceFilter from dcim.models import Device, Manufacturer @@ -55,7 +56,7 @@ class SoftwareProductVersionFilterSet(NetBoxModelFilterSet): software_product_id = ModelMultipleChoiceFilter( queryset=SoftwareProduct.objects.all(), - label="Software Product", + label=_("Software Product"), ) class Meta: @@ -82,12 +83,12 @@ class SoftwareProductInstallationFilterSet(NetBoxModelFilterSet): device_id = ModelMultipleChoiceFilter(queryset=Device.objects.all()) virtualmachine_id = ModelMultipleChoiceFilter( queryset=VirtualMachine.objects.all(), - label="Virtual Machine", + label=_("Virtual Machine"), ) cluster_id = ModelMultipleChoiceFilter(queryset=Cluster.objects.all()) software_product_id = ModelMultipleChoiceFilter( queryset=SoftwareProduct.objects.all(), - label="Software Product", + label=_("Software Product"), ) version_id = ModelMultipleChoiceFilter(queryset=SoftwareProductVersion.objects.all()) @@ -114,17 +115,17 @@ class SoftwareLicenseFilterSet(NetBoxModelFilterSet): name = CharFilter(lookup_expr="icontains") description = CharFilter(lookup_expr="icontains") type = CharFilter(lookup_expr="icontains") - spdx_expression = CharFilter(lookup_expr="icontains", label="SPDX expression") + spdx_expression = CharFilter(lookup_expr="icontains", label=_("SPDX expression")) stored_location = CharFilter(lookup_expr="icontains") software_product_id = ModelMultipleChoiceFilter( queryset=SoftwareProduct.objects.all(), - label="Software Product", + label=_("Software Product"), ) version_id = ModelMultipleChoiceFilter(queryset=SoftwareProductVersion.objects.all()) installation_id = ModelMultipleChoiceFilter(queryset=SoftwareProductInstallation.objects.all()) - tenant_group_id = ModelMultipleChoiceFilter(queryset=TenantGroup.objects.all(), label="Tenant Group") - tenant_id = ModelMultipleChoiceFilter(queryset=Tenant.objects.all(), label="Tenant") + tenant_group_id = ModelMultipleChoiceFilter(queryset=TenantGroup.objects.all(), label=_("Tenant Group")) + tenant_id = ModelMultipleChoiceFilter(queryset=Tenant.objects.all(), label=_("Tenant")) class Meta: model = SoftwareLicense diff --git a/netbox_slm/forms/software_license.py b/netbox_slm/forms/software_license.py index 4ab14f4..fd48d67 100644 --- a/netbox_slm/forms/software_license.py +++ b/netbox_slm/forms/software_license.py @@ -1,5 +1,6 @@ from django.forms import CharField, DateField, ChoiceField, IntegerField, NullBooleanField from django.urls import reverse_lazy +from django.utils.translation import gettext_lazy as _ from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm, NetBoxModelBulkEditForm from netbox_slm.models import ( @@ -31,9 +32,9 @@ class SoftwareLicenseForm(NetBoxModelForm): "software_product", "version", "installation", - name="Software License", + name=_("Software License"), ), - FieldSet("tenant_group", "tenant", name="Tenancy"), + FieldSet("tenant_group", "tenant", name=_("Tenancy")), FieldSet( "type", "spdx_expression", @@ -43,12 +44,12 @@ class SoftwareLicenseForm(NetBoxModelForm): "expiration_date", "support", "license_amount", - name="License Details", + name=_("License Details"), ), - FieldSet("tags", name="Tags"), + FieldSet("tags", name=_("Tags")), ) - spdx_expression = ChoiceField(required=False, choices=spdx_license_names(), label="SPDX expression") + spdx_expression = ChoiceField(required=False, choices=spdx_license_names(), label=_("SPDX expression")) stored_location_url = LaxURLField(required=False) start_date = DateField(required=False, widget=DatePicker()) expiration_date = DateField(required=False, widget=DatePicker()) @@ -56,7 +57,7 @@ class SoftwareLicenseForm(NetBoxModelForm): software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), required=True, - label="Software Product", + label=_("Software Product"), ) version = DynamicModelChoiceField( queryset=SoftwareProductVersion.objects.all(), @@ -75,13 +76,13 @@ class SoftwareLicenseForm(NetBoxModelForm): tenant_group = DynamicModelChoiceField( queryset=TenantGroup.objects.all(), required=False, - label="Tenant Group", + label=_("Tenant Group"), ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), required=False, query_params={"group_id": "$tenant_group"}, - label="Tenant", + label=_("Tenant"), ) class Meta: @@ -132,40 +133,42 @@ class SoftwareLicenseFilterForm(NetBoxModelFilterSetForm): name = CharField(required=False) description = CharField(required=False) type = CharField(required=False) - spdx_expression = CharField(required=False, label="SPDX expression") + spdx_expression = CharField(required=False, label=_("SPDX expression")) stored_location = CharField(required=False) support = ChoiceField(required=False, choices=BOOLEAN_WITH_BLANK_CHOICES) software_product_id = DynamicModelMultipleChoiceField( queryset=SoftwareProduct.objects.all(), required=False, - label="Software Product", + label=_("Software Product"), ) version_id = DynamicModelMultipleChoiceField( queryset=SoftwareProductVersion.objects.all(), required=False, - label="Version", + label=_("Version"), ) installation_id = DynamicModelMultipleChoiceField( queryset=SoftwareProductInstallation.objects.all(), required=False, - label="Installation", + label=_("Installation"), ) tenant_group_id = DynamicModelMultipleChoiceField( queryset=TenantGroup.objects.all(), required=False, - label="Tenant Group", + label=_("Tenant Group"), ) tenant_id = DynamicModelMultipleChoiceField( queryset=Tenant.objects.all(), required=False, query_params={"group_id": "$tenant_group_id"}, - label="Tenant", + label=_("Tenant"), ) class SoftwareLicenseBulkImportForm(NetBoxModelImportForm): - support = NullBooleanField(required=False, help_text="Support (values other than 'True' and 'False' are ignored)") + support = NullBooleanField( + required=False, help_text=_("Support (values other than 'True' and 'False' are ignored)") + ) class Meta: model = SoftwareLicense @@ -226,7 +229,7 @@ class SoftwareLicenseBulkEditForm(NetBoxModelBulkEditForm): comments = CommentField() type = CharField(required=False) - spdx_expression = ChoiceField(required=False, choices=spdx_license_names(), label="SPDX expression") + spdx_expression = ChoiceField(required=False, choices=spdx_license_names(), label=_("SPDX expression")) stored_location = CharField(required=False) stored_location_url = LaxURLField(required=False) start_date = DateField(required=False, widget=DatePicker()) @@ -237,7 +240,7 @@ class SoftwareLicenseBulkEditForm(NetBoxModelBulkEditForm): software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), required=False, - label="Software Product", + label=_("Software Product"), ) version = DynamicModelChoiceField( queryset=SoftwareProductVersion.objects.all(), @@ -256,11 +259,11 @@ class SoftwareLicenseBulkEditForm(NetBoxModelBulkEditForm): tenant_group = DynamicModelChoiceField( queryset=TenantGroup.objects.all(), required=False, - label="Tenant Group", + label=_("Tenant Group"), ) tenant = DynamicModelChoiceField( queryset=Tenant.objects.all(), required=False, query_params={"group_id": "$tenant_group"}, - label="Tenant", + label=_("Tenant"), ) diff --git a/netbox_slm/forms/software_product.py b/netbox_slm/forms/software_product.py index 1dc79f5..022772e 100644 --- a/netbox_slm/forms/software_product.py +++ b/netbox_slm/forms/software_product.py @@ -1,4 +1,5 @@ from django.forms import CharField +from django.utils.translation import gettext_lazy as _ from dcim.models import Manufacturer from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm, NetBoxModelBulkEditForm @@ -46,7 +47,7 @@ class SoftwareProductFilterForm(NetBoxModelFilterSetForm): manufacturer_id = DynamicModelMultipleChoiceField( queryset=Manufacturer.objects.all(), required=False, - label="Manufacturer", + label=_("Manufacturer"), ) diff --git a/netbox_slm/forms/software_product_installation.py b/netbox_slm/forms/software_product_installation.py index b648f7f..9bdcb52 100644 --- a/netbox_slm/forms/software_product_installation.py +++ b/netbox_slm/forms/software_product_installation.py @@ -1,5 +1,6 @@ from django.forms import ValidationError from django.urls import reverse_lazy +from django.utils.translation import gettext_lazy as _ from dcim.models import Device from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm, NetBoxModelBulkEditForm @@ -22,13 +23,13 @@ class SoftwareProductInstallationForm(NetBoxModelForm): virtualmachine = DynamicModelChoiceField( queryset=VirtualMachine.objects.all(), required=False, - label="Virtual Machine", + label=_("Virtual Machine"), ) cluster = DynamicModelChoiceField(queryset=Cluster.objects.all(), required=False) software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), required=True, - label="Software Product", + label=_("Software Product"), ) version = DynamicModelChoiceField( queryset=SoftwareProductVersion.objects.all(), @@ -54,8 +55,8 @@ class SoftwareProductInstallationForm(NetBoxModelForm): software_product = self.cleaned_data["software_product"] if version not in software_product.softwareproductversion_set.all(): raise ValidationError( - f"Version '{version}' doesn't exist on {software_product}, make sure you've " - f"selected a compatible version or first select the software product." + _("Version '%(version)s' does not belong to %(product)s. Select a compatible version.") + % {"version": version, "product": software_product} ) return version @@ -73,27 +74,27 @@ class SoftwareProductInstallationFilterForm(NetBoxModelFilterSetForm): device_id = DynamicModelMultipleChoiceField( queryset=Device.objects.all(), required=False, - label="Device", + label=_("Device"), ) virtualmachine_id = DynamicModelMultipleChoiceField( queryset=VirtualMachine.objects.all(), required=False, - label="Virtual Machine", + label=_("Virtual Machine"), ) cluster_id = DynamicModelMultipleChoiceField( queryset=Cluster.objects.all(), required=False, - label="Cluster", + label=_("Cluster"), ) software_product_id = DynamicModelMultipleChoiceField( queryset=SoftwareProduct.objects.all(), required=False, - label="Software Product", + label=_("Software Product"), ) version_id = DynamicModelMultipleChoiceField( queryset=SoftwareProductVersion.objects.all(), required=False, - label="Version", + label=_("Version"), ) @@ -122,13 +123,13 @@ class SoftwareProductInstallationBulkEditForm(NetBoxModelBulkEditForm): virtualmachine = DynamicModelChoiceField( queryset=VirtualMachine.objects.all(), required=False, - label="Virtual Machine", + label=_("Virtual Machine"), ) cluster = DynamicModelChoiceField(queryset=Cluster.objects.all(), required=False) software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), required=False, - label="Software Product", + label=_("Software Product"), ) version = DynamicModelChoiceField( queryset=SoftwareProductVersion.objects.all(), diff --git a/netbox_slm/forms/software_product_version.py b/netbox_slm/forms/software_product_version.py index 3510be3..32f2ecf 100644 --- a/netbox_slm/forms/software_product_version.py +++ b/netbox_slm/forms/software_product_version.py @@ -1,5 +1,6 @@ from django.forms import DateField, CharField, MultipleChoiceField from django.urls import reverse_lazy +from django.utils.translation import gettext_lazy as _ from dcim.models import Manufacturer from netbox.forms import NetBoxModelForm, NetBoxModelFilterSetForm, NetBoxModelImportForm, NetBoxModelBulkEditForm @@ -23,7 +24,7 @@ class SoftwareProductVersionForm(NetBoxModelForm): software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), required=True, - label="Software Product", + label=_("Software Product"), widget=APISelect(attrs={"data-url": reverse_lazy("plugins-api:netbox_slm-api:softwareproduct-list")}), ) @@ -64,17 +65,19 @@ class SoftwareProductVersionFilterForm(NetBoxModelFilterSetForm): manufacturer_id = DynamicModelMultipleChoiceField( queryset=Manufacturer.objects.all(), required=False, - label="Manufacturer", + label=_("Manufacturer"), ) software_product_id = DynamicModelMultipleChoiceField( queryset=SoftwareProduct.objects.all(), required=False, - label="Software Product", + label=_("Software Product"), ) class SoftwareProductVersionBulkImportForm(NetBoxModelImportForm): - release_type = CharField(help_text=f"Release type (possible values: {SoftwareReleaseTypes.values})") + release_type = CharField( + help_text=_("Release type (possible values: %(values)s)") % {"values": SoftwareReleaseTypes.values} + ) class Meta: model = SoftwareProductVersion @@ -122,5 +125,5 @@ class SoftwareProductVersionBulkEditForm(NetBoxModelBulkEditForm): software_product = DynamicModelChoiceField( queryset=SoftwareProduct.objects.all(), required=False, - label="Software Product", + label=_("Software Product"), ) diff --git a/netbox_slm/locale/de/LC_MESSAGES/django.mo b/netbox_slm/locale/de/LC_MESSAGES/django.mo new file mode 100644 index 0000000000000000000000000000000000000000..8303efd8e933cbc6ab43827182ae0d774692dd99 GIT binary patch literal 4593 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

- Installations + {% trans "Installations" %} {% if perms.netbox_slm.add_softwareproductinstallation %} {% endif %} diff --git a/netbox_slm/templates/netbox_slm/softwarelicense.html b/netbox_slm/templates/netbox_slm/softwarelicense.html index c532e85..12093fe 100644 --- a/netbox_slm/templates/netbox_slm/softwarelicense.html +++ b/netbox_slm/templates/netbox_slm/softwarelicense.html @@ -3,53 +3,54 @@ {% load static %} {% load helpers %} {% load plugins %} +{% load i18n %} {% block content %}
- Software License + {% trans "Software License" %}
- + - + - + - + - + - + - + - + - + - + {% if object.stored_location_url %} {% else %} @@ -57,19 +58,19 @@ {% endif %} - + - + - + - +
Name{% trans "Name" %} {{ object.name }}
Description{% trans "Description" %} {{ object.description }}
Type{% trans "Type" %} {{ object.type }}
SPDX expression{% trans "SPDX expression" %} {{ object.spdx_expression }}
Software Product{% trans "Software Product" %} {{ object.software_product|linkify }}
Version{% trans "Version" %} {{ object.version|linkify }}
Installation{% trans "Installation" %} {{ object.installation|linkify }}
Tenant Group{% trans "Tenant Group" %} {{ object.tenant_group|linkify }}
Tenant{% trans "Tenant" %} {{ object.tenant|linkify }}
Stored location{% trans "Stored location" %}{{ object.stored_location_txt }}
Start date{% trans "Start date" %} {{ object.start_date }}
Expiration date{% trans "Expiration date" %} {{ object.expiration_date }}
Support{% trans "Support" %} {{ object.support }}
License amount{% trans "License amount" %} {{ object.license_amount }}
diff --git a/netbox_slm/templates/netbox_slm/softwareproduct.html b/netbox_slm/templates/netbox_slm/softwareproduct.html index 0337c94..58f1c71 100644 --- a/netbox_slm/templates/netbox_slm/softwareproduct.html +++ b/netbox_slm/templates/netbox_slm/softwareproduct.html @@ -3,60 +3,61 @@ {% load static %} {% load helpers %} {% load plugins %} +{% load i18n %} {% block content %}
- Software Product + {% trans "Software Product" %}
- + - + - + - + - + - + diff --git a/netbox_slm/templates/netbox_slm/softwareproductinstallation.html b/netbox_slm/templates/netbox_slm/softwareproductinstallation.html index d608a72..dbb82ae 100644 --- a/netbox_slm/templates/netbox_slm/softwareproductinstallation.html +++ b/netbox_slm/templates/netbox_slm/softwareproductinstallation.html @@ -3,48 +3,49 @@ {% load static %} {% load helpers %} {% load plugins %} +{% load i18n %} {% block content %}
- Software Product Installation + {% trans "Software Product Installation" %}
Name{% trans "Name" %} {{ object.name }}
Description{% trans "Description" %} {{ object.description }}
Manufacturer{% trans "Manufacturer" %} {{ object.manufacturer|linkify }}
Versions{% trans "Versions" %} {% for version in object.softwareproductversion_set.all %} {{ version }} {% empty %} - None + {% trans "None" %} {% endfor %}
Installations{% trans "Installations" %} {% for installation in object.softwareproductinstallation_set.all %} {{ installation }} {% empty %} - None + {% trans "None" %} {% endfor %}
Licenses{% trans "Licenses" %} {% for license in object.softwarelicense_set.all %} {{ license }} {% empty %} - None + {% trans "None" %} {% endfor %}
{% if object.device %} - + {% elif object.virtualmachine %} - + {% else %} - + {% endif %} - + - + - + diff --git a/netbox_slm/templates/netbox_slm/softwareproductversion.html b/netbox_slm/templates/netbox_slm/softwareproductversion.html index 6e75476..2602157 100644 --- a/netbox_slm/templates/netbox_slm/softwareproductversion.html +++ b/netbox_slm/templates/netbox_slm/softwareproductversion.html @@ -3,37 +3,38 @@ {% load static %} {% load helpers %} {% load plugins %} +{% load i18n %} {% block content %}
- Software Product Version + {% trans "Software Product Version" %}
Device{% trans "Device" %} {{ object.device|linkify }}
Virtual Machine{% trans "Virtual Machine" %} {{ object.virtualmachine|linkify }}
Cluster{% trans "Cluster" %} {{ object.cluster|linkify }}
Software Product{% trans "Software Product" %} {{ object.software_product|linkify }}
Version{% trans "Version" %} {{ object.version|linkify }}
Licenses{% trans "Licenses" %} {% for license in object.softwarelicense_set.all %} {{ license }} {% empty %} - None + {% trans "None" %} {% endfor %}
- + - + - + - + - + - + {% if object.documentation_url %} {% else %} @@ -41,11 +42,11 @@ {% endif %} - + - + {% if object.file_link %} {% else %} @@ -53,34 +54,34 @@ {% endif %} - + - + - + - + diff --git a/netbox_slm/tests/test_models.py b/netbox_slm/tests/test_models.py index e8d3fc5..a96d4ad 100644 --- a/netbox_slm/tests/test_models.py +++ b/netbox_slm/tests/test_models.py @@ -1,4 +1,5 @@ from django.core.exceptions import ValidationError +from django.utils.translation import gettext, override from netbox_slm.forms import SoftwareLicenseForm from tenancy.models import Tenant, TenantGroup @@ -73,6 +74,12 @@ class ModelTestCase(SlmBaseTestCase): any("tenant_group" in fieldset.items and "tenant" in fieldset.items for fieldset in form.fieldsets) ) + def test_german_translation(self): + with override("de"): + self.assertEqual("Softwarelizenz", gettext("Software License")) + self.assertEqual("Mandantengruppe", gettext("Tenant Group")) + self.assertEqual("Lizenzen", gettext("Licenses")) + def test_software_license_rejects_tenant_from_other_group(self): other_group = TenantGroup.objects.create(name="other group", slug="other-group") other_tenant = Tenant.objects.create(name="other tenant", slug="other-tenant", group=other_group)
Name{% trans "Name" %} {{ object.name }}
Description{% trans "Description" %} {{ object.description }}
Manufacturer{% trans "Manufacturer" %} {{ object.software_product.manufacturer|linkify }}
Software Product{% trans "Software Product" %} {{ object.software_product|linkify }}
Release date{% trans "Release date" %} {{ object.release_date }}
Documentation url{% trans "Documentation URL" %}{{ object.documentation_url }}
End of support{% trans "End of support" %} {{ object.end_of_support }}
Filename{% trans "Filename" %}{{ object.filename }}
File checksum{% trans "File checksum" %} {{ object.file_checksum }}
Release type{% trans "Release type" %} {{ object.get_release_type_display }}
Installations{% trans "Installations" %} {% for installation in object.softwareproductinstallation_set.all %} {{ installation }} {% empty %} - None + {% trans "None" %} {% endfor %}
Licenses{% trans "Licenses" %} {% for license in object.softwarelicense_set.all %} {{ license }} {% empty %} - None + {% trans "None" %} {% endfor %}