Changeset 9a00f28 in Klonkt for src/views/pages/admin-push.ejs


Ignore:
Timestamp:
07/22/2026 08:18:39 AM (7 weeks ago)
Author:
Robin <roboburr@…>
Branches:
main
Children:
6b5d7da
Parents:
96c714f
git-author:
Robin <roboburr@…> (07/22/2026 08:18:19 AM)
git-committer:
Robin <roboburr@…> (07/22/2026 08:18:39 AM)
Message:

Fix: test feedback round, cirkels tagline + report details + full i18n

Three findings from Bart's test pass, tied together by the new i18n keys:

  1. The admin tagline said "Solo mode" even with Cirkels (federation) on. Solo-tenancy now distinguishes: apEnabled -> "Cirkels-modus: jouw site, verbonden met de fediverse", else the solo line. New key in nl/en/de.
  1. Reports only showed who reported; now they show the reason and WHICH post. getNotifications resolves the stored objects URIs of a report: our own /ap/notes/<id> become "Over de post: <title>" links under the description; an empty reason renders "Geen reden opgegeven". Other URIs (the actor itself) are skipped, the row already names the account.
  1. Notificaties and Betaalde posts were hardcoded Dutch on an English-configured Klonkt. Everything now goes through t(): the two admin pages (including their client-side status strings, passed via the JSON data block), the admin menu buttons, and the visitor-facing paid pages (gate, passkey, result). Server-side push payloads translate too, using the SITE's content language (fallback KLONKT_DEFAULT_LANG), and the test ping uses the request language. Full nl/en/de dictionaries.

Changed files:
src/services/i18n.js

  • admin.tagline_cirkels, admin.b_paid/b_push/back, notif.report_about/ report_noreason, and the push.*, apaid.*, pgate.*, ppk.*, pres.* blocks in nl/en/de

src/routes/admin.js, src/views/pages/admin.ejs

  • circlesOn (apEnabled) -> cirkels tagline; menu buttons via t()

src/services/ActivityPubService.js

  • report objects resolved to post links; push payloads via i18nT with pushLang(slug) (site language)

src/views/pages/fedi-notifications.ejs

  • report reason fallback + "Over de post" links (+ styles)

src/routes/admin-push.js, src/views/pages/admin-push.ejs

  • pageTitleKey push.t; all copy + JS status strings via t()

src/routes/admin-paid.js, src/views/pages/admin-paid.ejs

  • pageTitleKey apaid.t; all copy via t(), copy-button label via data-attr

src/routes/paid.js

  • pageTitleKey pres.t / ppk.t

src/views/pages/paid-gate.ejs, paid-passkey.ejs, paid-result.ejs

  • visitor copy + JS strings via t()

src/routes/push.js

  • test notification via resolveLang(req)

-robo
Co-Authored-By: Claude Opus 4.8 <noreply@…>

File:
1 edited

Legend:

Unmodified
Added
Removed
  • src/views/pages/admin-push.ejs

    r96c714f r9a00f28  
    11<div class="container" style="max-width:640px;margin:1.5rem auto 3rem;padding:0 1rem">
    2   <h1 style="margin:0 0 .3rem">Notificaties</h1>
     2  <h1 style="margin:0 0 .3rem"><%= t('push.t') %></h1>
    33  <p style="color:var(--ink-soft,#888);margin:0 0 1.2rem">
    4     Krijg een melding op dit apparaat bij nieuwe volgers, reacties en berichten,
    5     ook als de site niet open staat. Versleuteld tot in je browser; wij sturen zo
    6     min mogelijk inhoud mee.
     4    <%= t('push.intro') %>
    75  </p>
    86
    97  <% if (!vapidKey) { %>
    10     <p style="color:#c0392b">Push is op deze server niet beschikbaar (sleutel kon niet worden aangemaakt of de dependency ontbreekt).</p>
     8    <p style="color:#c0392b"><%= t('push.unavailable') %></p>
    119  <% } else { %>
    1210
    1311  <div id="np-unsupported" hidden style="color:#c0392b;margin:0 0 1rem">
    14     Deze browser ondersteunt geen push-notificaties.
     12    <%= t('push.unsupported') %>
    1513  </div>
    1614  <div id="np-ios-hint" hidden style="border:1px solid var(--border,#333);border-radius:10px;padding:.8rem 1rem;margin:0 0 1rem;font-size:.92rem;color:var(--ink-soft,#888)">
    17     Op iPhone/iPad werkt dit alleen als de site op je beginscherm staat:
    18     deel-knop → <em>Zet op beginscherm</em>, en open 'm daarna vanaf daar.
     15    <%= t('push.ios_hint') %>
    1916  </div>
    2017
    2118  <section style="border:1px solid var(--border,#333);border-radius:12px;padding:1rem 1.1rem;margin:0 0 1.2rem">
    22     <p style="margin:0 0 .6rem"><strong>Dit apparaat:</strong> <span id="np-state">controleren…</span></p>
     19    <p style="margin:0 0 .6rem"><strong><%= t('push.this_device') %></strong> <span id="np-state"><%= t('push.checking') %></span></p>
    2320    <div style="display:flex;gap:.6rem;flex-wrap:wrap">
    24       <button type="button" id="np-on" class="btn btn-primary" hidden>Zet aan op dit apparaat</button>
    25       <button type="button" id="np-off" class="btn" hidden>Zet uit</button>
    26       <button type="button" id="np-test" class="btn" hidden>Stuur testmelding</button>
     21      <button type="button" id="np-on" class="btn btn-primary" hidden><%= t('push.enable') %></button>
     22      <button type="button" id="np-off" class="btn" hidden><%= t('push.disable') %></button>
     23      <button type="button" id="np-test" class="btn" hidden><%= t('push.test') %></button>
    2724    </div>
    2825    <fieldset id="np-alerts" hidden style="border:none;padding:0;margin:1rem 0 0">
    29       <legend style="font-weight:600;margin-bottom:.4rem">Waarvoor wil je een melding?</legend>
    30       <label style="display:block"><input type="checkbox" data-alert="follow"> Nieuwe volger</label>
    31       <label style="display:block"><input type="checkbox" data-alert="reply"> Reactie of vermelding</label>
    32       <label style="display:block"><input type="checkbox" data-alert="like"> Waardering (ster)</label>
    33       <label style="display:block"><input type="checkbox" data-alert="boost"> Boost</label>
    34       <label style="display:block"><input type="checkbox" data-alert="dm"> Priv&eacute;bericht</label>
    35       <p id="np-saved" hidden style="color:var(--accent);margin:.4rem 0 0">Opgeslagen.</p>
     26      <legend style="font-weight:600;margin-bottom:.4rem"><%= t('push.what') %></legend>
     27      <label style="display:block"><input type="checkbox" data-alert="follow"> <%= t('push.a_follow') %></label>
     28      <label style="display:block"><input type="checkbox" data-alert="reply"> <%= t('push.a_reply') %></label>
     29      <label style="display:block"><input type="checkbox" data-alert="like"> <%= t('push.a_like') %></label>
     30      <label style="display:block"><input type="checkbox" data-alert="boost"> <%= t('push.a_boost') %></label>
     31      <label style="display:block"><input type="checkbox" data-alert="dm"> <%= t('push.a_dm') %></label>
     32      <p id="np-saved" hidden style="color:var(--accent);margin:.4rem 0 0"><%= t('push.saved') %></p>
    3633    </fieldset>
    3734  </section>
    3835
    3936  <% if (subscriptions.length) { %>
    40     <h2 style="font-size:1.05rem;margin:0 0 .5rem">Gekoppelde apparaten</h2>
     37    <h2 style="font-size:1.05rem;margin:0 0 .5rem"><%= t('push.devices') %></h2>
    4138    <ul style="list-style:none;padding:0;margin:0 0 1.2rem">
    4239      <% subscriptions.forEach(function (s) { %>
    4340        <li data-endpoint="<%= s.endpoint %>" style="display:flex;justify-content:space-between;gap:.8rem;align-items:center;padding:.45rem 0;border-bottom:1px solid var(--border,#2a2a2a)">
    44           <span style="min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"><%= s.ua_label || 'Apparaat' %> <small style="color:var(--ink-soft,#888)">sinds <%= String(s.created_at || '').slice(0, 10) %></small></span>
    45           <button type="button" class="btn np-remove" data-endpoint="<%= s.endpoint %>">Verwijder</button>
     41          <span style="min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap"><%= s.ua_label || t('push.device') %> <small style="color:var(--ink-soft,#888)"><%= t('push.since') %> <%= String(s.created_at || '').slice(0, 10) %></small></span>
     42          <button type="button" class="btn np-remove" data-endpoint="<%= s.endpoint %>"><%= t('push.remove') %></button>
    4643        </li>
    4744      <% }); %>
     
    5148  <% } %>
    5249
    53   <p style="margin-top:1.5rem"><a href="/admin">&larr; Terug naar Beheer</a></p>
     50  <p style="margin-top:1.5rem"><a href="/admin">&larr; <%= t('admin.back') %></a></p>
    5451</div>
    5552
     
    5956  alerts: defaultAlerts,
    6057  saved: subscriptions.reduce(function (m, s) { try { m[s.endpoint] = JSON.parse(s.alert_types || '{}'); } catch (e) { m[s.endpoint] = {}; } return m; }, {}),
     58  i18n: { on: t('push.state_on'), off: t('push.state_off'), denied: t('push.state_denied'), unknown: t('push.state_unknown'), unsupported: t('push.state_unsupported'), failed: t('push.enable_failed') },
    6159}).replace(/</g, '\\u003c') %></script>
    6260<script>
     
    7472  if (!('serviceWorker' in navigator) || !('PushManager' in window) || !('Notification' in window)) {
    7573    document.getElementById('np-unsupported').hidden = false;
    76     elState.textContent = 'niet ondersteund';
     74    elState.textContent = cfg.i18n.unsupported;
    7775    return;
    7876  }
     
    107105  function render(sub) {
    108106    currentEndpoint = sub ? sub.endpoint : null;
    109     elState.textContent = sub ? 'meldingen staan aan' : (Notification.permission === 'denied' ? 'geblokkeerd in de browserinstellingen' : 'meldingen staan uit');
     107    elState.textContent = sub ? cfg.i18n.on : (Notification.permission === 'denied' ? cfg.i18n.denied : cfg.i18n.off);
    110108    btnOn.hidden = !!sub || Notification.permission === 'denied';
    111109    btnOff.hidden = !sub;
     
    120118    setAlertBoxes((sub && cfg.saved[sub.endpoint]) ? Object.assign({}, cfg.alerts, cfg.saved[sub.endpoint]) : cfg.alerts);
    121119    render(sub);
    122   }).catch(function () { elState.textContent = 'status onbekend'; });
     120  }).catch(function () { elState.textContent = cfg.i18n.unknown; });
    123121
    124122  btnOn.addEventListener('click', function () {
     
    131129        return post('/push/subscribe', { subscription: sub.toJSON(), alerts: readAlertBoxes(), uaLabel: deviceLabel() })
    132130          .then(function (r) { if (!r.ok) throw new Error('subscribe failed'); render(sub); location.reload(); });
    133       }).catch(function () { btnOn.disabled = false; elState.textContent = 'aanzetten mislukt'; });
     131      }).catch(function () { btnOn.disabled = false; elState.textContent = cfg.i18n.failed; });
    134132    });
    135133  });
Note: See TracChangeset for help on using the changeset viewer.