diff --git a/django/utils/translation/trans_real.py b/django/utils/translation/trans_real.py
--- a/django/utils/translation/trans_real.py
+++ b/django/utils/translation/trans_real.py
@@ -159,11 +159,7 @@
                     res.merge(t)
             return res
 
-        for localepath in settings.LOCALE_PATHS:
-            if os.path.isdir(localepath):
-                res = _merge(localepath)
-
-        for appname in settings.INSTALLED_APPS:
+        for appname in reversed(settings.INSTALLED_APPS):
             app = import_module(appname)
             apppath = os.path.join(os.path.dirname(app.__file__), 'locale')
 
@@ -173,6 +169,10 @@
         if projectpath and os.path.isdir(projectpath):
             res = _merge(projectpath)
 
+        for localepath in reversed(settings.LOCALE_PATHS):
+            if os.path.isdir(localepath):
+                res = _merge(localepath)
+
         if res is None:
             if fallback is not None:
                 res = fallback
diff --git a/docs/howto/i18n.txt b/docs/howto/i18n.txt
--- a/docs/howto/i18n.txt
+++ b/docs/howto/i18n.txt
@@ -4,15 +4,23 @@
 Using internationalization in your own projects
 ===============================================
 
-At runtime, Django looks for translations by following this algorithm:
+At runtime, Django builds a in-memory unified catalog of literals-translations.
+To achieve this it looks for translations by following this algorithm regarding
+the order in which it examines the different file paths to load the compiled
+:term:`message files <message file>` (``.mo``) and the precedence of multiple
+translations for the same literal:
 
-    * First, it looks for a ``locale`` directory in the directory containing
-      your settings file.
-    * Second, it looks for a ``locale`` directory in the project directory.
-    * Third, it looks for a ``locale`` directory in each of the installed apps.
-      It does this in the reverse order of INSTALLED_APPS
-    * Finally, it checks the Django-provided base translation in
-      ``django/conf/locale``.
+    * The directories listed in :setting:`LOCALE_PATHS` have the highest
+      precedence, with the ones appearing first having higher precedence than
+      the ones appearing later.
+    * Then, it looks for and uses if it exists a ``locale`` directory in each
+      of the installed apps listed in :setting:`INSTALLED_APPS`.
+      The ones appearing first have higher precedence than the ones appearing
+      later.
+    * Then, it looks for a ``locale`` directory in the project directory, or
+      more accurately, in the directory containing your settings file.
+    * Finally, the Django-provided base translation in ``django/conf/locale``
+      is used as a fallback.
 
 In all cases the name of the directory containing the translation is expected to
 be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
@@ -37,7 +45,7 @@
     * ``$APPPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
     * ``$PROJECTPATH/locale/<language>/LC_MESSAGES/django.(po|mo)``
     * All paths listed in ``LOCALE_PATHS`` in your settings file are
-      searched in that order for ``<language>/LC_MESSAGES/django.(po|mo)``
+      searched for ``<language>/LC_MESSAGES/django.(po|mo)``
     * ``$PYTHONPATH/django/conf/locale/<language>/LC_MESSAGES/django.(po|mo)``
 
 To create message files, you use the :djadmin:`django-admin.py makemessages <makemessages>`
@@ -50,11 +58,6 @@
 to make the compiler process all the directories in your :setting:`LOCALE_PATHS`
 setting.
 
-Application message files are a bit complicated to discover -- they need the
-:class:`~django.middleware.locale.LocaleMiddleware`. If you don't use the
-middleware, only the Django message files and project message files will be
-installed and available at runtime.
-
 Finally, you should give some thought to the structure of your translation
 files. If your applications need to be delivered to other users and will
 be used in other projects, you might want to use app-specific translations.
diff --git a/docs/topics/i18n/deployment.txt b/docs/topics/i18n/deployment.txt
--- a/docs/topics/i18n/deployment.txt
+++ b/docs/topics/i18n/deployment.txt
@@ -171,16 +171,23 @@
 How Django discovers translations
 ---------------------------------
 
-As described in :ref:`using-translations-in-your-own-projects`,
-at runtime, Django looks for translations by following this algorithm:
+As described in :ref:`using-translations-in-your-own-projects`, Django looks for
+translations by following this algorithm regarding the order in which it
+examines the different file paths to load the compiled :term:`message files
+<message file>` (``.mo``) and the precedence of multiple translations for the
+same literal:
 
-    * First, it looks for a ``locale`` directory in the directory containing
-      your settings file.
-    * Second, it looks for a ``locale`` directory in the project directory.
-    * Third, it looks for a ``locale`` directory in each of the installed apps.
-      It does this in the reverse order of INSTALLED_APPS
-    * Finally, it checks the Django-provided base translation in
-      ``django/conf/locale``.
+    * The directories listed in :setting:`LOCALE_PATHS` have the highest
+      precedence, with the ones appearing first having higher precedence than
+      the ones appearing later.
+    * Then, it looks for and uses if it exists a ``locale`` directory in each
+      of the installed apps listed in :setting:`INSTALLED_APPS`.
+      The ones appearing first have higher precedence than the ones appearing
+      later.
+    * Then, it looks for a ``locale`` directory in the project directory, or
+      more accurately, in the directory containing your settings file.
+    * Finally, the Django-provided base translation in ``django/conf/locale``
+      is used as a fallback.
 
 In all cases the name of the directory containing the translation is expected to
 be named using :term:`locale name` notation. E.g. ``de``, ``pt_BR``, ``es_AR``,
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

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/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
+++ b/tests/regressiontests/i18n/other/locale/de/LC_MESSAGES/django.po
@@ -8,7 +8,7 @@
 "Project-Id-Version: django tests\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2010-02-14 17:33+0100\n"
-"PO-Revision-Date: 2011-01-16 17:14+0100\n"
+"PO-Revision-Date: 2011-01-21 21:37-0300\n"
 "Last-Translator: Jannis Leidel <jannis@leidel.info>\n"
 "Language-Team: de <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -18,22 +18,25 @@
 
 #: models.py:3
 msgid "Time"
-msgstr "Time (LOCALE_PATHS)"
+msgstr "Zeit (LOCALE_PATHS)"
 
 #: models.py:5
+msgid "Date/time"
+msgstr "Datum/Zeit (LOCALE_PATHS)"
+
+#: models.py:7
 msgctxt "month name"
 msgid "May"
 msgstr "Mai"
 
-#: models.py:7
+#: models.py:9
 msgctxt "verb"
 msgid "May"
 msgstr "Kann"
 
-#: models.py:9
+#: models.py:11
 msgctxt "search"
 msgid "%d result"
 msgid_plural "%d results"
 msgstr[0] "%d Resultat"
 msgstr[1] "%d Resultate"
-
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

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/tests/regressiontests/i18n/resolution/locale/de/LC_MESSAGES/django.po
+++ b/tests/regressiontests/i18n/resolution/locale/de/LC_MESSAGES/django.po
@@ -9,7 +9,7 @@
 "Project-Id-Version: PACKAGE VERSION\n"
 "Report-Msgid-Bugs-To: \n"
 "POT-Creation-Date: 2010-02-14 17:33+0100\n"
-"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
+"PO-Revision-Date: 2011-01-21 21:37-0300\n"
 "Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
 "Language-Team: LANGUAGE <LL@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -18,5 +18,9 @@
 "Plural-Forms: nplurals=2; plural=(n != 1)\n"
 
 #: models.py:3
+msgid "Time"
+msgstr "Zeit (APP)"
+
+#: models.py:5
 msgid "Date/time"
 msgstr "Datum/Zeit (APP)"
diff --git a/tests/regressiontests/i18n/tests.py b/tests/regressiontests/i18n/tests.py
--- a/tests/regressiontests/i18n/tests.py
+++ b/tests/regressiontests/i18n/tests.py
@@ -660,14 +660,14 @@
 
     def assertUgettext(self, msgid, msgstr):
         result = ugettext(msgid)
-        self.assert_(msgstr in result, ("The string '%s' isn't in the "
+        self.assertTrue(msgstr in result, ("The string '%s' isn't in the "
             "translation of '%s'; the actual result is '%s'." % (msgstr, msgid, result)))
 
 class AppResolutionOrderI18NTests(ResolutionOrderI18NTests):
 
     def setUp(self):
         self.old_installed_apps = settings.INSTALLED_APPS
-        settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) + ['regressiontests.i18n.resolution']
+        settings.INSTALLED_APPS = ['regressiontests.i18n.resolution'] + list(settings.INSTALLED_APPS)
         super(AppResolutionOrderI18NTests, self).setUp()
 
     def tearDown(self):
@@ -691,6 +691,22 @@
     def test_locale_paths_translation(self):
         self.assertUgettext('Time', 'LOCALE_PATHS')
 
+    def test_locale_paths_override_app_translation(self):
+        old_installed_apps = settings.INSTALLED_APPS
+        settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) + ['regressiontests.i18n.resolution']
+        try:
+            self.assertUgettext('Time', 'LOCALE_PATHS')
+        finally:
+            settings.INSTALLED_APPS = old_installed_apps
+
+    def test_locale_paths_override_project_translation(self):
+        old_settings_module = settings.SETTINGS_MODULE
+        settings.SETTINGS_MODULE = 'regressiontests'
+        try:
+            self.assertUgettext('Date/time', 'LOCALE_PATHS')
+        finally:
+            settings.SETTINGS_MODULE = old_settings_module
+
 class ProjectResolutionOrderI18NTests(ResolutionOrderI18NTests):
 
     def setUp(self):
@@ -708,19 +724,15 @@
     def test_project_override_app_translation(self):
         old_installed_apps = settings.INSTALLED_APPS
         settings.INSTALLED_APPS = list(settings.INSTALLED_APPS) + ['regressiontests.i18n.resolution']
-        self.assertUgettext('Date/time', 'PROJECT')
-        settings.INSTALLED_APPS = old_installed_apps
-
-    def test_project_override_locale_paths_translation(self):
-        old_locale_paths = settings.LOCALE_PATHS
-        settings.LOCALE_PATHS += (os.path.join(os.path.dirname(os.path.abspath(__file__)), 'other', 'locale'),)
-        self.assertUgettext('Date/time', 'PROJECT')
-        settings.LOCALE_PATHS = old_locale_paths
+        try:
+            self.assertUgettext('Date/time', 'PROJECT')
+        finally:
+            settings.INSTALLED_APPS = old_installed_apps
 
 class DjangoFallbackResolutionOrderI18NTests(ResolutionOrderI18NTests):
 
     def test_django_fallback(self):
-        self.assertUgettext('Date/time', 'Datum/Zeit')
+        self.assertEqual(ugettext('Date/time'), 'Datum/Zeit')
 
 
 class TestModels(TestCase):
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

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