From 0172ff315ae167c5bd943d5d9a413dd4e56ad9e5 Mon Sep 17 00:00:00 2001
From: Anthony Mangano <amangano@edx.org>
Date: Tue, 16 May 2017 15:06:33 -0400
Subject: [PATCH] add ability to show footer language selector on LMS

---
 cms/envs/bok_choy.env.json                    |  2 +-
 cms/envs/common.py                            |  4 +-
 cms/templates/widgets/header.html             |  5 ++-
 .../templates/static_content.html             |  9 ----
 lms/envs/bok_choy.env.json                    |  2 +-
 lms/envs/common.py                            |  7 +++-
 lms/envs/devstack_docker.py                   |  2 +-
 lms/templates/footer.html                     |  5 ++-
 lms/templates/navigation.html                 |  5 ++-
 .../widgets/footer-language-selector.html     |  7 +++-
 openedx/core/djangoapps/lang_pref/api.py      | 17 ++++++++
 .../djangoapps/lang_pref/tests/test_api.py    | 42 ++++++++++++++++++-
 themes/edx.org/lms/templates/footer.html      |  5 ++-
 themes/red-theme/lms/templates/footer.html    |  5 ++-
 .../stanford-style/lms/templates/footer.html  | 10 ++---
 15 files changed, 93 insertions(+), 34 deletions(-)

diff --git a/cms/envs/bok_choy.env.json b/cms/envs/bok_choy.env.json
index b858d700775..eb613edafc0 100644
--- a/cms/envs/bok_choy.env.json
+++ b/cms/envs/bok_choy.env.json
@@ -75,7 +75,7 @@
         "PREVIEW_LMS_BASE": "preview.localhost:8003",
         "ENABLE_CONTENT_LIBRARIES": true,
         "ENABLE_SPECIAL_EXAMS": true,
-        "SHOW_LANGUAGE_SELECTOR": true,
+        "SHOW_HEADER_LANGUAGE_SELECTOR": true,
         "ENABLE_EXTENDED_COURSE_DETAILS": true,
         "CUSTOM_COURSES_EDX": true
     },
diff --git a/cms/envs/common.py b/cms/envs/common.py
index e8579c8f3aa..cef002da59c 100644
--- a/cms/envs/common.py
+++ b/cms/envs/common.py
@@ -227,8 +227,8 @@ FEATURES = {
 
     'ORGANIZATIONS_APP': False,
 
-    # Show Language selector
-    'SHOW_LANGUAGE_SELECTOR': False,
+    # Show the language selector in the header
+    'SHOW_HEADER_LANGUAGE_SELECTOR': False,
 
     # Set this to False to facilitate cleaning up invalid xml from your modulestore.
     'ENABLE_XBLOCK_XML_VALIDATION': True,
diff --git a/cms/templates/widgets/header.html b/cms/templates/widgets/header.html
index 595e2179348..7e4439f617e 100644
--- a/cms/templates/widgets/header.html
+++ b/cms/templates/widgets/header.html
@@ -4,6 +4,7 @@
   from django.conf import settings
   from django.core.urlresolvers import reverse
   from django.utils.translation import ugettext as _
+  from openedx.core.djangoapps.lang_pref.api import header_language_selector_is_enabled, released_languages
 %>
 <div class="wrapper-header wrapper" id="view-top">
   <header class="primary" role="banner">
@@ -183,8 +184,8 @@
     </div>
 
     <div class="wrapper wrapper-r">
-      % if static.show_language_selector():
-        <% languages = static.get_released_languages() %>
+      % if header_language_selector_is_enabled():
+        <% languages = released_languages() %>
         % if len(languages) > 1:
         <nav class="user-language-selector" aria-label="${_('Language preference')}">
           <form action="/i18n/setlang/" method="post" class="settings-language-form" id="language-settings-form">
diff --git a/common/djangoapps/pipeline_mako/templates/static_content.html b/common/djangoapps/pipeline_mako/templates/static_content.html
index 69a45d9dcd9..1af6ee8a140 100644
--- a/common/djangoapps/pipeline_mako/templates/static_content.html
+++ b/common/djangoapps/pipeline_mako/templates/static_content.html
@@ -18,7 +18,6 @@ from openedx.core.djangoapps.theming.helpers import (
   is_request_in_themed_site,
 )
 from certificates.api import get_asset_url_by_slug
-from openedx.core.djangoapps.lang_pref.api import released_languages
 logger = logging.getLogger(__name__)
 %>
 
@@ -194,11 +193,3 @@ else:
 <%def name="get_tech_support_email_address()"><%
     return get_value('email_from_address', settings.TECH_SUPPORT_EMAIL)
 %></%def>
-
-<%def name="show_language_selector()"><%
-    return get_value('SHOW_LANGUAGE_SELECTOR', settings.FEATURES.get('SHOW_LANGUAGE_SELECTOR', False))
-%></%def>
-
-<%def name="get_released_languages()"><%
-    return released_languages()
-%></%def>
diff --git a/lms/envs/bok_choy.env.json b/lms/envs/bok_choy.env.json
index 924ed69f714..2abdf5dc683 100644
--- a/lms/envs/bok_choy.env.json
+++ b/lms/envs/bok_choy.env.json
@@ -88,7 +88,7 @@
         "AUTOMATIC_VERIFY_STUDENT_IDENTITY_FOR_TESTING": true,
         "ENABLE_COURSE_DISCOVERY": true,
         "ENABLE_SPECIAL_EXAMS": true,
-        "SHOW_LANGUAGE_SELECTOR": true,
+        "SHOW_HEADER_LANGUAGE_SELECTOR": true,
         "CUSTOM_COURSES_EDX": true
     },
     "FEEDBACK_SUBMISSION_EMAIL": "",
diff --git a/lms/envs/common.py b/lms/envs/common.py
index a67449c721a..db159c9f8e5 100644
--- a/lms/envs/common.py
+++ b/lms/envs/common.py
@@ -345,8 +345,11 @@ FEATURES = {
     # Enable LTI Provider feature.
     'ENABLE_LTI_PROVIDER': False,
 
-    # Show Language selector.
-    'SHOW_LANGUAGE_SELECTOR': False,
+    # Show the language selector in the header
+    'SHOW_HEADER_LANGUAGE_SELECTOR': False,
+
+    # Show the language selector in the footer
+    'SHOW_FOOTER_LANGUAGE_SELECTOR': False,
 
     # Write new CSM history to the extended table.
     # This will eventually default to True and may be
diff --git a/lms/envs/devstack_docker.py b/lms/envs/devstack_docker.py
index e4c8731ec5a..3973f22a1c7 100644
--- a/lms/envs/devstack_docker.py
+++ b/lms/envs/devstack_docker.py
@@ -30,8 +30,8 @@ FEATURES.update({
     'ENABLE_COURSEWARE_SEARCH': False,
     'ENABLE_COURSE_DISCOVERY': False,
     'ENABLE_DASHBOARD_SEARCH': False,
-    'SHOW_LANGUAGE_SELECTOR': True,
     'ENABLE_DISCUSSION_SERVICE': False,
+    'SHOW_HEADER_LANGUAGE_SELECTOR': True
 })
 
 ENABLE_MKTG_SITE = os.environ.get('ENABLE_MARKETING_SITE', False)
diff --git a/lms/templates/footer.html b/lms/templates/footer.html
index 860d1d9d2a7..5b25ecb994c 100644
--- a/lms/templates/footer.html
+++ b/lms/templates/footer.html
@@ -4,6 +4,7 @@
   from django.core.urlresolvers import reverse
   from django.utils.translation import ugettext as _
   from branding.api import get_footer
+  from openedx.core.djangoapps.lang_pref.api import footer_language_selector_is_enabled
 %>
 <% footer = get_footer(is_secure=is_secure) %>
 <%namespace name='static' file='static_content.html'/>
@@ -28,8 +29,8 @@
         </ol>
       </nav>
 
-      % if include_language_selector:
-          <%include file="widgets/footer-language-selector.html"/>
+      % if context.get('include_language_selector', footer_language_selector_is_enabled()):
+          <%include file="${static.get_template_path('widgets/footer-language-selector.html')}"/>
       % endif
 
       <div class="wrapper-logo">
diff --git a/lms/templates/navigation.html b/lms/templates/navigation.html
index 5ca116a8c7a..90d6156c00a 100644
--- a/lms/templates/navigation.html
+++ b/lms/templates/navigation.html
@@ -14,6 +14,7 @@ from branding import api as branding_api
 # app that handles site status messages
 from status.status import get_site_status_msg
 from openedx.features.enterprise_support.api import get_enterprise_customer_logo_url
+from openedx.core.djangoapps.lang_pref.api import header_language_selector_is_enabled, released_languages
 %>
 
 ## Provide a hook for themes to inject branding on top.
@@ -176,8 +177,8 @@ site_status_msg = get_site_status_msg(course_id)
         </%block>
       </ol>
     % endif
-    % if static.show_language_selector():
-     <% languages = static.get_released_languages() %>
+    % if header_language_selector_is_enabled():
+     <% languages = released_languages() %>
       % if len(languages) > 1:
       <ol class="user">
         <li class="primary">
diff --git a/lms/templates/widgets/footer-language-selector.html b/lms/templates/widgets/footer-language-selector.html
index 4a8b44e5522..d18450ddbdf 100644
--- a/lms/templates/widgets/footer-language-selector.html
+++ b/lms/templates/widgets/footer-language-selector.html
@@ -15,6 +15,7 @@
   if not settings.LANGUAGE_COOKIE:
       raise ValueError('settings.LANGUAGE_COOKIE is required to use footer-language-selector.')
 %>
+<%namespace name='static' file='../static_content.html'/>
 
 <div class="footer-language-selector">
     <label for="footer-language-select">
@@ -53,8 +54,10 @@
 
         setLanguageCookie: function(value, callback) {
             var cookie = '${settings.LANGUAGE_COOKIE | n, js_escaped_string}=' + value + ';path=/';
-            % if settings.SESSION_COOKIE_DOMAIN:
-                cookie += ';domain=${settings.SESSION_COOKIE_DOMAIN | n, js_escaped_string}';
+
+            <% session_cookie_domain = static.get_value('SESSION_COOKIE_DOMAIN', settings.SESSION_COOKIE_DOMAIN) %>
+            % if session_cookie_domain:
+                cookie += ';domain=${session_cookie_domain | n, js_escaped_string}';
             % endif
             % if COOKIE_DURATION:
                 cookie += ';max-age=${COOKIE_DURATION | n, js_escaped_string}';
diff --git a/openedx/core/djangoapps/lang_pref/api.py b/openedx/core/djangoapps/lang_pref/api.py
index 499033c43ed..9ff43120657 100644
--- a/openedx/core/djangoapps/lang_pref/api.py
+++ b/openedx/core/djangoapps/lang_pref/api.py
@@ -5,7 +5,9 @@ from collections import namedtuple
 
 from django.conf import settings
 from django.utils.translation import ugettext as _
+
 from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
+from openedx.core.djangoapps.site_configuration.helpers import get_value
 
 
 # Named tuples can be referenced using object-like variable
@@ -14,6 +16,21 @@ from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
 Language = namedtuple('Language', 'code name')
 
 
+def header_language_selector_is_enabled():
+    """Return true if the header language selector has been enabled via settings or site-specific configuration."""
+    setting = get_value('SHOW_HEADER_LANGUAGE_SELECTOR', settings.FEATURES.get('SHOW_HEADER_LANGUAGE_SELECTOR', False))
+
+    # The SHOW_LANGUAGE_SELECTOR setting is deprecated, but might still be in use on some installations.
+    deprecated_setting = get_value('SHOW_LANGUAGE_SELECTOR', settings.FEATURES.get('SHOW_LANGUAGE_SELECTOR', False))
+
+    return setting or deprecated_setting
+
+
+def footer_language_selector_is_enabled():
+    """Return true if the footer language selector has been enabled via settings or site-specific configuration."""
+    return get_value('SHOW_FOOTER_LANGUAGE_SELECTOR', settings.FEATURES.get('SHOW_FOOTER_LANGUAGE_SELECTOR', False))
+
+
 def released_languages():
     """Retrieve the list of released languages.
 
diff --git a/openedx/core/djangoapps/lang_pref/tests/test_api.py b/openedx/core/djangoapps/lang_pref/tests/test_api.py
index cc5826e2b58..ca8e9b9a8cf 100644
--- a/openedx/core/djangoapps/lang_pref/tests/test_api.py
+++ b/openedx/core/djangoapps/lang_pref/tests/test_api.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 """ Tests for the language API. """
 
+from mock import patch
 from django.test import TestCase
 from django.test.utils import override_settings
 from django.utils import translation
@@ -8,8 +9,8 @@ from django.contrib.auth.models import User
 import ddt
 
 from openedx.core.djangoapps.dark_lang.models import DarkLangConfig
-
 from openedx.core.djangoapps.lang_pref import api as language_api
+from openedx.core.djangoapps.site_configuration.tests.test_util import with_site_configuration_context
 
 EN = language_api.Language('en', 'English')
 ES_419 = language_api.Language('es-419', u'Español (Latinoamérica)')
@@ -20,6 +21,45 @@ class LanguageApiTest(TestCase):
     """
     Tests of the language APIs.
     """
+
+    @ddt.data(
+        # Should return the base config value
+        ({'SHOW_HEADER_LANGUAGE_SELECTOR': True}, {}, True),
+
+        # Should return the site config value
+        ({'SHOW_HEADER_LANGUAGE_SELECTOR': False}, {'SHOW_HEADER_LANGUAGE_SELECTOR': True}, True),
+        ({'SHOW_HEADER_LANGUAGE_SELECTOR': True}, {'SHOW_HEADER_LANGUAGE_SELECTOR': False}, False),
+
+        # SHOW_LANGUAGE_SELECTOR should supercede SHOW_HEADER_LANGUAGE_SELECTOR when true
+        ({'SHOW_HEADER_LANGUAGE_SELECTOR': False, 'SHOW_LANGUAGE_SELECTOR': True}, {}, True),
+        ({'SHOW_HEADER_LANGUAGE_SELECTOR': False}, {'SHOW_LANGUAGE_SELECTOR': True}, True)
+    )
+    @ddt.unpack
+    def test_header_language_selector_is_enabled(self, base_config, site_config, expected):
+        """
+        Verify that the header language selector config is correct.
+        """
+        with patch.dict('django.conf.settings.FEATURES', base_config):
+            with with_site_configuration_context(configuration=site_config):
+                self.assertEqual(language_api.header_language_selector_is_enabled(), expected)
+
+    @ddt.data(
+        # Should return the base config value
+        ({'SHOW_FOOTER_LANGUAGE_SELECTOR': True}, {}, True),
+
+        # Should return the site config value
+        ({'SHOW_FOOTER_LANGUAGE_SELECTOR': False}, {'SHOW_FOOTER_LANGUAGE_SELECTOR': True}, True),
+        ({'SHOW_FOOTER_LANGUAGE_SELECTOR': True}, {'SHOW_FOOTER_LANGUAGE_SELECTOR': False}, False)
+    )
+    @ddt.unpack
+    def test_footer_language_selector_is_enabled(self, base_config, site_config, expected):
+        """
+        Verify that the footer language selector config is correct.
+        """
+        with patch.dict('django.conf.settings.FEATURES', base_config):
+            with with_site_configuration_context(configuration=site_config):
+                self.assertEqual(language_api.footer_language_selector_is_enabled(), expected)
+
     @ddt.data(*[
         ('en', [], [], []),
         ('en', [EN], [], [EN]),
diff --git a/themes/edx.org/lms/templates/footer.html b/themes/edx.org/lms/templates/footer.html
index a991e193375..12751fbb31a 100644
--- a/themes/edx.org/lms/templates/footer.html
+++ b/themes/edx.org/lms/templates/footer.html
@@ -4,6 +4,7 @@
 
   from django.utils.translation import ugettext as _
   from branding.api import get_footer
+  from openedx.core.djangoapps.lang_pref.api import footer_language_selector_is_enabled
 %>
 <% footer = get_footer(is_secure=is_secure) %>
 <%namespace name='static' file='static_content.html'/>
@@ -45,8 +46,8 @@
             </ul>
           </nav>
 
-          % if include_language_selector:
-              <%include file="widgets/footer-language-selector.html"/>
+          % if context.get('include_language_selector', footer_language_selector_is_enabled()):
+              <%include file="${static.get_template_path('widgets/footer-language-selector.html')}"/>
           % endif
 
           <p class="copyright">${_(
diff --git a/themes/red-theme/lms/templates/footer.html b/themes/red-theme/lms/templates/footer.html
index 1046b37254e..cb48e10c32c 100755
--- a/themes/red-theme/lms/templates/footer.html
+++ b/themes/red-theme/lms/templates/footer.html
@@ -3,6 +3,7 @@
 <%!
 from django.core.urlresolvers import reverse
 from django.utils.translation import ugettext as _
+from openedx.core.djangoapps.lang_pref.api import footer_language_selector_is_enabled
 %>
 
 <div class="wrapper wrapper-footer">
@@ -43,8 +44,8 @@ from django.utils.translation import ugettext as _
       </ol>
       </nav>
 
-      % if include_language_selector:
-          <%include file='widgets/footer-language-selector.html'/>
+      % if context.get('include_language_selector', footer_language_selector_is_enabled()):
+          <%include file="${static.get_template_path('widgets/footer-language-selector.html')}"/>
       % endif
 
       <div class="wrapper-logo">
diff --git a/themes/stanford-style/lms/templates/footer.html b/themes/stanford-style/lms/templates/footer.html
index af226997181..15faea08121 100644
--- a/themes/stanford-style/lms/templates/footer.html
+++ b/themes/stanford-style/lms/templates/footer.html
@@ -1,11 +1,11 @@
 ## mako
 <%!
+  from datetime import date
   from django.core.urlresolvers import reverse
   from django.utils.translation import ugettext as _
+  from openedx.core.djangoapps.lang_pref.api import footer_language_selector_is_enabled
 %>
-<%!
-  from datetime import date
-%>
+<%namespace name='static' file='static_content.html'/>
 <!-- footer overrides for stanford theme go here -->
 <div class="wrapper-footer">
   <footer>
@@ -22,8 +22,8 @@
         </ol>
       </nav>
 
-      % if include_language_selector:
-          <%include file='widgets/footer-language-selector.html'/>
+      % if context.get('include_language_selector', footer_language_selector_is_enabled()):
+          <%include file="${static.get_template_path('widgets/footer-language-selector.html')}"/>
       % endif
 
     </div>
-- 
GitLab