Ticket #14924: 14924.2.diff

File 14924.2.diff, 20.5 KB (added by ramiro, 4 years ago)

New version of the patch, also includes fix for #10765. start deprecation path for loading of translations from the 'project' directory.. remeber to generate the .mo files under the tests/ subdir for the three modified .po files

  • django/utils/translation/__init__.py

    diff --git a/django/utils/translation/__init__.py b/django/utils/translation/__init__.py
    a b  
    11"""
    22Internationalization support.
    33"""
     4import os.path
     5
    46from django.utils.encoding import force_unicode
    5 from django.utils.functional import lazy, curry
     7from django.utils.functional import lazy
     8from django.utils.importlib import import_module
    69
    710
    811__all__ = ['gettext', 'gettext_noop', 'gettext_lazy', 'ngettext',
     
    3336    performance effect, as access to the function goes the normal path,
    3437    instead of using __getattr__.
    3538    """
     39    cnt = 0
     40
    3641    def __getattr__(self, real_name):
    3742        from django.conf import settings
    3843        if settings.USE_I18N:
    3944            from django.utils.translation import trans_real as trans
     45
     46            if not self.cnt:
     47                self.cnt += 1
     48                if settings.SETTINGS_MODULE is not None:
     49                    import warnings
     50                    parts = settings.SETTINGS_MODULE.split('.')
     51                    project = import_module(parts[0])
     52                    if os.path.isdir(os.path.join(os.path.dirname(project.__file__), 'locale')):
     53                        warnings.warn(
     54                            "Translations in the project directory aren't supported anymore. Use LOCALE_PATHS settings instead.",
     55                            PendingDeprecationWarning
     56                        )
     57
    4058        else:
    4159            from django.utils.translation import trans_null as trans
    4260        setattr(self, real_name, getattr(trans, real_name))
  • django/utils/translation/trans_real.py

    diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
    a b  
    125125
    126126        global _translations
    127127
    128         loc = to_locale(lang)
    129 
    130128        res = _translations.get(lang, None)
    131129        if res is not None:
    132130            return res
    133131
     132        loc = to_locale(lang)
     133
    134134        def _translation(path):
    135135            try:
    136136                t = gettext_module.translation('django', path, [loc], DjangoTranslation)
     
    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
  • django/views/i18n.py

    diff --git a/django/views/i18n.py b/django/views/i18n.py
    a b  
    196196    paths = []
    197197    en_selected = locale.startswith('en')
    198198    en_catalog_missing = True
    199     # first load all english languages files for defaults
     199    # paths of requested packages
    200200    for package in packages:
    201201        p = importlib.import_module(package)
    202202        path = os.path.join(os.path.dirname(p.__file__), 'locale')
    203203        paths.append(path)
     204    # add the filesystem paths listed in the LOCALE_PATHS setting
     205    paths.extend(list(reversed(settings.LOCALE_PATHS)))
     206    # first load all english languages files for defaults
     207    for path in paths:
    204208        try:
    205209            catalog = gettext_module.translation(domain, path, ['en'])
    206210            t.update(catalog._catalog)
     
    278282    src.append(LibFormatFoot)
    279283    src = ''.join(src)
    280284    return http.HttpResponse(src, 'text/javascript')
    281 
  • 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    1. 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    2. 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    3. Then, it looks for a ``locale`` directory in the project directory, or
     21       more accurately, in the directory containing your settings file.
     22    4. Finally, the Django-provided base translation in ``django/conf/locale``
     23       is used as a fallback.
     24
     25.. deprecated:: 1.3
     26    Lookup in the ``locale`` subdirectory of the directory containing your
     27    settings file (item 3 above) is deprecated since the 1.3 release and will be
     28    removed in 1.5. You can use the :setting:`LOCALE_PATHS` setting instead, by
     29    including the full filesystem path of the same location.
     30
     31.. seealso::
     32
     33    The translations for literals included in JavaScript assets are looked up
     34    following not a quite equivalent but a similar algorithm. See the
     35    :ref:`javascript_catalog view documentation <javascript_catalog-view>` for
     36    more details.
    1637
    1738In all cases the name of the directory containing the translation is expected to
    1839be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
     
    3758    * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
    3859    * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
    3960    * All paths listed in ``LOCALE_PATHS`` in your settings file are
    40       searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``
     61      searched for ``<language>/LC_MESSAGES/django.(po|mo)``
    4162    * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``
    4263
    4364To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>`
     
    5071to make the compiler process all the directories in your :setting:`LOCALE_PATHS`
    5172setting.
    5273
    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 
    5874Finally, you should give some thought to the structure of your translation
    5975files. If your applications need to be delivered to other users and will
    6076be 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    1. 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    2. 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    3. Then, it looks for a ``locale`` directory in the project directory, or
     188       more accurately, in the directory containing your settings file.
     189    4. Finally, the Django-provided base translation in ``django/conf/locale``
     190       is used as a fallback.
     191
     192.. deprecated:: 1.3
     193    Lookup in the ``locale`` subdirectory of the directory containing your
     194    settings file (item 3 above) is deprecated since the 1.3 release and will be
     195    removed in 1.5. You can use the :setting:`LOCALE_PATHS` setting instead, by
     196    including the full filesystem path of the same location.
     197
     198.. seealso::
     199
     200    The translations for literals included in JavaScript assets are looked up
     201    following not a quite equivalent but a similar algorithm. See the
     202    :ref:`javascript_catalog view documentation <javascript_catalog-view>` for
     203    more details.
    184204
    185205In all cases the name of the directory containing the translation is expected to
    186206be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
  • docs/topics/i18n/internationalization.txt

    diff --git a/docs/topics/i18n/internationalization.txt b/docs/topics/i18n/internationalization.txt
    a b  
    647647translations into JavaScript, so you can call ``gettext``, etc., from within
    648648JavaScript.
    649649
     650.. _javascript_catalog-view:
     651
    650652The ``javascript_catalog`` view
    651653-------------------------------
    652654
     
    657659The main solution to these problems is the :meth:`django.views.i18n.javascript_catalog`
    658660view, which sends out a JavaScript code library with functions that mimic the
    659661``gettext`` interface, plus an array of translation strings. Those translation
    660 strings are taken from the application, project or Django core, according to what
    661 you specify in either the info_dict or the URL.
     662strings are taken from the application, paths listed in :setting:`LOCALE_PATHS`
     663or Django core, according to what you specify in either the info_dict or the
     664URL.
    662665
    663666You hook it up like this::
    664667
     
    691694catalog file. As a security measure, these values can only be either
    692695``django.conf`` or any package from the :setting:`INSTALLED_APPS` setting.
    693696
     697The JavaScript translations found in the paths listed in the
     698:setting:`LOCALE_PATHS` setting are also always included (provided they have a
     699``locale`` subdirectory).
     700
     701To keep consistency with the translations lookup order algorithm used for Python
     702and templates, the directories listed in :setting:`LOCALE_PATHS` have the
     703highest precedence with the ones appearing first having higher precedence than
     704the ones appearing later. But Django core and :setting:`INSTALLED_APPS`
     705translations should be explicitly listed in the *packages* parameter.
     706
    694707Using the JavaScript translation catalog
    695708----------------------------------------
    696709
  • 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)"
  • tests/regressiontests/views/tests/i18n.py

    diff --git a/tests/regressiontests/views/tests/i18n.py b/tests/regressiontests/views/tests/i18n.py
    a b  
    11# -*- coding:utf-8 -*-
    22import gettext
     3import os
    34
    45from django.conf import settings
    56from django.test import TestCase
     
    150151        response = self.client.get('/views/jsi18n_multi_packages2/')
    151152        self.assertContains(response, javascript_quote('este texto de app3 debe ser traducido'))
    152153        deactivate()
     154
     155    def testI18NWithLocalePaths(self):
     156        settings.LANGUAGE_CODE = 'es-ar'
     157        self.old_locale_paths = settings.LOCALE_PATHS
     158        settings.LOCALE_PATHS += (os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'app3', 'locale'),)
     159        response = self.client.get('/views/jsi18n/')
     160        self.assertContains(response, javascript_quote('este texto de app3 debe ser traducido'))
     161        settings.LOCALE_PATHS = self.old_locale_paths
Back to Top