Repository: django-cms/django-cms

Issue:
i18n redirect_on_fallback=False and public=False bug
the combination of `redirect_on_fallback=False` with `public=False` creates undesired results.

``` python
LANGUAGE_CODE='de'
CMS_LANGUAGES = {
    1: [
        {
            'code': 'de',
            'name': _('German'),
        },
        {
            'code': 'en',
            'name': _('English'),
            'public': False,
        },
    ],
    'default': {
        'fallbacks': ['en', 'de'],
        'redirect_on_fallback': True,
        'hide_untranslated': False,
        'public': True,
    }
}
```

With the above settings, if you have a navigate to `/en/` (or have language cookie set to 'en' or your default browser language is 'en') as an anonymous/non-staff user, you'll see a page without content.

Expected would be either a redirect to the default language or a 404 (redirect would be more practical).



Discussion:

Resolving patch:
diff --git a/cms/views.py b/cms/views.py
--- a/cms/views.py
+++ b/cms/views.py
@@ -95,7 +95,7 @@ def details(request, slug):
         found = False
         for alt_lang in get_fallback_languages(current_language):
             if alt_lang in available_languages:
-                if get_redirect_on_fallback(current_language):
+                if get_redirect_on_fallback(current_language) or slug == "":
                     with force_language(alt_lang):
                         path = page.get_absolute_url(language=alt_lang, fallback=True)
                         # In the case where the page is not available in the


Test patch:
diff --git a/cms/tests/i18n.py b/cms/tests/i18n.py
--- a/cms/tests/i18n.py
+++ b/cms/tests/i18n.py
@@ -1,3 +1,4 @@
+from cms import api
 from cms.test_utils.testcases import SettingsOverrideTestCase
 from cms.utils import i18n
 
@@ -270,3 +271,38 @@ def test_get_languages_undefined_site(self):
         for lang in result:
             self.assertEqual(lang['public'], True)
             self.assertEqual(lang['hide_untranslated'], False)
+
+
+class TestLanguageFallbacks(SettingsOverrideTestCase):
+
+    settings_overrides = {
+        'LANGUAGE_CODE': 'en',
+        'LANGUAGES': (('fr', 'French'),
+                      ('en', 'English'),
+                      ('de', 'German'),
+                      ('es', 'Spanish')),
+        'CMS_LANGUAGES': {
+            1: [ {'code' : 'en',
+                  'name': 'English',
+                  'public': False},
+                 {'code': 'fr',
+                  'name': 'French',
+                  'public': True},
+            ],
+            'default': {
+                'fallbacks': ['en', 'fr'],
+                'redirect_on_fallback': False,
+                'public': True,
+                'hide_untranslated': False,
+            }
+        },
+        'SITE_ID': 1,
+    }
+
+    def test_language_code(self):
+        home = api.create_page("home", "nav_playground.html", "fr", published=True)
+        response = self.client.get('/')
+        self.assertEqual(response.status_code, 302)
+        response = self.client.get('/en/')
+        self.assertEqual(response.status_code, 302)
+        self.assertRedirects(response, '/fr/')
\ No newline at end of file
diff --git a/cms/tests/multilingual.py b/cms/tests/multilingual.py
--- a/cms/tests/multilingual.py
+++ b/cms/tests/multilingual.py
@@ -259,7 +259,7 @@ def test_language_fallback(self):
         lang_settings[1][1]['redirect_on_fallback'] = False
         with SettingsOverride(CMS_LANGUAGES=lang_settings):
             response = self.client.get("/de/")
-            self.assertEquals(response.status_code, 200)
+            self.assertEquals(response.status_code, 302)
 
     def test_no_english_defined(self):
         with SettingsOverride(TEMPLATE_CONTEXT_PROCESSORS=[],