Skip to content

Commit

Permalink
Localization and Banner Update (#517)
Browse files Browse the repository at this point in the history
* banner: add banner and localization improvements from ukwa branch:
- show 'view all captures' link if not live
- optional logo
- loc options, if available
- banner options set via window.banner_info in banner.html

localization support: 
- add init_loc() to templateview
- loc available if config options set
- tests: add tests for loading localized messages, override .gitignore to allow test messages.mo
  • Loading branch information
ikreymer authored Nov 11, 2019
1 parent 66ac3ca commit 0d819aa
Show file tree
Hide file tree
Showing 14 changed files with 457 additions and 37 deletions.
13 changes: 12 additions & 1 deletion pywb/apps/frontendapp.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from gevent.monkey import patch_all; patch_all()

from werkzeug.routing import Map, Rule, RequestRedirect
from werkzeug.routing import Map, Rule, RequestRedirect, Submount
from werkzeug.wsgi import pop_path_info
from six.moves.urllib.parse import urljoin
from six import iteritems
Expand Down Expand Up @@ -138,6 +138,17 @@ def _init_coll_routes(self, coll_prefix):
:rtype: None
"""
routes = self._make_coll_routes(coll_prefix)

# init loc routes, if any
loc_keys = list(self.rewriterapp.loc_map.keys())
if loc_keys:
routes.append(Rule('/', endpoint=self.serve_home))

submount_route = ', '.join(loc_keys)
submount_route = '/<any({0}):lang>'.format(submount_route)

self.url_map.add(Submount(submount_route, routes))

for route in routes:
self.url_map.add(route)

Expand Down
5 changes: 5 additions & 0 deletions pywb/apps/rewriterapp.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,11 @@ def __init__(self, framed_replay=False, jinja_env=None, config=None, paths=None)
jinja_env.jinja_env.install_null_translations()

self.jinja_env = jinja_env
self.loc_map = {}

self.jinja_env.init_loc(self.config.get('locales_root_dir'),
self.config.get('locales'),
self.loc_map)

self.redirect_to_exact = config.get('redirect_to_exact')

Expand Down
90 changes: 88 additions & 2 deletions pywb/rewrite/templateview.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@

from pywb.utils.loaders import load

from six.moves.urllib.parse import urlsplit
from six.moves.urllib.parse import urlsplit, quote

from jinja2 import Environment, TemplateNotFound
from jinja2 import Environment, TemplateNotFound, contextfunction
from jinja2 import FileSystemLoader, PackageLoader, ChoiceLoader

from babel.support import Translations

from webassets.ext.jinja2 import AssetsExtension
from webassets.loaders import YAMLLoader
from webassets.env import Resolver
Expand Down Expand Up @@ -115,6 +117,90 @@ def _make_loaders(self, paths, packages):

return loaders

def init_loc(self, locales_root_dir, locales, loc_map):
locales = locales or []

if locales_root_dir:
for loc in locales:
loc_map[loc] = Translations.load(locales_root_dir, [loc, 'en'])
#jinja_env.jinja_env.install_gettext_translations(translations)

def get_translate(context):
loc = context.get('env', {}).get('pywb_lang')
return loc_map.get(loc)

def override_func(jinja_env, name):
@contextfunction
def get_override(context, text):
translate = get_translate(context)
if not translate:
return text

func = getattr(translate, name)
return func(text)

jinja_env.globals[name] = get_override

# standard gettext() translation function
override_func(self.jinja_env, 'gettext')

# single/plural form translation function
override_func(self.jinja_env, 'ngettext')

# Special _Q() function to return %-encoded text, necessary for use
# with text in banner
@contextfunction
def quote_gettext(context, text):
translate = get_translate(context)
if not translate:
return text

text = translate.gettext(text)
return quote(text, safe='/: ')

self.jinja_env.globals['locales'] = list(loc_map.keys())
self.jinja_env.globals['_Q'] = quote_gettext

@contextfunction
def switch_locale(context, locale):
environ = context.get('env')
curr_loc = environ.get('pywb_lang', '')

request_uri = environ.get('REQUEST_URI', environ.get('PATH_INFO'))

if curr_loc:
return request_uri.replace(curr_loc, locale, 1)

app_prefix = environ.get('pywb.app_prefix', '')

if app_prefix and request_uri.startswith(app_prefix):
request_uri = request_uri.replace(app_prefix, '')

return app_prefix + '/' + locale + request_uri

@contextfunction
def get_locale_prefixes(context):
environ = context.get('env')
locale_prefixes = {}

orig_prefix = environ.get('pywb.app_prefix', '')
coll = environ.get('SCRIPT_NAME', '')

if orig_prefix:
coll = coll[len(orig_prefix):]

curr_loc = environ.get('pywb_lang', '')
if curr_loc:
coll = coll[len(curr_loc) + 1:]

for locale in loc_map.keys():
locale_prefixes[locale] = orig_prefix + '/' + locale + coll + '/'

return locale_prefixes

self.jinja_env.globals['switch_locale'] = switch_locale
self.jinja_env.globals['get_locale_prefixes'] = get_locale_prefixes

def template_filter(self, param=None):
"""Returns a decorator that adds the wrapped function to dictionary of template filters.
Expand Down
9 changes: 9 additions & 0 deletions pywb/static/calendar.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
162 changes: 146 additions & 16 deletions pywb/static/default_banner.css
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

#_wb_plain_banner, #_wb_frame_top_banner
#_wb_frame_top_banner
{
display: block !important;
top: 0px !important;
Expand All @@ -9,39 +9,137 @@
font-size: 18px !important;
background-color: #444 !important;
color: white !important;
text-align: center !important;
z-index: 2147483643 !important;
line-height: normal !important;
}

#title_or_url {
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
padding-right: 4px;
display: block;
}

#_wb_plain_banner
#title_or_url
{
position: absolute !important;
padding: 4px !important;
border: 1px solid !important;
display: block !important;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
max-width: 100%;
}

#_wb_frame_top_banner
{
position: absolute !important;
border: 0px;
height: 44px !important;

display: flex !important;
display: -webkit-box !important;
display: -moz-box !important;
display: -webkit-flex !important;
display: -ms-flexbox !important;

justify-content: space-between;
-webkit-box-pack: justify;
-moz-box-pack: justify;
-ms-flex-pack: justify;
align-items: center;
-webkit-box-align: center;
-moz-box-align: center;
-ms-flex-align: center;
}

#_wb_frame_top_banner ._wb_linked_logo
{
display: block;
height: 26px;
width: 71px;
margin-left: 15px;
flex-shrink: 0;
-webkit-flex-shrink: 1 0;
-moz-flex-shrink: 1 0;
-ms-flex: 0 0 71px;
}

#_wb_frame_top_banner ._wb_linked_logo img
{
width: auto;
height: 100%;
border: none;
}

#_wb_capture_info
{
flex-grow: 1;
-webkit-box-flex: 1;
-moz-box-flex: 1;
-webkit-flex-grow: 1;
-ms-flex: 1;

min-width: 0;
margin: 0 15px;

display: flex !important;
display: -webkit-box !important;
display: -moz-box !important;
display: -webkit-flex !important;
display: -ms-flexbox !important;

flex-direction: column;
-webkit-box-direction: normal;
-webkit-box-orient: vertical;
-moz-box-direction: normal;
-moz-box-orient: vertical;
-ms-flex-direction: column;

justify-content: center;
-webkit-box-pack: center;
-moz-box-pack: center;
-ms-flex-pack: center;

align-items: center;
-webkit-box-align: center;
-moz-box-align: center;
-ms-flex-align: center;

height: 100%;
-webkit-font-smoothing: antialiased;
}

._wb_capture_date
{
font-size: 13px;
}

#_wb_frame_top_banner #_wb_ancillary_links
{
font-size: 12px;
color: #FFF;
margin-right: 15px;
text-align: right;
flex-shrink: 1 0;
-webkit-flex-shrink: 1 0;
-moz-flex-shrink: 1 0;
-ms-flex: 0 0 115px;
}
#_wb_frame_top_banner #_wb_ancillary_links a:link,
#_wb_frame_top_banner #_wb_ancillary_links a:visited,
#_wb_frame_top_banner #_wb_ancillary_links a:active
{
color: #FFF;
text-decoration: none;
}
#_wb_frame_top_banner #_wb_ancillary_links a:hover
{
text-decoration: underline;
}
#_wb_frame_top_banner #_wb_ancillary_links a img
{
width: 10px;
height: 10px;
}

#wb_iframe_div
{
position: absolute;
width: 100%;
height: 100%;
padding: 44px 4px 4px 0px;
padding: 44px 0px 0px 0px;
border: none;
box-sizing: border-box;
-moz-box-sizing: border-box;
Expand All @@ -53,7 +151,39 @@
{
width: 100%;
height: 100%;
border: 2px solid #545454;
border: 2px solid #FFF;
border-width: 2px 0 0 0;
padding: 0px 0px 0px 0px;
overflow: scroll;
}

.mobile {
display: none;
}

@media screen and (max-width: 500px) {
#_wb_frame_top_banner ._wb_linked_logo
{
width: 26px;
height: 26px;
margin-left: 10px;
}
#_wb_frame_top_banner ._wb_linked_logo img:not(.mobile)
{
display: none;
}
#_wb_frame_top_banner .mobile
{
display: block;
}

#_wb_capture_info
{
margin: 0 5px;
}

#_wb_frame_top_banner .no-mobile
{
display: none;
}
}
Loading

0 comments on commit 0d819aa

Please sign in to comment.