Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add ability to set a custom verbose name #770

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions docs/modeltranslation/registration.rst
Original file line number Diff line number Diff line change
Expand Up @@ -344,6 +344,12 @@ Classes inheriting from ``TranslationOptions`` can have following attributes def
required_languages = ('en', 'de')
required_languages = {'de': ('title','text'), 'default': ('title',)}

.. attribute:: TranslationOptions.get_verbose_name

The verbose name by default is the field name followed by a space and the language code in brackets. This can be customized by implementing the ``get_verbose_name`` method.

def get_verbose_name(self, field_name, language):
return f"{language} - {field_name}"

.. _supported_field_matrix:

Expand Down
3 changes: 1 addition & 2 deletions modeltranslation/fields.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
from modeltranslation.utils import (
build_localized_fieldname,
build_localized_intermediary_model,
build_localized_verbose_name,
get_language,
resolution_order,
)
Expand Down Expand Up @@ -172,7 +171,7 @@ def __init__(

# Copy the verbose name and append a language suffix
# (will show up e.g. in the admin).
self.verbose_name = build_localized_verbose_name(translated_field.verbose_name, language)
self.verbose_name = trans_opts.get_verbose_name(translated_field.verbose_name, language)

if self.remote_field:
clear_ForeignObjectRel_caches(self.remote_field)
Expand Down
14 changes: 14 additions & 0 deletions modeltranslation/tests/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,20 @@ class Migration(migrations.Migration):
("title_en", models.CharField(max_length=255, null=True, unique=True)),
],
),
migrations.CreateModel(
name="CustomVerboseNameModel",
fields=[
(
"id",
models.AutoField(
auto_created=True, primary_key=True, serialize=False, verbose_name="ID"
),
),
("title", models.CharField(max_length=255, null=True, unique=True)),
("title_de", models.CharField(max_length=255, null=True, unique=True)),
("title_en", models.CharField(max_length=255, null=True, unique=True)),
],
),
migrations.CreateModel(
name="MultitableConflictModelB",
fields=[
Expand Down
4 changes: 4 additions & 0 deletions modeltranslation/tests/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@ class UniqueNullableModel(models.Model):
title = models.CharField(null=True, unique=True, max_length=255)


class CustomVerboseNameModel(models.Model):
title = models.CharField(null=True, unique=True, max_length=255)


# ######### Proxy model testing


Expand Down
10 changes: 9 additions & 1 deletion modeltranslation/tests/tests.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
request = None

# How many models are registered for tests.
TEST_MODELS = 40
TEST_MODELS = 41


class reload_override_settings(override_settings):
Expand Down Expand Up @@ -276,6 +276,14 @@ def test_verbose_name(self):
verbose_name = models.TestModel._meta.get_field("title_de").verbose_name
assert verbose_name == "title [de]"

def test_custom_verbose_name(self):
verbose_name = models.CustomVerboseNameModel._meta.get_field("title_de").verbose_name
assert verbose_name == "(de) title"

def test_custom_verbose_name_plural(self):
verbose_name = models.CustomVerboseNameModel._meta.get_field("title_de").verbose_name_plural
assert verbose_name == "(de) title"

def test_descriptor_introspection(self):
# See Django #8248
assert isinstance(
Expand Down
9 changes: 9 additions & 0 deletions modeltranslation/tests/translation.py
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,15 @@ class CustomManagerTestModelTranslationOptions(TranslationOptions):
fields = ("title",)


# # ######### TranslationOptions verbose name
@register(models.CustomVerboseNameModel)
class CustomVerboseNameModelTranslationOptions(TranslationOptions):
fields = ("title",)

def get_verbose_name(self, verbose_name, language):
return f"({language}) {verbose_name}"


# ######### TranslationOptions field inheritance testing


Expand Down
4 changes: 4 additions & 0 deletions modeltranslation/translator.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
build_localized_fieldname,
parse_field,
get_language,
build_localized_verbose_name,
)

# Re-export the decorator for convenience
Expand Down Expand Up @@ -170,6 +171,9 @@ def get_field_names(self) -> list[str]:
"""
return list(self.all_fields.keys()) + self.related_fields

def get_verbose_name(self, verbose_name, language):
return build_localized_verbose_name(verbose_name, language)

def __str__(self) -> str:
local = tuple(self.local_fields.keys())
inherited = tuple(set(self.all_fields.keys()) - set(local))
Expand Down
Loading