Opened 3 weeks ago
Last modified 6 days ago
#36884 assigned Bug
Translation of admin log messages fails due to case inconsistency in field names
| Reported by: | Meiyer | Owned by: | Thrishagowdabl |
|---|---|---|---|
| Component: | contrib.admin | Version: | 3.0 |
| Severity: | Normal | Keywords: | |
| Cc: | jaffar Khan | Triage Stage: | Accepted |
| Has patch: | no | Needs documentation: | no |
| Needs tests: | no | Patch needs improvement: | yes |
| Easy pickings: | no | UI/UX: | no |
Description
The Django Admin builds the log messages using construct_change_message, which looks at the fields of the change form, specifically their labels (https://github.com/django/django/blob/9814676ea75bfe5c5d5244c50ccfe1f652a2f058/django/contrib/admin/utils.py#L618). The helper function turns off the translation when building the change JSON, to apply the translation when a LogMessage is displayed. However, there is a flaw in the logic:
- the
verbose_nameparameter of the model field would typically be lower-cased (from the docs: “The convention is not to capitalize the first letter of the verbose_name. Django will automatically capitalize the first letter where it needs to.” ). - the labels generated by the forms have the first letter capitalized (from the docs: “the default label for a Field is generated from the field name by converting all underscores to spaces and upper-casing the first letter”) where for Model Forms, “Django will fall back on that model field’s verbose_name and then the field’s attribute name”.
This results in translation mismatch at render time. For example, the log message would include "fields": ["Occupation"] while the translation catalog has only the key “occupation”, coming from that field’s verbose_name. As a result, the field names are not properly translated.
I tracked the issue back to changes introduced in 3.0 and it persists in all versions up to 6.0.
Change History (7)
comment:1 by , 3 weeks ago
| Owner: | set to |
|---|---|
| Status: | new → assigned |
comment:2 by , 3 weeks ago
| Summary: | Translation of fields in admin log messages works incorrectly → Translation of admin log messages fails due to case inconsistency in field names |
|---|---|
| Triage Stage: | Unreviewed → Accepted |
comment:4 by , 13 days ago
Want to work on this ticket if the current assignee is no longer interested
comment:5 by , 13 days ago
| Cc: | added |
|---|
comment:6 by , 6 days ago
I confirm the issue.
The capitalisation is probably done in db\models\fields\__init__.py with "label": capfirst(self.verbose_name),.
For example, this column content: [{'changed': {'fields': ['Status']}}] is rendered in French str as: Modification de « t2>t2:90 » — Modification de Status.
According to the app .po file, the end of the text should be état., or maybe État.
comment:7 by , 6 days ago
Here is a proposed patch of contrib/admin/utils.py:
--- C:/D/tmp/utils_old.py Tue Feb 10 11:20:50 2026
+++ C:/D/tmp/utils_new.py Tue Feb 10 11:21:01 2026
@@ -1,8 +1,10 @@
def _get_changed_field_labels_from_form(form, changed_data):
changed_field_labels = []
+ opts = form.instance._meta
for field_name in changed_data:
try:
- verbose_field_name = form.fields[field_name].label or field_name
+ # can't use form.fields[field_name].label because it is wrapped in capfirst()
+ verbose_field_name = opts.get_field(field_name).verbose_name or field_name
except KeyError:
verbose_field_name = field_name
changed_field_labels.append(str(verbose_field_name))
Now, my example is:
column content: [{"changed": {"fields": ["status"]}}]
str of logentry: Modification de « t2>t2:90 » — Modification de état.
Thanks for the clear report and diagnosis.