Ticket #14924: 14924.1.diff

File 14924.1.diff, 13.7 KB (added by ramiro, 4 years ago)

Patch with modification of loading precedence as proposed by vanschelven + tests + docs mods. Remeber to regenerate the .mo files correspondig to the touche .po files

  • django/utils/translation/trans_real.py

    diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
    a b  
    159159                    res.merge(t)
    160160            return res
    161161
    162         for localepath in settings.LOCALE_PATHS:
    163             if os.path.isdir(localepath):
    164                 res = _merge(localepath)
    165 
    166         for appname in settings.INSTALLED_APPS:
     162        for appname in reversed(settings.INSTALLED_APPS):
    167163            app = import_module(appname)
    168164            apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
    169165
     
    173169        if projectpath and os.path.isdir(projectpath):
    174170            res = _merge(projectpath)
    175171
     172        for localepath in reversed(settings.LOCALE_PATHS):
     173            if os.path.isdir(localepath):
     174                res = _merge(localepath)
     175
    176176        if res is None:
    177177            if fallback is not None:
    178178                res = fallback
  • docs/howto/i18n.txt

    diff --git a/docs/howto/i18n.txt b/docs/howto/i18n.txt
    a b  
    44Using internationalization in your own projects
    55===============================================
    66
    7 At runtime, Django looks for translations by following this algorithm:
     7At runtime, Django builds a in-memory unified catalog of literals-translations.
     8To achieve this it looks for translations by following this algorithm regarding
     9the order in which it examines the different file paths to load the compiled
     10:term:`message files <message file>` (``.mo``) and the precedence of multiple
     11translations for the same literal:
    812
    9     * First, it looks for a ``locale`` directory in the directory containing
    10       your settings file.
    11     * Second, it looks for a ``locale`` directory in the project directory.
    12     * Third, it looks for a ``locale`` directory in each of the installed apps.
    13       It does this in the reverse order of INSTALLED_APPS
    14     * Finally, it checks the Django-provided base translation in
    15       ``django/conf/locale``.
     13    * The directories listed in :setting:`LOCALE_PATHS` have the highest
     14      precedence, with the ones appearing first having higher precedence than
     15      the ones appearing later.
     16    * Then, it looks for and uses if it exists a ``locale`` directory in each
     17      of the installed apps listed in :setting:`INSTALLED_APPS`.
     18      The ones appearing first have higher precedence than the ones appearing
     19      later.
     20    * Then, it looks for a ``locale`` directory in the project directory, or
     21      more accurately, in the directory containing your settings file.
     22    * Finally, the Django-provided base translation in ``django/conf/locale``
     23      is used as a fallback.
    1624
    1725In all cases the name of the directory containing the translation is expected to
    1826be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
     
    3745    * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
    3846    * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
    3947    * All paths listed in ``LOCALE_PATHS`` in your settings file are
    40       searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``
     48      searched for ``<language>/LC_MESSAGES/django.(po|mo)``
    4149    * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``
    4250
    4351To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>`
     
    5058to make the compiler process all the directories in your :setting:`LOCALE_PATHS`
    5159setting.
    5260
    53 Application message files are a bit complicated to discover -- they need the
    54 :class:`~django.middleware.locale.LocaleMiddleware`. If you don't use the
    55 middleware, only the Django message files and project message files will be
    56 installed and available at runtime.
    57 
    5861Finally, you should give some thought to the structure of your translation
    5962files. If your applications need to be delivered to other users and will
    6063be used in other projects, you might want to use app-specific translations.
  • docs/topics/i18n/deployment.txt

    diff --git a/docs/topics/i18n/deployment.txt b/docs/topics/i18n/deployment.txt
    a b  
    171171How Django discovers translations
    172172---------------------------------
    173173
    174 As described in :ref:`using-translations-in-your-own-projects`,
    175 at runtime, Django looks for translations by following this algorithm:
     174As described in :ref:`using-translations-in-your-own-projects`, Django looks for
     175translations by following this algorithm regarding the order in which it
     176examines the different file paths to load the compiled :term:`message files
     177<message file>` (``.mo``) and the precedence of multiple translations for the
     178same literal:
    176179
    177     * First, it looks for a ``locale`` directory in the directory containing
    178       your settings file.
    179     * Second, it looks for a ``locale`` directory in the project directory.
    180     * Third, it looks for a ``locale`` directory in each of the installed apps.
    181       It does this in the reverse order of INSTALLED_APPS
    182     * Finally, it checks the Django-provided base translation in
    183       ``django/conf/locale``.
     180    * The directories listed in :setting:`LOCALE_PATHS` have the highest
     181      precedence, with the ones appearing first having higher precedence than
     182      the ones appearing later.
     183    * Then, it looks for and uses if it exists a ``locale`` directory in each
     184      of the installed apps listed in :setting:`INSTALLED_APPS`.
     185      The ones appearing first have higher precedence than the ones appearing
     186      later.
     187    * Then, it looks for a ``locale`` directory in the project directory, or
     188      more accurately, in the directory containing your settings file.
     189    * Finally, the Django-provided base translation in ``django/conf/locale``
     190      is used as a fallback.
    184191
    185192In all cases the name of the directory containing the translation is expected to
    186193be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
  • tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo

    diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.mo
    index 6db1cb1a8ccf488dc7336d0fd707f6693a873a26..241de05ddb04199df4a515d720dc9ea263a06ca7
    GIT binary patch
    literal 668
    zc${sK!EVz)5QewGAZjEIZ~@W7a6oE>HnAO~R&G<Zgj5t9H426UmueeNoQ>?=Xm?#v
    zgm??YE5MlxZ@^n{;mSiWb|Ok8M*95ESpTfYJ3sGupBTjrVuMJCTf_&pj4#AG@s;q1
    zZ^UilJMn<{LEI#M5vOa6{U*I%pVMOOF6or?8tHq|d!!#*%X2=HuCc4pTB*0v>#Moy
    ze)dc_>^NB>OY29em79SQC3-_~!7K_hnR$;gFlej7vA>yR=V;Cv)5z#KP8>hZ_!~4<
    zY868^7b@4_&^qgnaiNXlLz~NtKdo}hQyqgpI!Sropm5Z|>p5bGf-vAg#KR{LZpYp3
    zW2yr(@-d!Ed&L*>AmmX9Q5bi(dC(<aBCO-75y}?AX%oW>p_H_cpv<s<y?Ij}6iwNd
    zYO43CN9C2sk*6q1nj2v+!-GP$waNGW;qh>A`BPy#@cVQ@sOU2n3!1~>JJ(qhLaJSu
    z%!IM%dau(XzH{lT$C;wx12xf^RCx?LXVUqjqB5f3N7|G&2DNBP+lzK#nf5jnJnTWZ
    t<<~2!%FbJq4mOjM{$VmW9UZ36Uv07fy&DQyZ)x0YNw|M=WH0Fk*dL85s@MPk
  • tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po

    diff --git a/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
    a b  
    88"Project-Id-Version: django tests\n"
    99"Report-Msgid-Bugs-To: \n"
    1010"POT-Creation-Date: 2010-02-14 17:33+0100\n"
    11 "PO-Revision-Date: 2011-01-16 17:14+0100\n"
     11"PO-Revision-Date: 2011-01-21 21:37-0300\n"
    1212"Last-Translator: Jannis Leidel <jannis@leidel.info>\n"
    1313"Language-Team: de <de@li.org>\n"
    1414"MIME-Version: 1.0\n"
     
    1818
    1919#: models.py:3
    2020msgid "Time"
    21 msgstr "Time (LOCALE_PATHS)"
     21msgstr "Zeit (LOCALE_PATHS)"
    2222
    2323#: models.py:5
     24msgid "Date/time"
     25msgstr "Datum/Zeit (LOCALE_PATHS)"
     26
     27#: models.py:7
    2428msgctxt "month name"
    2529msgid "May"
    2630msgstr "Mai"
    2731
    28 #: models.py:7
     32#: models.py:9
    2933msgctxt "verb"
    3034msgid "May"
    3135msgstr "Kann"
    3236
    33 #: models.py:9
     37#: models.py:11
    3438msgctxt "search"
    3539msgid "%d result"
    3640msgid_plural "%d results"
    3741msgstr[0] "%d Resultat"
    3842msgstr[1] "%d Resultate"
    39 
  • tests/regressiontests/i18n/resolution/locale/de/LC_MESSAGES/django.mo

    diff --git a/tests/regressiontests/i18n/resolution/locale/de/LC_MESSAGES/django.mo b/tests/regressiontests/i18n/resolution/locale/de/LC_MESSAGES/django.mo
    index 1c37ac5c87e9392a742ea3db6149b902c9667bd9..4d4f202be2e13a07a07dcb894e04f35e03092c91
    GIT binary patch
    literal 492
    zc$`&`!A=`75Qg2B9=fNh=N_gv5E`=HAb|`)EXf8%?1ojc;m}L#Chpd-u~)W(;6eIc
    zeF7xjgxPXPJM!n5k$#VV`{~opZ$|Ns_)HuU?}?nf#&_ZaA&DL0j`;S5v6k{j;t$mk
    z<!8#Y*ju)ZZYCSapn5^C6|1_fboN#)15Q?Wqny{)2q@FxReG7hO*WfPuBXvVwblhJ
    ze63e_v8g>)RzOr<S2%P^20Db@SOH1QV~i8zhro|SzrRm?OhTNgd+q<zaf~@891<@2
    zM;P}>mrEb8a?<!l2I~Zj7kLiTw8-EzE7D1Ro{mPdY(76Dsi`-zR#+*y7LcdY%SC7T
    zG|$f)ePCUE78R2s+dhgP#L>{2pbXvd*pi8$9zw5eq&6q8{3V@NVX&yic)ZnhUVbWv
    znOWMEHno7`A38*3vvIP)v2|-Nz_fo`KS)mCwH)jk_%Z;#7j@sgS@*sw9bh*t%RTl_
    F`2u-se*XXf
  • tests/regressiontests/i18n/resolution/locale/de/LC_MESSAGES/django.po

    diff --git a/tests/regressiontests/i18n/resolution/locale/de/LC_MESSAGES/django.po b/tests/regressiontests/i18n/resolution/locale/de/LC_MESSAGES/django.po
    a b  
    99"Project-Id-Version: PACKAGE VERSION\n"
    1010"Report-Msgid-Bugs-To: \n"
    1111"POT-Creation-Date: 2010-02-14 17:33+0100\n"
    12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
     12"PO-Revision-Date: 2011-01-21 21:37-0300\n"
    1313"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
    1414"Language-Team: LANGUAGE <LL@li.org>\n"
    1515"MIME-Version: 1.0\n"
     
    1818"Plural-Forms: nplurals=2; plural=(n != 1)\n"
    1919
    2020#: models.py:3
     21msgid "Time"
     22msgstr "Zeit (APP)"
     23
     24#: models.py:5
    2125msgid "Date/time"
    2226msgstr "Datum/Zeit (APP)"
  • tests/regressiontests/i18n/tests.py

    diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
    a b  
    660660
    661661    def assertUgettext(self, msgid, msgstr):
    662662        result = ugettext(msgid)
    663         self.assert_(msgstr in result, ("The string '%s' isn't in the "
     663        self.assertTrue(msgstr in result, ("The string '%s' isn't in the "
    664664            "translation of '%s'; the actual result is '%s'." % (msgstr, msgid, result)))
    665665
    666666class AppResolutionOrderI18NTests(ResolutionOrderI18NTests):
    667667
    668668    def setUp(self):
    669669        self.old_installed_apps = settings.INSTALLED_APPS
    670         settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) + ['regressiontests.i18n.resolution']
     670        settings.INSTALLED_APPS = ['regressiontests.i18n.resolution'] + list(settings.INSTALLED_APPS)
    671671        super(AppResolutionOrderI18NTests, self).setUp()
    672672
    673673    def tearDown(self):
     
    691691    def test_locale_paths_translation(self):
    692692        self.assertUgettext('Time', 'LOCALE_PATHS')
    693693
     694    def test_locale_paths_override_app_translation(self):
     695        old_installed_apps = settings.INSTALLED_APPS
     696        settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) + ['regressiontests.i18n.resolution']
     697        try:
     698            self.assertUgettext('Time', 'LOCALE_PATHS')
     699        finally:
     700            settings.INSTALLED_APPS = old_installed_apps
     701
     702    def test_locale_paths_override_project_translation(self):
     703        old_settings_module = settings.SETTINGS_MODULE
     704        settings.SETTINGS_MODULE = 'regressiontests'
     705        try:
     706            self.assertUgettext('Date/time', 'LOCALE_PATHS')
     707        finally:
     708            settings.SETTINGS_MODULE = old_settings_module
     709
    694710class ProjectResolutionOrderI18NTests(ResolutionOrderI18NTests):
    695711
    696712    def setUp(self):
     
    708724    def test_project_override_app_translation(self):
    709725        old_installed_apps = settings.INSTALLED_APPS
    710726        settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) + ['regressiontests.i18n.resolution']
    711         self.assertUgettext('Date/time', 'PROJECT')
    712         settings.INSTALLED_APPS = old_installed_apps
    713 
    714     def test_project_override_locale_paths_translation(self):
    715         old_locale_paths = settings.LOCALE_PATHS
    716         settings.LOCALE_PATHS += (os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'),)
    717         self.assertUgettext('Date/time', 'PROJECT')
    718         settings.LOCALE_PATHS = old_locale_paths
     727        try:
     728            self.assertUgettext('Date/time', 'PROJECT')
     729        finally:
     730            settings.INSTALLED_APPS = old_installed_apps
    719731
    720732class DjangoFallbackResolutionOrderI18NTests(ResolutionOrderI18NTests):
    721733
    722734    def test_django_fallback(self):
    723         self.assertUgettext('Date/time', 'Datum/Zeit')
     735        self.assertEqual(ugettext('Date/time'), 'Datum/Zeit')
    724736
    725737
    726738class TestModels(TestCase):
  • tests/regressiontests/locale/de/LC_MESSAGES/django.mo

    diff --git a/tests/regressiontests/locale/de/LC_MESSAGES/django.mo b/tests/regressiontests/locale/de/LC_MESSAGES/django.mo
    index 2ee860a80b5e75cd9f5fe727c02f74936918dc9c..81616ca7bdabe07ebff028d2480f6cada79b65f3
    GIT binary patch
    literal 500
    zc${63!EO^V5QYtu1AE|rIC2<nt<W^<O{G?DQ*}u;RbV$+Z8kk{0h5@mVPmgsrz#J^
    zd+`L^cn@ajA%c-V&y4hY{M)}?9Q<GuPl#8<3GtN3*+YCHo)MBbAifbFA2HTZeo6eK
    z`Z?v_lxeZYY#;qhHjzOMg5D}t_gm@gSG5i}+u)6IURxueOvmrj>kMwPYB^iXqe^ww
    z1uT4{H~4nfc&x2}s9e-Ic1i|1g#B0nNz7x66XYkrPsMQfhWeO<SgAYh|Iu-bIVKzu
    zE{3NV4@s9xAFy`P_*Mq%1WZ?X4)e6g;36y1S$>sHCRMgvUXs)_JJ~3#mD~!*)A{wP
    zw|tT3SFJv_uDOhgS&{7@#gF4?Y)w#x?)cu3iJ<PoplhWz=diw&&Z{t5)l)p%>v}I=
    zl*7!d?M9nMz}aUVqO#pN+2Yi?truXrzpWo7=kQRD4h_5>0Y8fR@7`?(ACwMoSXPU7
    L*|<Jp|FwSrmUDr3
  • tests/regressiontests/locale/de/LC_MESSAGES/django.po

    diff --git a/tests/regressiontests/locale/de/LC_MESSAGES/django.po b/tests/regressiontests/locale/de/LC_MESSAGES/django.po
    a b  
    99"Project-Id-Version: PACKAGE VERSION\n"
    1010"Report-Msgid-Bugs-To: \n"
    1111"POT-Creation-Date: 2010-02-14 17:33+0100\n"
    12 "PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
     12"PO-Revision-Date: 2011-01-21 21:37-0300\n"
    1313"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
    1414"Language-Team: LANGUAGE <LL@li.org>\n"
    1515"MIME-Version: 1.0\n"
     
    1818"Plural-Forms: nplurals=2; plural=(n != 1)\n"
    1919
    2020#: models.py:3
     21msgid "Time"
     22msgstr "Zeit (PROJECT)"
     23
     24#: models.py:5
    2125msgid "Date/time"
    2226msgstr "Datum/Zeit (PROJECT)"
Back to Top