Changeset 421c2d4 in Klonkt
- Timestamp:
- 06/21/2026 04:48:27 PM (3 months ago)
- Branches:
- main
- Children:
- d6bdbae
- Parents:
- 9effb80
- Location:
- src
- Files:
-
- 5 edited
-
middleware/render.js (modified) (2 diffs)
-
routes/admin-settings.js (modified) (1 diff)
-
services/i18n.js (modified) (3 diffs)
-
views/pages/admin-settings.ejs (modified) (1 diff)
-
views/pages/post-edit.ejs (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/middleware/render.js
r9effb80 r421c2d4 31 31 } catch { /* geen versie beschikbaar */ } 32 32 33 // Site-tijdzone (Beheer → Instellingen). Leeg = server-default (UTC). Wordt 34 // toegepast op álle server-side geformatteerde datums zodat ze in de zone van 35 // de site staan i.p.v. UTC. 36 const siteTimezone = () => getSetting('timezone') || undefined; 37 33 38 const formatDate = (iso) => { 34 39 if (!iso) return ''; 35 const d = new Date(iso); 36 const months = ['januari','februari','maart','april','mei','juni','juli','augustus','september','oktober','november','december']; 37 return `${d.getDate()} ${months[d.getMonth()]} ${d.getFullYear()}`; 40 return new Date(iso).toLocaleDateString('nl-NL', { timeZone: siteTimezone(), day: 'numeric', month: 'long', year: 'numeric' }); 38 41 }; 39 42 40 43 const formatDateTime = (iso) => { 41 44 if (!iso) return ''; 42 const d = new Date(iso); 43 return d.toLocaleString('nl-NL', { dateStyle: 'medium', timeStyle: 'short' }); 45 return new Date(iso).toLocaleString('nl-NL', { timeZone: siteTimezone(), dateStyle: 'medium', timeStyle: 'short' }); 44 46 }; 45 47 … … 91 93 t: (key, vars) => i18nT(_lang, key, vars), 92 94 langs: LANGS.map((c) => ({ code: c, name: LANG_NAMES[c], active: c === _lang })), 95 timezone: getSetting('timezone') || '', 93 96 userOwnsSite, 94 97 canSeeBeheer, -
src/routes/admin-settings.js
r9effb80 r421c2d4 116 116 setSetting('default_lang', SUPPORTED.includes(dl) ? dl : ''); 117 117 } 118 if (typeof req.body.timezone !== 'undefined') { 119 // Site-tijdzone (IANA, bv. Europe/Amsterdam). Leeg = server-default (UTC). 120 // Valideer met Intl zodat een onzin-waarde nooit de datum-rendering breekt. 121 const tz = (req.body.timezone || '').toString().trim(); 122 let valid = ''; 123 if (tz) { try { Intl.DateTimeFormat('en-US', { timeZone: tz }); valid = tz; } catch { valid = ''; } } 124 setSetting('timezone', valid); 125 } 118 126 if (typeof req.body.hub_title !== 'undefined') { 119 127 setSetting('hub_title', (req.body.hub_title || '').toString().slice(0, 80).trim()); -
src/services/i18n.js
r9effb80 r421c2d4 977 977 'aset.default_lang_hint': 'Wat nieuwe bezoekers zien voordat ze zelf een taal kiezen. Een ingelogde gebruiker met een eigen voorkeur ziet díe.', 978 978 'aset.default_lang_auto': 'Automatisch (browser-taal)', 979 'aset.timezone': 'Tijdzone', 980 'aset.timezone_hint': 'In welke tijdzone datums en geplande publicaties worden getoond en opgeslagen. Automatisch = serverstandaard (UTC).', 981 'aset.timezone_auto': 'Automatisch (UTC)', 979 982 }, 980 983 en: { … … 1936 1939 'aset.default_lang_hint': 'What new visitors see before they pick a language themselves. A logged-in user with their own preference sees that instead.', 1937 1940 'aset.default_lang_auto': 'Automatic (browser language)', 1941 'aset.timezone': 'Timezone', 1942 'aset.timezone_hint': 'The timezone used to show and schedule dates and planned posts. Automatic = server default (UTC).', 1943 'aset.timezone_auto': 'Automatic (UTC)', 1938 1944 }, 1939 1945 de: { … … 2895 2901 'aset.default_lang_hint': 'Was neue Besucher sehen, bevor sie selbst eine Sprache wählen. Ein angemeldeter Benutzer mit eigener Voreinstellung sieht diese.', 2896 2902 'aset.default_lang_auto': 'Automatisch (Browsersprache)', 2903 'aset.timezone': 'Zeitzone', 2904 'aset.timezone_hint': 'Die Zeitzone, in der Datumsangaben und geplante Veröffentlichungen angezeigt und gespeichert werden. Automatisch = Server-Standard (UTC).', 2905 'aset.timezone_auto': 'Automatisch (UTC)', 2897 2906 }, 2898 2907 }; -
src/views/pages/admin-settings.ejs
r9effb80 r421c2d4 52 52 <option value="<%= l.code %>"<%= defaultLang === l.code ? ' selected' : '' %>><%= l.name %></option> 53 53 <% }); %> 54 </select> 55 </label> 56 <button type="submit" class="btn btn-primary"><%= t('aset.save') %></button> 57 </form> 58 </section> 59 60 <%# ── Tijdzone ── %> 61 <section class="set-card" style="margin-top:1rem"> 62 <h2><%= t('aset.timezone') %></h2> 63 <p class="set-help"><%= t('aset.timezone_hint') %></p> 64 <form method="post" action="/admin/settings" class="set-form"> 65 <label class="set-field"> 66 <span><%= t('aset.timezone') %></span> 67 <select name="timezone"> 68 <option value=""<%= !timezone ? ' selected' : '' %>><%= t('aset.timezone_auto') %></option> 69 <% 70 var _tz = ['Europe/Amsterdam','Europe/Brussels','Europe/Berlin','Europe/Paris','Europe/London','Europe/Madrid','Europe/Rome','Europe/Lisbon','Europe/Warsaw','Europe/Athens','UTC','America/New_York','America/Chicago','America/Los_Angeles','America/Sao_Paulo','Asia/Tokyo','Asia/Dubai','Australia/Sydney']; 71 if (timezone && _tz.indexOf(timezone) < 0) _tz.unshift(timezone); 72 %> 73 <% _tz.forEach(function(z){ %><option value="<%= z %>"<%= timezone === z ? ' selected' : '' %>><%= z %></option><% }); %> 54 74 </select> 55 75 </label> -
src/views/pages/post-edit.ejs
r9effb80 r421c2d4 225 225 if (!cb || !box) return; 226 226 var inp = document.getElementById('pe-publish-at'); 227 var SITE_TZ = '<%= timezone || '' %>'; // ingestelde site-tijdzone; leeg = browser-lokaal 227 228 var pad = function (n) { return String(n).padStart(2, '0'); }; 228 // Prefill: opgeslagen UTC → lokale datetime-local-waarde (zodat je je229 // eigen tijdzone ziet, niet UTC).230 if (inp && inp.dataset.iso) {231 var d0 = new Date(inp.dataset.iso);232 if (!isNaN(d0)) inp.value = d0.getFullYear() + '-' + pad(d0.getMonth() + 1) + '-' + pad(d0.getDate()) + 'T' + pad(d0.getHours()) + ':' + pad(d0.getMinutes());229 // Offset (ms) tussen een tijdzone en UTC op een bepaald moment. 230 function tzOffset(date, tz) { 231 var f = new Intl.DateTimeFormat('en-US', { timeZone: tz, hour12: false, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit' }); 232 var p = {}; f.formatToParts(date).forEach(function (x) { p[x.type] = x.value; }); 233 return Date.UTC(+p.year, +p.month - 1, +p.day, +p.hour, +p.minute, +p.second) - date.getTime(); 233 234 } 234 // "Ingepland voor" in leesbare lokale tijd i.p.v. ruwe UTC-ISO. 235 // datetime-local "wandtijd" (in de site-zone) → UTC Date. 236 function wallToUtc(wall) { 237 if (!SITE_TZ) return new Date(wall); 238 var guess = new Date(wall + ':00Z').getTime(); 239 return new Date(guess - tzOffset(new Date(guess), SITE_TZ)); 240 } 241 // UTC-ISO → "YYYY-MM-DDTHH:MM" wandtijd in de site-zone. 242 function utcToWall(iso) { 243 var d = new Date(iso); if (isNaN(d)) return ''; 244 if (!SITE_TZ) return d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + 'T' + pad(d.getHours()) + ':' + pad(d.getMinutes()); 245 var f = new Intl.DateTimeFormat('en-CA', { timeZone: SITE_TZ, hour12: false, year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' }); 246 var p = {}; f.formatToParts(d).forEach(function (x) { p[x.type] = x.value; }); 247 return p.year + '-' + p.month + '-' + p.day + 'T' + p.hour + ':' + p.minute; 248 } 249 // Prefill: opgeslagen UTC → wandtijd in de site-zone. 250 if (inp && inp.dataset.iso) inp.value = utcToWall(inp.dataset.iso); 251 // "Ingepland voor" in leesbare tijd van de site-zone. 235 252 var when = document.getElementById('pe-sched-when'); 236 253 if (when && when.dataset.iso) { 237 254 var dw = new Date(when.dataset.iso); 238 if (!isNaN(dw)) when.textContent = '⏳ ' + when.dataset.label + ' ' + dw.toLocaleString( );255 if (!isNaN(dw)) when.textContent = '⏳ ' + when.dataset.label + ' ' + dw.toLocaleString(undefined, SITE_TZ ? { timeZone: SITE_TZ } : undefined); 239 256 } 240 257 function sync() { box.style.display = cb.checked ? '' : 'none'; if (inp) inp.disabled = !cb.checked; } 241 258 cb.addEventListener('change', sync); sync(); 242 // Bij opslaan: lokale invoer → UTC-ISO via een hidden veld, zodat de 243 // server de juiste tijd opslaat (datetime-local heeft geen tijdzone). 259 // Bij opslaan: wandtijd in de site-zone → UTC-ISO via een hidden veld. 244 260 var form = cb.closest('form'); 245 261 if (form) { … … 249 265 if (old) old.remove(); 250 266 if (cb.checked && inp && inp.value) { 251 var d2 = new Date(inp.value); // geïnterpreteerd in browser-tijdzone267 var d2 = wallToUtc(inp.value); 252 268 if (!isNaN(d2)) { 253 269 var h = document.createElement('input');
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)