Skip to content
1 change: 1 addition & 0 deletions springboard/defaults.ini
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ jinja2.filters =
format_date = springboard.filters:format_date_filter
thumbor = springboard.filters:thumbor_filter
markdown = springboard.filters:markdown_filter
display_language_name = springboard.filters:display_language_name_filter

unicorehub.host =
unicorehub.app_id =
Expand Down
10 changes: 10 additions & 0 deletions springboard/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@

from pyramid.threadlocal import get_current_registry

from babel import Locale
from pycountry import languages


@contextfilter
def format_date_filter(ctx, timestamp, format):
Expand All @@ -32,3 +35,10 @@ def markdown_filter(ctx, content):
if not content:
return content
return markdown(content)


@contextfilter
def display_language_name_filter(ctx, locale):
language_code, _, country_code = locale.partition('_')
term_code = languages.get(bibliographic=language_code).terminology
return Locale.parse(term_code).language_name
7 changes: 5 additions & 2 deletions springboard/templates/base.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,12 @@
<div id="header">
<div class="lang">
<div>
{% for lang_code, lang_name in display_languages %}
<li>
<a href="{{'locale_matched'|route_url(language=lang_code)"}}>{{lang_name}}</a>
<a>{{language|display_language_name}}</a>
</li>
{% for lang_code in display_languages %}
<li>
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We probably want to skip lang_code here if it's the same as language because otherwise we'd potentially get it twice.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's taken care of here https://github.com/universalcore/springboard/blob/feature/issue-21-add-locale-change/springboard/views.py#L55 in order to avoid duplication, but I'll put a check in the template, just to be sure

<a href="{{'locale_matched'|route_url(language=lang_code)}}">{{lang_code|display_language_name}}</a>
</li>
{% endfor %}
<li><a href="{{'locale_change'|route_url}}">&gt;&gt;</a></li>
Expand Down
4 changes: 2 additions & 2 deletions springboard/templates/locale_change.jinja2
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@
{% block content %}

<ul>
{% for lang_code, lang_name in view.get_available_languages() %}
{% for lang_code in available_languages %}
<li>
<a href="{{'locale_matched'|route_url(language=lang_code) }}">{{lang_name}}</a>
<a href="{{'locale_matched'|route_url(language=lang_code) }}">{{lang_code|display_language_name}}</a>
</li>
{% endfor %}
</ul>
Expand Down
36 changes: 9 additions & 27 deletions springboard/tests/test_language.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
from springboard.tests import SpringboardTestCase
from springboard.views import SpringboardViews

from pyramid import testing

Expand All @@ -8,16 +7,18 @@ class TestLanguages(SpringboardTestCase):

def setUp(self):
self.workspace = self.mk_workspace()

languages = ("[('eng_GB', 'English'), ('swa_KE', 'Swahili'),"
"('fre_FR', 'French'), ('spa_ES', 'Spanish')]")
featured_langs = "[('spa_ES', 'Spanish'), ('eng_GB', 'English')]"

settings = {
'unicore.repos_dir': self.working_dir,
'unicore.content_repo_urls': self.workspace.working_dir,
'available_languages': languages,
'featured_languages': featured_langs
'available_languages': '\n'.join([
'eng_GB',
'swa_KE',
'spa_ES',
]),
'featured_languages': '\n'.join([
'spa_ES',
'eng_GB',
])
}
self.config = testing.setUp(settings=settings)
self.app = self.mk_app(self.workspace, settings=settings)
Expand Down Expand Up @@ -51,7 +52,6 @@ def test_locale_cookie(self):

def test_change_locale_page(self):
resp = self.app.get('/locale/change/')
print resp.body
self.assertTrue(
u'<a href="http://localhost/locale/spa_ES/">espa\xf1ol</a>'
in resp.body.decode('utf-8'))
Expand All @@ -61,21 +61,3 @@ def test_change_locale_page(self):
self.assertTrue(
u'<a href="http://localhost/locale/swa_KE/">Kiswahili</a>'
in resp.body.decode('utf-8'))

def test_locales_displayed(self):
view = SpringboardViews(self.mk_request())
langs = view.get_display_languages()
self.assertEqual(
langs, [('eng_GB', 'English'), ('spa_ES', u'espa\xf1ol')])

view = SpringboardViews(self.mk_request(locale_name='fre_FR'))
langs = view.get_display_languages()
self.assertEqual(
langs,
[('fre_FR', u'fran\xe7ais'), ('eng_GB', 'English'),
('spa_ES', u'espa\xf1ol')])

view = SpringboardViews(self.mk_request(locale_name='spa_ES'))
langs = view.get_display_languages()
self.assertEqual(
langs, [('spa_ES', u'espa\xf1ol'), ('eng_GB', 'English')])
14 changes: 7 additions & 7 deletions springboard/tests/test_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,15 @@ def test_config_list(self):
self.assertEqual(['1', '2', '3'], config_list('1\n2\n3\n'))
self.assertEqual([], config_list(''))

def tst_config_dict(self):
def test_config_dict(self):
self.assertEqual({
'a': '1',
'b': '2',
'c': '3',
}, 'a=1\nb=2\nc=3')
}, config_dict('a=1\nb=2\nc=3'))
self.assertEqual({
'a': '1',
'b': '2',
'c': '3',
}, 'a=1\nb=2\nc=3\n')
self.assertEqual({}, '')
'foo': 'bar',
'gum': 'tree',
'elastic': 'search',
}, config_dict('foo=bar\ngum=tree\nelastic=search\n'))
self.assertEqual({}, config_dict(''))
3 changes: 2 additions & 1 deletion springboard/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,8 @@ def test_index_view(self):
context = views.index_view()
self.assertEqual(set(context.keys()),
set(['user', 'language', 'all_categories',
'all_pages']))
'all_pages', 'featured_languages',
'available_languages', 'display_languages']))

def test_category(self):
[category] = self.mk_categories(self.workspace, count=1)
Expand Down
25 changes: 25 additions & 0 deletions springboard/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,9 +42,34 @@ def wrapper(self, *args, **kwargs):


def config_list(data):
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Someone should shout at me for not having added docstrings.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

<3 nice.

"""
A function that takes a string of values separated by newline characters
and returns a list of those values

:param func context_func:
A function which takes one argument, a string of values separated by
newline characters

:returns:
A list containing the values separated by newline characters,
stripped of whitespace between the value and newline character

"""
return filter(None, (x.strip() for x in data.splitlines()))


def config_dict(data):
"""
A function that takes a string of pair values, indicated by '=', separated
by newline characters and returns a dict of those value pairs

:param func context_func:
A function which takes one argument, a string of value pairs with
'= between them' separated by newline characters

:returns:
A dict containing the value pairs separated by newline characters

"""
lines = config_list(data)
return dict(re.split('\s*=\s*', value) for value in lines)
66 changes: 17 additions & 49 deletions springboard/views.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,22 @@
import os

from babel import Locale
from pycountry import languages

from ast import literal_eval

from elasticgit.search import SM

from pyramid.view import view_config
from pyramid.view import notfound_view_config
from pyramid.httpexceptions import HTTPFound
from pyramid.response import Response

from springboard.utils import parse_repo_name, ga_context
from springboard.utils import (
parse_repo_name, ga_context, config_list)

from unicore.content.models import Category, Page
from unicore.distribute.tasks import fastforward

from slugify import slugify

ONE_YEAR = 31536000


class SpringboardViews(object):

Expand All @@ -34,7 +32,7 @@ def __init__(self, request):
repo_dir = self.settings.get('unicore.repos_dir', 'repos')
repo_names = map(
lambda repo_url: parse_repo_name(repo_url),
self.settings['unicore.content_repo_urls'].strip().split('\n'))
config_list(self.settings['unicore.content_repo_urls']))
self.all_repo_paths = map(
lambda repo_name: os.path.join(repo_dir, repo_name),
repo_names)
Expand All @@ -49,10 +47,19 @@ def __init__(self, request):
self.all_categories = SM(Category, **search_config).es(
**self.es_settings)
self.all_pages = SM(Page, **search_config).es(**self.es_settings)
self.available_languages = config_list(
self.settings.get('available_languages', ''))
self.featured_languages = config_list(
self.settings.get('featured_languages', ''))
self.display_languages = list(
set(self.featured_languages) - set([self.language]))

def context(self, **context):
defaults = {
'user': self.request.user,
'available_languages': self.available_languages,
'featured_languages': self.featured_languages,
'display_languages': self.display_languages,
'language': self.language,
'all_categories': self.all_categories,
'all_pages': self.all_pages,
Expand Down Expand Up @@ -101,18 +108,13 @@ def api_notify(self):
@notfound_view_config(renderer='springboard:templates/404.jinja2')
def notfound(self):
self.request.response.status = 404
return {}
return self.context()

@view_config(
route_name='locale_change',
renderer='springboard:templates/locale_change.jinja2')
def locale_change(self):
return self.context(
languages=(
self.get_featured_languages() +
sorted(list(set(self.get_available_languages()) -
set(self.get_featured_languages())),
key=lambda tup: tup[1].lower())))
return self.context()

@view_config(route_name='locale')
@view_config(route_name='locale_matched')
Expand All @@ -122,40 +124,6 @@ def set_locale_cookie(self):
self.request.GET.get('language')

if language:
response.set_cookie('_LOCALE_', value=language, max_age=31536000)
response.set_cookie('_LOCALE_', value=language, max_age=ONE_YEAR)

return HTTPFound(location='/', headers=response.headers)

def get_available_languages(self):
available_languages = sorted(literal_eval(
(self.settings.get('available_languages', '[]'))),
key=lambda tup: tup[1].lower())
return [
(code, self.get_display_name(code))
for code, name in available_languages]

def get_featured_languages(self):
featured_languages = sorted(literal_eval(
(self.settings.get('featured_languages', '[]'))),
key=lambda tup: tup[1].lower())
return [
(code, self.get_display_name(code))
for code, name in featured_languages]

def get_display_name(self, locale):
language_code, _, country_code = locale.partition('_')
term_code = languages.get(bibliographic=language_code).terminology
return Locale.parse(term_code).language_name

def get_display_languages(self):
to_display = [
code for code, name in
self.get_featured_languages() or self.get_available_languages()[:2]
]

featured_and_current = [self.language] + sorted(list(
set(to_display) - set([self.language])),
key=lambda tup: tup[1].lower())
return [
(code, self.get_display_name(code))
for code in featured_and_current]