diff --git a/modules/adfs/www/idp/metadata.php b/modules/adfs/www/idp/metadata.php
index e78548d328c4d8daec586633eaa62561f8b6bdee..8308373f342c67ccc9367277d839ba7fe6152efa 100644
--- a/modules/adfs/www/idp/metadata.php
+++ b/modules/adfs/www/idp/metadata.php
@@ -148,6 +148,13 @@ try {
 
         $t->data['clipboard.js'] = true;
         $t->data['available_certs'] = $availableCerts;
+        $certdata = array();
+        foreach(array_keys($availableCerts) as $availableCert) {
+               $certdata[$availableCert]['name'] = $availableCert;
+               $certdata[$availableCert]['url'] = SimpleSAML\Module::getModuleURL('saml/idp/certs.php') . '/' . $availableCert;
+               $certdata[$availableCert]['comment'] = ( $availableCerts[$availableCert]['certFingerprint'][0] === 'afe71c28ef740bc87425be13a2263d37971da1f9' ? 'This is the default certificate. Generate a new certificate if this is a production system.' : '');
+        }
+        $t->data['certdata'] = $certdata;
         $t->data['header'] = 'adfs-idp'; // TODO: Replace with headerString in 2.0
         $t->data['headerString'] = $t->noop('metadata_adfs-idp');
         $t->data['metaurl'] = \SimpleSAML\Utils\HTTP::getSelfURLNoQuery();
diff --git a/modules/authX509/lib/Auth/Source/X509userCert.php b/modules/authX509/lib/Auth/Source/X509userCert.php
index 54dc20fb4e31aba6c802072728702589278f972b..402ebbefbada8b9cd0b57553052d23e99b1f54f6 100644
--- a/modules/authX509/lib/Auth/Source/X509userCert.php
+++ b/modules/authX509/lib/Auth/Source/X509userCert.php
@@ -73,6 +73,7 @@ class X509userCert extends \SimpleSAML\Auth\Source
         $config = \SimpleSAML\Configuration::getInstance();
 
         $t = new \SimpleSAML\XHTML\Template($config, 'authX509:X509error.php');
+        $t->data['loginurl'] = \SimpleSAML\Utils\HTTP::getSelfURL();
         $t->data['errorcode'] = $state['authX509.error'];
         $t->data['errorcodes'] = \SimpleSAML\Error\ErrorCodes::getAllErrorCodeMessages();
 
diff --git a/modules/authX509/templates/X509error.twig b/modules/authX509/templates/X509error.twig
new file mode 100644
index 0000000000000000000000000000000000000000..c350ea53f1692b86911f6b9fa5a9ea3da0f5257a
--- /dev/null
+++ b/modules/authX509/templates/X509error.twig
@@ -0,0 +1,19 @@
+{% set pagetitle = 'X509 certificate authentication'|trans %}
+{% extends "base.twig" %}
+{% block content %}
+
+{% if errorcode -%}
+<h2>{% trans 'Error' %}</h2>
+		<h3>{% trans errortitle %}</h3>
+		<p>{% trans errordescr %}</p>
+{% endif -%}
+
+<h2>{% trans 'X509 certificate authentication' %}</h2>
+
+<p>{% trans 'X509 certificate authentication is required to access this service.' %}</p>
+
+<a href="{{ loginurl }}">
+{% trans 'Login' %}
+</a>
+
+{% endblock %}
diff --git a/modules/authX509/templates/X509warning.twig b/modules/authX509/templates/X509warning.twig
new file mode 100644
index 0000000000000000000000000000000000000000..59a65f64f0f30f533aaaa64864fcc6d4047cfcaa
--- /dev/null
+++ b/modules/authX509/templates/X509warning.twig
@@ -0,0 +1,26 @@
+{% set autofocus = 'proceedbutton' %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+<h2>{% trans 'Your certificate is about to expire.' %}</h2>
+<form action="{{ target | escape }}">
+
+    {% for name, value in data -%}
+    <input type="hidden" name="{{ name }}" value="{{ value }}" />
+    {%- endfor %}
+
+    <p>{% trans %}Your certificate will expire in {{ daysleft }} days.{% endtrans %}</p>
+
+    {% if renewurl -%}
+    <p>{% trans %}Please <a href="{{ renewurl }}">renew your certificate</a> in time.{% endtrans %}</p>
+    {% else -%}
+    <p>{% trans 'Please renew your certificate in time.' %}</p>
+    {% endif -%}
+
+    <p><input type="submit" name="proceed" id="proceedbutton" value="{% trans 'Proceed' %}" /></p>
+
+</form>
+
+{% endblock %}
diff --git a/modules/authYubiKey/templates/yubikeylogin.twig b/modules/authYubiKey/templates/yubikeylogin.twig
new file mode 100644
index 0000000000000000000000000000000000000000..c55a71af1779c359a4d529665adda2000edb7f16
--- /dev/null
+++ b/modules/authYubiKey/templates/yubikeylogin.twig
@@ -0,0 +1,25 @@
+{% set pagetitle = '{authYubiKey:yubikey:header}'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    {% if errorCode != null %}
+    <div style="border-left: 1px solid #e8e8e8; border-bottom: 1px solid #e8e8e8; background: #f5f5f5">
+        <img src="{{ baseurlpath }}resources/icons/experience/gtk-dialog-error.48x48.png" class="float-l" style="margin: 15px;" alt="" />
+        <h2>{{ '{login:error_header}'|trans }}</h2>
+        <p><span style="text-decoration: bold;">{{ errorTitle }}</p>
+        <p>{{ errorDesc }}</p>
+    </div>
+    {% endif %}
+
+    <img style="float: right" src="{{ logoUrl }}" alt="" />
+    <img style="clear: right; float: right" src="{{ devicepicUrl }}" alt="YubiKey" />
+
+    <h2>{{ '{authYubiKey:yubikey:header}'|trans }}</h2>
+    <form action="?" method="post" name="f">
+        <p>{{ '{authYubiKey:yubikey:intro}'|trans }}</p>
+        <p><input id="otp" style="border: 1px solid #ccc; background: #eee; padding: .5em; font-size: medium; width: 70%; color: #aaa" type="text" tabindex="2" name="otp" /></p>
+    {% for key, value in stateParams %}
+        <input type="hidden" name="{{ key|escape('html') }}" value="{{ value|escape('html') }}"/>
+    {% endfor %}
+    </form>
+{% endblock %}
diff --git a/modules/authYubiKey/www/yubikeylogin.php b/modules/authYubiKey/www/yubikeylogin.php
index 7d5f23d83c91a3f042f0a0c2250997c160b34ccd..ae9ec786a1bc8ee91dcc418fa4d48e0b3af7e1f4 100644
--- a/modules/authYubiKey/www/yubikeylogin.php
+++ b/modules/authYubiKey/www/yubikeylogin.php
@@ -10,23 +10,23 @@
  */
 
 if (!array_key_exists('AuthState', $_REQUEST)) {
-    throw new \SimpleSAML\Error\BadRequest('Missing AuthState parameter.');
+	throw new \SimpleSAML\Error\BadRequest('Missing AuthState parameter.');
 }
-$authStateId = $_REQUEST['AuthState'];
 
+$globalConfig = \SimpleSAML\Configuration::getInstance();
+$t = new \SimpleSAML\XHTML\Template($globalConfig, 'authYubiKey:yubikeylogin.php');
+
+$errorCode = null;
 if (array_key_exists('otp', $_REQUEST)) {
     // attempt to log in
     $errorCode = \SimpleSAML\Module\authYubiKey\Auth\Source\YubiKey::handleLogin($authStateId, $_REQUEST['otp']);
-} else {
-    $errorCode = null;
+    $errorCodes = \SimpleSAML\Error\ErrorCodes::getAllErrorCodeMessages();
+    $t->data['errorTitle'] = $errorCodes['title'][$errorCode];
+    $t->data['errorDesc'] = $errorCodes['desc'][$errorCode];
 }
 
-$globalConfig = \SimpleSAML\Configuration::getInstance();
-$t = new \SimpleSAML\XHTML\Template($globalConfig, 'authYubiKey:yubikeylogin.php');
-$t->data['stateparams'] = array('AuthState' => $authStateId);
-$t->data['errorcode'] = $errorCode;
-$t->data['errorcodes'] = \SimpleSAML\Error\ErrorCodes::getAllErrorCodeMessages();
-$t->data['logo_url'] = \SimpleSAML\Module::getModuleURL('authYubiKey/resources/logo.jpg');
-$t->data['devicepic_url'] = \SimpleSAML\Module::getModuleURL('authYubiKey/resources/yubikey.jpg');
+$t->data['errorCode'] = $errorCode;
+$t->data['stateParams'] = array('AuthState' => $_REQUEST['authStateId']);
+$t->data['logoUrl'] = \SimpleSAML\Module::getModuleURL('authYubiKey/resources/logo.jpg');
+$t->data['devicepicUrl'] = \SimpleSAML\Module::getModuleURL('authYubiKey/resources/yubikey.jpg');
 $t->show();
-exit();
diff --git a/modules/authorize/templates/authorize_403.twig b/modules/authorize/templates/authorize_403.twig
new file mode 100644
index 0000000000000000000000000000000000000000..1a60813dc7ca1a832c0d4e9bfd00f6e84975baa8
--- /dev/null
+++ b/modules/authorize/templates/authorize_403.twig
@@ -0,0 +1,11 @@
+{% extends "base.twig" %}
+
+{% block content %}
+  <h1>{{ '{authorize:Authorize:403_header}'|trans }}</h1>
+  <p>{{ '{authorize:Authorize:403_text}'|trans }}</p>
+  {% if LogoutURL is defined %}
+  <p>
+      <a href="{{ LogoutURL|escape('html') }}">{{ '{status:logout}'|trans }}</a>
+  </p>
+  {% endif %}
+{% endblock%}
diff --git a/modules/consent/templates/consentform.twig b/modules/consent/templates/consentform.twig
new file mode 100644
index 0000000000000000000000000000000000000000..e33dcf8a63c6839769098b9befa9b5a28c98d90b
--- /dev/null
+++ b/modules/consent/templates/consentform.twig
@@ -0,0 +1,38 @@
+{% set pagetitle = '{consent:consent:consent_header}'|trans %}
+{% extends "base.twig" %}
+
+{% block preload %}
+<link rel="stylesheet" type="text/css" href="{{ baseurlpath }}consent/style.css" />
+{% endblock %}
+
+{% block content %}
+<p>{{ consent_accept}}</p>
+
+{% if consent_purpose is defined %}
+    <p>{{ consent_purpose }}</p>
+{% endif %}
+
+<form id="consent_yes" action="{{ yesTarget|escape('url') }}">
+    {% if usestorage is defined %}
+    <input type="checkbox" name="saveconsent"{% if checked %} checked="checked"{% endif %} value="1" />
+    {{ '{consent:consent:remember}'|trans }}
+    {% endif %}
+
+    <input type="hidden" name="StateId" value="{{ stateId|escape('url') }}" />
+    <button type="submit" name="yes" class="btn" id="yesbutton">{{ '{consent:consent:yes}'|trans }}</button>
+</form>
+
+<form id="consent_no" action="{{ noTarget|escape('url') }}">
+    <input type="hidden" name="StateId" value="{{ stateId|escape('url') }}" />
+    <button type="submit" class="btn" name="no" id="nobutton">{{ '{consent:consent:no}'|trans }}</button>
+</form>
+
+{% if sppp != false %}
+<p>{{ '{consent:consent:consent_privacypolicy}'|trans }}
+    <a target='_blank' href='{{ sppp|escape('url') }} '>{{ dstName }}</a>
+</p>
+{% endif %}
+
+<h3 id="attributeheader">{{ consent_attributes_header }}</h3>
+{{ attributes_html|raw }}
+{% endblock %}
diff --git a/modules/consent/templates/logout_completed.twig b/modules/consent/templates/logout_completed.twig
new file mode 100644
index 0000000000000000000000000000000000000000..75503847c5bae4bca03e0132b22edae2ce9162da
--- /dev/null
+++ b/modules/consent/templates/logout_completed.twig
@@ -0,0 +1,7 @@
+{% set pagetitle = '{logout:title}'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+<h2>{{ header }}</h2>
+<p>{{ '{logout:logged_out_text}'|trans }}</p>
+{% endblock %}
diff --git a/modules/consent/templates/noconsent.twig b/modules/consent/templates/noconsent.twig
new file mode 100644
index 0000000000000000000000000000000000000000..f9b623aa01a46f3127dd1bb30fafe1efbd201317
--- /dev/null
+++ b/modules/consent/templates/noconsent.twig
@@ -0,0 +1,16 @@
+{% set pagetitle = '{consent:consent:noconsent_title}'|trans %}
+{% extends "base.twig" %}
+{% block content %}
+    <h2>{{ header }}</h2>
+    <p>{{ noconsent_text }}</p>
+
+    {% if resumeFrom %}
+    <p><a href="{{ resumeFrom|escape('url') }}">{{ '{consent:consent:noconsent_return}'|trans }}</a></p>
+    {% endif %}
+
+    {% if aboutService %}
+    <p><a href="{{ aboutService|escape('url') }}">{{ '{consent:consent:noconsent_goto_about}'|trans }}</a></p>
+    {% endif %}
+
+    <p><a href="{{ logoutLink|escape('url') }}">{{ noconsent_abort }}</a></p>
+{% endblock %}
diff --git a/modules/consent/www/getconsent.php b/modules/consent/www/getconsent.php
index 92c9623b045de07f2727694422f53d5b4ef7755b..4b9065c84f0ad54f7e4790ee1772667c7d7d0784 100644
--- a/modules/consent/www/getconsent.php
+++ b/modules/consent/www/getconsent.php
@@ -158,6 +158,37 @@ if (array_key_exists('descr_purpose', $state['Destination'])) {
 $t->data['srcName'] = $srcName;
 $t->data['dstName'] = $dstName;
 
+$srcName = htmlspecialchars(is_array($srcName) ? $translator->t($srcName) : $srcName);
+$dstName = htmlspecialchars(is_array($dstName) ? $translator->t($dstName) : $dstName);
+
+$t->data['consent_attributes_header'] = $translator->t(
+    '{consent:consent:consent_attributes_header}',
+    array('SPNAME' => $dstName, 'IDPNAME' => $srcName)
+);
+
+$t->data['consent_accept'] = $translator->t(
+    '{consent:consent:consent_accept}',
+    array('SPNAME' => $dstName, 'IDPNAME' => $srcName)
+);
+
+if (array_key_exists('descr_purpose', $state['Destination'])) {
+    $t->data['consent_purpose'] = $translator->t(
+        '{consent:consent:consent_purpose}',
+        array(
+            'SPNAME' => $dstName,
+            'SPDESC' => $translator->getPreferredTranslation(
+                \SimpleSAML\Utils\Arrays::arrayize(
+                    $state['Destination']['descr_purpose'],
+                    'en'
+                )
+            ),
+        )
+    );
+}
+
+$t->data['srcName'] = $srcName;
+$t->data['dstName'] = $dstName;
+
 // Fetch privacypolicy
 if (array_key_exists('privacypolicy', $state['Destination'])) {
     $privacypolicy = $state['Destination']['privacypolicy'];
@@ -247,7 +278,6 @@ function present_attributes($t, $attributes, $nameParent)
             $isHidden = in_array($nameraw, $t->data['hiddenAttributes'], true);
             if ($isHidden) {
                 $hiddenId = \SimpleSAML\Utils\Random::generateID();
-
                 $str .= '<div class="attrvalue hidden" id="hidden_'.$hiddenId.'">';
             } else {
                 $str .= '<div class="attrvalue">';
diff --git a/modules/consentAdmin/hooks/hook_frontpage.php b/modules/consentAdmin/hooks/hook_frontpage.php
index 61c4bd6b1f3b119a47b89efe6321b844d3f41888..9659a869f565e1f11b8cacd1743423c593255601 100644
--- a/modules/consentAdmin/hooks/hook_frontpage.php
+++ b/modules/consentAdmin/hooks/hook_frontpage.php
@@ -10,6 +10,6 @@ function consentAdmin_hook_frontpage(&$links) {
 
 	$links['config'][] = array(
 		'href' => SimpleSAML\Module::getModuleURL('consentAdmin/consentAdmin.php'),
-		'text' => '{consentAdmin:consentadmin:consentadmin_header}',
+		'text' => '{core:frontpage:link_consentAdmin}',
 	);
 }
diff --git a/modules/consentAdmin/templates/consentadminajax.twig b/modules/consentAdmin/templates/consentadminajax.twig
new file mode 100644
index 0000000000000000000000000000000000000000..1ffd174b65a7e036475f7c2ff6c06adfae6167fe
--- /dev/null
+++ b/modules/consentAdmin/templates/consentadminajax.twig
@@ -0,0 +1,3 @@
+{% block content}
+{{ res|trans }}
+{% endblock %}
diff --git a/modules/core/locales/en/LC_MESSAGES/core.po b/modules/core/locales/en/LC_MESSAGES/core.po
index bf9ee93f84563aa26e9c3d3fc638d1737b66bdb9..9ddd25f62f64f4858ba2ccc18b6c525873f43a2c 100644
--- a/modules/core/locales/en/LC_MESSAGES/core.po
+++ b/modules/core/locales/en/LC_MESSAGES/core.po
@@ -54,6 +54,30 @@ msgstr "OpenID Provider site - Alpha version (test code)"
 msgid "{core:frontpage:link_doc_install}"
 msgstr "Installing SimpleSAMLphp"
 
+msgid "{core:frontpage:link_consentAdmin}"
+msgstr "Consent Administration"
+
+msgid "{core:frontpage:link_memcacheMonitor}"
+msgstr "MemCache Statistics"
+
+msgid "{core:frontpage:link_oauth}"
+msgstr "OAuth Consumer Registry"
+
+msgid "{core:frontpage:link_cron}"
+msgstr "Cron module information page"
+
+msgid "{core:frontpage:link_statistics}"
+msgstr "Show statistics"
+
+msgid "{core:frontpage:link_statistics_metadata}"
+msgstr "Show statistics metadata"
+
+msgid "{core:frontpage:link_metarefresh}"
+msgstr "Metarefresh: fetch metadata"
+
+msgid "{core:frontpage:link_sanitycheck}"
+msgstr "Sanity check of your SimpleSAMLphp setup"
+
 msgid "{core:frontpage:link_diagnostics}"
 msgstr "Diagnostics on hostname, port and protocol"
 
diff --git a/modules/core/templates/_frontpage_menu.twig b/modules/core/templates/_frontpage_menu.twig
new file mode 100644
index 0000000000000000000000000000000000000000..7b363ffaf4a9178c234fb6e87bff8476e8a101d2
--- /dev/null
+++ b/modules/core/templates/_frontpage_menu.twig
@@ -0,0 +1,25 @@
+<div class="pure-g frontpage-menu">
+  <div class="pure-u-2-3">
+    <div class="pure-menu pure-menu-horizontal">
+    <ul class="pure-menu-list">
+      <li class="pure-menu-item {% if frontpage_section == "welcome" %} pure-menu-selected{% endif %}">
+        <a href="frontpage_welcome.php" class="pure-menu-link">Welcome</a></li>
+      <li class="pure-menu-item {% if frontpage_section == "config" %} pure-menu-selected{% endif %}">
+        <a href="frontpage_config.php" class="pure-menu-link">Configuration</a></li>
+      <li class="pure-menu-item {% if frontpage_section == "auth" %} pure-menu-selected{% endif %}">
+        <a href="frontpage_auth.php" class="pure-menu-link">Authentication</a></li>
+      <li class="pure-menu-item {% if frontpage_section == "federation" %} pure-menu-selected{% endif %}">
+        <a href="frontpage_federation.php" class="pure-menu-link">Federation</a></li>
+    </ul>
+    </div>
+  </div>
+  <div class="pure-u-1-3">
+    {% if isadmin %}
+    <p class="float-r youareadmin">{{ '{core:frontpage:loggedin_as_admin}'|trans }}</p>
+    {% else %}
+    <p class="float-r youareadmin">
+        <a href="{{ loginurl }}">{{ '{core:frontpage:login_as_admin}'|trans }}</a>
+    </p>
+    {% endif %}
+  </div>
+</div>
diff --git a/modules/core/templates/authsource_list.twig b/modules/core/templates/authsource_list.twig
new file mode 100644
index 0000000000000000000000000000000000000000..acf0d57fa51de28382b6bd9c6760723772cf1121
--- /dev/null
+++ b/modules/core/templates/authsource_list.twig
@@ -0,0 +1,11 @@
+{% set pagetitle = 'Test Authentication Sources'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h1>{{ header }}</h1>
+    <ul>
+    {% for key, name in sources %}
+    <li><a href="?as={{ name|escape('url') }}">{{ name|escape('html') }}</a></li>
+    {% endfor %}
+    </ul>
+{% endblock %}
diff --git a/modules/core/templates/frontpage_auth.twig b/modules/core/templates/frontpage_auth.twig
new file mode 100644
index 0000000000000000000000000000000000000000..cfe3c4f9d1f385e00bb3ecb2da497c0cf9e61013
--- /dev/null
+++ b/modules/core/templates/frontpage_auth.twig
@@ -0,0 +1,18 @@
+{% set pagetitle = '{core:frontpage:page_title}'|trans %}
+{% set frontpage_section = 'auth' %}
+{% extends "base.twig" %}
+
+{% block content %}
+    {% include "@core/_frontpage_menu.twig" %}
+
+    <ul>
+    {% for key, link in links_auth %}
+        <li>
+            <a href="{{ link.href }}">{{ link.text|trans|escape('html') }}</a>
+            {% if link.deprecated is defined and link.deprecated is not empty %}
+            <strong>{{ '{core:frontpage:deprecated}'|trans }}</strong>
+            {% endif %}
+        </li>
+    {% endfor %}
+    </ul>
+{% endblock %}
diff --git a/modules/core/templates/frontpage_config.tpl.php b/modules/core/templates/frontpage_config.tpl.php
index 4bf19eff9390aa5086561ed410b0f33ca5f7035b..aeaa64af1d337a26f992286681715319f2da1c97 100644
--- a/modules/core/templates/frontpage_config.tpl.php
+++ b/modules/core/templates/frontpage_config.tpl.php
@@ -40,11 +40,11 @@ if ($this->data['isadmin']) {
 	$icon_disabled = '<img src="/' . $this->data['baseurlpath'] . 'resources/icons/silk/delete.png" alt="disabled" />';
 	?>
 	
-		<tr class="<?php echo $this->data['enablematrix']['saml20-idp'] ? 'enabled' : 'disabled'; ?>"><td>SAML 2.0 IdP</td>
-			<td><?php echo $this->data['enablematrix']['saml20-idp'] ? $icon_enabled : $icon_disabled; ?></td></tr>
+		<tr class="<?php echo $this->data['enablematrix']['saml20idp'] ? 'enabled' : 'disabled'; ?>"><td>SAML 2.0 IdP</td>
+			<td><?php echo $this->data['enablematrix']['saml20idp'] ? $icon_enabled : $icon_disabled; ?></td></tr>
 			
-		<tr class="<?php echo $this->data['enablematrix']['shib13-idp'] ? 'enabled' : 'disabled'; ?>"><td>Shib 1.3 IdP</td>
-			<td><?php echo $this->data['enablematrix']['shib13-idp'] ? $icon_enabled : $icon_disabled; ?></td></tr>
+		<tr class="<?php echo $this->data['enablematrix']['shib13idp'] ? 'enabled' : 'disabled'; ?>"><td>Shib 1.3 IdP</td>
+			<td><?php echo $this->data['enablematrix']['shib13idp'] ? $icon_enabled : $icon_disabled; ?></td></tr>
 		
 	</table>
 </div>
diff --git a/modules/core/templates/frontpage_config.twig b/modules/core/templates/frontpage_config.twig
new file mode 100644
index 0000000000000000000000000000000000000000..21a65bbfdef3ef4c26c4597542102f76fabe11bb
--- /dev/null
+++ b/modules/core/templates/frontpage_config.twig
@@ -0,0 +1,60 @@
+{% set pagetitle = '{core:frontpage:page_title}'|trans %}
+{% set frontpage_section = 'config' %}
+{% extends "base.twig" %}
+
+{% block content %}
+    {% include "@core/_frontpage_menu.twig" %}
+
+    <div>
+        <code class="simplesaml_version">{{ directory }} ({{ version }})</code>
+    </div>
+
+    {% set icon_enabled = '<img src="/' ~ baseurlpath ~ 'resources/icons/silk/accept.png" alt="enabled" />' %}
+    {% set icon_disabled = '<img src="/' ~ baseurlpath ~ 'resources/icons/silk/delete.png" alt="disabled" />' %}
+
+    <div class="enablebox mini">
+        <table>
+	    <tr class="{%- if enablematrix.saml20idp %}enabled{% else %}disabled{% endif -%}">
+                <td>SAML 2.0 IdP</td>
+                <td>{%- if enablematrix.saml20idp %}{{ icon_enabled|raw }}{% else %}{{ icon_disabled|raw }}{% endif -%}</td>
+            </tr>
+	    <tr class="{%- if enablematrix.shib13idp %}enabled{% else %}disabled{% endif -%}">
+                <td>Shib 1.3 IdP</td>
+                <td>{%- if enablematrix.shib13idp %}{{ icon_enabled|raw }}{% else %}{{ icon_disabled|raw }}{% endif -%}</td>
+            </tr>
+        </table>
+    </div>
+
+    <h2>{{ '{core:frontpage:configuration}'|trans }}</h2>
+    <ul>
+        {% for key, link in links_config %}
+        <li><a href="{{ link.href|escape('html') }}">{{ link.text|trans|escape('html') }}</a></li>
+        {% endfor %}
+    </ul>
+
+    {% if warnings is defined and warnings is not empty %}
+    <h2>{{ '{core:frontpage:warnings}'|trans|escape('html') }}</h2>
+    {% for key, warning in warnings %}
+    {% if warning is iterable %}
+    <div class="caution">{{ warning[0]|trans(warning[1], "app")|raw }}</div>
+    {% else %}
+    <div class="caution">{{ warning|trans|raw }}</div>
+    {% endif %}
+    {% endfor %}
+    {% endif %}
+
+    {% if isadmin %}
+    <h2>{{ '{core:frontpage:checkphp}'|trans }}</h2>
+    <div class="enablebox">
+        <table>
+        {% for key, func in funcmatrix %}
+	    <tr class="{%- if func.enabled %}enabled{% else %}disabled{% endif -%}">
+                <td>{%- if func.enabled %}{{ icon_enabled|raw }}{% else %}{{ icon_disabled|raw }}{% endif -%}</td>
+                <td>{{ requiredmap[func.required]|trans }}</td>
+                <td>{{ func.descr }}</td>
+            </tr>
+        {% endfor %}
+        </table>
+    </div>
+    {% endif %}
+{% endblock %}
diff --git a/modules/core/templates/frontpage_federation.twig b/modules/core/templates/frontpage_federation.twig
new file mode 100644
index 0000000000000000000000000000000000000000..35acde2d64bf5db106cee6300d41100a4a0a8483
--- /dev/null
+++ b/modules/core/templates/frontpage_federation.twig
@@ -0,0 +1,84 @@
+{% set pagetitle = '{core:frontpage:page_title}'|trans %}
+{% set frontpage_section = 'federation' %}
+{% extends "base.twig" %}
+
+{% block content %}
+    {% include "@core/_frontpage_menu.twig" %}
+
+    {% if metaentries.hosted is iterable and metaentries.hosted is not empty %}
+    <dl>
+    {% for key, set in metaentries.hosted %}
+        {% set metadataset = attribute(set, 'metadata-set') %}
+        <dt>{{ mtype[metadataset]|trans }}</dt>
+        <dd>
+        <p>Entity ID: <code>{{ set.entityid }}</code>
+            {% if set.deprecated is defined and set.deprecated %}
+            <br /><span class="entity-deprecated">Deprecated</span>
+            {% endif %}
+            {% if set.entityid != attribute(set, 'metadata-index') %}
+            <br />Index: {{ attribute(set, 'metadata-index') }}
+            {% endif %}
+            {% if set.name_translated is defined %}
+            <br /><span class="entity-name">{{ set.name_translated }}</span>
+            {% endif %}
+            {% if set.descr_translated is defined %}
+            <br /><span class="entity-name">{{ set.descr_translated }}</span>
+            {% endif %}
+            <br />[ <a href="{{ attribute(set, 'metadata-url') }}">{{'{core:frontpage:show_metadata}'|trans }}</a> ]
+        </p>
+        </dd>
+    {% endfor %}
+    </dl>
+    {% endif %}
+
+    {% if metaentries.remote is iterable and metaentries.remote is not empty %}
+    {% for key, set in metaentries.remote %}
+    <fieldset class="fancyfieldset">
+        <legend>{{ mtype[key]|trans }} (Trusted)</legend>
+        <ul>
+        {% for entityid, entity in set %}
+            <li><a href="{{ (metadata_url ~ '?entityid=' ~ entity.entityid ~ '&set=' ~ key)|escape('html') }}">
+            {%- if entity.name_translated is defined %}
+            {{ entity.name_translated }}
+            {% elseif entity.organizationdisplayname_translated is defined %}
+            {{ entity.organizationdisplayname_translated }}
+            {% else %}{{ entity.entityid|escape('html') }}
+            {% endif -%}</a>
+
+            {%- if entity.expire is defined %}
+            {% if entity.expire > date().timestamp %}
+            <span class="entity-expired"> (expired {{ ((date().timestamp - entity.expire) / 3600) }} hours ago)</span>
+            {% else %} (expires in {{ ((entity.expire - date().timestamp) / 3600) }} hours){% endif -%}{% endif %}
+            </li>
+        {% endfor %}
+        </ul>
+    </fieldset>
+    {% endfor %}
+    {% endif %}
+
+    <h2>{{ '{core:frontpage:tools}'|trans }}</h2>
+    <ul>
+        {% for key, link in links_federation %}
+        <li><a href="{{ link.href|escape('html') }}">{{ link.text|trans|escape('html') }}</a></li>
+        {% endfor %}
+    </ul>
+
+    {% if isadmin %}
+    <fieldset class="fancyfieldset">
+        <legend>Lookup metadata</legend>
+        <form action="{{ metadata_url }}" method="get">
+            <p>Look up metadata for entity:
+                <select name="set">
+                {% if metaentries.remote is defined and metaentries.remote is not empty %}
+                {% for key, set in metaentries.remote %}
+                    <option value="{{ key|escape('html') }}">{{ mtype[key]|trans }}</option>
+                {% endfor %}
+                {% endif %}
+                </select>
+                <input type="text" name="entityid" />
+                <button class="btn" type="submit">Lookup </button>
+            </p>
+        </form>
+    </fieldset>
+    {% endif %}
+{% endblock %}
diff --git a/modules/core/templates/frontpage_welcome.twig b/modules/core/templates/frontpage_welcome.twig
new file mode 100644
index 0000000000000000000000000000000000000000..de2f3757ca2897b077d688bdceb14e86ab0cd5ed
--- /dev/null
+++ b/modules/core/templates/frontpage_welcome.twig
@@ -0,0 +1,17 @@
+{% set pagetitle = '{core:frontpage:page_title}'|trans %}
+{% set frontpage_section = 'welcome' %}
+{% extends "base.twig" %}
+
+{% block content %}
+    {% include "@core/_frontpage_menu.twig" %}
+
+    <p>{{ '{core:frontpage:intro}'|trans|raw }}</p>
+    <ul>
+        {% for key, link in links_welcome %}
+        <li><a href="{{ link.href|escape('html') }}">{{ link.text|trans|escape('html') }}</a></li>
+        {% endfor %}
+    </ul>
+
+    <h2>{{ '{core:frontpage:about_header}'|trans }}</h2>
+    <p>{{ '{core:frontpage:about_text}'|trans|raw }}</p>
+{% endblock %}
diff --git a/modules/core/templates/login.twig b/modules/core/templates/login.twig
new file mode 100644
index 0000000000000000000000000000000000000000..adf3f8426029a838847c170c28d8c70946067a9d
--- /dev/null
+++ b/modules/core/templates/login.twig
@@ -0,0 +1,20 @@
+{% set pagetitle = 'Authenticate'|trans %}
+{% extends "@core/base.twig" %}
+
+{% block content %}
+<h1>{{ pagetitle|trans }}</h1>
+    <p>Please choose one of the following authentication methods: </p>
+
+{% if sources is empty -%}
+    <p>Please check your SimpleSAML configuration.<br>
+        Follow the link and log in with administrator credentials. <a href="{{ loginurl }}">Admin login.</a></p>
+{% else %}
+    <div class="pure-menu custom-restricted-width">
+        <ul class="pure-menu-list auth_methods">
+            {% for id, config in sources -%}
+                <li class="pure-menu-item"><a href="?as={{ id|url_encode }}" class="pure-menu-link">{{ config.name|translateFromArray|default(id) }}</a></li>
+            {% endfor -%}
+        </ul>
+    </div>
+{% endif %}
+{% endblock %}
\ No newline at end of file
diff --git a/modules/core/templates/loginuserpass.twig b/modules/core/templates/loginuserpass.twig
new file mode 100644
index 0000000000000000000000000000000000000000..7f27bc186072f50cb616145daf0d596c4b12d79d
--- /dev/null
+++ b/modules/core/templates/loginuserpass.twig
@@ -0,0 +1,125 @@
+{% set pagetitle = 'Enter your username and password'|trans %}
+
+{% extends "@core/base.twig" %}
+
+{% block content %}
+    {% if errorcode -%}
+    <div class="pure-g">
+        <div class="pure-u-1">
+            <div class="message-box error">
+
+                {% set errtitles = errorcodes['title'] %}
+                {% set errtitle = errtitles[errorcode] %}
+
+                <h3>{{ errtitle|trans(errorparams) }}</h3>
+
+                {% set errdescs = errorcodes['descr'] %}
+                {% set errdesc = errdescs[errorcode] %}
+
+                <p>{{ errdesc|trans(errorparams) }}</p>
+
+            </div>
+        </div>
+    </div>
+    {%- endif %}
+
+    <h1>{{ 'Enter your username and password'|trans }}</h1>
+
+    <p>{{ 'A service has requested you to authenticate yourself. Please enter your username and password in the form below.'|trans }}</p>
+    <br>
+    <div class="center">
+        <form class="pure-form pure-form-aligned center-form" action="?" method="post" name="f">
+            <div class="form-align">
+
+                <div class="show-for-medium v-center-right">
+                    <img class="pure-img" src="/{{ baseurlpath }}resources/icons/experience/gtk-dialog-authentication.48x48.png"
+                         alt=""/>
+                </div>
+
+                <div class="pure-control-group">
+                    <label for="username">{{ 'Username'|trans }}</label>
+                    <input id="username" {{ forceUsername ? 'disabled="disabled"' }} placeholder="{{ username }}" type="text" name="username" class="edge"
+            {%- if not forceUsername %} tabindex="1" value="{{ username }}" {% endif %}
+            {%- if not forceUsername and not username %} autofocus {% endif %} />
+                {% if rememberUsernameEnabled and not forceUsername -%}
+                </div>
+                <div class="pure-controls pure-form-message">
+                    <label for="remember_username" class="pure-checkbox">
+                        <input id="remember_username" type="checkbox" tabindex="4"
+                                {{ rememberUsernameChecked ? 'checked="checked"' }} name="remember_username" value="Yes"/>
+                        <small>{{ 'Remember my username'|trans }}</small>
+                    </label>
+                {%- endif %}
+                </div>
+
+                <div class="pure-control-group">
+                    <label for="password">{{ 'Password'|trans}}</label>
+                    <input id="password" type="password" tabindex="2" name="password" class="edge"
+                    {%- if forceUsername or username %} autofocus {% endif %} />
+
+                {% if rememberMeEnabled -%}
+                </div>
+                <div class="pure-controls pure-form-message">
+                    <label for="remember_me" class="pure-checkbox">
+                    <input id="remember_me" type="checkbox" tabindex="5"
+                            {{ rememberMeChecked ? 'checked="checked"' }} name="remember_me" value="Yes"/>
+                        <small>{{ 'Remember me'|trans }}</small>
+                    </label>
+                {%- endif %}
+                </div>
+                {% if organizations is defined -%}
+                <div class="pure-control-group">
+                    <label for="organization">{{ 'Organization'|trans }}</label>
+                    <div class="pure-select right pure-input-1-2 pure-input-sm-1-1">
+                        <select name="organization" class="selectize" id="organization" tabindex="3">
+                            {{ selectedOrg ?: null }}
+                            {%- for id, orgDesc in organizations -%}
+                                {% if id == selectedOrg -%}
+                                    {%- set selected = 'selected="selected"' %}
+                                {%- else -%}
+                                    {% set selected = '' -%}
+                                {% endif -%}
+                                {% if orgDesc -%}
+                                    <option value="{{ id }}" {{ selected }}>{{ orgDesc|trans }}</option>
+                                {% endif -%}
+                            {% endfor %}
+                        </select>
+                    </div>
+                    {% if rememberOrganizationEnabled is defined -%}
+                    <div class="pure-controls pure-form-message">
+                        <label for="remember_organization" class="pure-checkbox">
+ 	                    <input type="checkbox" id="remember_organization" tabindex="5" name="remember_organization" value="Yes"
+                                {{ rememberOrganizationChecked ? 'checked="checked"' }} />
+                            <small>{{ 'Remember my organization'|trans }}</small>
+                        </label>
+                    </div>
+                    {%- endif %}
+                </div> <!--pure-control-group-->
+            {%- endif %}
+
+            </div> <!-- form-align-->
+            <br><br>
+            <button class="pure-button pure-button-red pure-input-1-2 pure-input-sm-1-1 right" type="submit" onclick="this.value='{{ 'Processing...'|trans }}';" tabindex="6">
+                {{ 'Login'|trans }}
+            </button>
+
+            {% for name, value in stateparams -%}
+                <input type="hidden" name="{{ name }}" value="{{ value }}" />
+            {%- endfor %}
+        </form>
+    </div><!--center-->
+    {% if links -%}
+    <ul>
+        {% for link in links -%}
+        <li><a href="{{ link.href }}">{{ link['text']|trans }}</a></li>
+        {% endfor %}
+    </ul>
+    {%- endif %}
+
+    <br><br>
+    <div class="pure-form-message">
+        <strong>{{ 'Help! I don\'t remember my password.'|trans }}</strong>
+        <p>{{ 'Without your username and password you cannot authenticate yourself for access to the service. There may be someone that can help you. Consult the help desk at your organization!'|trans }}</p>
+    </div>
+
+{% endblock %}
diff --git a/modules/core/templates/logout-iframe-wrapper.twig b/modules/core/templates/logout-iframe-wrapper.twig
new file mode 100644
index 0000000000000000000000000000000000000000..7c9e415d072d9d25553bdb7e8eee4b05c76a4810
--- /dev/null
+++ b/modules/core/templates/logout-iframe-wrapper.twig
@@ -0,0 +1,16 @@
+
+{% set pagetitle = '{logout:progress}'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    {# pretty arbitrary height, but should have enough safety margins for most cases #}
+    {% set iframeHeight = (25 + (SPs|length * 4)) %}
+
+    <iframe style="width:100%; height: {{ iframeHeight }}em; border:0;" src="logout-iframe.php?type=embed&id={{ auth_state|escape('url') }}"></iframe>
+
+    {% for assocId, sp in SPs %}
+    {% if attribute(sp, 'core:Logout-IFrame:State') == 'inprogress' %}
+    <iframe style="width:0; height:0; border:0;" src="{{ attribute(sp, 'core:Logout-IFrame:URL')|escape('html') }}</iframe>
+    {% endif %}
+    {% endfor %}
+{% endblock %}
diff --git a/modules/core/templates/no_cookie.twig b/modules/core/templates/no_cookie.twig
new file mode 100644
index 0000000000000000000000000000000000000000..7205318e2a3a3355de51097c2012bd4e07ea9fda
--- /dev/null
+++ b/modules/core/templates/no_cookie.twig
@@ -0,0 +1,13 @@
+
+{% set pagetitle = '{core:no_cookie:header}'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h2>{{ header }}</h2>
+    <p>{{ description }}</p>
+    {% if retryURL is not null %}
+    <ul>
+        <li><a href="{{ retryURL|escape('html') }}" id="retry">{{ retry }}</a></li>
+    </ul>
+    {% endif %}
+{% endblock %}
diff --git a/modules/core/templates/no_metadata.twig b/modules/core/templates/no_metadata.twig
new file mode 100644
index 0000000000000000000000000000000000000000..818c08a8ca46d0a222f8f64c87b00f588ecbc23e
--- /dev/null
+++ b/modules/core/templates/no_metadata.twig
@@ -0,0 +1,7 @@
+<p>{{ '{core:no_metadata:config_problem}' | trans }}</p>
+
+<ul>
+    <li>{{ '{core:no_metadata:suggestion_user_link}' | trans }}</li>
+    <li>{{ '{core:no_metadata:suggestion_developer}' | trans }}</li>
+</ul>
+
diff --git a/modules/core/templates/no_state.twig b/modules/core/templates/no_state.twig
new file mode 100644
index 0000000000000000000000000000000000000000..9ae61fb5dcbc9316dfab58a2286b69698e6ec2d4
--- /dev/null
+++ b/modules/core/templates/no_state.twig
@@ -0,0 +1,12 @@
+<h3>{{ '{core:no_state:suggestions}' | trans }}</h3>
+<ul>
+    <li>{{ '{core:no_state:suggestion_goback}' | trans }}</li>
+    <li>{{ '{core:no_state:suggestion_closebrowser}' | trans }}</li>
+</ul>
+
+<h3>{{ '{core:no_state:causes}' | trans }}</h3>
+<ul>
+    <li>{{ '{core:no_state:cause_backforward}'  | trans }}</li>
+    <li>{{ '{core:no_state:cause_openbrowser}'  | trans }}</li>
+    <li>{{ '{core:no_state:cause_nocookie}'  | trans }}</li>
+</ul>
diff --git a/modules/core/templates/short_sso_interval.twig b/modules/core/templates/short_sso_interval.twig
new file mode 100644
index 0000000000000000000000000000000000000000..91288cd9f7d5cfe94ca5b20de621dcb4c51262ac
--- /dev/null
+++ b/modules/core/templates/short_sso_interval.twig
@@ -0,0 +1,16 @@
+{% set pagetitle = 'SimpleSAMLphp'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h1>{{ header }}</h1>
+    <form style="display: inline; margin: 0px; padding: 0px" action="{{ target|escape('html') }}">
+        {% for name, value in params %}
+            <input type="hidden" name="{{ name|escape('html') }}" value="{{ value|escape('html') }}" />
+        {% endfor %}
+        <p>{{ '{core:short_sso_interval:warning}'|trans }}</p>
+        <div class="trackidtext">
+            <p>{{ '{errors:report_trackid}'|trans }}<span class="trackid">{{ trackId }}</span></p>
+        </div>
+        <input type="submit" name="continue" id="contbutton" value="'{core:short_sso_interval:retry}'|trans|escape('html') }}" />
+    </form>
+{% endblock %}
diff --git a/modules/core/templates/show_metadata.twig b/modules/core/templates/show_metadata.twig
new file mode 100644
index 0000000000000000000000000000000000000000..aca8878376620280dc8910013b80fe06d2fc5ad8
--- /dev/null
+++ b/modules/core/templates/show_metadata.twig
@@ -0,0 +1,19 @@
+{% set pagetile = 'SimpleSAMLphp Show Metadata'|trans %}
+{% extends 'base.twig' %}
+{% block content %}
+    <div class="code-box">
+        <div class="code-box-title">
+            <h3>{{ 'Metadata'|trans }}</h3>
+            <button data-clipboard-target="#metadata" id="btn{{ loop.index }}" class="pure-button right clipboard-btn">
+                <span class="fa fa-copy"></span>
+            </button>
+        </div>
+        <div class="code-box-content">
+            <pre id="metadata">$metadata[{{ entityid }}] => {{ metadata|escape }}</pre>
+        </div>
+    </div>
+    <div class="center">
+        {# TODO: translation needed #}
+        <a href="{{ backlink }}" class="pure-button pure-button-red">{{ 'Back'|trans }}</a>
+    </div>
+{% endblock content %}
diff --git a/modules/core/www/frontpage_auth.php b/modules/core/www/frontpage_auth.php
index 7e3efb97987effea8767396acb73716d153f6829..fd61b0b8c0fd2fd0605b309f19ceffbcf7d2256c 100644
--- a/modules/core/www/frontpage_auth.php
+++ b/modules/core/www/frontpage_auth.php
@@ -18,7 +18,7 @@ $links_auth = array();
 $links_federation = array();
 
 $links_auth[] = array(
-	'href' => 'authenticate.php',
+	'href' => 'login.php',
 	'text' => '{core:frontpage:authtest}',
 );
 
@@ -36,6 +36,7 @@ $t->data['pageid'] = 'frontpage_auth';
 $t->data['isadmin'] = $isadmin;
 $t->data['loginurl'] = $loginurl;
 
+$t->data['header'] = $t->getTranslator()->t('{core:frontpage:page_title}');
 $t->data['links'] = $links;
 $t->data['links_welcome'] = $links_welcome;
 $t->data['links_config'] = $links_config;
diff --git a/modules/core/www/frontpage_config.php b/modules/core/www/frontpage_config.php
index 3909bb461a7249a4c901c2a43fdaca76134f55df..050695c2786af52e8807aa4e86e284060a8c0c1c 100644
--- a/modules/core/www/frontpage_config.php
+++ b/modules/core/www/frontpage_config.php
@@ -50,7 +50,7 @@ $allLinks = array(
     'welcome'    => &$links_welcome,
     'config'     => &$links_config,
     'auth'       => &$links_auth,
-   'federation' => &$links_federation,
+    'federation' => &$links_federation,
 );
 \SimpleSAML\Module::callHooks('frontpage', $allLinks);
 
@@ -160,6 +160,7 @@ $funcmatrix[] = array(
 
 $t = new \SimpleSAML\XHTML\Template($config, 'core:frontpage_config.tpl.php');
 $t->data['pageid'] = 'frontpage_config';
+$t->data['header'] = $t->getTranslator()->t('{core:frontpage:page_title}');
 $t->data['isadmin'] = $isadmin;
 $t->data['loginurl'] = $loginurl;
 $t->data['warnings'] = $warnings;
diff --git a/modules/core/www/frontpage_federation.php b/modules/core/www/frontpage_federation.php
index 95d45d1143c5ebf365a01909fadfbf51e02887c0..658147dcac508a6280876e1f40cd5e1d1ad7236d 100644
--- a/modules/core/www/frontpage_federation.php
+++ b/modules/core/www/frontpage_federation.php
@@ -96,6 +96,40 @@ foreach ($metaentries['remote'] as $key => $value) {
 
 $t = new \SimpleSAML\XHTML\Template($config, 'core:frontpage_federation.tpl.php');
 
+$language = $t->getTranslator()->getLanguage()->getLanguage();
+$defaultLanguage = $config->getString('language.default', 'en');
+
+$translators = array(
+    'name' => 'name_translated',
+    'descr' => 'descr_translated',
+    'OrganizationDisplayName' => 'organizationdisplayname_translated',
+);
+
+foreach ($metaentries['hosted'] as $index => $entity) {
+    foreach ($translators as $old => $new) {
+        if (isset($entity[$old][$language])) {
+            $metaentries['hosted'][$index][$new] = $entity[$old][$language];
+        } elseif (isset($entity[$old][$defaultLanguage])) {
+            $metaentries['hosted'][$index][$new] = $entity[$old][$defaultLanguage];
+        } elseif (isset($metaentries['hosted'][$index][$old])) {
+            $metaentries['hosted'][$index][$new] = $metaentries['hosted'][$index][$old];
+        }
+    }
+}
+foreach ($metaentries['remote'] as $key => $set) {
+    foreach ($set as $entityid => $entity) {
+        foreach ($translators as $old => $new) {
+            if (isset($entity[$old][$language])) {
+                $metaentries['remote'][$key][$entityid][$new] = $entity[$old][$language];
+            } elseif (isset($entity[$old][$defaultLanguage])) {
+                $metaentries['remote'][$key][$entityid][$new] = $entity[$old][$defaultLanguage];
+            } elseif (isset($metaentries['remote'][$key][$entityid][$old])) {
+                $metaentries['remote'][$key][$entityid][$new] = $metaentries['remote'][$key][$entityid][$old];
+            }
+        }
+    }
+}
+
 # look up translated string
 $mtype = array(
     'saml20-sp-remote' => $t->noop('{admin:metadata_saml20-sp}'),
@@ -122,12 +156,11 @@ $t->data['links_welcome'] = $links_welcome;
 $t->data['links_config'] = $links_config;
 $t->data['links_auth'] = $links_auth;
 $t->data['links_federation'] = $links_federation;
+$t->data['header'] = $t->getTranslator()->t('{core:frontpage:page_title}');
 
-
-
+$t->data['metadata_url'] = \SimpleSAML\Module::getModuleURL('core/show_metadata.php');
 $t->data['metaentries'] = $metaentries;
 $t->data['mtype'] = $mtype;
 
-
 $t->show();
 
diff --git a/modules/core/www/frontpage_welcome.php b/modules/core/www/frontpage_welcome.php
index f96a61634e3260e040ccc14749d5e0f8faa6afed..60b9ef9565cc0b24061718a604e201f8d62e2337 100644
--- a/modules/core/www/frontpage_welcome.php
+++ b/modules/core/www/frontpage_welcome.php
@@ -42,7 +42,7 @@ $t->data['links_welcome'] = $links_welcome;
 $t->data['links_config'] = $links_config;
 $t->data['links_auth'] = $links_auth;
 $t->data['links_federation'] = $links_federation;
-
+$t->data['header'] = $t->getTranslator()->t('{core:frontpage:page_title}');
 
 
 
diff --git a/modules/core/www/idp/logout-iframe.php b/modules/core/www/idp/logout-iframe.php
index 298ffb053be2120cb134bd7d155fc7c8339bae77..547d86a1048c2a91dd5fbbfd008cbe11f44bf57a 100644
--- a/modules/core/www/idp/logout-iframe.php
+++ b/modules/core/www/idp/logout-iframe.php
@@ -122,6 +122,8 @@ if ($type === 'nojs') {
 
 $t = new \SimpleSAML\XHTML\Template($globalConfig, $template_id);
 $t->data['auth_state'] = $id;
+$t->data['header'] = $t->getTranslator()->t('{logout:progress}');
+
 /**
  * @deprecated The "id" variable will be removed. Please use "auth_state" instead.
  */
diff --git a/modules/core/www/login.php b/modules/core/www/login.php
new file mode 100644
index 0000000000000000000000000000000000000000..d4babee68df32100470f5756103adc9f2d9beb1e
--- /dev/null
+++ b/modules/core/www/login.php
@@ -0,0 +1,63 @@
+<?php
+
+$config = \SimpleSAML\Configuration::getInstance();
+$sources = \SimpleSAML\Configuration::getOptionalConfig('authsources.php')->toArray();
+
+//delete admin
+if (isset($sources['admin'])) {
+    unset($sources['admin']);
+}
+
+//if only 1 auth
+if (count($sources)==1) {
+    $_REQUEST['as'] = key($sources);
+}
+
+if (!array_key_exists('as', $_REQUEST)) {
+    $t = new \SimpleSAML\XHTML\Template($config, 'core:login.twig');
+
+    $t->data['loginurl'] = \SimpleSAML\Utils\Auth::getAdminLoginURL();
+    $t->data['sources'] = $sources;
+    $t->show();
+    exit();
+}
+
+$asId = (string) $_REQUEST['as'];
+$as = new \SimpleSAML\Auth\Simple($asId);
+
+if (array_key_exists('logout', $_REQUEST)) {
+    $as->logout($config->getBasePath().'logout.php');
+}
+
+if (array_key_exists(\SimpleSAML\Auth\State::EXCEPTION_PARAM, $_REQUEST)) {
+    // This is just a simple example of an error
+
+    $state = \SimpleSAML\Auth\State::loadExceptionState();
+    assert(array_key_exists(\SimpleSAML\Auth\State::EXCEPTION_DATA, $state));
+    $e = $state[\SimpleSAML\Auth\State::EXCEPTION_DATA];
+
+    throw $e;
+}
+
+if (!$as->isAuthenticated()) {
+    $url = \SimpleSAML\Module::getModuleURL('core/login.php', array('as' => $asId));
+    $params = array(
+        'ErrorURL' => $url,
+        'ReturnTo' => $url,
+    );
+    $as->login($params);
+}
+
+$attributes = $as->getAttributes();
+$session = \SimpleSAML\Session::getSessionFromRequest();
+
+$t = new \SimpleSAML\XHTML\Template($config, 'auth_status.twig', 'attributes');
+
+
+$t->data['header'] = '{status:header_saml20_sp}';
+$t->data['attributes'] = $attributes;
+$t->data['nameid'] = !is_null($as->getAuthData('saml:sp:NameID')) ? $as->getAuthData('saml:sp:NameID') : false;
+$t->data['logouturl'] = \SimpleSAML\Utils\HTTP::getSelfURLNoQuery().'?as='.urlencode($asId).'&logout';
+$t->data['remaining'] = $session->getAuthData($asId, 'Expire')-time();
+
+$t->show();
diff --git a/modules/core/www/loginuserpass.php b/modules/core/www/loginuserpass.php
index af7b9000fcb701135400243477d5d41cede4ef6f..0b97e55cbd14077e511e121365083ed7919eac62 100644
--- a/modules/core/www/loginuserpass.php
+++ b/modules/core/www/loginuserpass.php
@@ -40,6 +40,13 @@ if (array_key_exists('password', $_REQUEST)) {
 
 $errorCode = null;
 $errorParams = null;
+$queryParams = array();
+
+if (isset($state['error'])) {
+    $errorCode = $state['error']['code'];
+    $errorParams = $state['error']['params'];
+    $queryParams = array('AuthState' => $authStateId);
+}
 
 if (!empty($_REQUEST['username']) || !empty($password)) {
     // Either username or password set - attempt to log in
@@ -69,6 +76,15 @@ if (!empty($_REQUEST['username']) || !empty($password)) {
         /* Login failed. Extract error code and parameters, to display the error. */
         $errorCode = $e->getErrorCode();
         $errorParams = $e->getParameters();
+        $state['error']= array(
+            'code' => $errorCode,
+            'params' => $errorParams
+        );
+        $authStateId = \SimpleSAML\Auth\State::saveState($state, \SimpleSAML\Module\core\Auth\UserPassBase::STAGEID);
+        $queryParams = array('AuthState' => $authStateId);
+	}
+	if (isset($state['error'])){
+	    unset($state['error']);
     }
 }
 
@@ -97,6 +113,9 @@ $t->data['links'] = $source->getLoginLinks();
 $t->data['errorcode'] = $errorCode;
 $t->data['errorcodes'] = SimpleSAML\Error\ErrorCodes::getAllErrorCodeMessages();
 $t->data['errorparams'] = $errorParams;
+if (!empty($queryParams)) {
+    $t->data['queryParams'] = $queryParams;
+}
 
 if (isset($state['SPMetadata'])) {
     $t->data['SPMetadata'] = $state['SPMetadata'];
diff --git a/modules/core/www/loginuserpassorg.php b/modules/core/www/loginuserpassorg.php
index 91a858a017bb035c8514ba1f3e721ba87ac40676..acbad36735b11c8e327a19b32e362824f6bf262e 100644
--- a/modules/core/www/loginuserpassorg.php
+++ b/modules/core/www/loginuserpassorg.php
@@ -51,6 +51,14 @@ if (array_key_exists('organization', $_REQUEST)) {
 
 $errorCode = null;
 $errorParams = null;
+$queryParams = array();
+
+if (isset($state['error'])) {
+    $errorCode = $state['error']['code'];
+    $errorParams = $state['error']['params'];
+    $queryParams = array('AuthState' => $authStateId);
+}
+
 if ($organizations === null || !empty($organization)) {
     if (!empty($username) || !empty($password)) {
 
@@ -76,6 +84,15 @@ if ($organizations === null || !empty($organization)) {
             // Login failed. Extract error code and parameters, to display the error
             $errorCode = $e->getErrorCode();
             $errorParams = $e->getParameters();
+            $state['error']= array(
+                'code' => $errorCode,
+                'params' => $errorParams
+            );
+            $authStateId = \SimpleSAML\Auth\State::saveState($state, \SimpleSAML\Module\core\Auth\UserPassOrgBase::STAGEID);
+            $queryParams = array('AuthState' => $authStateId);
+        }
+        if (isset($state['error'])){
+            unset($state['error']);
         }
     }
 }
@@ -101,6 +118,10 @@ $t->data['errorcode'] = $errorCode;
 $t->data['errorcodes'] = \SimpleSAML\Error\ErrorCodes::getAllErrorCodeMessages();
 $t->data['errorparams'] = $errorParams;
 
+if (!empty($queryParams)) {
+    $t->data['queryParams'] = $queryParams;
+}
+
 if ($organizations !== null) {
     $t->data['selectedOrg'] = $organization;
     $t->data['organizations'] = $organizations;
diff --git a/modules/core/www/no_cookie.php b/modules/core/www/no_cookie.php
index 8ad2e3c83ea97ad30d35bde4ada7914afd5229fd..3575d85f6b4b3cc3e623baa4c457c7dff2cd7de7 100644
--- a/modules/core/www/no_cookie.php
+++ b/modules/core/www/no_cookie.php
@@ -9,5 +9,10 @@ if (isset($_REQUEST['retryURL'])) {
 
 $globalConfig = \SimpleSAML\Configuration::getInstance();
 $t = new \SimpleSAML\XHTML\Template($globalConfig, 'core:no_cookie.tpl.php');
+$translator = $t->getTranslator();
+
+$t->data['header'] = htmlspecialchars($translator->t('{core:no_cookie:header}'));
+$t->data['description'] = htmlspecialchars($translator->t('{core:no_cookie:description}'));
+$t->data['retry'] = htmlspecialchars($translator->t('{core:no_cookie:retry}'));
 $t->data['retryURL'] = $retryURL;
 $t->show();
diff --git a/modules/core/www/short_sso_interval.php b/modules/core/www/short_sso_interval.php
index 7618d9c970dc059a43188e3148168eb8f3505d14..d1f5ae32dd5dfec1fa3b38d08f83163411c98c81 100644
--- a/modules/core/www/short_sso_interval.php
+++ b/modules/core/www/short_sso_interval.php
@@ -24,4 +24,6 @@ $t = new \SimpleSAML\XHTML\Template($globalConfig, 'core:short_sso_interval.php'
 $t->data['target'] = \SimpleSAML\Module::getModuleURL('core/short_sso_interval.php');
 $t->data['params'] = array('StateId' => $id);
 $t->data['trackId'] = $session->getTrackID();
+$this->data['header'] = $this->t('{core:short_sso_interval:warning_header}');
+$this->data['autofocus'] = 'contbutton';
 $t->show();
diff --git a/modules/core/www/show_metadata.php b/modules/core/www/show_metadata.php
index 2edfd3e78e11eeb3fa0ea46feebe31f87cdc3e05..389d12a3309d5818a154b8ced1a79b6ca357f5e2 100644
--- a/modules/core/www/show_metadata.php
+++ b/modules/core/www/show_metadata.php
@@ -30,5 +30,8 @@ $t->data['pageid'] = 'show_metadata';
 $t->data['header'] = 'SimpleSAMLphp Show Metadata';
 $t->data['backlink'] = \SimpleSAML\Module::getModuleURL('core/frontpage_federation.php');
 $t->data['m'] = $m;
+$t->data['entityid'] = $m['metadata-index'];
+unset($m['metadata-index']);
+$t->data['metadata'] = var_export($m, true);
 
 $t->show();
diff --git a/modules/cron/hooks/hook_frontpage.php b/modules/cron/hooks/hook_frontpage.php
index d4d11edd09aae31994ff2563db64c595df60323b..340b01636df85feda476c725bd003b04f56d48a0 100644
--- a/modules/cron/hooks/hook_frontpage.php
+++ b/modules/cron/hooks/hook_frontpage.php
@@ -10,7 +10,7 @@ function cron_hook_frontpage(&$links) {
 
 	$links['config'][] = array(
 		'href' => SimpleSAML\Module::getModuleURL('cron/croninfo.php'),
-		'text' => array('en' => 'Cron module information page'),
+		'text' => '{core:frontpage:link_cron}',
 	);
 
 }
diff --git a/modules/cron/templates/croninfo-result.twig b/modules/cron/templates/croninfo-result.twig
new file mode 100644
index 0000000000000000000000000000000000000000..f226ffe07e9c24c14680f98223b10bb0b5ce7ef2
--- /dev/null
+++ b/modules/cron/templates/croninfo-result.twig
@@ -0,0 +1,30 @@
+{% set pagetitle = 'Cron result page'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+
+<p>
+{{ 'Here are the result for the cron job execution:'|trans }}
+</p>
+
+<div class="code-box code-box-content">
+<h2>{{ 'Cron report'|trans }}</h2>
+
+<code>
+{{ 'Cron ran at'|trans }} {{ time }}
+<p>
+URL: {{ url }}
+</p>
+<p>
+Tag: {{ tag }}
+</p>
+<p><ul>
+{% for sum in summary %}
+        <li> {{ sum }}</li>
+{% endfor %}
+</ul><br />
+</p>
+</code>
+
+</div>
+{% endblock %}
diff --git a/modules/cron/templates/croninfo.twig b/modules/cron/templates/croninfo.twig
new file mode 100644
index 0000000000000000000000000000000000000000..a4deaaa7716c8e0412f5a2c9142eddd18f344129
--- /dev/null
+++ b/modules/cron/templates/croninfo.twig
@@ -0,0 +1,25 @@
+{% set pagetitle = 'Cron result page'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h2>{{ 'Cron result page'|trans }}</h2>
+    <p>{{ 'Cron is a way to run things regularly on unix systems.'|trans }}<br /><br /></p>
+    <p>{{ 'Here is a suggestion for a crontab file:'|trans }}<br /><br /></p>
+
+    <div class="code-box code-box-content">
+        <code>
+        {% for url in urls %}
+                # {{ 'Run cron:'|trans }} [{{ url.tag }}]<br />
+                {{ url.int }} curl --silent "{{ url.href }}" > /dev/null 2>&1<br />
+        {% endfor %}
+    </code></div><br />
+
+    <p>{{ 'Click here to run the cron jobs:'|trans }}</p>
+      <ul>
+        {% for url in urls %}
+        <li><a href="{{ url.href }}&amp;output=xhtml">{{ 'Run cron:'|trans }} {{ url.tag }}</a></li>
+        {% endfor %}
+      </ul>
+    </p>
+
+{% endblock %}    
diff --git a/modules/discopower/lib/PowerIdPDisco.php b/modules/discopower/lib/PowerIdPDisco.php
index d1d143eaefb1da13f5bba094d5805761c9471545..cbfa86270920e45f91cc51eac672ea027e5b64b9 100644
--- a/modules/discopower/lib/PowerIdPDisco.php
+++ b/modules/discopower/lib/PowerIdPDisco.php
@@ -127,7 +127,7 @@ class PowerIdPDisco extends \SimpleSAML\XHTML\IdPDisco
                 $tags = $val['tags'];
             }
             foreach ($tags as $tag) {
-                if (!empty($enableTabs) && !in_array($tag, $enableTabs, true)) {
+                if (!empty($enableTabs) && !in_array($tag, $enableTabs)) {
                     continue;
                 }
                 $slist[$tag][$key] = $val;
@@ -153,21 +153,21 @@ class PowerIdPDisco extends \SimpleSAML\XHTML\IdPDisco
      */
     private function processFilter($filter, $entry, $default = true)
     {
-        if (in_array($entry['entityid'], $filter['entities.include'], true)) {
+        if (in_array($entry['entityid'], $filter['entities.include'])) {
             return true;
         }
-        if (in_array($entry['entityid'], $filter['entities.exclude'], true)) {
+        if (in_array($entry['entityid'], $filter['entities.exclude'])) {
             return false;
         }
 
         if (array_key_exists('tags', $entry)) {
             foreach ($filter['tags.include'] as $fe) {
-                if (in_array($fe, $entry['tags'], true)) {
+                if (in_array($fe, $entry['tags'])) {
                     return true;
                 }
             }
             foreach ($filter['tags.exclude'] as $fe) {
-                if (in_array($fe, $entry['tags'], true)) {
+                if (in_array($fe, $entry['tags'])) {
                     return false;
                 }
             }
@@ -246,44 +246,121 @@ class PowerIdPDisco extends \SimpleSAML\XHTML\IdPDisco
         $idpList = $this->getIdPList();
         $idpList = $this->idplistStructured($this->filterList($idpList));
         $preferredIdP = $this->getRecommendedIdP();
-        $faventry = null;
-        foreach ($idpList AS $tab => $slist) {
-            if (!empty($preferredIdP) && array_key_exists($preferredIdP, $slist)) {
-                $faventry = $slist[$preferredIdP];
-            }
-        }
 
         $t = new \SimpleSAML\XHTML\Template($this->config, 'discopower:disco.tpl.php', 'disco');
         $discoPowerTabs = array(
-            'denmark' => $t->noop('{discopower:tabs:denmark}'),
-            'edugain' => $t->noop('{discopower:tabs:edugain}'),
-            'finland' => $t->noop('{discopower:tabs:finland}'),
-            'greece' => $t->noop('{discopower:tabs:greece}'),
-            'southafrica' => $t->noop('{discopower:tabs:southafrica}'),
-            'iceland' => $t->noop('{discopower:tabs:iceland}'),
-            'incommon' => $t->noop('{discopower:tabs:incommon}'),
-            'kalmar' => $t->noop('{discopower:tabs:kalmar}'),
-            'misc' => $t->noop('{discopower:tabs:misc}'),
-            'norway' => $t->noop('{discopower:tabs:norway}'),
-            'sweden' => $t->noop('{discopower:tabs:sweden}'),
-            'switzerland' => $t->noop('{discopower:tabs:switzerland}'),
-            'ukacessfederation' => $t->noop('{discopower:tabs:ukacessfederation}'),
+            'denmark' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:denmark}'),
+            'edugain' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:edugain}'),
+            'finland' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:finland}'),
+            'greece' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:greece}'),
+            'southafrica' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:southafrica}'),
+            'iceland' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:iceland}'),
+            'incommon' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:incommon}'),
+            'kalmar' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:kalmar}'),
+            'misc' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:misc}'),
+            'norway' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:norway}'),
+            'sweden' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:sweden}'),
+            'switzerland' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:switzerland}'),
+            'ukacessfederation' => \SimpleSAML\Locale\Translate::noop('{discopower:tabs:ukacessfederation}'),
         );
-        $t->data['faventry'] = $faventry;
-        $t->data['tabNames'] = $discoPowerTabs;
-        $t->data['idplist'] = $idpList;
-        $t->data['preferredidp'] = $preferredIdP;
+
         $t->data['return'] = $this->returnURL;
         $t->data['returnIDParam'] = $this->returnIdParam;
         $t->data['entityID'] = $this->spEntityId;
+        $t->data['defaulttab'] = $this->discoconfig->getValue('defaulttab', 0);
+
+        $idpList = $this->processMetadata($t, $idpList, $preferredIdP);
+
+        $t->data['idplist'] = $idpList;
+        $faventry = null;
+        foreach ($idpList as $tab => $slist) {
+            if (!empty($preferredIdP) && array_key_exists($preferredIdP, $slist)) {
+                $t->data['faventry'] = $slist[$preferredIdP];
+                break;
+            }
+        }
+
+        if (!empty($t->data['faventry'])) {
+            $t->data['autofocus'] = 'favouritesubmit';
+        }
+
+        $search = '<script type="text/javascript">
+            $(document).ready(function() {
+                $("#tabdiv").tabs({ selected: ' . $t->data['defaulttab'] . ' });';
+        $i = 0;
+        foreach ($idpList as $tab => $slist) {
+            $search .= "\n" . '$("#query_' . $tab . '").liveUpdate("#list_' . $tab . '")' .
+		(($i++ == 0) && (empty($this->data['faventry'])) ? '.focus()' : '') . ';';
+        }
+        $search .= "});\n</script>";
+
+        $t->data['search'] = $search;
+        $t->data['score'] = $this->discoconfig->getValue('score', 'quicksilver');
+        $t->data['tabNames'] = $discoPowerTabs;
+        $t->data['preferredidp'] = $preferredIdP;
         $t->data['urlpattern'] = htmlspecialchars(\SimpleSAML\Utils\HTTP::getSelfURLNoQuery());
         $t->data['rememberenabled'] = $this->config->getBoolean('idpdisco.enableremember', false);
         $t->data['rememberchecked'] = $this->config->getBoolean('idpdisco.rememberchecked', false);
-        $t->data['defaulttab'] = $this->discoconfig->getValue('defaulttab', 0);
-        $t->data['score'] = $this->discoconfig->getValue('score', 'quicksilver');
+        $t->data['jquery'] = array('core' => true, 'ui' => true);
         $t->show();
     }
 
+    private function processMetadata($t, $metadata, $favourite)
+    {
+        $basequerystring = '?' . 
+		'entityID=' . urlencode($t->data['entityID']) . '&amp;' . 
+		'return=' . urlencode($t->data['return']) . '&amp;' . 
+		'returnIDParam=' . urlencode($t->data['returnIDParam']) . '&amp;idpentityid=';
+
+        foreach ($metadata as $tab => $idps) {
+            foreach ($idps as $entityid => $entity) {
+                $translation = false;
+
+                // Translate name
+                if (isset($entity['UIInfo']['DisplayName'])) {
+                    $displayName = $entity['UIInfo']['DisplayName'];
+
+                    // Should always be an array of language code -> translation
+                    assert(is_array($displayName));
+
+                    if (!empty($displayName)) {
+                        $translation = $t->getTranslator()->getPreferredTranslation($displayName);
+                    }
+                }
+	
+                if (($translation === false) && array_key_exists('name', $entity)) {
+                    if (is_array($entity['name'])) {
+                        $translation = $t->getTranslator()->getPreferredTranslation($entity['name']);
+                    } else {
+                        $translation = $entity['name'];
+                    }
+                }
+
+                if ($translation === false) {
+                    $translation = $entity['entityid'];
+                }
+                $entity['translated'] = $translation;
+
+                // HTML output
+                if ($entity['entityid'] === $favourite) {
+                    $html = '<a class="metaentry favourite" href="' . $basequerystring . urlencode($entity['entityid']) . '">';
+                } else {
+                    $html = '<a class="metaentry" href="' . $basequerystring . urlencode($entity['entityid']) . '">';
+                }
+                $html .= $entity['translated'];
+                if (array_key_exists('icon', $entity) && $entity['icon'] !== null) {
+                    $iconUrl = \SimpleSAML\Utils\HTTP::resolveURL($entity['icon']);
+                    $html .= '<img alt="Icon for identity provider" class="entryicon" src="' . htmlspecialchars($iconUrl) . '" />';
+                }
+                $html .= '</a>';
+                $entity['html'] = $html;
+
+                // Save processed data
+                $metadata[$tab][$entityid] = $entity;
+            }
+        }
+        return $metadata;
+    }
 
     /**
      * Get the IdP entities saved in the common domain cookie.
diff --git a/modules/discopower/templates/disco.tpl.php b/modules/discopower/templates/disco.tpl.php
index b7b1001219a31da01cb39fd8219fd950f990631d..396b1527353b128604cd5e76b97dc41b1b080a0e 100644
--- a/modules/discopower/templates/disco.tpl.php
+++ b/modules/discopower/templates/disco.tpl.php
@@ -8,28 +8,8 @@ $this->data['jquery'] = array('core' => TRUE, 'ui' => TRUE, 'css' => TRUE);
 
 $this->data['head'] = '<link rel="stylesheet" media="screen" type="text/css" href="' . SimpleSAML\Module::getModuleUrl('discopower/style.css')  . '" />';
 
-$this->data['head'] .= '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/jquery.livesearch.js')  . '"></script>';
-$this->data['head'] .= '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/' . $this->data['score'] . '.js')  . '"></script>';
-
-$this->data['head'] .= '<script type="text/javascript">
-
-$(document).ready(function() {
-	$("#discotabs").tabs({ selected: ' . $this->data['defaulttab'] . ' }); ';
-	
-$i = 0;
-foreach ($this->data['idplist'] AS $tab => $slist) {
-	$this->data['head'] .= "\n" . '$("#query_' . $tab . '").liveUpdate("#list_' . $tab . '")' .
-		(($i++ == 0) && (empty($this->data['faventry'])) ? '.focus()' : '') .
-		';';
-
-
-}
-
-$this->data['head'] .= '
-});
-
-</script>';
-
+$this->data['post'] = '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/jquery.livesearch.js')  . '"></script>';
+$this->data['post'] .= '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/quicksilver.js')  . '"></script>';
 
 
 
@@ -116,15 +96,21 @@ if (!empty($this->data['faventry'])) {
 
 
 
-<div id="discotabs"> 
+<div id="tabdiv"> 
 
     <ul class="tabset_tabs">     
     	<?php
     	
     		$tabs = array_keys( $this->data['idplist']);
+                $i = 1;
     		foreach ($tabs AS $tab) {
 			if(!empty($this->data['idplist'][$tab])) {
-				echo '<li><a href="#' . $tab . '"><span>' . $this->t($this->data['tabNames'][$tab]) . '</span></a></li> ';
+                                if ($i === 1) {
+					echo '<li class="tab-link current" data-tab="'.$tab.'"><a href="#' . $tab . '"><span>' . $this->t($this->data['tabNames'][$tab]) . '</span></a></li>';
+				} else {
+					echo '<li class="tab-link" data-tab="'.$tab.'"><a href="#' . $tab . '"><span>' . $this->t($this->data['tabNames'][$tab]) . '</span></a></li> ';
+				}
+				$i++;
 			}
     		}
     	
@@ -138,14 +124,17 @@ if (!empty($this->data['faventry'])) {
 
 
 foreach( $this->data['idplist'] AS $tab => $slist) {
-
-	echo '<div id="' . $tab . '">';
-
+        $first = array_keys($this->data['idplist']);
+        if ($first[0] === $tab) {
+	    echo '<div id="' . $tab . '" class="tabset_content current">';
+        } else {
+	    echo '<div id="' . $tab . '" class="tabset_content">';
+        }	
 	if (!empty($slist)) {
 
 		echo('	<div class="inlinesearch">');
 		echo('	<p>Incremental search...</p>');
-		echo('	<form id="idpselectform" action="?" method="get"><input class="inlinesearchf" type="text" value="" name="query_' . $tab . '" id="query_' . $tab . '" /></form>');
+		echo('	<form id="idpselectform" action="?" method="get"><input class="inlinesearch" type="text" value="" name="query_' . $tab . '" id="query_' . $tab . '" /></form>');
 		echo('	</div>');
 	
 		echo('	<div class="metalist" id="list_' . $tab  . '">');
@@ -171,5 +160,22 @@ foreach( $this->data['idplist'] AS $tab => $slist) {
 
 </div>
 
-		
-<?php $this->includeAtTemplateBase('includes/footer.php');
+<script type="text/javascript">
+$(document).ready(function() {
+<?php
+$i = 0;
+foreach ($this->data['idplist'] AS $tab => $slist) {
+	echo "\n" . '$("#query_' . $tab . '").liveUpdate("#list_' . $tab . '")' .
+		(($i++ == 0) && (empty($this->data['faventry'])) ? '.focus()' : '') .
+		';';
+
+
+}
+?>
+});
+
+</script>
+
+<?php
+$this->data['post'] .= '<script type="text/javascript" src="' . SimpleSAML\Module::getModuleUrl('discopower/js/javascript.js') . '"></script>';
+$this->includeAtTemplateBase('includes/footer.php');
diff --git a/modules/discopower/templates/disco.twig b/modules/discopower/templates/disco.twig
new file mode 100644
index 0000000000000000000000000000000000000000..3645cdb169a6b53dc3b78446236430b7b425ec87
--- /dev/null
+++ b/modules/discopower/templates/disco.twig
@@ -0,0 +1,66 @@
+{% set pagetitle = 'selectidp'|trans %}
+{% extends "base.twig" %}
+
+{% block preload %}
+    <link href="{{ baseurlpath }}style.css" rel="stylesheet" type="text/css" media="screen" />
+{% endblock %}
+{% block postload %}
+    <script type="text/javascript" src="{{ baseurlpath }}js/jquery.livesearch.js"></script>
+    <script type="text/javascript" src="{{ baseurlpath }}js/{{ score }}.js"></script>
+    {{ search|raw }}
+{% endblock %}
+
+{% block content %}
+    {% if faventry is not empty %}
+    <div class="favourite">{{ '{disco:previous_auth}'|trans }}
+        <strong>{{ faventry.translated|escape('html') }}</strong>
+        <form id="idpselectform" method="get" action="{{ urlpattern }}">
+            <input type="hidden" name="entityID" value="{{ entityID|escape('html') }}" />
+            <input type="hidden" name="return" value="{{ return|escape('html') }}" />
+            <input type="hidden" name="returnIDParam" value="{{ returnIDParam|escape('html') }}" />
+            <input type="hidden" name="idpentityid" value="{{ faventry.entityid|escape('html') }}" />
+            <input type="submit" name="formsubmit" id="favouritesubmit" value="{{ '{disco:login_at}'|trans }} {{ faventry.translated|escape('html') }}" /> 
+	</form>
+    </div>
+    {% endif %}
+
+    <div id="tabdiv">
+        <ul class="tabset_tabs">
+        {% set i = 1 %}
+        {% for tab, idps in idplist %}
+            {% if idps is not empty %}
+            {% if i == 1 %}
+            <li class="tab-link current" data-tab="{{ tab }}"><a href="#{{ tab }}"><span>{{ tabNames[tab]|trans }}</span></a></li>
+            {% set i = 2 %}
+            {% else %}
+            <li class="tab-link" data-tab="{{ tab }}"><a href="#{{ tab }}"><span>{{ tabNames[tab]|trans }}</span></a></li>
+            {% endif %}
+            {% endif %}
+        {% endfor %}
+        </ul>
+
+        {% set i = 1 %}
+        {% for tab, idps in idplist %}
+        {% if idps is not empty %}
+          {% if i == 1 %}
+          <div id="{{ tab }}" class="tabset_content current">
+          {% set i = 2 %}
+          {% else %}
+          <div id="{{ tab }}" class="tabset_content">
+          {% endif %}
+          <div class="inlinesearch">
+              <p>Incremental search...</p>
+              <form id="idpselectform" method="get">
+                  <input class="inlinesearch" type="text" value="" name="query_{{ tab }}" id="query_{{ tab }}" />
+              </form>
+          </div>
+          <div class="metalist" id="list_{{ tab }}">
+          {% for entityid, entity in idps %}
+              {{ entity.html|raw }}
+          {% endfor %}
+          </div>
+          </div>
+        {% endif %}
+        {% endfor %}
+    </div>
+{% endblock %}
diff --git a/modules/discopower/www/style.css b/modules/discopower/www/style.css
index 709c53601ad3a326dc8909e56c13a78f844a3a86..dddb03c2221ba40ca07a1783f20b0f1b345ed233 100644
--- a/modules/discopower/www/style.css
+++ b/modules/discopower/www/style.css
@@ -1,16 +1,10 @@
-.inlinesearch:hover {
-
-}
 .inlinesearch {
     float: right;
     margin: 0em 3px .5em 1em;
-	
-/*  padding: .3em;*/
 }
 .inlinesearch p {
     font-size: 94%;
     color: #aaa;
-
 }
 .inlinesearch input {
     background-image:url('../../resources/icons/silk/magnifier.png');
@@ -42,7 +36,6 @@ a.metaentry.favourite {
     background-image:url('../../resources/icons/silk/heart.png');
     background-repeat:no-repeat;
     background-position:center left;
-
 }
 a.metaentry:hover {
     border: 1px solid #ccc;
@@ -71,3 +64,44 @@ div.favourite {
     border: 1px solid #ccc;
     background-color: #eee;
 }
+
+div#content {
+    margin: .4em ! important;
+}
+
+form {
+    display: inline;
+}
+
+table#statmeta {
+    width: 100%;
+}
+
+ul.tabset_tabs {
+    margin: 0px;
+    padding: 0px;
+    list-style: none;
+}
+
+ul.tabset_tabs li {
+    background: none;
+    color: #222;
+    display: inline-block;
+    padding: 10px 15px;
+    cursor: pointer;
+}
+
+ul.tabset_tabs li.current {
+    background: #ededed;
+    color: #222;
+}
+
+.tabset_content {
+    display: none;
+    background: #ededed;
+    padding: 15px;
+}
+
+.tabset_content.current {
+    display: inherit;
+}
diff --git a/modules/expirycheck/templates/about2expire.php b/modules/expirycheck/templates/about2expire.php
index e2be96973a3344bac195bbc1ada897dcdede511c..f8749fdf6203c1076a1ab1c9de70183358f02402 100644
--- a/modules/expirycheck/templates/about2expire.php
+++ b/modules/expirycheck/templates/about2expire.php
@@ -16,50 +16,6 @@
  * @package SimpleSAMLphp
  */
 
-# netid will expire today
-if ($this->data['daysleft'] == 0) {
-	$this->data['header'] = $this->t('{expirycheck:expwarning:warning_header_today}', array(
-				'%NETID%' => htmlspecialchars($this->data['netId'])
-			));
-
-	$warning = $this->t('{expirycheck:expwarning:warning_today}', array(
-				'%NETID%' => htmlspecialchars($this->data['netId'])
-			));
-
-}
-# netid will expire in one day
-elseif ($this->data['daysleft'] == 1) {
-
-	$this->data['header'] = $this->t('{expirycheck:expwarning:warning_header}', array(
-				'%NETID%' => htmlspecialchars($this->data['netId']),
-				'%DAYS%' => $this->t('{expirycheck:expwarning:day}'),
-				'%DAYSLEFT%' => htmlspecialchars($this->data['daysleft']),
-			));
-
-	$warning = $this->t('{expirycheck:expwarning:warning}', array(
-				'%NETID%' => htmlspecialchars($this->data['netId']),
-				'%DAYS%' => $this->t('{expirycheck:expwarning:day}'),
-				'%DAYSLEFT%' => htmlspecialchars($this->data['daysleft']),
-			));
-
-}
-# netid will expire in next <daysleft> days
-else {
-	$this->data['header'] = $this->t('{expirycheck:expwarning:warning_header}', array(
-				'%NETID%' => htmlspecialchars($this->data['netId']),
-				'%DAYS%' => $this->t('{expirycheck:expwarning:days}'),
-				'%DAYSLEFT%' => htmlspecialchars($this->data['daysleft']),
-			));
-
-	$warning = $this->t('{expirycheck:expwarning:warning}', array(
-				'%NETID%' => htmlspecialchars($this->data['netId']),
-				'%DAYS%' => $this->t('{expirycheck:expwarning:days}'),
-				'%DAYSLEFT%' => htmlspecialchars($this->data['daysleft']),
-			));
-
-
-}
-
 $this->data['autofocus'] = 'yesbutton';
 
 $this->includeAtTemplateBase('includes/header.php');
diff --git a/modules/expirycheck/templates/about2expire.twig b/modules/expirycheck/templates/about2expire.twig
new file mode 100644
index 0000000000000000000000000000000000000000..c60788051a4a8339aeb5f86a986062dfb80b4360
--- /dev/null
+++ b/modules/expirycheck/templates/about2expire.twig
@@ -0,0 +1,13 @@
+{% set pagetitle = 'SimpleSAMLphp'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <form style="display: inline; margin: 0px; padding: 0px" action="{{ yesTarget|escape('html') }}">
+        {% for name, value in yesData %}
+        <input type="hidden" name="{{ name|escape('html') }}" value="{{ value|escape('html') }}" />
+        {% endfor %}
+        <h3>{{ warning }}</h3>
+        <p>{{ '{expirycheck:expwarning:expiry_date_text}'|trans }} {{ expireOnDate }}</p>
+        <input type="submit" name="yes" id="yesbutton" value="{{ '{expirycheck:expwarning:btn_continue}'|trans }}" />
+    </form>
+{% endblock %}
diff --git a/modules/expirycheck/templates/expired.twig b/modules/expirycheck/templates/expired.twig
new file mode 100644
index 0000000000000000000000000000000000000000..8c0cecbc116646505319812cd30ecb088c069ae7
--- /dev/null
+++ b/modules/expirycheck/templates/expired.twig
@@ -0,0 +1,9 @@
+{% set pagetitle = 'SimpleSAMLphp'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h2>{{ '{expirycheck:expwarning:access_denied}'|trans }})</h2>
+    <p>{{ '{expirycheck:expwarning:no_access_to}'|trans({'%NETID%': netId}, "app") }}</p>
+    <p>{{ '{expirycheck:expwarning:expiry_date_text}'|trans }} <b>{{ expireOnDate }}</b></p>
+    <p>{{ '{expirycheck:expwarning:contact_home}'|trans }}</p>
+{% endblock %}
diff --git a/modules/expirycheck/www/about2expire.php b/modules/expirycheck/www/about2expire.php
index 56e2fdc13f19c62969999a2c1ab9972e1a4f222b..fa502121e5699db9df40972157ea2d3cb91a307f 100644
--- a/modules/expirycheck/www/about2expire.php
+++ b/modules/expirycheck/www/about2expire.php
@@ -21,10 +21,49 @@ if (array_key_exists('yes', $_REQUEST)) {
 
 $globalConfig = \SimpleSAML\Configuration::getInstance();
 
+$daysleft = $state['daysleft'];
+
 $t = new \SimpleSAML\XHTML\Template($globalConfig, 'expirycheck:about2expire.php');
+$t->data['autofocus'] = 'yesbutton';
 $t->data['yesTarget'] = \SimpleSAML\Module::getModuleURL('expirycheck/about2expire.php');
 $t->data['yesData'] = array('StateId' => $id);
-$t->data['daysleft'] = $state['daysleft'];
+$t->data['warning'] = $warning;
 $t->data['expireOnDate'] = $state['expireOnDate'];
 $t->data['netId'] = $state['netId'];
+
+if ($daysleft == 0) {
+    # netid will expire today
+    $this->data['header'] = $this->t('{expirycheck:expwarning:warning_header_today}', array(
+                                '%NETID%' => htmlspecialchars($this->data['netId'])
+                        ));
+    $this->data['warning'] = $this->t('{expirycheck:expwarning:warning_today}', array(
+                                '%NETID%' => htmlspecialchars($this->data['netId'])
+                        ));
+} elseif ($daysleft == 1) {
+    # netid will expire in one day
+
+    $this->data['header'] = $this->t('{expirycheck:expwarning:warning_header}', array(
+                                '%NETID%' => htmlspecialchars($this->data['netId']),
+                                '%DAYS%' => $this->t('{expirycheck:expwarning:day}'),
+                                '%DAYSLEFT%' => htmlspecialchars($daysleft),
+                        ));
+    $this->data['warning'] = $this->t('{expirycheck:expwarning:warning}', array(
+                                '%NETID%' => htmlspecialchars($this->data['netId']),
+                                '%DAYS%' => $this->t('{expirycheck:expwarning:day}'),
+                                '%DAYSLEFT%' => htmlspecialchars($daysleft),
+                        ));
+} else {
+    # netid will expire in next <daysleft> days
+    $this->data['header'] = $this->t('{expirycheck:expwarning:warning_header}', array(
+                                '%NETID%' => htmlspecialchars($this->data['netId']),
+                                '%DAYS%' => $this->t('{expirycheck:expwarning:days}'),
+                                '%DAYSLEFT%' => htmlspecialchars($daysleft),
+                        ));
+    $this->data['warning'] = $this->t('{expirycheck:expwarning:warning}', array(
+                                '%NETID%' => htmlspecialchars($this->data['netId']),
+                                '%DAYS%' => $this->t('{expirycheck:expwarning:days}'),
+                                '%DAYSLEFT%' => htmlspecialchars($daysleft),
+                        ));
+}
+
 $t->show();
diff --git a/modules/memcacheMonitor/hooks/hook_frontpage.php b/modules/memcacheMonitor/hooks/hook_frontpage.php
index fa0d4503809806c67683ae1418fc5c7a511d1194..526359b05bfcde960ea89f88832c5a38ad2e5508 100644
--- a/modules/memcacheMonitor/hooks/hook_frontpage.php
+++ b/modules/memcacheMonitor/hooks/hook_frontpage.php
@@ -10,7 +10,7 @@ function memcacheMonitor_hook_frontpage(&$links) {
 
 	$links['config'][] = array(
 		'href' => SimpleSAML\Module::getModuleURL('memcacheMonitor/memcachestat.php'),
-		'text' => array('en' => 'MemCache Statistics'),
+		'text' => '{core:frontpage:link_memcacheMonitor}',
 	);
 	
 }
diff --git a/modules/memcacheMonitor/templates/memcachestat.twig b/modules/memcacheMonitor/templates/memcachestat.twig
new file mode 100644
index 0000000000000000000000000000000000000000..f3d4cbd013eb655c0c9bc986f06501d7f85be7f9
--- /dev/null
+++ b/modules/memcacheMonitor/templates/memcachestat.twig
@@ -0,0 +1,38 @@
+{% set pagetitle = 'SimpleSAMLphp Memcache Monitor'|trans %}
+{% extends "base.twig" %}
+
+{% block preload %}
+    <link href="{{ baseurlpath }}style.css" rel="stylesheet" />
+{% endblock %}
+
+{% block content %}
+    <h2>{{ title }}</h2>
+    <table class="statustable">
+        <tr>
+            <th>&nbsp;</th>
+            {% for key, title in colTitles %}
+            <th>{{ title|escape('html') }}</th>
+            {% endfor %}
+        </tr>
+        {% for rowTitle, rowData in table %}
+        <tr>
+            <th class="rowtitle" style="text-align: right">{{ rowTitles[rowTitle]|trans }}</th>
+            {% for key, colTitle in colTitles %}
+            {% if rowData[colTitle] is defined %}
+            <td>{{ rowData[colTitle]|escape('html') }}</td>
+            {% else %}
+            <td>&nbsp;</td>
+            {% endif %}
+            {% endfor %}
+        </tr>
+        {% endfor %}
+    </table>
+
+    {% if usage is defined %}
+    {% for key, value in usage %}
+    <h3>Storage usage on [{{ key }}]</h3>
+        <div class="bmax" style="width: {{ maxpix }}">
+            <div class="bused" style="width: {{ usage[key] }}">Used: {{ table.bytes[key] }}</div>Total available: {{ table.limit_maxbytes[key] }}</div>
+    {% endfor %}
+    {% endif %}
+{% endblock %}
diff --git a/modules/memcacheMonitor/www/memcachestat.php b/modules/memcacheMonitor/www/memcachestat.php
index ccf97bb049af9d0fa3e7ef9d68837c1e08f810ce..30eb76cbeff8c3b72c8f30c4ddbcc94663c39237 100644
--- a/modules/memcacheMonitor/www/memcachestat.php
+++ b/modules/memcacheMonitor/www/memcachestat.php
@@ -145,8 +145,30 @@ $rowTitles = array(
     'uptime' => \SimpleSAML\Locale\Translate::noop('{memcacheMonitor:memcachestat:uptime}'),
     'version' => \SimpleSAML\Locale\Translate::noop('{memcacheMonitor:memcachestat:version}'),
 );
+
+// Identify column headings
+$colTitles = array();
+foreach ($stats as $rowTitle => $rowData) {
+    foreach ($rowData as $colTitle => $foo) {
+        if (!in_array($colTitle, $colTitles, true)) {
+            $colTitles[] = $colTitle;
+        }
+    }
+}
+
+if (array_key_exists('bytes', $statsraw) && array_key_exists('limit_maxbytes', $statsraw)) {
+    $usage = array();
+    $maxpix = 400;
+    foreach ($statsraw['bytes'] as $key => $row_data) {
+        $pix = floor($statsraw['bytes'][$key] * $maxpix / $statsraw['limit_maxbytes'][$key]);
+        $usage[$key] = $pix . 'px';
+    }
+    $t->data['maxpix'] = $maxpix . 'px';
+    $t->data['usage'] = $usage;
+}
+
 $t->data['title'] = 'Memcache stats';
-$t->data['rowtitles'] = $rowTitles;
+$t->data['rowTitles'] = $rowTitles;
+$t->data['colTitles'] = $colTitles;
 $t->data['table'] = $stats;
-$t->data['statsraw'] = $statsraw;
 $t->show();
diff --git a/modules/memcacheMonitor/www/style.css b/modules/memcacheMonitor/www/style.css
new file mode 100644
index 0000000000000000000000000000000000000000..b57c376543bd555804df4394a9453a9d318cfacc
--- /dev/null
+++ b/modules/memcacheMonitor/www/style.css
@@ -0,0 +1,20 @@
+table.statustable td, table.statustable th {
+    border: 1px solid #eee;
+    padding: 2px 6px;
+}
+
+table.statustable {
+    border-collapse: collapse;
+}
+
+.bmax {
+    border: 1px solid #555;
+    background: #eee;
+}
+
+.bused {
+    border-right: 1px solid #555;
+    border-bottom: 1px solid #555;
+    color: white;
+    background: #833;
+}
diff --git a/modules/metarefresh/locales/en/LC_MESSAGES/metarefresh.po b/modules/metarefresh/locales/en/LC_MESSAGES/metarefresh.po
new file mode 100644
index 0000000000000000000000000000000000000000..483051bab4f733daa6bc6892c06e9cc43b5a73b4
--- /dev/null
+++ b/modules/metarefresh/locales/en/LC_MESSAGES/metarefresh.po
@@ -0,0 +1,25 @@
+
+#, fuzzy
+msgid ""
+msgstr ""
+"Project-Id-Version: SimpleSAMLphp 1.15\n"
+"Report-Msgid-Bugs-To: simplesamlphp-translation@googlegroups.com\n"
+"POT-Creation-Date: 2017-12-06 09:23+0200\n"
+"PO-Revision-Date: 2017-12-06 12:14+0200\n"
+"Last-Translator: \n"
+"Language: en\n"
+"Language-Team: \n"
+"Plural-Forms: nplurals=2; plural=(n != 1)\n"
+"MIME-Version: 1.0\n"
+"Content-Type: text/plain; charset=utf-8\n"
+"Content-Transfer-Encoding: 8bit\n"
+"Generated-By: Babel 2.3.4\n"
+
+msgid "metarefresh_header"
+msgstr "Metarefresh"
+
+msgid "metarefresh_no_output"
+msgstr "No output from metarefresh."
+
+msgid "metarefresh_fetched"
+msgstr "Fetched metadata"
diff --git a/modules/metarefresh/templates/fetch.twig b/modules/metarefresh/templates/fetch.twig
new file mode 100644
index 0000000000000000000000000000000000000000..d8765ab3dd1e345a453196ac5d5350e870affb6c
--- /dev/null
+++ b/modules/metarefresh/templates/fetch.twig
@@ -0,0 +1,18 @@
+{% set pagetitle = "metarefresh_header" | trans %}
+
+{% extends "base.twig" %}
+
+{% block content %}
+
+{% if logentries %}
+        <h1>{{ "metarefresh_fetched" | trans }}</h1>
+        <ul>
+            {% for logentry in logentries %}
+            <li>{{ logentry }}</li>
+            {% endfor %}
+        </ul>
+{% else %}
+{{ "metarefresh_no_output" | trans }}
+{% endif %}
+
+{% endblock content %}
diff --git a/modules/multiauth/lib/Auth/Source/MultiAuth.php b/modules/multiauth/lib/Auth/Source/MultiAuth.php
index b9b16b6d34eb624a4403cbba5df1e704154d9fb4..6714560e281eeff71158900e27e2f6d0b52215f6 100644
--- a/modules/multiauth/lib/Auth/Source/MultiAuth.php
+++ b/modules/multiauth/lib/Auth/Source/MultiAuth.php
@@ -71,6 +71,9 @@ class MultiAuth extends \SimpleSAML\Auth\Source
 				$text = array($defaultLanguage => $source);
 			}
 
+                        if (array_key_exists('help', $info)) {
+                                $help = $info['help'];
+                        }
 			if (array_key_exists('css-class', $info)) {
 				$css_class = $info['css-class'];
 			} else {
@@ -86,6 +89,7 @@ class MultiAuth extends \SimpleSAML\Auth\Source
 			$this->sources[] = array(
 				'source' => $source,
 				'text' => $text,
+                                'help' => $help,
 				'css_class' => $css_class,
 			);
 		}
diff --git a/modules/multiauth/templates/selectsource.twig b/modules/multiauth/templates/selectsource.twig
new file mode 100644
index 0000000000000000000000000000000000000000..d308d457afa092088005cea3e90f8199ac811efd
--- /dev/null
+++ b/modules/multiauth/templates/selectsource.twig
@@ -0,0 +1,27 @@
+{% set pagetitle = '{multiauth:multiauth:select_source_header}'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h2>{{ '{multiauth:multiauth:select_source_header}'| trans }}</h2>
+    <p>{{ '{multiauth:multiauth:select_source_text}'| trans }}</p>
+
+    <form action="{{ selfUrl|escape('html') }}" method="get">
+        <input type="hidden" name="AuthState" value="{{ authstate|escape('html') }} " />
+        <ul>
+        {% for key, source in sources %}
+            {% set name = ('src-' ~ source.source64) %}
+            {% set button = ('button-' ~ source.source) %}
+	    <li class="{{ source.css_class|escape('html') }} authsource">
+            {% if source.source == preferred %}
+                <input type="submit" name="{{ name|escape('html') }}" autofocus="autofocus" id="{{ button|escape('html') }}" value="{{ source.text|escape('html') }}" />
+            {% else %}
+                <input type="submit" name="{{ name|escape('html') }}" id="{{ button|escape('html') }}" value="{{ source.text|escape('html') }}" />
+            {% endif %}
+            {% if source.help %}
+              <p>{{ source.help|escape('html') }}</p>
+            {% endif %}
+            </li>
+        {% endfor %}
+        </ul>
+    </form>
+{% endblock %}
diff --git a/modules/multiauth/www/selectsource.php b/modules/multiauth/www/selectsource.php
index 8becbeb201c648658d26209b259f8ccdf4f1530e..1a8d141f94ca4f3824375c9795501f69bcf3740e 100644
--- a/modules/multiauth/www/selectsource.php
+++ b/modules/multiauth/www/selectsource.php
@@ -49,8 +49,21 @@ if (array_key_exists('multiauth:preselect', $state)) {
 
 $globalConfig = \SimpleSAML\Configuration::getInstance();
 $t = new \SimpleSAML\XHTML\Template($globalConfig, 'multiauth:selectsource.php');
+
+$defaultLanguage = $globalConfig->getString('language.default', 'en');
+$language = $t->getTranslator()->getLanguage()->getLanguage();
+
+$sources = $state[\SimpleSAML\Module\multiauth\Auth\Source\MultiAuth::SOURCESID];
+foreach ($sources as $key => $source){
+    $sources[$key]['source64'] = base64_encode($sources[$key]['source']);
+    $sources[$key]['text'] = (isSet($sources[$key]['text'][$language]) ? $sources[$key]['text'][$language] : $sources[$key]['text'][$defaultLanguage]);
+    $sources[$key]['help'] = (isSet($sources[$key]['help'][$language]) ? $sources[$key]['help'][$language] : $sources[$key]['help'][$defaultLanguage]);
+}
+
 $t->data['authstate'] = $authStateId;
-$t->data['sources'] = $state[\SimpleSAML\Module\multiauth\Auth\Source\MultiAuth::SOURCESID];
+$t->data['sources'] = $sources;
+$t->data['selfUrl'] = $_SERVER['PHP_SELF'];
+
 if ($as !== null) {
     $t->data['preferred'] = $as->getPreviousSource();
 } else {
diff --git a/modules/negotiate/templates/disable.twig b/modules/negotiate/templates/disable.twig
new file mode 100644
index 0000000000000000000000000000000000000000..07fccdd269674e0262a98e5eada9541e90354c64
--- /dev/null
+++ b/modules/negotiate/templates/disable.twig
@@ -0,0 +1,9 @@
+{% extends "base.twig" %}
+
+{% block content %}
+    <h1>{{ '{negotiate:negotiate:disable_title}'|trans }}</h1>
+    <br />
+    {{ '{negotiate:negotiate:disable_info_pre}'|trans({'%URL%': url}, "app")|raw }}
+    <br />
+    {{ '{negotiate:negotiate:info_post}'|trans|raw }}
+{% endblock %}
diff --git a/modules/negotiate/templates/enable.twig b/modules/negotiate/templates/enable.twig
new file mode 100644
index 0000000000000000000000000000000000000000..07e5579646ad3cd524995969a6553a58fef1fe58
--- /dev/null
+++ b/modules/negotiate/templates/enable.twig
@@ -0,0 +1,9 @@
+{% extends "base.twig" %}
+
+{% block content %}
+    <h1>{{ '{negotiate:negotiate:enable_title}'|trans }}</h1>
+    <br />
+    {{ '{negotiate:negotiate:enable_info_pre}'|trans({'%URL%': url}, "app")|raw }}
+    <br />
+    {{ '{negotiate:negotiate:info_post}'|trans|raw }}
+{% endblock %}
diff --git a/modules/oauth/config-template/module_oauth.php b/modules/oauth/config-template/module_oauth.php
index e6bc549b83a4f4a2ce59fb66fbfbd4d36d2766b8..a99f2acf121553267045dedf33ee739d66f1521a 100644
--- a/modules/oauth/config-template/module_oauth.php
+++ b/modules/oauth/config-template/module_oauth.php
@@ -22,4 +22,3 @@ $config = array(
     'auth' => 'default-sp',
     'useridattr', 'user',
 );
-
diff --git a/modules/oauth/hooks/hook_cron.php b/modules/oauth/hooks/hook_cron.php
index 35e355f3be89a60e4b1539466b8fa478ff6a2c77..1a37cb41d6e4777583b75d23cad64f509ed2fc87 100644
--- a/modules/oauth/hooks/hook_cron.php
+++ b/modules/oauth/hooks/hook_cron.php
@@ -31,4 +31,3 @@ function oauth_hook_cron(&$croninfo)
         $croninfo['summary'][] = $message;
     }
 }
-
diff --git a/modules/oauth/templates/registry.edit.twig b/modules/oauth/templates/registry.edit.twig
new file mode 100644
index 0000000000000000000000000000000000000000..baa44d4f966634fc952e48ad96ad3b1aa21ee30e
--- /dev/null
+++ b/modules/oauth/templates/registry.edit.twig
@@ -0,0 +1,28 @@
+{% set pagetitle = 'SimpleSAMLphp'|trans %}
+{% extends "base.twig" %}
+
+{% block preload %}
+    <link href="{{ baseurlpath }}resources/style.css" rel="stylesheet" />
+{% endblock %}
+
+{% block postload %}
+<script type="text/javascript">
+    $(document).ready(function() {
+	$("#tabdiv").tabs();
+        $('ul.tabset_tabs li').click(
+            function() {
+                $("html, body").animate({ scrollTop: 0 }, "slow");
+            }
+        )
+
+    });
+</script>
+{% endblock %}
+
+{% block content %}
+    <h1>OAuth Client</h1>
+    {{ form|raw }}
+    <p style="float: right">
+        <a href="registry.php">Return to entity listing <strong>without saving...</strong></a>
+    </p>
+{% endblock %}
diff --git a/modules/oauth/templates/registry.list.twig b/modules/oauth/templates/registry.list.twig
new file mode 100644
index 0000000000000000000000000000000000000000..e6ec234c6020d7623373ee2dd0de468033250f2a
--- /dev/null
+++ b/modules/oauth/templates/registry.list.twig
@@ -0,0 +1,58 @@
+{% set pagetitle = 'SimpleSAMLphp'|trans %}
+{% extends "base.twig" %}
+
+{% block preload %}
+    <link href="{{ baseurlpath }}style.css" rel="stylesheet" />
+{% endblock %}
+
+{% block content %}
+    <h1>OAuth Client Registry</h1>
+    <p>Here you can register new OAuth Clients. You are successfully logged in as {{ userid|escape('html') }}</p>
+    <h2>Your clients</h2>
+
+    <table class="metalist" style="width: 100%;">
+    {% for key, entryc in entries.mine %}
+        {% if loop.index0  % 2 == 0 %}
+            {% set class = 'even' %}
+        {% else %}
+            {% set class = 'odd' %}
+        {% endif %}
+        {% set entry = entryc.value %}
+        <tr class="{{ class }}">
+            <td>{{ entry.name|escape('html') }}</td>
+            <td><kbd>{{ entry.key|escape('html') }}</kbd></td>
+            <td>
+                <a href="registry.edit.php?editkey={{ entry.key|escape('url') }}">edit</a>
+                <a href="registry.php?delete={{ entry.key|escape('url') }}">delete</a>
+            </td>
+        </tr>
+    {% else %}
+        <tr><td colspan="3">No entries registered</td></tr>
+    {% endfor %}
+    </table>
+
+    <p><a href="registry.edit.php">Add new client</a></p>
+    <h2>Other clients</h2>
+
+    <table class="metalist" style="width: 100%">
+    {% for key, entryc in entries.others %}
+        {% if loop.index0  % 2 == 0 %}
+            {% set class = 'even' %}
+        {% else %}
+            {% set class = 'odd' %}
+        {% endif %}
+        {% set entry = entryc.value %}
+        <tr class="{{ class }}">
+            <td>{{ entry.name|escape('html') }}</td>
+            <td><kbd>{{ entry.key|escape('html') }}</kbd></td>
+            {% if eentry.owner is defined %}}
+            <td>{{ entry.owner|escape('html') }}</td>
+            {% else %}
+            <td>No owner</td>
+            {% endif %}
+        </tr>
+    {% else %}
+        <tr><td colspan="3">No entries registered</td></tr>
+    {% endfor %}
+    </table>
+{% endblock%}
diff --git a/modules/oauth/templates/registry.saved.twig b/modules/oauth/templates/registry.saved.twig
new file mode 100644
index 0000000000000000000000000000000000000000..6c36465f7162b6b759ba0f41fdb4497b0364a8da
--- /dev/null
+++ b/modules/oauth/templates/registry.saved.twig
@@ -0,0 +1,9 @@
+{% set pagetitle = 'SimpleSAMLphp'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h1>OAith Client saved</h1>
+    <p>
+        <a href="registry.php">Go back to OAuth client listing</a>
+    </p>
+{% endblock %}
diff --git a/modules/oauth/www/resources/style.css b/modules/oauth/www/resources/style.css
index 1240db06576e85af71049ead441122ca26354a04..4df7a79504106ad9102dfb88d797561b12f9a55b 100644
--- a/modules/oauth/www/resources/style.css
+++ b/modules/oauth/www/resources/style.css
@@ -34,4 +34,52 @@ table.metalist tr td {
 }
 table.metalist tr.even td {
 	background: #e5e5e5;
-}
\ No newline at end of file
+}
+
+@media all {
+    div#content {
+        margin: .4em ! important;
+    }
+
+    form {
+        display: inline;
+    }
+
+    ul.tabset_tabs {
+        margin: 0px;
+        padding: 0px;
+        list-style: none;
+    }
+
+    ul.tabset_tabs li {
+        background: none;
+        color: #222;
+        display: inline-block;
+        padding: 10px 15px;
+        cursor: pointer;
+    }
+
+    ul.tabset_tabs li.current {
+        background: #ededed;
+        color: #222;
+    }
+
+    .tabset_content {
+        display: none;
+        background: #ededed;
+        padding: 15px;
+    }
+
+    .tabset_content.current {
+        display: inherit;
+    }
+
+    #graph img {
+        max-width: 77%;
+        height: auto;
+    }
+    #table img {
+        max-width: 77%;
+        height: auto;
+    }
+}
diff --git a/modules/preprodwarning/templates/warning.twig b/modules/preprodwarning/templates/warning.twig
new file mode 100644
index 0000000000000000000000000000000000000000..9a86ffb69eab0654e68e8d54dba08e34dfa6e845
--- /dev/null
+++ b/modules/preprodwarning/templates/warning.twig
@@ -0,0 +1,19 @@
+{% set pagetitle = 'Warning about accessing a pre-production system'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+
+<form action="{{ yesTarget }}">
+
+        <p>{% trans %}You are now accessing a pre-production system. This authentication setup is for testing and pre-production verification only. If someone sent you a link that pointed you here, and you are not <i>a tester</i> you probably got the wrong link, and should <b>not be here</b>.{% endtrans %}</p><br />
+{% for name,value in yesData %}
+        <input type="hidden" name="{{ name }}" value="{{ value }}" />
+{% endfor %}
+<p>
+        <input type="submit" name="yes" class="pure-button pure-button-red" value="{{'Yes, I know I am accessing a pre-production system'|trans}}" />
+
+</p>
+
+</form>
+
+{% endblock %}
diff --git a/modules/saml/templates/proxy/invalid_session.twig b/modules/saml/templates/proxy/invalid_session.twig
new file mode 100644
index 0000000000000000000000000000000000000000..c970efabfa76c4b24389b0c8d4fdf90b987fc9f4
--- /dev/null
+++ b/modules/saml/templates/proxy/invalid_session.twig
@@ -0,0 +1,12 @@
+{% set pagetitle = 'SimpleSAMLphp'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h2>{{ '{saml:proxy:invalid_idp}'|trans }}</h2>
+    <p>{{ '{saml:proxy:invalid_idp_description}'|trans({"%IDP%": idp_name, "%SP%": sp_name}, "app")|raw</p>
+    <form method="post" action="?">
+        <input type="hidden" name="AuthState" value="{{ AuthState|escape('html') }}" />
+        <input type="submit" name="continue" value="{{ '{general:yes_continue}'|trans }}" />
+        <input type="submit" name="cancel" value="{{ '{general:no_cancel}'|trans }}" />
+    </form>
+{% endblock %}
diff --git a/modules/saml/templates/sp/wrong_authncontextclassref.twig b/modules/saml/templates/sp/wrong_authncontextclassref.twig
new file mode 100644
index 0000000000000000000000000000000000000000..5a5012c87407efe0f5f5259756c596f795d75472
--- /dev/null
+++ b/modules/saml/templates/sp/wrong_authncontextclassref.twig
@@ -0,0 +1,7 @@
+{% set pagetitle = 'SimpleSAMLphp'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h2>{{ '{saml:wrong_authncontextclassref:header}'|trans|escape('html') }}</h2>
+    <p>{{ '{saml:wrong_authncontextclassref:description}'|trans|escape('html') }}</p>
+{% endblock %}
diff --git a/modules/sanitycheck/hooks/hook_frontpage.php b/modules/sanitycheck/hooks/hook_frontpage.php
index ab73959270360031a9aefd44b2f43d4a7494468e..7a13de7c73a6a949e0eabfc1f63a54129eb5c5c0 100644
--- a/modules/sanitycheck/hooks/hook_frontpage.php
+++ b/modules/sanitycheck/hooks/hook_frontpage.php
@@ -11,7 +11,6 @@ function sanitycheck_hook_frontpage(&$links)
 
     $links['config']['sanitycheck'] = array(
         'href' => SimpleSAML\Module::getModuleURL('sanitycheck/index.php'),
-        'text' => array('en' => 'Sanity check of your SimpleSAMLphp setup'),
-        'shorttext' => array('en' => 'SanityCheck'),
+        'text' => '{core:frontpage:link_sanitycheck}',
     );
 }
diff --git a/modules/sanitycheck/locales/en/LC_MESSAGES/messages.po b/modules/sanitycheck/locales/en/LC_MESSAGES/messages.po
new file mode 100644
index 0000000000000000000000000000000000000000..2b50d34d18dce5a79e59d9c8139ea8d5172e2da9
--- /dev/null
+++ b/modules/sanitycheck/locales/en/LC_MESSAGES/messages.po
@@ -0,0 +1,6 @@
+msgid "These checks failed:"
+msgstr "These checks failed:"
+
+msgid "These checks succeeded:"
+msgstr "These checks succeeded:"
+
diff --git a/modules/sanitycheck/locales/it/LC_MESSAGES/messages.po b/modules/sanitycheck/locales/it/LC_MESSAGES/messages.po
new file mode 100644
index 0000000000000000000000000000000000000000..558b243e066a7ab4408a5223ad3529b804efc737
--- /dev/null
+++ b/modules/sanitycheck/locales/it/LC_MESSAGES/messages.po
@@ -0,0 +1,6 @@
+msgid "These checks failed:"
+msgstr "I seguenti controlli hanno riscontrato dei problemi:"
+
+msgid "These checks succeeded:"
+msgstr "I seguenti controlli sono stati eseguiti con successo:"
+
diff --git a/modules/sanitycheck/templates/check.twig b/modules/sanitycheck/templates/check.twig
index ab53e5c5fd6f27a1317d9df03094b83202f9f0f0..fe51f41809cade804ccfcb83bdd5eb9b3dccfa8a 100644
--- a/modules/sanitycheck/templates/check.twig
+++ b/modules/sanitycheck/templates/check.twig
@@ -5,30 +5,41 @@
 <h2>{{ pagetitle }}</h2>
 
 {% if errors %}
-<div style="border: 1px solid #800; background: #caa; margin: 1em; padding: .5em">
-<p><img class="float-r" src="/{{ baseurlpath }}resources/icons/silk/delete.png" alt="Failed" />
-These checks failed:</p>
-
-<ul>
-{% for err in errors %}
-    <li>{{ err }}</li>
-{% endfor %}
-</ul>
 
+<div class="message-box error">
+    <div class="pure-g">
+        <div class="pure-u-1-12">
+            <span class="fa fa-times-circle fa-2x"></span>
+        </div>
+        <div class="pure-u-11-12">
+            <p>{{ 'These checks failed:'|trans }}</p>
+
+            <ul class="error-list">
+            {% for err in errors %}
+                <li>{{ err }}</li>
+            {% endfor %}
+            </ul>
+        </div>
+    </div>
 </div>
 {% endif %}
 
 {% if info %}
-<div style="border: 1px solid #ccc; background: #eee; margin: 1em; padding: .5em">
-<p><img class="float-r" src="/{{ baseurlpath }}resources/icons/silk/accept.png" alt="OK" />
-These checks succeeded:</p> 
-
-<ul>
-{% for i in info %}
-    <li>{{ i }}</li>
-{% endfor %}
-</ul>
-
+<div class="message-box success">
+    <div class="pure-g">
+        <div class="pure-u-1-12">
+            <span class="fa fa-check fa-2x"> </span>
+        </div>
+        <div class="pure-u-11-12">
+            <p>{{ 'These checks succeeded:'|trans }}</p>
+
+            <ul>
+            {% for i in info %}
+                <li>{{ i }}</li>
+            {% endfor %}
+            </ul>
+        </div>
+    </div>
 </div>
 {% endif %}
 
diff --git a/modules/statistics/hooks/hook_frontpage.php b/modules/statistics/hooks/hook_frontpage.php
index 03a97aa52bdb5013f3fb2f2faa785940c355d010..a97da1f2c5f31ee8b900b6b3eb0aba82c1a3e2f0 100644
--- a/modules/statistics/hooks/hook_frontpage.php
+++ b/modules/statistics/hooks/hook_frontpage.php
@@ -11,12 +11,11 @@ function statistics_hook_frontpage(&$links)
 
     $links['config']['statistics'] = array(
         'href' => SimpleSAML\Module::getModuleURL('statistics/showstats.php'),
-        'text' => array('en' => 'Show statistics', 'no' => 'Vis statistikk'),
-        'shorttext' => array('en' => 'Statistics', 'no' => 'Statistikk'),
+        'text' => '{core:frontpage:link_statistics}',
     );
     $links['config']['statisticsmeta'] = array(
         'href' => SimpleSAML\Module::getModuleURL('statistics/statmeta.php'),
-        'text' => array('en' => 'Show statistics metadata', 'no' => 'Vis statistikk metadata'),
+        'text' => '{core:frontpage:link_statistics_metadata}',
         'shorttext' => array('en' => 'Statistics metadata', 'no' => 'Statistikk metadata'),
     );
 }
diff --git a/modules/statistics/templates/statistics.twig b/modules/statistics/templates/statistics.twig
new file mode 100644
index 0000000000000000000000000000000000000000..00da9ca2d2f8826985cf478d75123240f0c5c388
--- /dev/null
+++ b/modules/statistics/templates/statistics.twig
@@ -0,0 +1,222 @@
+{% set pagetitle = 'SimpleSAMLphp Statistics'|trans %}
+{% extends "base.twig" %}
+
+{% block preload %}
+    <link href="{{ baseurlpath }}style.css" rel="stylesheet" />
+{% endblock %}
+
+{% block postload %}
+<script type="text/javascript">
+    $(document).ready(function() {
+	$("#tabdiv").tabs();
+        $('ul.tabset_tabs li').click(
+            function() {
+                $("html, body").animate({ scrollTop: 0 }, "slow");
+            }
+        )
+    });
+</script>
+{% endblock %}
+
+{% block content %}
+    <h1>{{ current_rule.name }}</h1>
+    <p>{{ current_rule.descr }}</p>
+
+    <table class="selecttime">
+        <tr>
+            <td class="selecttime_icon">
+                <img src="/{{ baseurlpath }}resources/icons/crystal_project/kchart.32x32.png" alt="Report settings" />
+            </td>
+            <td>
+                <form action="#">
+                    {% for key, value in post_rule %}
+                    <input type="hidden" name="{{ key|escape('html') }}" value="{{ value|escape('html') }}">
+                    {% endfor %}
+                    <select onchange="submit();" name="rule">
+                    {% for key, rule in available_rules %}
+                        {% if key == selected_rule %}
+                        <option selected="selected" value="{{ key }}">{{ rule.name }}</option>
+                        {% else %}
+                        <option value="{{ key }}">{{ rule.name }}</option>
+                        {% endif %}
+                    {% endfor %}
+                    </select>
+                </form>
+            </td>
+            <td class="td_right">
+                <form action="#">
+                    {% for key, value in post_d %}
+                    <input type="hidden" name="{{ key|escape('html') }}" value="{{ value|escape('html') }}">
+                    {% endfor %}
+                    <select onchange="submit();" name="d">
+                    {% for key, delim in availdelimiters %}
+                        {% set delimName = delim %}
+
+                        {% if delimiterPresentation[delim] is defined %}
+                        {% set delimName = delimiterPresentation[delim] %}
+                        {% endif %}
+
+                        {% if key == "_" %}
+                        <option value="_">Total</option>
+                        {% elseif request_d is defined and delim == request_d %}
+                        <option selected="selected" value="{{ delim|escape('html') }}">{{ delimName|escape('html') }}</option>
+                        {% else %}
+                        <option value="{{ delim|escape('html') }}">{{ delimName|escape('html') }}</option>
+                        {% endif %}
+                    {% endfor %}
+                    </select>
+                </form>
+            </td>
+        </tr>
+    </table>
+
+    <table class="selecttime">
+        <tr>
+            <td class="selecttime_icon">
+                <img src="/{{ baseurlpath }}resources/icons/crystal_project/date.32x32.png" alt="Select date and time" />
+            </td>
+            {% if available_times_prev %}
+            <td><a href="{{ get_times_prev }}">&laquo; Previous</a></td>
+            {% else %}
+            <td class="selecttime_link_grey">&laquo; Previous</td>
+            {% endif %}
+            <td class="td_right">
+                <form action="#">
+                    {% for key, value in post_res %}
+                    <input type="hidden" name="{{ key|escape('html') }}" value="{{ value|escape('html') }}">
+                    {% endfor %}
+                    <select onchange="submit();" name="res">
+                    {% for key, timeresname in available_timeres %}
+                        {% if key == selected_timeres %}
+                        <option selected="selected" value="{{ key }}">{{ timeresname }}</option>
+                        {% else %}
+                        <option value="{{ key }}">{{ timeresname }}</option>
+                        {% endif %}
+                    {% endfor %}
+                    </select>
+                </form>
+            </td>
+            <td class="td_left">
+                <form action="#">
+                    {% for key, value in post_time %}
+                    <input type="hidden" name="{{ key|escape('html') }}" value="{{ value|escape('html') }}">
+                    {% endfor %}
+                    <select onchange="submit();" name=time>
+                    {% for key, timedescr in available_times %}
+                        {% if key == selected_time %}
+                        <option selected="selected" value="{{ key }}">{{ timedescr }}</option>
+                        {% else %}
+                        <option value="{{ key }}">{{ timedescr }}</option>
+                        {% endif%}
+                    {% endfor %}
+                    </select>
+                </form>
+            </td>
+            {% if available_times_next %}
+                <td class="td_right td_next_right"><a href="{{ get_times_next }}">Next &raquo;</a></td>
+            {% else %}
+                <td class="td_right selecttime_link_grey">Next &raquo;</td>
+            {% endif %}
+        </tr>
+    </table>
+
+    <div id="tabdiv">
+        <ul class="tabset_tabs">
+            <li class="tab-link current" data-tab="graph"><a href="#graph">Graph</a></li>
+            <li class="tab-link" data-tab="table"><a href="#table">Summary table</a></li>
+            <li class="tab-link" data-tab="debug"><a href="#debug">Time serie</a></li>
+        </ul>
+
+        <div id="graph" class="tabset_content current">
+            <img src="{{ imgurl }}" alt="Graph" />
+            <form action="#">
+                <p class="p_right">Compare with total from this dataset
+                <select onchange="submit();" name="rule2">
+                    <option value="_">None</option>
+                    {% for key, rule in available_rules %}
+                    {% if key == selected_rule2 %}
+                    <option selected="selected" value="{{ key }}">{{ rule.name }}</option>
+                    {% else %}
+                    <option value="{{ key }}">{{ rule.name }}</option>
+                    {% endif %}
+                    {% endfor %}
+                </select>
+                </p>
+            </form>
+        </div>
+
+        <div id="table" class="tabset_content">
+            {% if pieimgurl is defined %}
+            <img src="{{ pieimgurl }}" alt="Pie chart" />
+            {% endif %}
+
+            <table class="tableview">
+                <tr>
+                    <th class="value">Value</th>
+                    <th class="category">Data range</th>
+                </tr>
+                {% for key, value in summaryDataset %}
+                {% if loop.index0  % 2 == 0 %}
+                    {% set class = 'even' %}
+                {% else %}
+                    {% set class = 'odd' %}
+                {% endif %}
+
+                {% set keyName = key %}
+                {% if delimiterPresentation[key] is defined %}
+                {% set keyName = delimiterPresentation[key] %}
+                {% endif %}
+
+                {% if key == "_" %}
+                <tr class="total {{ class }}">
+                    <td class="value">{{ value }}</td>
+                    <td class="category">{{ keyName }}</td>
+                </tr>
+                {% else %}
+                <tr class="{{ class }}">
+                    <td class="value">{{ value }}</td>
+                    <td class="category">{{ keyName }}</td>
+                </tr>
+                {% endif %}
+                {% endfor %}
+            </table>
+        </div>
+
+        <div id="debug" class="tabset_content">
+            <table class="timeseries">
+                <tr>
+                    <th>Time</th>
+                    <th>Total</th>
+                    {% for key, value in topdelimiters %}
+                    {% set keyName = key %}
+                    {% if delimiterPresentation[key] is defined %}
+                        {% set keyName = delimiterPresentation[key] %}
+                    {% endif %}
+                    <th>{{ keyName }}</th>
+                    {% endfor %}
+                </tr>
+                {% set i = 0 %}
+                {% for slot, dd in debugdata %}
+
+                {% if i % 2 == 0 %}
+                    {% set class = 'even' %}
+                {% else %}
+                    {% set class = 'odd' %}
+                {% endif %}
+
+                <tr class="{{ class }}">
+                    <td>{{ dd[0] }}</td>
+                    <td class="datacontent">{{ dd[1] }}</td>
+                    {% for key, value in topdelimiters %}
+                    {% if results.slot is defined %}
+                    <td class="datacontent">{{ results.slot.key }}</td>
+                    {% else %}
+                    <td class="datacontent">&nbsp;</td>
+                    {% endif %}
+                    {% endfor %}
+                </tr>
+                {% endfor %}
+            </table>
+        </div>
+    </div>
+{% endblock %}
diff --git a/modules/statistics/templates/statmeta.twig b/modules/statistics/templates/statmeta.twig
new file mode 100644
index 0000000000000000000000000000000000000000..dd2c475c552376eb815c69729eef252f222ab9b4
--- /dev/null
+++ b/modules/statistics/templates/statmeta.twig
@@ -0,0 +1,39 @@
+{% set pagetitle = 'SimpleSAMLphp Statistics Metadata'|trans %}
+{% extends "base.twig" %}
+
+{% block preload %}
+    <link href="{{ baseurlpath }}style.css" rel="stylesheet" />
+{% endblock %}
+
+{% block content %}
+    <table id="statmeta">
+    {% if metadata is defined %}
+        {% if metadata.lastrun is defined %}
+            <tr><td>Aggregator last run at</td><td>{{ metadata.lastrun }}</td></tr>
+        {% endif %}
+
+        {% if metadata.notBefore is defined %}
+            <tr><td>Aggregated data until</td><td>{{ metadata.notBefore }}</td></tr>
+        {% endif %}
+
+        {% if metadata.memory is defined %}
+            <tr><td>Memory usage</td><td>{{ metadata.memory }} MB</td></tr>
+        {% endif %}
+
+        {% if metadata.memory is defined %}
+            <tr><td>Execution time</td><td>{{ metadata.time }} seconds</td></tr>
+        {% endif %}
+
+        {% if metadata.memory is defined %}
+            <tr><td>SHA1 of last processed logline</td><td>{{ metadata.lastlinehash }}</td></tr>
+        {% endif %}
+
+        {% if metadata.memory is defined %}
+            <tr><td>Last processed logline</td><td>{{ metadata.lastline }}</td></tr>
+        {% endif %}
+    {% else %}
+        <tr><td>No metadata found</td></tr>
+    {% endif %}
+    </table>
+    <p>[ <a href="{{ baseurlpath }}showstats.php">Show statistics</a> ]</p>
+{% endblock %}
diff --git a/modules/statistics/www/javascript.js b/modules/statistics/www/javascript.js
deleted file mode 100644
index a5aa421a67fffda6c3c2f4527c8227e58b1b9cde..0000000000000000000000000000000000000000
--- a/modules/statistics/www/javascript.js
+++ /dev/null
@@ -1,4 +0,0 @@
-$(document).ready(function() {
-        $("#tabdiv").tabs();
-});
-
diff --git a/modules/statistics/www/showstats.php b/modules/statistics/www/showstats.php
index b2dd8a26f49e6b67d19320f807db01ce748daa3b..c160026d2035e9510897e58d7d468fc71375dbe0 100644
--- a/modules/statistics/www/showstats.php
+++ b/modules/statistics/www/showstats.php
@@ -29,6 +29,7 @@ if (array_key_exists('res', $_REQUEST)) {
 }
 if (array_key_exists('d', $_REQUEST)) {
     $delimiter = $_REQUEST['d'];
+    $t->data['request_d'] = $delimiter;
 }
 
 if ($preferRule2 === '_') {
@@ -115,14 +116,20 @@ $t->data['imgurl'] = $grapher->show($axis['axis'], $axis['axispos'], $datasets,
 if (isset($piedata)) {
     $t->data['pieimgurl'] = $grapher->showPie($dataset->getDelimiterPresentationPie(), $piedata);
 }
-$t->data['available.times'] = $statrule->availableFileSlots($timeres);
-$t->data['available.timeres'] = $statrule->availableTimeRes();
-$t->data['available.times.prev'] = $timeNavigation['prev'];
-$t->data['available.times.next'] = $timeNavigation['next'];
 
-$t->data['selected.time'] = $fileslot;
-$t->data['selected.timeres'] = $timeres;
-$t->data['selected.delimiter'] = $delimiter;
+$t->data['available_rules'] = $ruleset->availableRulesNames();
+$t->data['available_times'] = $statrule->availableFileSlots($timeres);
+$t->data['available_timeres'] = $statrule->availableTimeRes();
+$t->data['available_times_prev'] = $timeNavigation['prev'];
+$t->data['available_times_next'] = $timeNavigation['next'];
+
+$t->data['current_rule'] = $t->data['available_rules'][$rule];
+
+$t->data['selected_rule'] = $rule;
+$t->data['selected_rule2'] = $preferRule2;
+$t->data['selected_time'] = $fileslot;
+$t->data['selected_timeres'] = $timeres;
+$t->data['selected_delimiter'] = $delimiter;
 
 $t->data['debugdata'] = $dataset->getDebugData();
 $t->data['results'] = $dataset->getResults();
@@ -137,23 +144,25 @@ $t->data['post_rule2'] = getBaseURL($t, 'post', 'rule2');
 $t->data['post_d'] = getBaseURL($t, 'post', 'd');
 $t->data['post_res'] = getBaseURL($t, 'post', 'res');
 $t->data['post_time'] = getBaseURL($t, 'post', 'time');
-$t->data['get_times_prev'] = getBaseURL($t, 'get', 'time', $t->data['available.times.prev']);
-$t->data['get_times_next'] = getBaseURL($t, 'get', 'time', $t->data['available.times.next']);
+$t->data['get_times_prev'] = getBaseURL($t, 'get', 'time', $t->data['available_times_prev']);
+$t->data['get_times_next'] = getBaseURL($t, 'get', 'time', $t->data['available_times_next']);
+
+$t->data['jquery'] = array('core' => false, 'ui' => true, 'css' => true);
 
 $t->show();
 
 function getBaseURL($t, $type = 'get', $key = null, $value = null)
 {
     $vars = array(
-        'rule' => $t->data['selected.rule'],
-        'time' => $t->data['selected.time'],
-        'res' => $t->data['selected.timeres'],
+        'rule' => $t->data['selected_rule'],
+        'time' => $t->data['selected_time'],
+        'res' => $t->data['selected_timeres'],
     );
-    if (isset($t->data['selected.delimiter'])) {
-        $vars['d'] = $t->data['selected.delimiter'];
+    if (isset($t->data['selected_delimiter'])) {
+        $vars['d'] = $t->data['selected_delimiter'];
     }
-    if (!empty($t->data['selected.rule2']) && $t->data['selected.rule2'] !== '_') {
-        $vars['rule2'] = $t->data['selected.rule2'];
+    if (!empty($t->data['selected_rule2']) && $t->data['selected_rule2'] !== '_') {
+        $vars['rule2'] = $t->data['selected_rule2'];
     }
 
     if (isset($key)) {
@@ -167,11 +176,6 @@ function getBaseURL($t, $type = 'get', $key = null, $value = null)
 
     if ($type === 'get') {
         return \SimpleSAML\Module::getModuleURL("statistics/showstats.php").'?'.http_build_query($vars, '', '&amp;');
-    } else {
-        $text = '';
-        foreach ($vars as $k => $v) {
-            $text .= '<input type="hidden" name="'.$k.'" value="'.htmlspecialchars($v).'" />'."\n";
-        }
-        return $text;
     }
+    return $vars;
 }
diff --git a/modules/statistics/www/style.css b/modules/statistics/www/style.css
index 1485d07910f3e7bb23af42fc43546184c050338b..4d0d163d600681ffe26fa34cee7cd7cbd9505bc4 100644
--- a/modules/statistics/www/style.css
+++ b/modules/statistics/www/style.css
@@ -1,6 +1,4 @@
 @media all {
-    .ui-tabs-panel { padding: .5em }
-
     div#content {
         margin: .4em ! important;
     }
@@ -35,10 +33,6 @@
         text-align: right;
     }
 
-    div.corner_t {
-        max-width: none ! important;
-    }
-
     table.timeseries tr.odd td {
         background-color: #f4f4f4;
     }
@@ -92,4 +86,42 @@
     table#statmeta {
         width: 100%;
     }
+
+    ul.tabset_tabs {
+        margin: 0px;
+        padding: 0px;
+        list-style: none;
+    }
+
+    ul.tabset_tabs li {
+        background: none;
+        color: #222;
+        display: inline-block;
+        padding: 10px 15px;
+        cursor: pointer;
+    }
+
+    ul.tabset_tabs li.current {
+        background: #ededed;
+        color: #222;
+    }
+
+    .tabset_content {
+        display: none;
+        background: #ededed;
+        padding: 15px;
+    }
+
+    .tabset_content.current {
+        display: inherit;
+    }
+
+    #graph img {
+        max-width: 77%;
+        height: auto;
+    }
+    #table img {
+        max-width: 77%;
+        height: auto;
+    }
 }
diff --git a/templates/_footer.twig b/templates/_footer.twig
index e5fdde185e30ab4db002183c22a6280e9fa82cb8..8b9e730222779f9a58f446997dee3a891c5e8283 100644
--- a/templates/_footer.twig
+++ b/templates/_footer.twig
@@ -1,6 +1,14 @@
-    <hr>
-
-    <img src="/{{ baseurlpath }}resources/icons/ssplogo-fish-small.png" alt="Small fish logo" style="float: right">
-    Copyright © 2007-2018 <a href="http://uninett.no/">UNINETT AS</a>
-
-    <br style="clear: right">
+        <div id="footer">
+            <div class="wrap">
+                <div class="center copyrights dark-bg">
+                    <br>Copyright © 2007-2018
+                    <br>
+                    <i class="fa fa-github" aria-hidden="true"></i> <a href="https://github.com/simplesamlphp/simplesamlphp">SimpleSAMLphp</a>
+                </div>
+                <div class="logo-footer-right">
+                    <div class="logo-footer">
+                        <img class="pure-img" src="/{{ baseurlpath }}resources/icons/ssplogo-fish-small.png" alt="Small fish logo">
+                    </div>
+                </div>
+            </div>
+        </div>
diff --git a/templates/_header.twig b/templates/_header.twig
index 461dfd25d1b2eacd5ea6d27d908728972f116b59..69711aeb2e624df50a1964cb42e9e0b8d6d71b9c 100644
--- a/templates/_header.twig
+++ b/templates/_header.twig
@@ -1,22 +1,72 @@
-<div id="header">
-    <h1><a style="text-decoration: none; color: white" href="/{{ baseurlpath }}">{{ pagetitle }}</a></h1>
-</div>
+        <div id="header">
+            <div class="wrap">
+                <div class="left">
+                    <div class="v-center logo-header">
+                        <div id="logo">
+                            <span class="simple">Simple</span><span class="saml">SAML</span><span class="simple">php</span>
+                            <img class="pure-img hidden" src="" alt="LOGO">
+                        </div>
+                    </div>
+                </div>
+                <div class="right">
+                    <a href="#menu" id="menuLink" class="menu-link hide-for-large">
+                        <!-- Hamburger icon -->
+                        <span class="fa fa-language fa-2x" aria-hidden="true"></span>
+                    </a>
+                </div>
 
-{% if not hideLanguageBar %}
-<div id="languagebar">
-    {% for lang in languageBar %}
-        {%- if not loop.first -%}|{% endif -%}
-        {% if lang.url %}
-            <a href="{{ lang.url -}}
-            {%- if queryParams %}&{% endif -%}
-            {%- for name, value in queryParams -%}
-                {%- if not loop.first %}&{% endif -%}
-                {%- if value %}{{ name }}={{ value }}{% else %}{{ name }}{% endif -%}
-            {%- endfor %}">{{ lang.name }}</a>
-        {% else %}
-            {{ lang.name }}
-        {% endif %}
+                {% if not hideLanguageBar -%}
+                    <div id="languagebar">
+                        <div id="menu">
+                            <div class="pure-menu">
+                                <ul class="pure-menu-list">
+                                {% for key, lang in languageBar -%}
+                                    {% if key == currentLanguage -%}
+                                    <a class="pure-menu-heading" href="#">{{ lang.name }}</a>
+                                    {% else -%}
+                                    {% if lang.url -%}
+                                    <li class="pure-menu-item"><a href="{{ lang.url }}{%- spaceless %}
+                                        {% if queryParams -%}&{% endif -%}
+                                        {% for name, value in queryParams -%}
+                                            {%- if not loop.first %}&{% endif -%}
+                                            {%- if value %}{{ name }}={{ value }}{% else %}{{ name }}{%- endif %}
+                                        {%- endfor %}"{% endspaceless %} class="pure-menu-link">{{ lang.name }}</a></li>
+                                    {% endif -%}
+                                {% endif -%}
+                            {% endfor -%}
+                                </ul>
+                            </div>
+                        </div>
+                    </div>
+                {%- endif %}
+
+                <div class="right show-for-large">
+                    <div class="v-center language-bar">
+                        <form id="SelectLang" class="pure-form" method="get">
+                            {% if not hideLanguageBar -%}
+                            <div id="languagebar">
+                            {% for name, value in queryParams -%}
+                                {% if value -%}
+                                <input type="hidden" name="{{ name }}" value="{{ value }}" />
+                                {%- else -%}
+                                <input type="hidden" name="{{ name }}" />
+                                {%- endif -%}
+                            {%- endfor %}
+
+                                <select  class="pure-input-1-4 language-menu selectize" name="language" id="language_selector">
+                                    {% for key, lang in languageBar -%}
+                                    {% if key == currentLanguage -%}
+                                    <option value="{{ key }}" selected="selected">&#xf1ab;  {{ lang.name }}</option>
+                                    {% else -%}
+                                    <option value="{{ key }}">{{ lang.name }}</option>
+                                    {% endif -%}
+                                {% endfor -%}
+                                </select>
+                            </div>
+                        {% endif -%}
+                        </form>
+                    </div> <!--language-bar-->
+                </div><!--show-for-large-->
+            </div> <!-- wrap -->
+        </div> <!-- header -->
 
-    {% endfor %}
-</div>
-{% endif %}
diff --git a/templates/_table.twig b/templates/_table.twig
new file mode 100644
index 0000000000000000000000000000000000000000..5d8d4aff6fc954ecbfe1d78978f958a739c55095
--- /dev/null
+++ b/templates/_table.twig
@@ -0,0 +1,24 @@
+
+<table id="table_with_attributes"  class="attributes pure-table pure-table-striped pure-table-attributes" summary="attribute overview">
+
+{% for name, values in items %}
+    <tr class="{{ cycle(['odd', 'even'], loop.index0) }}">
+        {% block namecol -%}
+            <td class="attrname">{{ name }}</td>
+        {%- endblock %}
+
+        <td class="attrvalue">{% spaceless %}
+                {% for value in values %}
+                    {% if loop.length>1 and loop.first %}<ul>{% endif %}
+                    {% if loop.length>1 %}<li>{% endif -%}
+
+                    {% block value %}{% endblock %}
+
+                    {% if loop.length>1 %}</li>{% endif %}
+                    {% if loop.length>1 and loop.last %}</ul>{% endif %}
+                {% endfor %}
+            {% endspaceless -%}
+        </td>
+    </tr>
+{% endfor %}
+</table><br>
\ No newline at end of file
diff --git a/templates/auth_status.twig b/templates/auth_status.twig
new file mode 100644
index 0000000000000000000000000000000000000000..a36cb7623d17b9913e665c0b68e8f710de79c2c3
--- /dev/null
+++ b/templates/auth_status.twig
@@ -0,0 +1,82 @@
+{% set pagetitle = 'Authentication status'|trans %}
+{% extends 'base.twig' %}
+
+{% block content %}
+<h2>{{ pagetitle }}</h2>
+
+    <p>{% trans %}Hi, this is the status page of SimpleSAMLphp. Here you can see if your session is timed out, how long it lasts until it times out and all the attributes that are attached to your session.{% endtrans %}</p>
+
+{% if remaining %}
+    <p>{% trans %}Your session is valid for {{ remaining }} seconds from now.{% endtrans %}</p>
+{% endif %}
+
+
+<h2>{{ 'Your attributes'|trans }}</h2>
+    {% set items = attributes %}
+
+{% embed '_table.twig' -%}
+
+    {% block namecol -%}
+    {% set attr = ('{attributes:attribute_'~(name|lower)~'}') %}
+    {% set translated = attr|trans %}
+    <td class="attrname">{% if translated != attr %} {{ translated }} <br>{% endif %} <samp>{{ name }}</samp></td>
+    {% endblock %}
+
+
+    {% block value -%}
+    {% if name =='jpegPhoto'-%}
+        <img src="data:image/jpeg;base64,{{ value }}" />
+    {% else %}{{ value }}{% endif -%}
+    {% endblock %}
+
+{%- endembed %}
+
+
+{% if nameid %}
+    <h2>{{ 'SAML Subject'|trans }}</h2>
+
+    {%  set items = {'NameId' : nameid.value} %}
+
+    {% if not nameid.value %}
+        {%  set items = items|merge({'NameId' : 'not set'|trans}) %}
+    {% endif %}
+
+    {% if nameid.Format %}
+        {% set items = items|merge({('Format'|trans) : nameid.Format}) %}
+    {% endif %}
+
+    {% if nameid.NameQualifier %}
+        {% set items = items|merge({'NameQualifier' : nameid.NameQualifier}) %}
+    {% endif %}
+
+    {% if nameid.SPNameQualifier %}
+        {% set items = items|merge({'SPNameQualifier' : nameid.SPNameQualifier}) %}
+    {% endif %}
+
+    {% if nameid.SPProvidedID %}
+        {% set items = items|merge({'SPProvidedID' : nameid.SPProvidedID}) %}
+    {% endif %}
+
+    <table id="table_with_attributes"  class="attributes pure-table pure-table-striped pure-table-attributes" summary="attribute overview">
+        {% for name, value in items %}
+            <tr class="{{ cycle(['odd', 'even'], loop.index0) }}">
+                <td class="attrname">{{ name }}</td>
+                <td class="attrname">{{ value }}</td>
+            </tr>
+        {% endfor %}
+    </table><br>
+
+{% endif %}
+
+
+{% if logout %}
+    <h2>{% trans %}Logout{% endtrans %}</h2>
+    <p> {{ logout }}</p>
+{% endif %}
+
+{% if logouturl %}
+    <div class="center">
+        <a class="pure-button pure-button-red" href="{{ logouturl }}">{{ 'Logout'|trans }}</a>
+    </div>
+{% endif %}
+{% endblock %}
diff --git a/templates/base.twig b/templates/base.twig
index 249cb2e23c1aaf14d11f43179e46f1fc7f8a1a7f..b895f0ce1bb9b4a42c8e71f1b8bd38ddcb9470a6 100644
--- a/templates/base.twig
+++ b/templates/base.twig
@@ -4,50 +4,55 @@
     <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
     <meta name="viewport" content="initial-scale=1.0">
     <title>{{ pagetitle }}</title>
-    <link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}resources/default.css">
+    <link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}assets/css/lib/pure-min.css">
+    <link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}assets/css/lib/selectize.default.css">
+    <link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}assets/css/lib/font-awesome/css/font-awesome.css">
+    <link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}assets/css/src/default.css">
     <link rel="icon" type="image/icon" href="/{{ baseurlpath }}resources/icons/favicon.ico">
     {% if jquery and jquery.css %}
     <link rel="stylesheet" media="screen" type="text/css" href="/{{ baseurlpath }}resources/uitheme1.8/jquery-ui.css" />
     {% endif %}
-    {% if isRTL %}<link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}resources/default-rtl.css" />{% endif %}
+    {% if isRTL %}<link rel="stylesheet" type="text/css" href="/{{ baseurlpath }}assets/css/src/default-rtl.css" />{% endif %}
     <meta name="robots" content="noindex, nofollow">
     {% block preload %}{% endblock %}
 </head>
-<body>
-    <div id="wrap">
-
-        {% block header %}{% include "_header.twig" %}{% endblock %}
-
+<body id="{{ templateId }}">
+    <div id="layout">
+{% block header %}{% include "_header.twig" %}{% endblock %}
         <div id="content">
-        {% block contentwrapper %}
-        {% block content %}{% endblock %}
-        {% endblock %}
-        </div><!-- #content -->
-
-        <div id="footer">
-            {% block footer %}{% include "_footer.twig" %}{% endblock %}
-        </div>
+            <div class="wrap">
+                {% block contentwrapper -%}
+                    {% block content %}{% endblock -%}
+                {% endblock %}
+            </div>
+        </div><!-- content -->
+        <div id="push"></div>
+    </div><!-- layout -->
 
-    </div><!-- #wrap -->
+    <div id="foot">
+{% block footer %}{% include "_footer.twig" %}{% endblock %}
+    </div>
 
     <!-- postload javascript -->
-    <script type="text/javascript" src="/{{ baseurlpath }}resources/script.js"></script>
-    {% if jquery %}
-    {% set version = '1.8' %}
-    {% if jquery.version %}
-    {% set version = jquery.version %}
-    {% endif %}
-    {% if version == '1.8' %}
-    {% if jquery.core %}
+    <script type="text/javascript" src="/{{ baseurlpath }}assets/js/lib/jquery-3.2.1.min.js"></script>
+    {% spaceless %}{% if jquery %}
+        {% set version = '1.8' %}
+        {% if jquery.version %}
+            {% set version = jquery.version %}
+        {% endif %}
+        {% if version == '1.8' %}
+            {% if jquery.core %}
     <script type="text/javascript" src="/{{ baseurlpath }}resources/jquery-1.8.js"></script>
-    {% endif %}
-    {% if jquery.ui %}
+            {% endif %}
+            {% if jquery.ui %}
     <script type="text/javascript" src="/{{ baseurlpath }}resources/jquery-ui-1.8.js"></script>
-    {% endif %}
-    {% endif %}
-    {% endif %}
-    {% if clipboard %}
-    <script type="text/javascript" src="/{{ baseurlpath }}resources/clipboard.min.js"></script>
-    {% endif %}
-    {% block postload %}{% endblock %}
+            {% endif %}
+        {% endif %}
+    {% endif %}{% endspaceless -%}
+    <script type="text/javascript" src="/{{ baseurlpath }}assets/js/lib/clipboard.min.js"></script>
+    <script type="text/javascript" src="/{{ baseurlpath }}assets/js/lib/selectize.min.js"></script>
+    <script type="text/javascript" src="/{{ baseurlpath }}assets/js/src/language.js"></script>
+    <script type="text/javascript" src="/{{ baseurlpath }}assets/js/src/side_menu.js"></script>
+    <script type="text/javascript" src="/{{ baseurlpath }}assets/js/src/script.js"></script>
+{% block postload %}{% endblock %}
 </body></html>
diff --git a/templates/error.twig b/templates/error.twig
new file mode 100644
index 0000000000000000000000000000000000000000..0f42558804cc0988b999d9214322ea849dae8fad
--- /dev/null
+++ b/templates/error.twig
@@ -0,0 +1,57 @@
+
+{% set pagetitle = dictTitle | trans %}
+{% extends "base.twig" %}
+{% block content %}
+    <h2>{{ dictTitle | trans }}</h2>
+    {{ dictDescr | trans(parameters) }}
+
+    {# include optional information for error
+       Some exceptions set 'includeTemplate' to the name of a template to include.
+       e.g. "core:no_state.tpl.php". The format is "<module>:<template name>"
+    #}
+    {% if includeTemplate -%}
+        {% include(includeTemplate) %}
+    {%- endif %}
+
+    <div class="message-box">
+        <p>{{ '{errors:report_trackid}' | trans }}</p>
+        <div class="pure-button-group two-elements" role="group">
+            <label class="pure-button hollow" disabled><pre id="trackid">{{ error.trackId }}</pre></label>
+            <button data-clipboard-target="#trackid" id="btntrackid" class="pure-button clipboard-btn">
+                <i class="fa fa-copy"></i>
+            </button>
+        </div>
+    </div>
+
+    {# print out exception only if the exception is available #}
+    {% if showerrors -%}
+        <h2>{{'{errors:debuginfo_header}' | trans}}</h2>
+        <p>{{'{errors:debuginfo_text}' | trans}}</p>
+        <div class="code-box code-box-content">
+            <pre>{{ error.exceptionMsg }}<br />{{ error.exceptionTrace }}
+            </pre>
+        </div>
+    {%- endif %}
+
+    {# Add error report submit section if we have a valid technical contact. 'errorreportaddress' will only be set if
+       the technical contact email address has been set. #}
+    {% if errorReportAddress -%}
+        <h2>{{ '{errors:report_header}' | trans }}</h2>
+        <form action="{{ errorReportAddress }}" class="pure-form" method="post">
+            <p>{{ '{errors:report_text}' | trans }}</p>
+            <label for="email">{{ '{errors:report_email}' | trans }}</label>
+                <input type="email" name="email" id="email" class="edge" value="{{ email }}" />
+            </p>
+
+            <textarea class="text-area edge" name="text" rows="6" cols="50" placeholder="{{ '{errors:report_explain}' | trans }}" required></textarea>
+        <p class="center">
+            <input type="hidden" name="reportId" value="{{ error.reportId }}" />
+            <input type="submit" name="send" class="pure-button pure-button-red" value="{{ '{errors:report_submit}' | trans }}" />
+        </p>
+        </form>
+    {%- endif %}
+
+    <h2>{{ '{errors:howto_header}' | trans }}</h2>
+    <p>{{ '{errors:howto_text}' | trans }}</p>
+
+{% endblock %}
diff --git a/templates/errorreport.twig b/templates/errorreport.twig
new file mode 100644
index 0000000000000000000000000000000000000000..d491aaa8cdf29195e1b86680f534c6e04c9cb61c
--- /dev/null
+++ b/templates/errorreport.twig
@@ -0,0 +1,8 @@
+{% set pagetitle = 'Error report sent'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h2>{{ pagetitle }}</h2>
+
+    <p>{{ 'The error report has been sent to the administrators.' |trans }}</p>
+{% endblock %}
diff --git a/templates/hostnames.twig b/templates/hostnames.twig
new file mode 100644
index 0000000000000000000000000000000000000000..79f6411f034b1202436513f6d76d345237ec4f34
--- /dev/null
+++ b/templates/hostnames.twig
@@ -0,0 +1,20 @@
+{% set pagetitle = 'Diagnostics on hostname, port and protocol'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h2>{{ pagetitle }}</h2>
+    {% set items = attributes %}
+
+    {% embed '_table.twig' %}
+
+        {% block namecol %}
+            <td class="attrname"><samp>{{ name }}</samp></td>
+        {% endblock %}
+
+        {% block value %}
+                {{ value }}
+        {% endblock %}
+
+    {% endembed %}
+
+{% endblock %}
diff --git a/templates/includes/header.php b/templates/includes/header.php
index dc3d141c3adb78267934499e86bc72077875ed86..b58d4a1920a21f75dd520d9ddb980eee772dbbb5 100644
--- a/templates/includes/header.php
+++ b/templates/includes/header.php
@@ -46,7 +46,7 @@ header('X-Frame-Options: SAMEORIGIN');
 <head>
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
 <meta name="viewport" content="initial-scale=1.0" />
-<script type="text/javascript" src="/<?php echo $this->data['baseurlpath']; ?>resources/script.js"></script>
+<script type="text/javascript" src="/<?php echo $this->data['baseurlpath']; ?>assets/js/src/script.js"></script>
 <title><?php
 if (array_key_exists('header', $this->data)) {
     echo $this->data['header'];
diff --git a/templates/logout.twig b/templates/logout.twig
new file mode 100644
index 0000000000000000000000000000000000000000..e860aff557443d4a5283f43bb98f9dfc2f613fac
--- /dev/null
+++ b/templates/logout.twig
@@ -0,0 +1,12 @@
+{% set pagetitle = 'Logged out'|trans %}
+{% extends "base.twig" %}
+
+{% block content %}
+    <h1>{{ 'Logged out'|trans }}</h1>
+    <br>
+    <h3>{% trans %}You have been logged out.{% endtrans %}</h3>
+    <br>
+    {% if text %}
+    <p><a href="{{ link }}">{{ text|trans }}</a></p>
+    {% endif %}
+{% endblock %}
\ No newline at end of file
diff --git a/templates/metadata-converter.twig b/templates/metadata-converter.twig
new file mode 100644
index 0000000000000000000000000000000000000000..fff4d685fed2abf8cfaf3a6909fa2289404d74b1
--- /dev/null
+++ b/templates/metadata-converter.twig
@@ -0,0 +1,49 @@
+{% set pagetitle = 'Metadata parser'|trans %}
+{% extends "base.twig" %}
+
+{%  set i=1 %}
+{% block content %}
+    <h1>{{ pagetitle }}</h1>
+    <form method="post" class="pure-form" enctype="multipart/form-data">
+        <h3> {% trans 'XML metadata' %}</h3>
+        <div class="pure-control-group">
+            <textarea name="xmldata" rows="20" class="text-area edge">{{ xmldata }}</textarea>
+        </div>
+        <br>
+        <div class="center">
+            <div class="pure-button-group two-elements" role="group">
+                <label class="pure-button">
+                    <span class="fa fa-folder-open"></span>{{ 'or select a file:'|trans }}
+                    <input type="file" name="xmlfile" class="hidden" multiple>
+                </label>
+                {#needs translation#}
+                <label id="show-file" class="pure-button hollow show-files" disabled>No file selected.</label>
+            </div>
+            <br>
+            <button class="pure-button pure-button-red pure-input-1-3">{{ 'Parse'|trans }}</button>
+        </div>
+    </form>
+
+    {% if output -%}
+    <br>
+    <h2>{{ 'Converted metadata'|trans }}</h2>
+        {% for type, text in output if text -%}
+    <div class="code-box">
+        <div class="code-box-title">
+            <h3> {{ type }}</h3>
+            <button data-clipboard-target="#metadata{{ loop.index }}" id="btn{{ loop.index }}" class="pure-button right clipboard-btn">
+                <i class="fa fa-copy"></i>
+            </button>
+        </div>
+        <div class="code-box-content">
+            <pre id="metadata{{ loop.index }}">
+                {%- spaceless %}{{ text|escape }}{% endspaceless -%}
+            </pre>
+        </div>
+    </div>
+            <br><br>
+            {%- set i=i+1 %}
+        {%- endfor -%}
+    {% endif -%}
+{% endblock content -%}
+
diff --git a/templates/metadata.twig b/templates/metadata.twig
new file mode 100644
index 0000000000000000000000000000000000000000..f62aa13a63de424c49fdf92649d063af9f360f4b
--- /dev/null
+++ b/templates/metadata.twig
@@ -0,0 +1,54 @@
+{% set pagetile = 'SimpleSAMLphp Show Metadata'|trans %}
+{% extends 'base.twig' %}
+{% block content %}
+    <h2>{{ header }}</h2>
+    <p>{{ metadata_intro }}</p>
+
+{% if metaurl is defined %}
+    <p>{{ 'You can get the metadata xml on a dedicated URL:' | trans }}</p>
+    <div class="input-group">
+        <pre id="metadataurl" class="input-left">{{ metaurl }}</pre>
+        <button data-clipboard-target="#metadataurl" id="btnurl" class="pure-button right clipboard-btn">
+            <span class="fa fa-copy"></span>
+        </button>
+    </div>
+{% endif %}
+
+    <h2>{{ 'Metadata' | trans }}</h2>
+    <div class="code-box">
+        <div class="code-box-title">
+    <p>{{ 'In SAML 2.0 Metadata XML format:' | trans }}</p>
+            <button data-clipboard-target="#xmlmetadata" id="btnxml" class="pure-button right clipboard-btn">
+                <span class="fa fa-copy"></span>
+            </button>
+        </div>
+        <div class="code-box-content">
+            <pre id="xmlmetadata">{{ metadata | raw }}</pre>
+        </div>
+    </div>
+
+    <div class="code-box">
+        <div class="code-box-title">
+    <p>{{ 'In SimpleSAMLphp flat file format - use this if you are using a SimpleSAMLphp entity on the other side:' | trans }}</p>
+            <button data-clipboard-target="#phpmetadata" id="btnphp" class="pure-button right clipboard-btn">
+                <span class="fa fa-copy"></span>
+            </button>
+        </div>
+        <div class="code-box-content">
+            <pre id="phpmetadata">{{ metadataflat | raw }}</pre>
+        </div>
+    </div>
+
+{% if certdata is defined %}
+    <h2>{{ 'Certificates' |trans }}</h2>
+    <p>{{ 'Download the X509 certificates as PEM-encoded files.' |trans }}</p>
+
+    <ul>
+    {% for cert in certdata %}
+        <li><a href="{{ cert.url }}">{{ cert.name }}</a> {{ cert.comment }}</li>
+    {% endfor %}
+    </ul>
+
+{% endif %}
+
+{% endblock content %}
diff --git a/www/index.php b/www/index.php
index 42344ed94eeb4331489f6ccccf579ae215cc09b0..b5b456c7a8c3828829d28652896aae3aac3a1595 100644
--- a/www/index.php
+++ b/www/index.php
@@ -2,4 +2,10 @@
 
 require_once('_include.php');
 
+$config = \SimpleSAML\Configuration::getInstance();
+
+if ($config->getBoolean('usenewui', false)) {
+    \SimpleSAML\Utils\HTTP::redirectTrustedURL(SimpleSAML\Module::getModuleURL('core/login.php'));
+}
+
 \SimpleSAML\Utils\HTTP::redirectTrustedURL(SimpleSAML\Module::getModuleURL('core/frontpage_welcome.php'));
diff --git a/www/saml2/idp/metadata.php b/www/saml2/idp/metadata.php
index c79485129607ea8ab8562b37e34d10808ac87259..d15262f5a8ce81cf318a80e1b0305ed0a778fb0a 100644
--- a/www/saml2/idp/metadata.php
+++ b/www/saml2/idp/metadata.php
@@ -219,6 +219,13 @@ try {
 
         $t->data['clipboard.js'] = true;
         $t->data['available_certs'] = $availableCerts;
+        $certdata = array();
+        foreach(array_keys($availableCerts) as $availableCert) {
+               $certdata[$availableCert]['name'] = $availableCert;
+               $certdata[$availableCert]['url'] = SimpleSAML\Module::getModuleURL('saml/idp/certs.php') . '/' . $availableCert;
+               $certdata[$availableCert]['comment'] = ( $availableCerts[$availableCert]['certFingerprint'][0] === 'afe71c28ef740bc87425be13a2263d37971da1f9' ? 'This is the default certificate. Generate a new certificate if this is a production system.' : '');
+        }
+        $t->data['certdata'] = $certdata;
         $t->data['header'] = 'saml20-idp'; // TODO: Replace with headerString in 2.0
         $t->data['headerString'] = $t->noop('metadata_saml20-idp');
         $t->data['metaurl'] = HTTP::getSelfURLNoQuery();