Changeset 03fa548 in Klonkt
- Timestamp:
- 06/20/2026 01:39:41 PM (3 months ago)
- Branches:
- main
- Children:
- 91c0a39
- Parents:
- d0f4c10
- Location:
- src
- Files:
-
- 2 added
- 6 edited
-
middleware/render.js (modified) (2 diffs)
-
routes/lang.js (added)
-
server.js (modified) (2 diffs)
-
services/i18n.js (added)
-
views/partials/footer.ejs (modified) (3 diffs)
-
views/partials/post-nav.ejs (modified) (4 diffs)
-
views/partials/topnav.ejs (modified) (8 diffs)
-
views/partials/view-switcher.ejs (modified) (3 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/middleware/render.js
rd0f4c10 r03fa548 20 20 import { isPremium as isPremiumInstance, premiumEnabled, premiumUnlocked } from '../services/PatreonService.js'; 21 21 import { PLATFORMS as PLATFORMS_CATALOG } from '../services/PlatformIcons.js'; 22 import { t as i18nT, resolveLang, SUPPORTED as LANGS, LANG_NAMES } from '../services/i18n.js'; 22 23 23 24 const __dirname = path.dirname(fileURLToPath(import.meta.url)); … … 77 78 const canSeeBeheer = !!(_u && (_role === 'god' || _role === 'admin' || _role === 'kijker' || userOwnsSite)); 78 79 80 // Interface-taal (bezoeker-instelbaar): sessie-keuze → browser-taal → nl. 81 const _lang = resolveLang(req); 82 79 83 // Common locals 80 84 const locals = { 81 85 user: _u, 86 lang: _lang, 87 t: (key, vars) => i18nT(_lang, key, vars), 88 langs: LANGS.map((c) => ({ code: c, name: LANG_NAMES[c], active: c === _lang })), 82 89 userOwnsSite, 83 90 canSeeBeheer, -
src/server.js
rd0f4c10 r03fa548 46 46 import artistsRoutes from './routes/artists.js'; 47 47 import postsRoutes from './routes/posts.js'; 48 import langRoutes from './routes/lang.js'; 48 49 import federationRoutes from './routes/federation.js'; 49 50 import { startCircleSyncLoop } from './services/CircleService.js'; … … 288 289 app.use('/', showsRoutes); // /shows agenda + notify-me (premium) 289 290 app.use('/', changelogRoutes); // /changelog publieke release-/wijzigingen-pagina 291 app.use('/', langRoutes); // /lang/:code — interface-taal kiezen (vóór de catch-all) 290 292 app.use('/', postsRoutes); 291 293 -
src/views/partials/footer.ejs
rd0f4c10 r03fa548 2 2 <% if (typeof footerNewsletter !== 'undefined' && footerNewsletter && (typeof premiumUnlocked === 'undefined' || premiumUnlocked) && typeof site !== 'undefined' && site) { %> 3 3 <div class="container footer-nl"> 4 <span class="footer-nl-label">📬 Blijf op de hoogte</span>4 <span class="footer-nl-label">📬 <%= t('footer.subscribe_cta') %></span> 5 5 <form method="post" action="<%= (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '' %>/nieuwsbrief" class="footer-nl-form"> 6 <input type="email" name="email" required placeholder=" jouw@email.nl" autocomplete="email" aria-label="E-mailadres">7 <button type="submit"> Inschrijven</button>6 <input type="email" name="email" required placeholder="<%= t('common.email_placeholder') %>" autocomplete="email" aria-label="E-mailadres"> 7 <button type="submit"><%= t('footer.subscribe') %></button> 8 8 </form> 9 9 </div> … … 17 17 <button type="button" class="install-app-btn install-app-btn--footer" data-pcms-install-app> 18 18 <svg viewBox="0 0 24 24" width="16" height="16" aria-hidden="true"><path d="M5 20h14v-2H5v2zm7-18L5.33 9h3.84v6h5.66V9h3.84L12 2z" fill="currentColor"/></svg> 19 <span> Installeer app</span>19 <span><%= t('footer.install') %></span> 20 20 </button> 21 21 <div class="footer-meta"> 22 <% if (typeof langs !== 'undefined' && langs && langs.length > 1) { %> 23 <select class="footer-lang" aria-label="<%= t('nav.language') %>" 24 onchange="location.href='/lang/'+this.value+'?r='+encodeURIComponent(location.pathname+location.search)"> 25 <% langs.forEach(function(l){ %><option value="<%= l.code %>"<%= l.active ? ' selected' : '' %>><%= l.name %></option><% }); %> 26 </select> 27 <% } %> 22 28 <a class="footer-version" href="<%= (typeof siteUrlBase !== 'undefined' && siteUrlBase) ? siteUrlBase : '' %>/changelog" title="Bekijk wat er per release veranderd is">Klonkt Beta<%= (typeof appVersion !== 'undefined' && appVersion) ? ' v' + appVersion : '' %></a> 23 29 <%# Mobile-only theme toggle. On desktop the topnav has its own toggle … … 101 107 display: inline-flex; align-items: center; gap: 0.75rem; 102 108 } 109 .footer-lang { 110 background: transparent; color: var(--ink); opacity: 1; 111 border: 1px solid var(--rule); border-radius: 999px; 112 padding: 0.3rem 0.5rem; font-size: 0.78rem; cursor: pointer; 113 font-family: inherit; 114 } 115 .footer-lang:hover { border-color: var(--accent); } 103 116 .footer-version { color: inherit; text-decoration: none; } 104 117 .footer-version:hover { color: var(--accent); text-decoration: underline; } -
src/views/partials/post-nav.ejs
rd0f4c10 r03fa548 8 8 hx-get="/<%= newerPost.slug %>?partial=1" hx-target="#pcms-main" 9 9 hx-push-url="/<%= newerPost.slug %>" hx-indicator="#pcms-loading"<% } %>> 10 <span class="post-nav-label"><% if (newerPost.pinned) { %><span class="post-nav-pin" title="Vastgepind">📌</span> <% } %>← Newer</span>10 <span class="post-nav-label"><% if (newerPost.pinned) { %><span class="post-nav-pin" title="Vastgepind">📌</span> <% } %>← <%= t('postnav.newer') %></span> 11 11 <span class="post-nav-title"><%= newerPost.title %></span> 12 12 </a> … … 14 14 <div class="post-nav-prev is-empty" aria-hidden="true"> 15 15 <span class="post-nav-label">← Newer</span> 16 <span class="post-nav-title"> Nieuwste post</span>16 <span class="post-nav-title"><%= t('postnav.newest') %></span> 17 17 </div> 18 18 <% } %> … … 21 21 hx-get="/<%= olderPost.slug %>?partial=1" hx-target="#pcms-main" 22 22 hx-push-url="/<%= olderPost.slug %>" hx-indicator="#pcms-loading"<% } %>> 23 <span class="post-nav-label"> Older→<% if (olderPost.pinned) { %> <span class="post-nav-pin" title="Vastgepind">📌</span><% } %></span>23 <span class="post-nav-label"><%= t('postnav.older') %> →<% if (olderPost.pinned) { %> <span class="post-nav-pin" title="Vastgepind">📌</span><% } %></span> 24 24 <span class="post-nav-title"><%= olderPost.title %></span> 25 25 </a> … … 27 27 <div class="post-nav-next is-empty" aria-hidden="true"> 28 28 <span class="post-nav-label">Older →</span> 29 <span class="post-nav-title"> Oudste post</span>29 <span class="post-nav-title"><%= t('postnav.oldest') %></span> 30 30 </div> 31 31 <% } %> -
src/views/partials/topnav.ejs
rd0f4c10 r03fa548 26 26 <div class="masthead-brand"> 27 27 <% if (_isAdmin) { %> 28 <a href="<%= _siteUrlBase %>/" class="nav-link nav-link-admin"> ← Terug naar site</a>28 <a href="<%= _siteUrlBase %>/" class="nav-link nav-link-admin"><%= t('nav.back_to_site') %></a> 29 29 <% } else if (typeof tenancy !== 'undefined' && tenancy === 'hub') { %> 30 30 <%# Hub: de brand gaat naar de hub-home via HTMX. De chrome wordt in hub-modus … … 64 64 hx-indicator="#pcms-loading"> 65 65 <svg class="icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M21 8v13H3V8"/><rect x="1" y="3" width="22" height="5" rx="1"/><line x1="10" y1="12" x2="14" y2="12"/></svg> 66 <span class="nav-label"> Archief</span>66 <span class="nav-label"><%= t('nav.archive') %></span> 67 67 </a> 68 68 <% } %> … … 118 118 hx-push-url="/account" hx-indicator="#pcms-loading"> 119 119 <svg class="udi-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20 21v-2a4 4 0 0 0-4-4H8a4 4 0 0 0-4 4v2"/><circle cx="12" cy="7" r="4"/></svg> 120 <span> Account</span>120 <span><%= t('nav.account') %></span> 121 121 </a> 122 122 <a href="/favorieten" role="menuitem" class="udi" … … 124 124 hx-push-url="/favorieten" hx-indicator="#pcms-loading"> 125 125 <svg class="udi-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></svg> 126 <span> Favorieten</span>126 <span><%= t('nav.favorites') %></span> 127 127 </a> 128 128 <% if (typeof canSeeBeheer !== 'undefined' && canSeeBeheer) { %> … … 131 131 hx-push-url="/admin" hx-indicator="#pcms-loading"> 132 132 <svg class="udi-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M3 3h7v7H3z"/><path d="M14 3h7v7h-7z"/><path d="M14 14h7v7h-7z"/><path d="M3 14h7v7H3z"/></svg> 133 <span> Beheer</span>133 <span><%= t('nav.admin') %></span> 134 134 </a> 135 135 <% } %> … … 139 139 hx-push-url="<%= _siteUrlBase %>/posts/new" hx-indicator="#pcms-loading"> 140 140 <svg class="udi-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M12 20h9"/><path d="M16.5 3.5a2.121 2.121 0 0 1 3 3L7 19l-4 1 1-4 12.5-12.5z"/></svg> 141 <span> Nieuwe post</span>141 <span><%= t('nav.new_post') %></span> 142 142 </a> 143 143 <% } %> … … 147 147 <a href="/auth/logout" role="menuitem" class="udi udi-danger"> 148 148 <svg class="udi-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 21H5a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h4"/><polyline points="16 17 21 12 16 7"/><line x1="21" y1="12" x2="9" y2="12"/></svg> 149 <span> Uitloggen</span>149 <span><%= t('nav.logout') %></span> 150 150 </a> 151 151 </div> … … 156 156 hx-get="/auth/login?partial=1" hx-target="#pcms-main" hx-swap="innerHTML" 157 157 hx-push-url="/auth/login" hx-indicator="#pcms-loading"> 158 <span class="nav-label"> Inloggen</span>158 <span class="nav-label"><%= t('nav.login') %></span> 159 159 </a> 160 160 <% } %> -
src/views/partials/view-switcher.ejs
rd0f4c10 r03fa548 19 19 <a class="vs-agenda<%= _onShows ? ' is-active' : '' %>" href="<%= _sbA %>/shows" aria-label="Agenda — evenementen"> 20 20 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="4" width="18" height="18" rx="2"/><line x1="16" y1="2" x2="16" y2="6"/><line x1="8" y1="2" x2="8" y2="6"/><line x1="3" y1="10" x2="21" y2="10"/></svg> 21 <span> Agenda</span>21 <span><%= t('switch.agenda') %></span> 22 22 </a> 23 23 </div> … … 29 29 <div class="feed-scope" role="tablist" aria-label="Solo of cirkel"> 30 30 <a class="feed-scope-btn<%= (!_neutral && !_onCirkel) ? ' is-active' : '' %>" href="<%= _sb %>/" 31 role="tab" aria-selected="<%= (!_neutral && !_onCirkel) ? 'true' : 'false' %>"> Solo</a>31 role="tab" aria-selected="<%= (!_neutral && !_onCirkel) ? 'true' : 'false' %>"><%= t('switch.solo') %></a> 32 32 <a class="feed-scope-btn<%= (!_neutral && _onCirkel) ? ' is-active' : '' %>" href="<%= _sb %>/cirkel" 33 role="tab" aria-selected="<%= (!_neutral && _onCirkel) ? 'true' : 'false' %>"> Cirkel</a>33 role="tab" aria-selected="<%= (!_neutral && _onCirkel) ? 'true' : 'false' %>"><%= t('switch.circle') %></a> 34 34 </div> 35 35 <% } %> … … 38 38 aria-selected="<%= (!_neutral && !(typeof site !== 'undefined' && site && site.feed_view_default === 'grid')) ? 'true' : 'false' %>"> 39 39 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></svg> 40 <span> Tijdlijn</span>40 <span><%= t('switch.timeline') %></span> 41 41 </button> 42 42 <button type="button" class="view-switch-btn" data-view="grid" role="tab" 43 43 aria-selected="<%= (!_neutral && (typeof site !== 'undefined' && site && site.feed_view_default === 'grid')) ? 'true' : 'false' %>"> 44 44 <svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/></svg> 45 <span> Grid</span>45 <span><%= t('switch.grid') %></span> 46 46 </button> 47 47 </div>
Note:
See TracChangeset
for help on using the changeset viewer.
![(please configure the [header_logo] section in trac.ini)](/chrome/site/your_project_logo.png)