Changeset 834bcc3 in Klonkt for src/routes/posts.js


Ignore:
Timestamp:
06/23/2026 06:14:27 PM (3 months ago)
Author:
Robin Genis <roboburr@…>
Branches:
main
Children:
d774679
Parents:
bb42dfb
Message:

i18n: translate Dutch code comments to English across src/

Comments in routes/services/views/config/middleware/assets translated to
English for the public repo. A few dev-facing throw/console message strings
were Englished too. No user-facing UI strings or i18n dictionary values changed
(src/services/i18n.js untouched). Logic unchanged.

Co-Authored-By: Claude <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/routes/posts.js

    rbb42dfb r834bcc3  
    4949});
    5050
    51 // Maakt een unieke slug binnen de site: 'titel', 'titel-2', 'titel-3', …
    52 // Zo wordt een tweede post met dezelfde titel NIET geweigerd ("bestaat al"),
    53 // maar krijgt 'ie automatisch een vrij achtervoegsel. exceptId = de post die
    54 // we bijwerken (mag z'n eigen slug houden).
     51// Generates a unique slug within the site: 'title', 'title-2', 'title-3', …
     52// A second post with the same title is NOT rejected ("already exists"),
     53// but automatically gets a free suffix. exceptId = the post being updated
     54// (allowed to keep its own slug).
    5555function uniqueSlug(siteId, base, exceptId = null) {
    5656  let candidate = base;
     
    190190  if (RESERVED_SLUGS.has(finalSlug)) finalSlug = `${finalSlug}-post`;
    191191
    192   // Dubbele titel/slug? Automatisch uniek maken (titel-2, titel-3, …) i.p.v. weigeren.
     192  // Duplicate title/slug? Make it unique automatically (title-2, title-3, …) instead of rejecting.
    193193  finalSlug = uniqueSlug(site.id, finalSlug);
    194194
     
    199199  let finalStatus = status || 'draft';
    200200  let publishedAt = finalStatus === 'published' ? now : null;
    201   // Release-planning: gepubliceerd + een toekomstige publish_at -> 'scheduled'
    202   // (de Scheduler zet 'm live op het moment zelf). Verleden/leeg -> meteen live.
     201  // Release planning: published + a future publish_at -> 'scheduled'
     202  // (the Scheduler makes it live at that moment). Past/empty -> live immediately.
    203203  let publishAt = null;
    204204  const pa = Date.parse(req.body.publish_at || '');
     
    297297    const cleaned = newSlug.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
    298298    const safe = RESERVED_SLUGS.has(cleaned) ? `${cleaned}-post` : cleaned;
    299     // Dubbele slug? Automatisch uniek maken i.p.v. weigeren (eigen post mag z'n slug houden).
     299    // Duplicate slug? Make it unique automatically instead of rejecting (own post may keep its slug).
    300300    finalSlug = uniqueSlug(site.id, safe, post.id);
    301301  }
     
    310310  }
    311311
    312   // Release-planning: gepubliceerd + toekomstige publish_at -> 'scheduled'.
     312  // Release planning: published + future publish_at -> 'scheduled'.
    313313  let publishAt = null;
    314314  const pa = Date.parse(req.body.publish_at || '');
     
    412412});
    413413
    414 // Pad naar de like-knop-partial (voor de htmx-toggle re-render).
     414// Path to the like button partial (for the htmx toggle re-render).
    415415const LIKE_PARTIAL = path.join(__dirname, '..', 'views', 'partials', 'like-button.ejs');
    416416
    417 // ==================== LIKE / FAVORIET ====================
    418 // Een ingelogde gebruiker (geen kijker — de globale guard blokkeert non-GET voor
    419 // kijkers) togglet een like op een gepubliceerde post. Geeft de her-gerenderde
    420 // knop terug (htmx outerHTML-swap).
     417// ==================== LIKE / FAVOURITE ====================
     418// A logged-in user (not a viewer — the global guard blocks non-GET for viewers)
     419// toggles a like on a published post. Returns the re-rendered button (htmx outerHTML swap).
    421420router.post('/posts/:id/like', requireAuth, (req, res) => {
    422421  const userId = req.session.user.id;
     
    430429  } else {
    431430    db.prepare('INSERT OR IGNORE INTO post_likes (post_id, user_id) VALUES (?, ?)').run(post.id, userId);
    432     // Melding voor de post-auteur (notify slaat jezelf-liken over).
     431    // Notification for the post author (notify skips self-likes).
    433432    notify({
    434433      userId: post.author_id, actorId: userId, actorName: req.session.user.username, type: 'like',
     
    444443});
    445444
    446 // Favorieten = de posts die de ingelogde gebruiker likete. Solo: binnen de
    447 // huidige site. Hub: over alle sites (met juiste /user/<slug>-links).
     445// Favourites = posts the logged-in user has liked. Solo: within the current
     446// site. Hub: across all sites (with correct /user/<slug> links).
    448447router.get('/favorieten', requireAuth, (req, res) => {
    449448  const userId = req.session.user.id;
     
    469468});
    470469
    471 // Newer/Older-buren over ALLE posts in feed-volgorde. Gedeeld door de volledige
    472 // post-render én de fan-gate (premium fan_only), zodat de navigatie overal gelijk
    473 // is. Solo: binnen de site (pinned eerst, dan datum). Hub: globaal op datum.
     470// Newer/Older neighbours across ALL posts in feed order. Shared by the full
     471// post render and the fan gate (premium fan_only) so navigation is consistent
     472// everywhere. Solo: within the site (pinned first, then date). Hub: globally by date.
    474473function postNeighbors(site, post, isHub) {
    475474  const urlBaseFor = (p) => (isHub && p && p.site_slug) ? `/user/${p.site_slug}` : '';
     
    507506  `).get(site.id, req.params.slug);
    508507
    509   if (!post) return next(); // onbekende slug -> nette 404 catch-all
     508  if (!post) return next(); // unknown slug -> clean 404 catch-all
    510509
    511510  // Permission to view: published OR (logged in + can edit)
     
    515514  }
    516515
    517   // Fan-only preview (premium #3): volledige inhoud alleen voor ingelogde fans.
    518   // Anonieme bezoekers krijgen een nette login-gate i.p.v. de inhoud (de titel/
    519   // teaser mag elders wel als lokkertje verschijnen).
     516  // Fan-only preview (premium #3): full content only for logged-in fans.
     517  // Anonymous visitors get a clean login gate instead of the content (the title/
     518  // teaser may still appear elsewhere as a teaser).
    520519  if (post.fan_only && !(req.session && req.session.user)) {
    521     // Zelfde Newer/Older-navigatie als op een gewone post, zodat de bezoeker op
    522     // de fan-gate niet vastloopt maar verder kan bladeren.
     520    // Same Newer/Older navigation as on a normal post, so the visitor doesn't get
     521    // stuck on the fan gate but can keep browsing.
    523522    const { newerPost, olderPost } = postNeighbors(site, post, res.locals.tenancy === 'hub');
    524523    return renderPage(req, res, 'pages/fan-gate', {
     
    532531  }
    533532
    534   // Statistieken: tel de weergave (skipt beheerders + niet-gepubliceerd-eigen-preview).
     533  // Statistics: count the view (skips admins + unpublished own-preview).
    535534  if (post.status === 'published') recordPostView(post, req);
    536535
     
    588587      const byAlbum = new Map();
    589588      for (const r of albumRows) {
    590         // Link-only tracks (geen bestand) blijven in het album-overzicht (url '').
     589        // Link-only tracks (no file) remain in the album overview (url '').
    591590        if (!byAlbum.has(r.album)) byAlbum.set(r.album, []);
    592591        byAlbum.get(r.album).push({
     
    625624  }
    626625  } else {
    627     // LITE-modus (KLONKT_AUDIO=off): geen eigen audio (geen ffmpeg/stream-route).
    628     // Externe embeds (YouTube/SoundCloud/Spotify) blijven wel; de eigen-audio-
    629     // shortcodes ([[track]]/[[album]]/[[playlist]]) verwijderen we netjes.
     626    // LITE mode (KLONKT_AUDIO=off): no own audio (no ffmpeg/stream route).
     627    // External embeds (YouTube/SoundCloud/Spotify) remain; the own-audio
     628    // shortcodes ([[track]]/[[album]]/[[playlist]]) are cleanly stripped.
    630629    html = AudioEmbedService.autoembed(html);
    631630    html = AudioEmbedService.embedMediaShortcodes(html);
     
    665664  // Prev / next chronological (kept for back-compat — "post-nav" feature
    666665  // below the article still uses these as a simple linear navigation).
    667   // Hub-modus: Gerelateerde posts + Newer/Older trekken uit ALLE users (alle
    668   // sites), nieuwste->oudste. Solo-modus: binnen de huidige site (oud gedrag).
     666  // Hub mode: Related posts + Newer/Older pull from ALL users (all sites),
     667  // newest first. Solo mode: within the current site (old behaviour).
    669668  const isHub = res.locals.tenancy === 'hub';
    670   // Per-post URL-basis: in hub wijst een link naar /user/<site-slug>/<post-slug>.
     669  // Per-post URL base: in hub a link points to /user/<site-slug>/<post-slug>.
    671670  const urlBaseFor = (p) => (isHub && p && p.site_slug) ? `/user/${p.site_slug}` : '';
    672671
    673   // Newer/Older over ALLE posts (gedeelde helper — ook door de fan-gate gebruikt).
     672  // Newer/Older across ALL posts (shared helper — also used by the fan gate).
    674673  const { newerPost, olderPost } = postNeighbors(site, post, isHub);
    675674
     
    727726  relatedPosts = relatedPosts.map(({ _overlap, tags, ...rest }) => ({ ...rest, _urlBase: urlBaseFor(rest) }));
    728727
    729   // Likes / favorieten: aantal + of de ingelogde gebruiker deze post likete.
     728  // Likes / favourites: count + whether the logged-in user liked this post.
    730729  const likeCount = db.prepare('SELECT COUNT(*) AS c FROM post_likes WHERE post_id = ?').get(post.id).c;
    731730  const likedByMe = !!(req.session?.user &&
Note: See TracChangeset for help on using the changeset viewer.