Explorar el Código

Fixes #23702: Translate remaining import-time labels lazily

Labels on filter forms, bulk import forms, tables, models, data backends
and API serializers were translated with gettext at import, freezing them
in DEFAULT_LANGUAGE. Use gettext_lazy so they render in the user's
language.

Dashboard widget titles and core event type labels stay eager. A lazy
widget title would be stored in the dashboard's JSON config and fail to
save, and a lazy event type label breaks EventType.__str__ and
get_event_text.
Jason Novinger hace 13 horas
padre
commit
771993d820

+ 1 - 1
netbox/circuits/forms/filtersets.py

@@ -1,5 +1,5 @@
 from django import forms
 from django import forms
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from circuits.choices import (
 from circuits.choices import (
     CircuitCommitRateChoices,
     CircuitCommitRateChoices,

+ 1 - 1
netbox/core/data_backends.py

@@ -7,7 +7,7 @@ from urllib.parse import urlparse
 
 
 from django import forms
 from django import forms
 from django.core.exceptions import ImproperlyConfigured
 from django.core.exceptions import ImproperlyConfigured
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from netbox.data_backends import DataBackend
 from netbox.data_backends import DataBackend
 from netbox.utils import register_data_backend
 from netbox.utils import register_data_backend

+ 1 - 1
netbox/core/models/files.py

@@ -6,7 +6,7 @@ from django.conf import settings
 from django.core.exceptions import ValidationError
 from django.core.exceptions import ValidationError
 from django.core.files.storage import storages
 from django.core.files.storage import storages
 from django.db import models
 from django.db import models
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from extras.storage import ScriptFileSystemStorage
 from extras.storage import ScriptFileSystemStorage
 from netbox.models.features import SyncedDataMixin
 from netbox.models.features import SyncedDataMixin

+ 1 - 1
netbox/core/models/jobs.py

@@ -13,7 +13,7 @@ from django.core.validators import MinValueValidator
 from django.db import models, router, transaction
 from django.db import models, router, transaction
 from django.urls import reverse
 from django.urls import reverse
 from django.utils import timezone
 from django.utils import timezone
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 from rq.exceptions import InvalidJobOperation
 from rq.exceptions import InvalidJobOperation
 
 
 from core.choices import JobNotificationChoices, JobStatusChoices
 from core.choices import JobNotificationChoices, JobStatusChoices

+ 1 - 1
netbox/core/models/object_types.py

@@ -7,7 +7,7 @@ from django.contrib.postgres.indexes import GinIndex
 from django.core.exceptions import ObjectDoesNotExist
 from django.core.exceptions import ObjectDoesNotExist
 from django.db import connection, models
 from django.db import connection, models
 from django.db.models import Q
 from django.db.models import Q
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from netbox.context import query_cache
 from netbox.context import query_cache
 from netbox.plugins import PluginConfig
 from netbox.plugins import PluginConfig

+ 16 - 2
netbox/core/tests/test_models.py

@@ -10,9 +10,9 @@ from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ObjectDoesNotExist
 from django.core.exceptions import ObjectDoesNotExist
 from django.core.management import call_command
 from django.core.management import call_command
 from django.db import IntegrityError, connection
 from django.db import IntegrityError, connection
-from django.test import TestCase, override_settings
+from django.test import TestCase, override_settings, tag
 from django.test.utils import CaptureQueriesContext
 from django.test.utils import CaptureQueriesContext
-from django.utils import timezone
+from django.utils import timezone, translation
 
 
 from core.choices import DataSourceStatusChoices, JobNotificationChoices, JobStatusChoices, ObjectChangeActionChoices
 from core.choices import DataSourceStatusChoices, JobNotificationChoices, JobStatusChoices, ObjectChangeActionChoices
 from core.data_backends import LocalBackend
 from core.data_backends import LocalBackend
@@ -663,3 +663,17 @@ class JobTestCase(TestCase):
         job.terminate(status=JobStatusChoices.STATUS_COMPLETED)
         job.terminate(status=JobStatusChoices.STATUS_COMPLETED)
 
 
         self.assertIsNone(job.execution_time)
         self.assertIsNone(job.execution_time)
+
+
+class LabelTranslationTestCase(TestCase):
+    """
+    Labels defined at import render in the active language (#23702).
+    """
+
+    @tag('regression')  # Ref: #23702
+    def test_model_verbose_name(self):
+        # Set in the model's Meta class body
+        with translation.override('nl'):
+            self.assertEqual(str(Job._meta.verbose_name), 'taak')
+        with translation.override('en'):
+            self.assertEqual(str(Job._meta.verbose_name), 'job')

+ 1 - 1
netbox/dcim/api/serializers_/devices.py

@@ -2,7 +2,7 @@ import decimal
 from functools import cached_property
 from functools import cached_property
 
 
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 from drf_spectacular.utils import extend_schema_field
 from drf_spectacular.utils import extend_schema_field
 from rest_framework import serializers
 from rest_framework import serializers
 
 

+ 1 - 1
netbox/dcim/api/serializers_/devicetypes.py

@@ -1,6 +1,6 @@
 import decimal
 import decimal
 
 
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 from rest_framework import serializers
 from rest_framework import serializers
 
 
 from dcim.choices import *
 from dcim.choices import *

+ 1 - 1
netbox/dcim/api/serializers_/racks.py

@@ -1,4 +1,4 @@
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.utils import extend_schema_field
 from drf_spectacular.utils import extend_schema_field
 from rest_framework import serializers
 from rest_framework import serializers

+ 1 - 1
netbox/extras/dashboard/forms.py

@@ -1,6 +1,6 @@
 from django import forms
 from django import forms
 from django.urls import reverse_lazy
 from django.urls import reverse_lazy
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from extras.choices import DashboardWidgetColorChoices
 from extras.choices import DashboardWidgetColorChoices
 from netbox.registry import registry
 from netbox.registry import registry

+ 1 - 1
netbox/extras/tables/columns.py

@@ -1,6 +1,6 @@
 import django_tables2 as tables
 import django_tables2 as tables
 from django.utils.html import format_html
 from django.utils.html import format_html
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from extras.choices import CustomFieldStatusChoices
 from extras.choices import CustomFieldStatusChoices
 from netbox.tables.columns import ActionsColumn, ActionsItem
 from netbox.tables.columns import ActionsColumn, ActionsItem

+ 1 - 1
netbox/ipam/api/serializers_/services.py

@@ -1,6 +1,6 @@
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
 from django.core.exceptions import ValidationError as DjangoValidationError
 from django.core.exceptions import ValidationError as DjangoValidationError
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 from rest_framework import serializers
 from rest_framework import serializers
 
 
 from ipam.choices import *
 from ipam.choices import *

+ 1 - 1
netbox/netbox/api/fields.py

@@ -2,7 +2,7 @@ from functools import cached_property
 
 
 from django.core.exceptions import ObjectDoesNotExist
 from django.core.exceptions import ObjectDoesNotExist
 from django.db.backends.postgresql.psycopg_any import NumericRange
 from django.db.backends.postgresql.psycopg_any import NumericRange
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.types import OpenApiTypes
 from drf_spectacular.utils import extend_schema_field
 from drf_spectacular.utils import extend_schema_field
 from netaddr import IPNetwork
 from netaddr import IPNetwork

+ 1 - 1
netbox/netbox/tests/dummy_plugin/navigation.py

@@ -1,4 +1,4 @@
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from netbox.plugins.navigation import PluginMenu, PluginMenuButton, PluginMenuItem
 from netbox.plugins.navigation import PluginMenu, PluginMenuButton, PluginMenuItem
 
 

+ 1 - 1
netbox/users/forms/bulk_import.py

@@ -1,5 +1,5 @@
 from django import forms
 from django import forms
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from users.choices import TokenVersionChoices
 from users.choices import TokenVersionChoices
 from users.models import *
 from users.models import *

+ 1 - 1
netbox/users/tables.py

@@ -1,5 +1,5 @@
 import django_tables2 as tables
 import django_tables2 as tables
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from netbox.tables import NetBoxTable, columns
 from netbox.tables import NetBoxTable, columns
 from users.models import Group, ObjectPermission, Owner, OwnerGroup, Token, User
 from users.models import Group, ObjectPermission, Owner, OwnerGroup, Token, User

+ 1 - 1
netbox/utilities/forms/bulk_import.py

@@ -4,7 +4,7 @@ from io import StringIO
 
 
 import yaml
 import yaml
 from django import forms
 from django import forms
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from core.forms.mixins import SyncedDataMixin
 from core.forms.mixins import SyncedDataMixin
 from netbox.choices import CSVDelimiterChoices, ImportFormatChoices, ImportMethodChoices
 from netbox.choices import CSVDelimiterChoices, ImportFormatChoices, ImportMethodChoices

+ 1 - 1
netbox/utilities/forms/forms.py

@@ -1,7 +1,7 @@
 import re
 import re
 
 
 from django import forms
 from django import forms
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from netbox.models.features import ChangeLoggingMixin
 from netbox.models.features import ChangeLoggingMixin
 from utilities.forms.fields import QueryField
 from utilities.forms.fields import QueryField

+ 1 - 1
netbox/vpn/forms/filtersets.py

@@ -1,6 +1,6 @@
 from django import forms
 from django import forms
 from django.contrib.contenttypes.models import ContentType
 from django.contrib.contenttypes.models import ContentType
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 
 
 from dcim.models import Device, Region, Site
 from dcim.models import Device, Region, Site
 from ipam.models import VLAN, RouteTarget
 from ipam.models import VLAN, RouteTarget