Przeglądaj źródła

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 13 godzin temu
rodzic
commit
771993d820

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

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

+ 1 - 1
netbox/core/data_backends.py

@@ -7,7 +7,7 @@ from urllib.parse import urlparse
 
 from django import forms
 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.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.files.storage import storages
 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 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.urls import reverse
 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 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.db import connection, models
 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.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.management import call_command
 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.utils import timezone
+from django.utils import timezone, translation
 
 from core.choices import DataSourceStatusChoices, JobNotificationChoices, JobStatusChoices, ObjectChangeActionChoices
 from core.data_backends import LocalBackend
@@ -663,3 +663,17 @@ class JobTestCase(TestCase):
         job.terminate(status=JobStatusChoices.STATUS_COMPLETED)
 
         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 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 rest_framework import serializers
 

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

@@ -1,6 +1,6 @@
 import decimal
 
-from django.utils.translation import gettext as _
+from django.utils.translation import gettext_lazy as _
 from rest_framework import serializers
 
 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.utils import extend_schema_field
 from rest_framework import serializers

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

@@ -1,6 +1,6 @@
 from django import forms
 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 netbox.registry import registry

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

@@ -1,6 +1,6 @@
 import django_tables2 as tables
 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 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.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 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.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.utils import extend_schema_field
 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
 

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

@@ -1,5 +1,5 @@
 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.models import *

+ 1 - 1
netbox/users/tables.py

@@ -1,5 +1,5 @@
 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 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
 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 netbox.choices import CSVDelimiterChoices, ImportFormatChoices, ImportMethodChoices

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

@@ -1,7 +1,7 @@
 import re
 
 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 utilities.forms.fields import QueryField

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

@@ -1,6 +1,6 @@
 from django import forms
 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 ipam.models import VLAN, RouteTarget