Repository: django-cms/django-cms

Issue:
CMSMenu uses "page_queryset.published(lang)" which hides untranslated page always
Hello,
 i think the "hide_untranslated" option set to False in CMS_LANGUAGES will not work (for me it does not)  because the  CMSMenu::get_nodes Method uses the ueryset.published(lang) with current language as parmater. So the queryset returned does not contain page translations which are flagged with in_navigation=True when fallback languages are configured and those translation exists.

https://github.com/divio/django-cms/blob/develop/cms/menu.py#L233-L234

``` python
        if not use_draft(request):
            page_queryset = page_queryset.published(lang)
```

and see https://github.com/divio/django-cms/blob/develop/cms/models/query.py#L48-L62

``` python
    def published(self, language=None, site=None):

        if language:
            pub = self.on_site(site).filter(
                Q(publication_date__lte=timezone.now()) | Q(publication_date__isnull=True),
                Q(publication_end_date__gt=timezone.now()) | Q(publication_end_date__isnull=True),
                title_set__published=True, title_set__language=language
            )
        else:
            pub = self.on_site(site).filter(
                Q(publication_date__lte=timezone.now()) | Q(publication_date__isnull=True),
                Q(publication_end_date__gt=timezone.now()) | Q(publication_end_date__isnull=True),
                title_set__published=True
            )
        return pub
```

So in case that hide_untranslated(lang, site.pk) returns False the CMSMenu should give language=None?

Thanks.

EDIT: Sorry forgot: Django-CMS 3.0.5 and Django 1.4.5



Discussion:

Resolving patch:
diff --git a/cms/menu.py b/cms/menu.py
--- a/cms/menu.py
+++ b/cms/menu.py
@@ -231,7 +231,7 @@ def get_nodes(self, request):
             filters['title_set__language'] = lang
 
         if not use_draft(request):
-            page_queryset = page_queryset.published(lang)
+            page_queryset = page_queryset.published()
         pages = page_queryset.filter(**filters).order_by("tree_id", "lft")
         ids = {}
         nodes = []


Test patch:
diff --git a/cms/tests/multilingual.py b/cms/tests/multilingual.py
--- a/cms/tests/multilingual.py
+++ b/cms/tests/multilingual.py
@@ -9,6 +9,7 @@
 from cms.api import create_page, create_title, publish_page, add_plugin
 from cms.exceptions import LanguageError
 from cms.forms.utils import update_site_and_page_choices
+from cms.menu import CMSMenu
 from cms.models import Title, EmptyTitle
 from cms.test_utils.testcases import (SettingsOverrideTestCase,
                                       URL_CMS_PAGE_CHANGE_LANGUAGE, URL_CMS_PAGE_PUBLISH)
@@ -142,6 +143,37 @@ def test_multilingual_page(self):
         self.assertEqual(placeholder.cmsplugin_set.filter(language=TESTLANG2).count(), 1)
         self.assertEqual(placeholder.cmsplugin_set.filter(language=TESTLANG).count(), 1)
 
+    def test_hide_untranslated(self):
+        TESTLANG = get_primary_lanaguage()
+        TESTLANG2 = get_secondary_lanaguage()
+        page = create_page("mlpage-%s" % TESTLANG, "nav_playground.html", TESTLANG)
+        create_title(TESTLANG2, "mlpage-%s" % TESTLANG2, page, slug=page.get_slug())
+        page2 = create_page("mlpage-2-%s" % TESTLANG, "nav_playground.html", TESTLANG, parent=page)
+        page.publish(TESTLANG)
+        page.publish(TESTLANG2)
+        page2.publish(TESTLANG)
+
+        menu = CMSMenu()
+        lang_settings = copy.deepcopy(get_cms_setting('LANGUAGES'))
+
+        request_1 = self.get_request('/%s/' % TESTLANG, TESTLANG)
+        request_2 = self.get_request('/%s/' % TESTLANG2, TESTLANG2)
+
+        lang_settings[1][1]['hide_untranslated'] = False
+        with SettingsOverride(CMS_LANGUAGES=lang_settings):
+            list_1 = [node.id for node in menu.get_nodes(request_1)]
+            list_2 = [node.id for node in menu.get_nodes(request_2)]
+            self.assertEqual(list_1, list_2)
+            self.assertEqual(len(list_1), 2)
+
+        lang_settings[1][1]['hide_untranslated'] = True
+        with SettingsOverride(CMS_LANGUAGES=lang_settings):
+            list_1 = [node.id for node in menu.get_nodes(request_1)]
+            list_2 = [node.id for node in menu.get_nodes(request_2)]
+            self.assertNotEqual(list_1, list_2)
+            self.assertEqual(len(list_2), 1)
+            self.assertEqual(len(list_1), 2)
+
     def test_frontend_lang(self):
         lang_settings = copy.deepcopy(get_cms_setting('LANGUAGES'))
         lang_settings[1][0]['public'] = False