Added multilingual and theme switching support, fixed multiple

positioning issues, added articles to sidebar
This commit is contained in:
2026-08-13 12:41:05 +02:00
parent 6e1812c2df
commit 1bd70cb16b
4 changed files with 471 additions and 68 deletions
+338 -28
View File
@@ -1,4 +1,4 @@
@import url("pygments.css"); @import url("pygments.css");
@import url("pygments-dark.css") (prefers-color-theme: dark); @import url("pygments-dark.css") (prefers-color-theme: dark);
@font-face { @font-face {
@@ -50,7 +50,7 @@
} }
@media (prefers-color-scheme: dark) { @media (prefers-color-scheme: dark) {
:root { :root:not([data-theme]) {
--main-bg-color: hsl(0, 5%, 10%); --main-bg-color: hsl(0, 5%, 10%);
--main-text-color: hsl(210, 20%, 98%); --main-text-color: hsl(210, 20%, 98%);
--main-link-color: hsl(0, 100%, 65%); --main-link-color: hsl(0, 100%, 65%);
@@ -59,6 +59,22 @@
} }
} }
:root[data-theme="dark"] {
--main-bg-color: hsl(0, 5%, 10%);
--main-text-color: hsl(210, 20%, 98%);
--main-link-color: hsl(0, 100%, 65%);
--table-border-color: hsl(0, 0%, 15%);
--table-head-border-color: hsl(0, 0%, 30%);
}
:root[data-theme="light"] {
--main-bg-color: hsl(210, 20%, 98%);
--main-text-color: hsl(0, 5%, 10%);
--main-link-color: hsl(0, 100%, 35%);
--table-border-color: hsl(0, 0%, 85%);
--table-head-border-color: hsl(0, 0%, 70%);
}
*, *::before, *::after { *, *::before, *::after {
box-sizing: border-box; box-sizing: border-box;
} }
@@ -92,6 +108,37 @@ body {
text-rendering: optimizeLegibility; text-rendering: optimizeLegibility;
} }
header {
position: relative;
}
.header-controls {
position: absolute;
top: 0;
right: 0;
display: flex;
align-items: center;
gap: 0.75rem;
padding: 0;
margin: -1.75rem -0.5rem 0 0;
}
.header-delimiter {
color: var(--table-border-color);
font-size: 1rem;
line-height: 1;
user-select: none;
}
.lang-switcher {
position: static;
list-style: none;
display: flex;
gap: 0.5rem;
margin: 0;
padding: 0;
}
p { p {
text-align: justify; text-align: justify;
hyphens: auto; hyphens: auto;
@@ -165,25 +212,48 @@ ul, ol {
padding: 0; padding: 0;
} }
ul.menuitems {
list-style: none;
margin: 3rem 0 0 0;
font-size: 0.9rem;
}
#theme-toggle {
background: none;
border: none;
padding: 0;
margin: 0;
font-size: 1.1rem;
line-height: 1;
color: var(--main-link-color);
cursor: pointer;
display: flex;
align-items: center;
justify-content: center;
opacity: 0.85;
transition: opacity 0.15s ease;
}
#theme-toggle:hover,
#theme-toggle:focus-visible {
opacity: 1;
}
#theme-toggle:focus-visible {
outline: 2px solid hsl(220, 90%, 52%);
outline-offset: 2px;
}
#banner, #contentinfo { #banner, #contentinfo {
width: 100%; width: 100%;
text-align: center; text-align: center;
} }
#categories {
margin-top: 40px;
}
#categories:before {
content: "Categories:";
}
#contentinfo { #contentinfo {
flex-shrink: 0; flex-shrink: 0;
margin-top: 40px margin-top: 40px
} }
#container { #container {
flex: 1 0 auto; flex: 1 0 auto;
display: flex; display: flex;
@@ -201,21 +271,95 @@ ul, ol {
min-width: 300px; min-width: 300px;
} }
#pages:before {
content: "Pages:";
}
#recent-articles:before {
content: "Recent Articles:";
}
#categories:before {
content: "Categories:";
}
#translations {
text-align: right;
}
#translations:before {
content: "Translations: ";
}
html[lang="de"] {
#pages:before {
content: "Seiten:";
}
#recent-articles:before {
content: "Neueste Artikel:";
}
#categories:before {
content: "Kategorien:";
}
#translations:before {
content: "Übersetzungen:";
}
}
.menuitems { .menuitems {
list-style: none; list-style: none;
margin: 3rem 0 0 0;
font-size: 0.9rem;
}
.menuitems li {
margin-bottom: 0.85rem;
}
.menuitems:before {
display: block;
font-size: 1.4rem;
line-height: 1.8rem;
margin-bottom: 0.75rem;
}
.menuitems a {
display: -webkit-box;
-webkit-line-clamp: 2;
-webkit-box-orient: vertical;
overflow: hidden;
text-overflow: ellipsis;
line-height: 1.3;
text-decoration: none;
padding-bottom: 1px;
}
.menuitems a:hover,
.menuitems a:focus-visible {
text-decoration: underline;
} }
#content { #content {
flex: 1 1 auto; flex: 1 1 auto;
} }
/*#post-list > li:first-child > article > header > h2,
main h2:first-child{
margin-top: 0;
}*/
#post-list li { #post-list li {
list-style: none; list-style: none;
margin: 0;
} }
.entry-title { .entry-title {
text-align: center; text-align: center;
} }
div.post-info { div.post-info {
text-align: center; text-align: center;
} }
@@ -234,22 +378,87 @@ footer.post-info {
} }
/* /*
* Links * ToC
*/
.toc a,
.entry-content a.headerlink {
pointer-events: auto;
cursor: pointer;
}
.toc {
padding: 1rem 1.5rem;
margin: 1.5rem 0;
}
.toc ul {
list-style: none;
padding-left: 1.25rem;
margin: 0.25rem 0;
counter-reset: toc-item;
}
.toc > ul {
padding-left: 0;
}
.toc li {
counter-increment: toc-item;
}
.toc li::before {
content: counters(toc-item, '.') '. ';
padding-right: 0.5rem;
color: var(--main-link-color);
}
.toc a {
text-decoration: none;
}
.toc a:hover {
text-decoration: underline;
}
/*
* Headings
*/ */
.entry-content { .entry-content {
counter-reset: entrylinks 0 figures 0 tables 0 listings 0; counter-reset: entrylinks 0 figures 0 tables 0 listings 0 h2counter 0;
} }
.entry-content a { .entry-content a {
counter-increment: entrylinks;
text-decoration: none; text-decoration: none;
color: inherit; color: inherit;
outline: none; outline: none;
cursor: default; cursor: default;
pointer-events: none; pointer-events: none;
} }
.entry-content a:after {
.entry-content a.headerlink {
opacity: 0;
margin-left: 0.5rem;
text-decoration: none;
color: var(--main-link-color);
transition: opacity 0.15s ease;
}
#
.entry-content h1:hover a.headerlink,
.entry-content h2:hover a.headerlink,
.entry-content h3:hover a.headerlink,
.entry-content h4:hover a.headerlink,
.entry-content h5:hover a.headerlink,
.entry-content h6:hover a.headerlink {
opacity: 1;
}
.entry-content a:not(.toc a):not(.headerlink) {
counter-increment: entrylinks;
}
.entry-content a:not(.toc a):not(.headerlink):after {
content: '[' counter(entrylinks) ']'; content: '[' counter(entrylinks) ']';
margin-left: 2px; margin-left: 2px;
color: var(--main-link-color); color: var(--main-link-color);
@@ -257,6 +466,36 @@ footer.post-info {
pointer-events: auto; pointer-events: auto;
} }
/*
* Heading numbering
*/
.entry-content h2 {
counter-reset: h3counter;
counter-increment: h2counter;
}
.entry-content h3 {
counter-reset: h4counter;
counter-increment: h3counter;
}
.entry-content h4 {
counter-increment: h4counter;
}
.entry-content h2::before {
content: counter(h2counter) '. ';
}
.entry-content h3::before {
content: counter(h2counter) '.' counter(h3counter) '. ';
}
.entry-content h4::before {
content: counter(h2counter) '.' counter(h3counter) '.' counter(h4counter) '. ';
}
/* /*
* Lists * Lists
*/ */
@@ -281,6 +520,7 @@ footer.post-info {
max-width: 80%; max-width: 80%;
margin: 0 auto 0 auto; margin: 0 auto 0 auto;
padding: 1rem; padding: 1rem;
cursor: zoom-in;
} }
.entry-content img~em{ .entry-content img~em{
@@ -294,6 +534,89 @@ footer.post-info {
font-weight: bold; font-weight: bold;
} }
/*
* Lightbox
*/
.lightbox-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
background: rgba(255, 255, 255, 0.95);
z-index: 1000;
cursor: zoom-out;
align-items: center;
justify-content: center;
}
.lightbox-overlay.active {
display: flex;
flex-direction: column;
}
.lightbox-overlay .lightbox-content {
display: flex;
flex-direction: column;
align-items: center;
max-width: 95vw;
max-height: 95vh;
}
.lightbox-overlay img {
max-width: 95vw;
max-height: 85vh;
object-fit: contain;
background: #fff;
}
.lightbox-overlay #lightbox-caption {
color: #111;
text-align: center;
margin-top: 0.75rem;
font-size: 0.95rem;
}
.lightbox-overlay #lightbox-caption .fig-number {
font-weight: bold;
}
/* Fallback: Systemeinstellung, nur falls kein manueller Override gesetzt ist */
@media (prefers-color-scheme: dark) {
:root:not([data-theme]) .lightbox-overlay {
background: rgba(0, 0, 0, 0.95);
}
:root:not([data-theme]) .lightbox-overlay img {
background: transparent;
}
:root:not([data-theme]) .lightbox-overlay #lightbox-caption {
color: #fff;
}
}
/* Manueller Override, gewinnt immer gegen Media-Query */
:root[data-theme="dark"] .lightbox-overlay {
background: rgba(0, 0, 0, 0.95);
}
:root[data-theme="dark"] .lightbox-overlay img {
background: transparent;
}
:root[data-theme="dark"] .lightbox-overlay #lightbox-caption {
color: #fff;
}
:root[data-theme="light"] .lightbox-overlay {
background: rgba(255, 255, 255, 0.95);
}
:root[data-theme="light"] .lightbox-overlay img {
background: #fff;
}
:root[data-theme="light"] .lightbox-overlay #lightbox-caption {
color: #111;
}
/* /*
* Tables * Tables
*/ */
@@ -405,19 +728,6 @@ footer.post-info {
/* This is old stuff, inherited from LaTeX.css, probably unused */ /* This is old stuff, inherited from LaTeX.css, probably unused */
/* Nested ordered list for ToC */
.toc ol {
counter-reset: item;
padding-left: 2rem;
}
.toc li {
display: block;
}
.toc li:before {
content: counters(item, '.') ' ';
counter-increment: item;
padding-right: 0.85rem;
}
/* Make footnote text smaller and left align it (looks bad with long URLs) */ /* Make footnote text smaller and left align it (looks bad with long URLs) */
.footnotes p { .footnotes p {
+126 -28
View File
@@ -3,66 +3,99 @@
<html lang="{% block html_lang %}{{ DEFAULT_LANG }}{% endblock html_lang %}"> <html lang="{% block html_lang %}{{ DEFAULT_LANG }}{% endblock html_lang %}">
<head> <head>
{% block head %} {% block head %}
<title>{% block title %}{{ SITENAME }}{% endblock title %}</title> <title>{% block title %}{{ SITENAME }}{% endblock title %}</title>
<meta charset="utf-8" /> <meta charset="utf-8" />
<link rel="stylesheet" type="text/css" href="{{ SITEURL }}/theme/css/site.css" /> <script>
(function () {
const stored = localStorage.getItem('theme');
if (stored === 'dark' || stored === 'light') {
document.documentElement.setAttribute('data-theme', stored);
}
})();
</script>
<link rel="stylesheet" type="text/css" href="{{ main_siteurl | default(SITEURL) }}/theme/css/site.css" />
{% if FEED_ALL_ATOM %} {% if FEED_ALL_ATOM %}
<link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_ATOM_URL %}{{ FEED_ALL_ATOM_URL }}{% else %}{{ FEED_ALL_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Full Atom Feed" /> <link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_ATOM_URL %}{{ FEED_ALL_ATOM_URL }}{% else %}{{ FEED_ALL_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Full Atom Feed" />
{% endif %} {% endif %}
{% if FEED_ALL_RSS %} {% if FEED_ALL_RSS %}
<link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_RSS_URL %}{{ FEED_ALL_RSS_URL }}{% else %}{{ FEED_ALL_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Full RSS Feed" /> <link href="{{ FEED_DOMAIN }}/{% if FEED_ALL_RSS_URL %}{{ FEED_ALL_RSS_URL }}{% else %}{{ FEED_ALL_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Full RSS Feed" />
{% endif %} {% endif %}
{% if FEED_ATOM %} {% if FEED_ATOM %}
<link href="{{ FEED_DOMAIN }}/{%if FEED_ATOM_URL %}{{ FEED_ATOM_URL }}{% else %}{{ FEED_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Atom Feed" /> <link href="{{ FEED_DOMAIN }}/{%if FEED_ATOM_URL %}{{ FEED_ATOM_URL }}{% else %}{{ FEED_ATOM }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Atom Feed" />
{% endif %} {% endif %}
{% if FEED_RSS %} {% if FEED_RSS %}
<link href="{{ FEED_DOMAIN }}/{% if FEED_RSS_URL %}{{ FEED_RSS_URL }}{% else %}{{ FEED_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} RSS Feed" /> <link href="{{ FEED_DOMAIN }}/{% if FEED_RSS_URL %}{{ FEED_RSS_URL }}{% else %}{{ FEED_RSS }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} RSS Feed" />
{% endif %} {% endif %}
{% if CATEGORY_FEED_ATOM and category %} {% if CATEGORY_FEED_ATOM and category %}
<link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_ATOM_URL %}{{ CATEGORY_FEED_ATOM_URL.format(slug=category.slug) }}{% else %}{{ CATEGORY_FEED_ATOM.format(slug=category.slug) }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Categories Atom Feed" /> <link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_ATOM_URL %}{{ CATEGORY_FEED_ATOM_URL.format(slug=category.slug) }}{% else %}{{ CATEGORY_FEED_ATOM.format(slug=category.slug) }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Categories Atom Feed" />
{% endif %} {% endif %}
{% if CATEGORY_FEED_RSS and category %} {% if CATEGORY_FEED_RSS and category %}
<link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_RSS_URL %}{{ CATEGORY_FEED_RSS_URL.format(slug=category.slug) }}{% else %}{{ CATEGORY_FEED_RSS.format(slug=category.slug) }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Categories RSS Feed" /> <link href="{{ FEED_DOMAIN }}/{% if CATEGORY_FEED_RSS_URL %}{{ CATEGORY_FEED_RSS_URL.format(slug=category.slug) }}{% else %}{{ CATEGORY_FEED_RSS.format(slug=category.slug) }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Categories RSS Feed" />
{% endif %} {% endif %}
{% if TAG_FEED_ATOM and tag %} {% if TAG_FEED_ATOM and tag %}
<link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_ATOM_URL %}{{ TAG_FEED_ATOM_URL.format(slug=tag.slug) }}{% else %}{{ TAG_FEED_ATOM.format(slug=tag.slug) }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Tags Atom Feed" /> <link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_ATOM_URL %}{{ TAG_FEED_ATOM_URL.format(slug=tag.slug) }}{% else %}{{ TAG_FEED_ATOM.format(slug=tag.slug) }}{% endif %}" type="application/atom+xml" rel="alternate" title="{{ SITENAME }} Tags Atom Feed" />
{% endif %} {% endif %}
{% if TAG_FEED_RSS and tag %} {% if TAG_FEED_RSS and tag %}
<link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_RSS_URL %}{{ TAG_FEED_RSS_URL.format(slug=tag.slug) }}{% else %}{{ TAG_FEED_RSS.format(slug=tag.slug) }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Tags RSS Feed" /> <link href="{{ FEED_DOMAIN }}/{% if TAG_FEED_RSS_URL %}{{ TAG_FEED_RSS_URL.format(slug=tag.slug) }}{% else %}{{ TAG_FEED_RSS.format(slug=tag.slug) }}{% endif %}" type="application/rss+xml" rel="alternate" title="{{ SITENAME }} Tags RSS Feed" />
{% endif %} {% endif %}
{% endblock head %} {% endblock head %}
</head> </head>
<body id="index" class="home"> <body id="index" class="home">
<header id="banner" class="body"> <header id="banner" class="body">
<div class="header-controls">
{% if extra_siteurls is defined %}
<ul class="lang-switcher">
{% for lang, siteurl in extra_siteurls.items() %}
<li>
{% if article is defined and article %}
<a href="{{ siteurl }}/{{ article.slug }}.html">{{ lang }}</a>
{% elif page is defined and page %}
<a href="{{ siteurl }}/pages/{{ page.slug }}.html">{{ lang }}</a>
{% else %}
<a href="{{ siteurl }}/">{{ lang }}</a>
{% endif %}
</li>
{% endfor %}
</ul>
<span class="header-delimiter">·</span>
{% endif %}
<button id="theme-toggle" aria-label="Toggle color theme"></button>
</div>
<h1><a href="{{ SITEURL }}/">{{ SITENAME }} <strong>{{ SITESUBTITLE }}</strong></a></h1> <h1><a href="{{ SITEURL }}/">{{ SITENAME }} <strong>{{ SITESUBTITLE }}</strong></a></h1>
</header><!-- /#banner --> </header><!-- /#banner -->
<div id="container"> <div id="container">
<nav id="menu"> <nav id="menu">
{% for title, link in MENUITEMS %} {% for title, link in MENUITEMS %}
<ul class="menuitems"> <ul class="menuitems">
<li><a href="{{ link }}">{{ title }}</a></li> <li><a href="{{ link }}">{{ title }}</a></li>
</ul> </ul>
{% endfor %} {% endfor %}
{% if DISPLAY_PAGES_ON_MENU %} {% if DISPLAY_PAGES_ON_MENU %}
<ul id="pages" class="menuitems"> <ul id="pages" class="menuitems">
{% for p in pages %} {% for p in pages %}
<li{% if p == page %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li> <li{% if p == page %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ p.url }}">{{ p.title }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %}
{% if DISPLAY_RECENT_ARTICLES_ON_MENU | default(true) and articles is defined and articles %}
<ul id="recent-articles" class="menuitems">
{% for recent_article in articles[:(RECENT_ARTICLES_COUNT | default(10))] %}
<li{% if article is defined and recent_article == article %} class="active"{% endif %}>
<a href="{{ SITEURL }}/{{ recent_article.url }}">{{ recent_article.title }}</a>
</li>
{% endfor %}
</ul>
{% endif %} {% endif %}
{% if DISPLAY_CATEGORIES_ON_MENU %} {% if DISPLAY_CATEGORIES_ON_MENU %}
<ul id="categories" class="menuitems"> <ul id="categories" class="menuitems">
{% for cat, null in categories %} {% for cat, null in categories %}
<li{% if cat == category %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ cat.url }}">{{ cat }}</a></li> <li{% if cat == category %} class="active"{% endif %}><a href="{{ SITEURL }}/{{ cat.url }}">{{ cat }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
{% endif %} {% endif %}
</nav><!-- /#menu --> </nav><!-- /#menu -->
<main id="content"> <main id="content">
@@ -77,8 +110,73 @@
</address><!-- /#about --> </address><!-- /#about -->
</footer><!-- /#contentinfo --> </footer><!-- /#contentinfo -->
<div class="lightbox-overlay" id="lightbox-overlay">
<div class="lightbox-content">
<img id="lightbox-img" src="" alt="">
<p id="lightbox-caption"></p>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', function () {
const overlay = document.getElementById('lightbox-overlay');
const overlayImg = document.getElementById('lightbox-img');
const overlayCaption = document.getElementById('lightbox-caption');
document.querySelectorAll('.entry-content img').forEach(function (img, index) {
const figureNumber = index + 1;
img.addEventListener('click', function () {
overlayImg.src = img.src;
overlayImg.alt = img.alt;
const captionEl = img.nextElementSibling;
const captionText = (captionEl && captionEl.tagName === 'EM') ? captionEl.textContent : '';
overlayCaption.innerHTML = captionText
? '<span class="fig-number">Figure ' + figureNumber + ':</span> ' + captionText
: '';
overlay.classList.add('active');
});
});
overlay.addEventListener('click', function () {
overlay.classList.remove('active');
overlayImg.src = '';
overlayCaption.innerHTML = '';
});
document.addEventListener('keydown', function (e) {
if (e.key === 'Escape') {
overlay.classList.remove('active');
overlayImg.src = '';
overlayCaption.innerHTML = '';
}
});
});
</script>
<script>
document.addEventListener('DOMContentLoaded', function () {
const toggleBtn = document.getElementById('theme-toggle');
const root = document.documentElement;
function getCurrentTheme() {
const attr = root.getAttribute('data-theme');
if (attr) return attr;
return window.matchMedia('(prefers-color-scheme: dark)').matches ? 'dark' : 'light';
}
function updateIcon() {
toggleBtn.textContent = getCurrentTheme() === 'dark' ? '☀' : '☾';
}
updateIcon();
toggleBtn.addEventListener('click', function () {
const next = getCurrentTheme() === 'dark' ? 'light' : 'dark';
root.setAttribute('data-theme', next);
localStorage.setItem('theme', next);
updateIcon();
});
});
</script>
</body> </body>
</html> </html>
<!-- vim:ts=2:sw=2:et:ft=html -->
+2 -8
View File
@@ -2,11 +2,7 @@
{% block content %} {% block content %}
<section id="content"> <section id="content-section">
{% block content_title %}
<h2>All articles</h2>
{% endblock %}
<ol id="post-list"> <ol id="post-list">
{% for article in articles_page.object_list %} {% for article in articles_page.object_list %}
<li> <li>
@@ -37,8 +33,6 @@
{% include 'pagination.html' %} {% include 'pagination.html' %}
{% endif %} {% endif %}
</section><!-- /#content --> </section><!-- /#content-section -->
{% endblock content %} {% endblock content %}
<!-- vim:ts=2:sw=2:et:ft=html -->
+5 -4
View File
@@ -1,9 +1,10 @@
{% macro translations_for(article) %} {% macro translations_for(article) %}
{% if article.translations %} {% if article.translations %}
Translations: <div id="translations">
{% for translation in article.translations %} {% for translation in article.translations %}
<a href="{{ SITEURL }}/{{ translation.url }}" hreflang="{{ translation.lang }}">{{ translation.lang }}</a> <a href="{{ SITEURL }}/{{ translation.url }}" hreflang="{{ translation.lang }}">{{ translation.lang }}</a>
{% endfor %} {% endfor %}
</div>
{% endif %} {% endif %}
{% endmacro %} {% endmacro %}