source: Klonkt/src/views/pages/paid-passkey.ejs@ 9a00f28

main
Last change on this file since 9a00f28 was 9a00f28, checked in by Robin <roboburr@…>, 7 weeks ago

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@…>

  • Property mode set to 100644
File size: 2.7 KB
Line 
1<section class="pk">
2 <div class="pk-card">
3 <div class="pk-ic">🔑</div>
4 <h1 class="pk-h1"><%= t('ppk.h') %></h1>
5 <p class="pk-sub">
6 <%= t('ppk.sub') %>
7 </p>
8 <button type="button" id="pk-go" class="pk-btn"><%= t('ppk.make') %></button>
9 <p id="pk-status" class="pk-status" hidden></p>
10 </div>
11</section>
12
13<script src="/assets/vendor/simplewebauthn-browser.umd.min.js"></script>
14<script>
15(function () {
16 var options = <%- optionsJson %>;
17 var blob = "<%= regBlob %>";
18 var I = { unsupported: "<%= t('ppk.unsupported') %>", follow: "<%= t('ppk.follow') %>", done: "<%= t('ppk.done') %>", failed: "<%= t('ppk.failed') %>", cancelled: "<%= t('ppk.cancelled') %>", error: "<%= t('pgate.error') %>" };
19 var postUrl = "<%= (typeof siteUrlBase !== 'undefined' && siteUrlBase ? siteUrlBase : '') %>/<%= postSlug %>";
20 var btn = document.getElementById('pk-go');
21 var status = document.getElementById('pk-status');
22 function say(msg, err) { status.hidden = false; status.textContent = msg; status.classList.toggle('is-err', !!err); }
23
24 if (!window.SimpleWebAuthnBrowser || !window.PublicKeyCredential) {
25 btn.disabled = true;
26 say(I.unsupported, true);
27 return;
28 }
29 btn.addEventListener('click', function () {
30 btn.disabled = true;
31 say(I.follow);
32 window.SimpleWebAuthnBrowser.startRegistration({ optionsJSON: options })
33 .then(function (response) {
34 return fetch('/paid/register', {
35 method: 'POST', headers: { 'Content-Type': 'application/json' },
36 body: JSON.stringify({ response: response, blob: blob }),
37 });
38 })
39 .then(function (r) { return r.json(); })
40 .then(function (j) {
41 if (j && j.ok) { say(I.done); setTimeout(function () { location.href = postUrl; }, 900); }
42 else { btn.disabled = false; say(I.failed.replace('{err}', (j && j.error) || '?'), true); }
43 })
44 .catch(function (e) { btn.disabled = false; say(e && e.name === 'NotAllowedError' ? I.cancelled : I.error, true); });
45 });
46})();
47</script>
48
49<style>
50 .pk { max-width: 480px; margin: 0 auto; padding: 56px 18px; text-align: center; }
51 .pk-card { border: 1px solid color-mix(in srgb, var(--ink,#000) 16%, transparent); border-radius: 18px; padding: 34px 26px; }
52 .pk-ic { font-size: 40px; margin-bottom: 8px; }
53 .pk-h1 { font-size: 24px; margin: 0 0 6px; }
54 .pk-sub { opacity: .85; line-height: 1.6; margin: 0 0 20px; }
55 .pk-btn { padding: 12px 24px; border: none; border-radius: 10px; background: var(--accent,#6b8f71); color: #fff; font-weight: 600; font: inherit; font-weight: 600; cursor: pointer; }
56 .pk-btn:disabled { opacity: .6; cursor: default; }
57 .pk-status { margin: 14px 0 0; opacity: .9; }
58 .pk-status.is-err { color: #c0392b; }
59</style>
Note: See TracBrowser for help on using the repository browser.