Browse Source

Capfirst should be used on model verbose name instead of title (#12358)

SebCorbin 6 months ago
parent
commit
83f00a8363

+ 1 - 0
CHANGELOG.txt

@@ -15,6 +15,7 @@ Changelog
  * Implement universal listings for workflow usage and page type usage views (Sage Abdullah)
  * Add search and filters to form pages listing (Sage Abdullah)
  * Deprecate the `WAGTAIL_AUTO_UPDATE_PREVIEW` setting, use `WAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL = 0` instead (Sage Abdullah)
+ * Consistently use `capfirst` for title-casing model verbose names (Sébastien Corbin)
  * Fix: Prevent page type business rules from blocking reordering of pages (Andy Babic, Sage Abdullah)
  * Fix: Improve layout of object permissions table (Sage Abdullah)
  * Fix: Fix typo in aria-label attribute of page explorer navigation link (Sébastien Corbin)

+ 1 - 0
docs/releases/6.3.md

@@ -27,6 +27,7 @@ This release adds formal support for Django 5.1.
  * Implement universal listings for workflow usage and page type usage views (Sage Abdullah)
  * Add search and filters to form pages listing (Sage Abdullah)
  * Deprecate the `WAGTAIL_AUTO_UPDATE_PREVIEW` setting, use `WAGTAIL_AUTO_UPDATE_PREVIEW_INTERVAL = 0` instead (Sage Abdullah)
+ * Consistently use `capfirst` for title-casing model verbose names (Sébastien Corbin)
 
 ### Bug fixes
 

+ 3 - 3
wagtail/admin/tests/test_widgets.py

@@ -119,7 +119,7 @@ class TestAdminPageChooserWidget(TestCase):
         )
 
         html = widget.render("test", self.child_page, {"id": "test-id"})
-        self.assertIn("Choose a page (Simple Page)", html)
+        self.assertIn("Choose a page (Simple page)", html)
 
     def test_render_with_target_model_as_single_instance(self):
         widget = widgets.AdminPageChooser(target_models=SimplePage)
@@ -131,7 +131,7 @@ class TestAdminPageChooserWidget(TestCase):
         )
 
         html = widget.render("test", self.child_page, {"id": "test-id"})
-        self.assertIn("Choose a page (Simple Page)", html)
+        self.assertIn("Choose a page (Simple page)", html)
 
     def test_render_with_target_model_as_single_string(self):
         widget = widgets.AdminPageChooser(target_models="tests.SimplePage")
@@ -143,7 +143,7 @@ class TestAdminPageChooserWidget(TestCase):
         )
 
         html = widget.render("test", self.child_page, {"id": "test-id"})
-        self.assertIn("Choose a page (Simple Page)", html)
+        self.assertIn("Choose a page (Simple page)", html)
 
     def test_render_with_multiple_target_models(self):
         target_models = [SimplePage, "tests.eventpage"]

+ 3 - 3
wagtail/admin/tests/viewsets/test_model_viewset.py

@@ -40,8 +40,8 @@ class TestModelViewSetGroup(WagtailTestUtils, TestCase):
             response,
             '"name": "tests", "label": "Tests", "icon_name": "folder-open-inverse"',
         )
-        # Title-cased from verbose_name_plural
-        self.assertContains(response, "Json Stream Models")
+        # Capitalized-first from verbose_name_plural
+        self.assertContains(response, "JSON stream models")
         self.assertContains(response, reverse("streammodel:index"))
         self.assertEqual(reverse("streammodel:index"), "/admin/streammodel/")
         # Set on class
@@ -81,7 +81,7 @@ class TestModelViewSetGroup(WagtailTestUtils, TestCase):
         )
 
         # The menu item for the model is shown
-        self.assertContains(response, "Json Stream Models")
+        self.assertContains(response, "JSON stream models")
         self.assertContains(response, reverse("streammodel:index"))
         self.assertEqual(reverse("streammodel:index"), "/admin/streammodel/")
 

+ 3 - 2
wagtail/admin/viewsets/model.py

@@ -8,6 +8,7 @@ from django.forms.models import modelform_factory
 from django.shortcuts import redirect
 from django.urls import path
 from django.utils.functional import cached_property
+from django.utils.text import capfirst
 
 from wagtail import hooks
 from wagtail.admin.admin_url_finder import (
@@ -514,7 +515,7 @@ class ModelViewSet(ViewSet):
 
     @cached_property
     def menu_label(self):
-        return self.model_opts.verbose_name_plural.title()
+        return capfirst(self.model_opts.verbose_name_plural)
 
     @cached_property
     def menu_item_class(self):
@@ -696,7 +697,7 @@ class ModelViewSetGroup(ViewSetGroup):
     def get_app_label_from_subitems(self):
         for instance in self.registerables:
             if app_label := getattr(instance, "app_label", ""):
-                return app_label.title()
+                return capfirst(app_label)
         return ""
 
     @cached_property

+ 2 - 1
wagtail/admin/widgets/chooser.py

@@ -7,6 +7,7 @@ from django.template.loader import render_to_string
 from django.urls import reverse
 from django.utils.functional import cached_property
 from django.utils.safestring import mark_safe
+from django.utils.text import capfirst
 from django.utils.translation import gettext_lazy as _
 
 from wagtail.admin.admin_url_finder import AdminURLFinder
@@ -250,7 +251,7 @@ class AdminPageChooser(BaseChooser):
             cleaned_target_models = [Page]
 
         if len(cleaned_target_models) == 1 and cleaned_target_models[0] is not Page:
-            model_name = cleaned_target_models[0]._meta.verbose_name.title()
+            model_name = capfirst(cleaned_target_models[0]._meta.verbose_name)
             self.choose_one_text += " (" + model_name + ")"
 
         self.user_perms = user_perms

+ 2 - 2
wagtail/snippets/tests/test_viewset.py

@@ -1136,14 +1136,14 @@ class TestMenuItemRegistration(BaseSnippetViewSetTests):
         self.model = RevisableModel
         revisable_item = group_item.menu_items[0]
         self.assertEqual(revisable_item.name, "revisable-models")
-        self.assertEqual(revisable_item.label, "Revisable Models")
+        self.assertEqual(revisable_item.label, "Revisable models")
         self.assertEqual(revisable_item.icon_name, "snippet")
         self.assertEqual(revisable_item.url, self.get_url("list"))
 
         self.model = RevisableChildModel
         revisable_child_item = group_item.menu_items[1]
         self.assertEqual(revisable_child_item.name, "revisable-child-models")
-        self.assertEqual(revisable_child_item.label, "Revisable Child Models")
+        self.assertEqual(revisable_child_item.label, "Revisable child models")
         self.assertEqual(revisable_child_item.icon_name, "snippet")
         self.assertEqual(revisable_child_item.url, self.get_url("list"))
 

+ 1 - 1
wagtail/snippets/views/snippets.py

@@ -831,7 +831,7 @@ class SnippetViewSet(ModelViewSet):
 
         **Deprecated** - the preferred way to customise this is to define a ``menu_label`` property.
         """
-        return self.model_opts.verbose_name_plural.title()
+        return capfirst(self.model_opts.verbose_name_plural)
 
     @cached_property
     def menu_name(self):

+ 17 - 0
wagtail/test/testapp/migrations/0041_alter_jsonstreammodel_options.py

@@ -0,0 +1,17 @@
+# Generated by Django 5.1 on 2024-09-25 15:35
+
+from django.db import migrations
+
+
+class Migration(migrations.Migration):
+
+    dependencies = [
+        ("tests", "0040_nocreatablesubpagetypespage_nosubpagetypespage"),
+    ]
+
+    operations = [
+        migrations.AlterModelOptions(
+            name="jsonstreammodel",
+            options={"verbose_name": "JSON stream model"},
+        ),
+    ]

+ 3 - 0
wagtail/test/testapp/models.py

@@ -1524,6 +1524,9 @@ class JSONStreamModel(models.Model):
         ],
     )
 
+    class Meta:
+        verbose_name = "JSON stream model"
+
 
 class JSONMinMaxCountStreamModel(models.Model):
     body = StreamField(