Region locales' translation objects get overwritten
|Reported by:||oggy||Owned by:||Malcolm Tredinnick|
|Severity:||Keywords:||translation gettext region locale|
|Has patch:||yes||Needs documentation:||no|
|Needs tests:||no||Patch needs improvement:||yes|
Internal caching performed by Python's gettext module causes translation objects for different region locales of the same language (e.g. en-us and en-gb) to get overwritten.
Consider the scenario of having en-us and en-gb localized versions of a project or an app. When the translation for one of these locales is first loaded, Django loads the translation objects by processing .mo files in this order:
- From root django conf/locale dir
- From project locale dir
- From settings.LOCALE_PATHS
- From apps' locale dirs
Due to the way that Python's ugettext module works, since no en_US or en_GB subdirs are found in step 1, the base language 'en' translation in conf/locale/en will be used. Hence, both of these translations will refer to the same .mo file. However, this will cause ugettext to cache, returning two translation objects which share the same _catalog dictionary.
In : t1 = gettext.translation('django', '/usr/lib/python2.5/site-packages/django/conf/locale/', ['en_US']) In : t2 = gettext.translation('django', '/usr/lib/python2.5/site-packages/django/conf/locale/', ['en_GB']) In : id(t1._catalog) Out: 3079088844L In : id(t2._catalog) Out: 3079088844L
Therefore, any changes to one translation at stages 2-4 will effectively change the other one as well, rendering regional translations useless at the project/LOCALE_DIRS/app level. To prevent this, it's necessary to perform a deep copy of the translation object at stage 1. Since Django implements its own caching of translation objects, this should not affect the performance too much.
Change History (11)
comment:1 Changed 8 years ago by
|Patch needs improvement:||unset|
comment:4 Changed 8 years ago by
|Owner:||changed from nobody to Malcolm Tredinnick|
|Patch needs improvement:||set|
|Triage Stage:||Ready for checkin → Accepted|