Description

unicode(contenttype_instance) always returns the English name of the respective model class. More accurately, it returns the "name" field which contains the underlying model class'es verbose_name_raw. It would have helped me if it said in django/django/contrib/contenttypes/models.py line 87:

First, I was wrong that the field name is technical. Quite the opposite, it's intended to be a human-readable representation. So the simplest solution to your use-case is changing the name to whatever you want. However this won't work in a multilingual environment since the field's content cannot be translated (at the moment).

I've conducted a little research. ContentType.name is initialized with model's untranslated verbose name — verbose_name_raw, a property which was introduced in [5225] specifically for the purpose of using for content types. I don't know why it was done this way. It might be a good idea to change this to using a usual translated verbose names of a model but it's technically backwards incompatible.

I'm marking this as DDN to get an opinion of a core developer. To summarize:

ContentType uses a dedicated field for its human-readable representation. The idea is to use real verbose names of models.

My own take would be to go for a change since I doubt ContentType.name}} is widely used **and** is different from {{{verbose_name of a model. Most probably we will even save maintenance for people who routinely change names of content type according to model's verbose names.

I don't see any good reason why ContentType should have a denormalized name field stored in the database, rather than looking up the appropriate model verbose_name at runtime - its not as if the latter is an expensive operation, and translation is a real problem with the current approach.

I think we can make this fix in a backwards-compatible way. The __unicode__ method can check if the name field is equal to the model's verbose_name_raw (i.e. hasn't been manually changed), and if so look up the real verbose_name (possibly translated) and return that. If the name field has been changed, return it. This still leaves open the possibility that in the future (once we have a schema-alteration framework in core) we could deprecate and then remove the name field entirely.

In the meantime, there's also a workaround that I think can help multilingual sites: on ModelForms for models with an FK to ContentType, you can replace the form field for that FK with a subclass of ModelChoiceField that overrides the label_for_instance method to do the translated verbose_name lookup. This ​is documented; it's fairly verbose (which is why I'm not simply pointing to it and closing this wontfix), but it should do the trick for the time being.

I don't know if there a point of attaching compiled language files that don't get included in the patch, it might be easier to compile them from tests/regressiontests/i18n/contenttypes directory by hand

I left a comment in django/contrib/contenttypes/models.py regarding deprecation of self.name but wasn't sure if we should actually raise a DeprecationWarning there?

I don't know if there a point of attaching compiled language files that don't get included in the patch, it might be easier to compile them from tests/regressiontests/i18n/contenttypes directory by hand

I left a comment in django/contrib/contenttypes/models.py regarding deprecation of self.name but wasn't sure if we should actually raise a DeprecationWarning there?

I think actual deprecation of the name field should wait until we have schema migrations in core, so that we can actually remove the field at the end of the deprecation. For now the comment is fine - I might expand on it to note that we'll do a real deprecation later.

Looks good otherwise, except I'm now getting four UnicodeDecodeErrors in the admin_views tests with this patch. Probably due to the added translation with non-ASCII chars in it, haven't dug in to find the best solution.