Changeset 0202104 in Klonkt
- Timestamp:
- 07/28/2026 11:40:37 PM (6 weeks ago)
- Branches:
- main
- Children:
- 439f095
- Parents:
- 6eab7e9
- Location:
- src
- Files:
-
- 8 edited
-
assets/css/guardian.css (modified) (1 diff)
-
assets/js/guardian.js (modified) (4 diffs)
-
middleware/render.js (modified) (1 diff)
-
routes/guardian.js (modified) (3 diffs)
-
routes/posts.js (modified) (1 diff)
-
services/i18n.js (modified) (3 diffs)
-
views/pages/guardian.ejs (modified) (1 diff)
-
views/pages/messages.ejs (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
src/assets/css/guardian.css
r6eab7e9 r0202104 145 145 .g-warn .row { margin-top: 10px; gap: 8px; } 146 146 button.danger { background: var(--danger); color: #fff; border-color: var(--danger); } 147 148 /* ── Beschikbaarheid (FEP-633c 3.6) ──────────────────────────────────────── 149 De buddy-list-stip op de verantwoordelijkheids-as: groen beschikbaar, geel 150 afwezig-verklaard met een einde, grijs slapend-geconstateerd (een antwoord 151 herstelt alles). Labels zijn UI; de draad houdt de spec-termen. */ 152 .g-avdot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; flex: 0 0 auto; } 153 .g-avdot.is-active { background: var(--ok); } 154 .g-avdot.is-away { background: #e0a83a; } 155 .g-avdot.is-dormant { background: #8a93a3; } 156 .g-avlabel { color: var(--sub); font-size: .8rem; white-space: nowrap; } 157 .row.g-guard { gap: 8px; margin-top: 6px; } 158 .g-away-row { display: flex; gap: 8px; } 159 .g-card.lapse { border-left: 3px solid #8a93a3; } 160 .g-card.lapse .row { margin-top: 8px; gap: 8px; } -
src/assets/js/guardian.js
r6eab7e9 r0202104 123 123 return card; 124 124 } 125 /** A running lapse (FEP-633c 3.6.3): the available co-guardians deciding 126 * to release a dormant one. Votes ride the same Accept/Reject wire as the 127 * offers; buttons appear only for set members (the ward watches, it does 128 * not vote). */ 129 function lapseCard(l) { 130 var card = el('div', 'g-card lapse'); 131 card.appendChild(el('div', 'who', (T.lapse_line || '{who} has stopped answering as a guardian of {ward}.') 132 .replace('{who}', handleOf(l.object.object)).replace('{ward}', handleOf(l.object['shaer:ward'])))); 133 card.appendChild(el('div', 'g-avlabel', (T.lapse_tally || '{n} of {need} agreed; closes {date}.') 134 .replace('{n}', l['shaer:accepts']).replace('{need}', l['shaer:threshold']) 135 .replace('{date}', new Date(l['shaer:closesAt']).toLocaleDateString()))); 136 var row = el('div', 'row'); 137 var inSet = (l['shaer:set'] || []).indexOf(S.me) >= 0; 138 if (inSet && !l['shaer:myVote']) { 139 var yes = el('button', 'small', T.lapse_agree || 'Agree'); 140 yes.addEventListener('click', function () { answer(l.id, 'accept', yes); }); 141 var no = el('button', 'quiet small', T.lapse_disagree || 'Disagree'); 142 no.addEventListener('click', function () { answer(l.id, 'reject', no); }); 143 row.appendChild(yes); row.appendChild(no); 144 } else if (inSet) { 145 row.appendChild(el('span', 'g-avlabel', T.voted || 'You voted')); 146 } 147 card.appendChild(row); 148 card.appendChild(el('p', 'g-empty small', T.lapse_note || '')); 149 return card; 150 } 151 125 152 function renderPending() { 126 153 var list = document.getElementById('pending-list'); 127 154 list.textContent = ''; 128 155 var offers = S.offers || []; 129 offers.forEach(function (o) { list.appendChild(offerCard(o)); }); 130 show('pending-section', offers.length > 0); 156 // The offers state carries the adoption offers; the lapse proposals ride 157 // separately so a lapse never renders as an adoption. 158 var lapses = (S.lapses || []).filter(function (l) { return l['shaer:outcome'] === 'open'; }); 159 offers.forEach(function (o) { 160 if (o.object && o.object.type === 'shaer:Lapse') return; // rendered below 161 list.appendChild(offerCard(o)); 162 }); 163 lapses.forEach(function (l) { list.appendChild(lapseCard(l)); }); 164 show('pending-section', offers.length > 0 || lapses.length > 0); 131 165 } 132 166 … … 233 267 } 234 268 269 /** The availability dot (FEP-633c 3.6): buddy-list language on the 270 * responsibility axis. Green available, yellow declared away with an end, 271 * grey observed dormant (one answer restores). */ 272 function availLabel(g) { 273 if (g.availability === 'away') { 274 var date = g.awayUntil ? new Date(g.awayUntil).toLocaleDateString() : '?'; 275 return (T.avail_away || 'Unavailable till {date}').replace('{date}', date); 276 } 277 if (g.availability === 'dormant') return T.avail_dormant || 'Offline'; 278 return T.avail_available || 'Available'; 279 } 280 function availRow(g, wardUri) { 281 var row = el('div', 'row g-guard'); 282 var dot = el('span', 'g-avdot ' + (g.availability === 'away' ? 'is-away' : g.availability === 'dormant' ? 'is-dormant' : 'is-active')); 283 row.appendChild(dot); 284 row.appendChild(el('span', 'who grow', handleOf(g.uri, g.handle))); 285 row.appendChild(el('span', 'g-avlabel', availLabel(g))); 286 // A dormant fellow guardian without a running lapse: the deliberate, 287 // rare next step (3.6.3). Never shown for anyone still answering. 288 if (g.availability === 'dormant' && !g.lapse && g.uri !== S.me) { 289 var btn = el('button', 'quiet small', T.lapse_propose || 'Propose release'); 290 btn.addEventListener('click', function () { 291 btn.disabled = true; 292 fetch('/guardian/api/lapse', { 293 method: 'POST', headers: { 'Content-Type': 'application/json' }, 294 body: JSON.stringify({ ward: wardUri, target: g.uri, site: S.site }), 295 }).then(refresh).catch(function () { btn.disabled = false; }); 296 }); 297 row.appendChild(btn); 298 } 299 return row; 300 } 301 235 302 function wardPanel(w) { 236 303 var uri = w.other_uri; … … 244 311 set.appendChild(setRow); 245 312 panel.appendChild(set); 313 314 // The fellow guardians of this child, with availability (3.6). For a 315 // ward on another server the states live there, and saying so honestly 316 // beats guessing. 317 var gsec = el('div', 'g-panel-sec'); 318 gsec.appendChild(el('h3', null, T.panel_guards || 'Guardians of this child')); 319 if (w.guardians && w.guardians.length) { 320 w.guardians.forEach(function (g) { gsec.appendChild(availRow(g, uri)); }); 321 } else { 322 gsec.appendChild(el('p', 'g-empty small', T.panel_guards_remote || '')); 323 } 324 panel.appendChild(gsec); 246 325 247 326 sectionInto(panel, T.panel_follow || 'Follow requests', … … 314 393 }); 315 394 show('wards-empty', wards.length === 0); 316 } 395 // Step away (3.6.1) only means something with wards to tell. 396 show('away-section', wards.length > 0); 397 } 398 399 // ── 4b. Step away (FEP-633c 3.6.1) ───────────────────────────────────── 400 function declareAway(days, btn) { 401 btn.disabled = true; 402 fetch('/guardian/api/away', { 403 method: 'POST', headers: { 'Content-Type': 'application/json' }, 404 body: JSON.stringify({ days: days, site: S.site }), 405 }).then(function (r) { return r.json(); }) 406 .then(function (j) { 407 btn.disabled = false; 408 var msg = document.getElementById('away-msg'); 409 msg.hidden = false; 410 if (j && j.ok) { 411 msg.className = 'g-msg'; 412 msg.textContent = (T.away_done || 'Your wards know you are unavailable until {date}.') 413 .replace('{date}', new Date(j.until).toLocaleDateString()); 414 } else { 415 msg.className = 'g-msg err'; 416 msg.textContent = (j && j.error) || (T.failed || 'failed'); 417 } 418 }) 419 .catch(function () { btn.disabled = false; }); 420 } 421 var awayWeek = document.getElementById('away-week'); 422 var awayMonth = document.getElementById('away-month'); 423 if (awayWeek) awayWeek.addEventListener('click', function () { declareAway(7, awayWeek); }); 424 if (awayMonth) awayMonth.addEventListener('click', function () { declareAway(30, awayMonth); }); 317 425 318 426 function sendWave(uri, btn) { -
src/middleware/render.js
r6eab7e9 r0202104 97 97 const parseStamp = (v) => { 98 98 if (!v) return null; 99 if (typeof v === 'number') { // epoch ms (e.g. an availability endTime) 100 const d = new Date(v); 101 return Number.isNaN(d.getTime()) ? null : d; 102 } 99 103 const s = String(v); 100 104 const d = /^\d{4}-\d{2}-\d{2}[ T]\d{2}:\d{2}(:\d{2})?$/.test(s) -
src/routes/guardian.js
r6eab7e9 r0202104 48 48 // Releasing a ward: a deliberate two-step answer, never one click. 49 49 'release_title', 'release_effect', 'release_local', 'release_step_down', 50 'release_last', 'release_unknown', 'release_yes', 'release_no']; 50 'release_last', 'release_unknown', 'release_yes', 'release_no', 51 // Availability (FEP-633c 3.6): the dots, the step-away, the lapse. 52 'avail_available', 'avail_away', 'avail_dormant', 'panel_guards', 'panel_guards_remote', 53 'lapse_propose', 'lapse_line', 'lapse_tally', 'lapse_note', 'lapse_agree', 'lapse_disagree', 'voted', 54 'away_title', 'away_sub', 'away_week', 'away_month', 'away_done']; 51 55 const s = Object.fromEntries(keys.map((k) => [k, i18nT(L, `guardian.${k}`)])); 52 56 s.wave = i18nT(L, 'guardian.wave'); … … 79 83 // `embeds` is null for a ward we do not host: that setting lives on the 80 84 // ward's own server, so we show it as not-adjustable rather than lying. 81 wards: Guardianship.listWards(site.slug).map((w) => ({ ...w, embeds: wardEmbedSetting(w.other_uri) })), 85 // `guardians` (FEP-633c 3.6): the fellow guardians of a LOCAL ward with 86 // their availability; null for a remote ward, whose server tracks it. 87 wards: Guardianship.listWards(site.slug).map((w) => ({ 88 ...w, 89 embeds: wardEmbedSetting(w.other_uri), 90 guardians: wardGuardianStatuses(w.other_uri), 91 })), 82 92 offers: Guardianship.offersCollection(`${me}/queues/offers`, site.slug, me).orderedItems, 93 // Running lapses (3.6.3) this guardian or its local wards are party to. 94 lapses: Guardianship.availability.lapseQueueItems(site.slug, me, Date.now()), 83 95 help, 84 96 strings: uiStrings(L), 85 97 }; 98 } 99 100 /** The guardians of a ward WE host, with availability (3.6.1: owner-only in 101 * spirit; the co-guardians are among the owners of the relationship). Null 102 * for a remote ward: its server tracks availability, not us. */ 103 function wardGuardianStatuses(wardUri) { 104 const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, ''); 105 if (!base || !String(wardUri || '').startsWith(`${base}/`)) return null; 106 const slug = String(wardUri).trim().replace(/\/+$/, '').split('/').pop(); 107 try { 108 const uris = Guardianship.listGuardians(slug).map((g) => ({ uri: g.other_uri, handle: g.other_handle })); 109 const st = Object.fromEntries( 110 Guardianship.availability.statusesFor(slug, uris.map((u) => u.uri), Date.now()).map((s) => [s.id, s]), 111 ); 112 return uris.map((u) => ({ 113 uri: u.uri, 114 handle: u.handle, 115 availability: (st[u.uri] || {})['shaer:availability'] || 'active', 116 awayUntil: (st[u.uri] || {})['shaer:awayUntil'] || null, 117 lapse: (st[u.uri] || {})['shaer:lapse'] || null, 118 })); 119 } catch { return null; } 86 120 } 87 121 … … 264 298 // "complete"). All three are a C2S Accept/Reject on the offer id; the 265 299 // handshake module decides when it commits (§3.1). 300 // ── Step away (FEP-633c 3.6.1): the guardian declares itself unavailable ── 301 // One direct note with shaer:away and an endTime to every ward, the same 302 // path Shaer takes over C2S. Wards on this instance are applied directly (a 303 // local inbox never receives its own delivery); the rest travels S2S. 304 router.post('/api/away', requireAuth, express.json({ limit: '2kb' }), async (req, res) => { 305 const site = siteForUser(req); 306 if (!site) return res.status(404).json({ error: 'no_site' }); 307 const days = Math.min(365, Math.max(1, parseInt(req.body?.days, 10) || 0)); 308 if (!days) return res.status(400).json({ error: 'away_needs_an_end' }); 309 const wards = Guardianship.listWards(site.slug).map((w) => w.other_uri); 310 if (!wards.length) return res.status(409).json({ error: 'no_wards' }); 311 const until = Date.now() + days * 24 * 3600 * 1000; 312 const base = (process.env.PUBLIC_BASE_URL || '').replace(/\/+$/, ''); 313 const me = AP.actorId(base, site.slug); 314 let applied = 0; 315 for (const uri of wards) { 316 const wslug = uri.startsWith(`${base}/`) ? uri.replace(/\/+$/, '').split('/').pop() : null; 317 if (wslug && Guardianship.listGuardians(wslug).some((g) => g.other_uri === me)) { 318 Guardianship.availability.declareAway(wslug, me, until); 319 applied++; 320 } 321 } 322 const L = resolveLang(req); 323 const text = i18nT(L, 'guardian.away_msg', { date: new Date(until).toLocaleDateString('nl-NL') }); 324 const r = await AP.deliverDirectNote(site, { recipients: wards, text, awayUntil: until }).catch(() => null); 325 if (!applied && !(r && r.id)) return res.status(502).json({ error: 'away_failed' }); 326 res.json({ ok: true, until }); 327 }); 328 329 // ── Propose a lapse (FEP-633c 3.6.3) against a dormant co-guardian ──────── 330 // The same C2S pipeline the Shaer apps would use: an Offer of shaer:Lapse. 331 // A local ward opens directly; a remote ward gets the proposal delivered, 332 // because the ward's server is the one that tallies and enforces. 333 router.post('/api/lapse', requireAuth, express.json({ limit: '4kb' }), async (req, res) => { 334 const site = siteForUser(req); 335 if (!site) return res.status(404).json({ error: 'no_site' }); 336 const ward = String(req.body?.ward || '').trim(); 337 const target = String(req.body?.target || '').trim(); 338 if (!ward || !target) return res.status(400).json({ error: 'missing_ward_or_target' }); 339 if (!Guardianship.listWards(site.slug).some((w) => w.other_uri === ward)) { 340 return res.status(403).json({ error: 'not_my_ward' }); 341 } 342 const r = await AP.ingestOutboxActivity(site, req.session.user, { 343 type: 'Offer', object: { type: 'shaer:Lapse', 'shaer:ward': ward, object: target }, 344 }); 345 if (!r || r.status >= 400) return res.status(r?.status || 500).json({ error: r?.error || 'lapse_failed' }); 346 res.json({ ok: true, lapse: r.id }); 347 }); 348 266 349 router.post('/offer', requireAuth, express.json({ limit: '4kb' }), async (req, res) => { 267 350 const site = siteForUser(req); -
src/routes/posts.js
r6eab7e9 r0202104 947 947 catch { return uri; } 948 948 }; 949 // With their availability (FEP-633c 3.6.1): the ward always sees the real 950 // size of its safety net, not just the names. Owner-only by construction: 951 // this page is the owner's. 952 const gStatus = site ? Object.fromEntries( 953 Guardianship.availability.statusesFor(site.slug, Guardianship.listGuardians(site.slug).map((g) => g.other_uri), Date.now()) 954 .map((s) => [s.id, s]), 955 ) : {}; 949 956 const myGuardians = (site ? Guardianship.listGuardians(site.slug) : []) 950 .map((g) => ({ uri: g.other_uri, handle: guardianHandle(g.other_uri, g.other_handle) })); 957 .map((g) => ({ 958 uri: g.other_uri, 959 handle: guardianHandle(g.other_uri, g.other_handle), 960 availability: (gStatus[g.other_uri] || {})['shaer:availability'] || 'active', 961 awayUntil: (gStatus[g.other_uri] || {})['shaer:awayUntil'] || null, 962 })); 951 963 renderPage(req, res, 'pages/messages', { 952 964 pageTitleKey: 'msg.title', bodyClass: 'on-special', items, seenAt, -
src/services/i18n.js
r6eab7e9 r0202104 67 67 'admin.b_paid': 'Betaalde posts', 'admin.b_push': 'Notificaties', 'admin.back': 'Terug naar Beheer', 68 68 'push.t': 'Notificaties', 'push.intro': 'Krijg een melding op dit apparaat bij nieuwe volgers, reacties en berichten, ook als de site niet open staat. Versleuteld tot in je browser; wij sturen zo min mogelijk inhoud mee.', 'push.unavailable': 'Push is op deze server niet beschikbaar (sleutel kon niet worden aangemaakt of de dependency ontbreekt).', 'push.unsupported': 'Deze browser ondersteunt geen push-notificaties.', 'push.ios_hint': 'Op iPhone/iPad werkt dit alleen als de site op je beginscherm staat: deel-knop, dan "Zet op beginscherm", en open de site daarna vanaf daar.', 'push.this_device': 'Dit apparaat:', 'push.checking': 'controleren…', 'push.state_on': 'meldingen staan aan', 'push.state_off': 'meldingen staan uit', 'push.state_denied': 'geblokkeerd in de browserinstellingen', 'push.state_unknown': 'status onbekend', 'push.state_unsupported': 'niet ondersteund', 'push.enable': 'Zet aan op dit apparaat', 'push.disable': 'Zet uit', 'push.test': 'Stuur testmelding', 'push.what': 'Waarvoor wil je een melding?', 'push.a_follow': 'Nieuwe volger', 'push.a_reply': 'Reactie of vermelding', 'push.a_like': 'Waardering (ster)', 'push.a_boost': 'Boost', 'push.a_dm': 'Privébericht', 'push.saved': 'Opgeslagen.', 'push.devices': 'Gekoppelde apparaten', 'push.device': 'Apparaat', 'push.since': 'sinds', 'push.remove': 'Verwijder', 'push.enable_failed': 'aanzetten mislukt', 'push.on_short': 'Word supporter', 69 'push.n_follow_t': 'Nieuwe volger', 'push.n_follow_b': '{who} volgt je nu', 'push.n_reply_t': 'Reactie op "{title}"', 'push.n_mention_t': 'Vermelding', 'push.n_dm_t': 'Privébericht', 'push.n_dm_b': 'Nieuw bericht van {who}', 'push.n_like_t': 'Nieuwe waardering', 'push.n_like_b': '{who} waardeerde "{title}"', 'push.n_boost_t': 'Geboost', 'push.n_boost_b': '{who} boostte "{title}"', 'msg.guard_offer': 'wil je guardian worden. Bespreek dit met je ouders of verzorgers voordat je beslist.', 'msg.guard_accept': 'Accepteer', 'msg.guard_reject': 'Weiger', 'msg.guard_accepted': 'Guardian geaccepteerd. Jullie zijn nu verbonden.', 'msg.guard_rejected': 'Aanvraag geweigerd.', 'msg.guard_failed': 'Dat lukte niet; probeer het opnieuw.', 'msg.guardians_label': 'Jouw guardians', 'msg.waved_at_you': 'zwaaide naar je', 'msg.help_request': 'vroeg om hulp', 'msg. wave_r1': 'Wat leuk!', 'msg.wave_r2': 'Bel me even', 'msg.wave_back': '👋 Terug', 'msg.wave_sent': 'Zwaai verstuurd.', 'guardian.feed_title': 'Van je wards', 'guardian.feed_sub': 'Meelezen met wat je wards plaatsen. Alleen kijken.', 'guardian.follow_title': 'Volgverzoeken', 'guardian.follow_sub': 'Iemand wil een van je wards volgen. Jij beslist.', 'guardian.wave': '👋 Zwaai', 'guardian.waved': '👋 verstuurd', 'guardian.app_name': 'Klonkt Guardian', 'guardian.tagline': 'Wards beheren en hulpverzoeken opvangen.', 'guardian.acting_as': 'Je handelt als', 'guardian.help_title': 'Hulpverzoeken', 'guardian.help_sub': 'Als een ward de reddingsboei gebruikt, verschijnt het hier.', 'guardian.help_empty': 'Geen hulpverzoeken. Mooi zo.', 'guardian.adopt_title': 'Ward adopteren', 'guardian.adopt_sub': 'Vul de handle van het kind in (@kind@server.eu). Ze krijgen een aanvraag in hun Klonkt die ze accepteren.', 'guardian.adopt_label': 'Handle van de ward', 'guardian.adopt_btn': 'Verstuur aanvraag', 'guardian.pending_title': 'Verzonden aanvragen', 'guardian.pending_sub': 'Wacht tot de ward accepteert.', 'guardian.wards_title': 'Mijn wards', 'guardian.release_title': '{who} loslaten?', 'guardian.release_effect': 'Je stopt als guardian. Je ziet hun berichten niet meer, je krijgt geen hulpvragen meer van ze, en je beoordeelt geen volgverzoeken meer voor ze. Terugkomen kan alleen met een nieuwe aanvraag die zij accepteren.', 'guardian.release_local': 'Hun server en de andere guardians krijgen dit door, dus daarna sta jij ook bij hen niet meer als guardian.', 'guardian.release_step_down': 'Zij houden hun andere guardians, dus zij blijven een ward.', 'guardian.release_last': 'Je bent hun laatste guardian. Dat is emancipatie, en volgens FEP-633c 3.4 is dat niet aan een guardian alleen: daar horen drie instemmende volwassenen bij, of een meerderheid met twee getuigen. Deze knop kan dat dus niet: je blijft hun guardian tot dat geregeld is.', 'guardian.release_unknown': 'We konden hun server niet bereiken, dus we weten niet of jij hun laatste guardian bent.', 'guardian.release_yes': 'Ja, loslaten', 'guardian.release_no': 'Nee, toch niet', 'guardian.settings_title': 'Instellingen', 'guardian.panel_open': 'Bekijken', 'guardian.panel_close': 'Sluiten', 'guardian.panel_help': 'Hulpvragen van dit kind', 'guardian.panel_help_empty': 'Nog geen hulpvragen.', 'guardian.panel_follow': 'Volgverzoeken', 'guardian.panel_follow_empty': 'Geen openstaande volgverzoeken.', 'guardian.panel_posts': 'Recente berichten', 'guardian.panel_posts_empty': 'Nog niets te zien.', 'guardian.panel_actions': 'Acties', 'guardian.badge_help': 'hulpvragen', 'guardian.badge_follow': 'volgverzoeken', 'guardian.badge_follow_one': 'volgverzoek', 'guardian.wards_empty': 'Nog geen wards. Adopteer er hierboven een.', 'guardian.push_title': 'Meldingen', 'guardian.push_sub': 'Ontvang een melding bij een hulpverzoek of voogdij-antwoord, ook als de app dicht is.', 'guardian.push_on': 'Zet meldingen aan', 'guardian.push_off': 'Meldingen staan aan; tik om uit te zetten', 'guardian.sent': 'Aanvraag verstuurd. Zie hieronder bij Verzonden aanvragen.', 'guardian.sent_retry': 'Aanvraag opgeslagen; we blijven proberen te bezorgen.', 'guardian.sending': 'Versturen…', 'guardian.not_found': 'Die handle konden we niet vinden.', 'guardian.failed': 'Mislukt', 'guardian.network': 'Netwerkfout.', 'guardian.pending': 'wacht op antwoord', 'guardian.active': 'actief', 'guardian.retract': 'Intrekken', 'guardian.release': 'Loslaten', 'guardian.embeds_on': 'Linkvoorbeelden: aan', 'guardian.embeds_off': 'Linkvoorbeelden: uit', 'guardian.embeds_propose': 'Linkvoorbeelden voorstellen', 'guardian.embeds_waiting': 'wacht op de andere guardians', 'guardian.release_confirm': '{who} loslaten?\n\nJe stopt dan als guardian. Je ziet hun berichten niet meer, je krijgt geen hulpverzoeken meer van ze, en je kunt volgverzoeken niet meer voor ze beoordelen.\n\nTerugkomen kan alleen met een nieuwe aanvraag die zij accepteren.', 'guardian.open': 'open', 'guardian.accept': 'Accepteer', 'guardian.reject': 'Weiger', 'guardian.complete': 'Voltooien', 'guardian.awaiting_others': 'wacht op de andere partijen', 'guardian.coguard': 'mede-voogdij-aanvraag', 'guardian.push_unavailable': 'Push niet beschikbaar', 'push.n_help_t': 'Hulpvraag', 'push.n_help_b': '{who} vraagt om je hulp', 'push.n_guard_offer_t': 'Voogdij-aanvraag', 'push.n_guard_offer_b': '{who} wil je guardian worden', 'push.n_guard_ward_t': 'Ward geaccepteerd', 'push.n_guard_left_t': 'Een guardian is gestopt', 'push.n_guard_left_b': '{who} is niet langer je guardian', 'push.n_guard_cogleft_t': 'Mede-guardian gestopt', 'push.n_guard_cogleft_b': '{who} heeft de guardianship beeindigd', 'push.n_guard_ward_b': '{who} accepteerde je als guardian', 'push.n_guard_cog_t': 'Mede-voogdij gevraagd', 'push.n_guard_cog_b': 'Er is een guardian-aanvraag voor {who}', 'push.n_test_t': 'Klonkt-testnotificatie', 'push.n_test_b': 'Werkt. Zo komen meldingen binnen op dit apparaat.',69 'push.n_follow_t': 'Nieuwe volger', 'push.n_follow_b': '{who} volgt je nu', 'push.n_reply_t': 'Reactie op "{title}"', 'push.n_mention_t': 'Vermelding', 'push.n_dm_t': 'Privébericht', 'push.n_dm_b': 'Nieuw bericht van {who}', 'push.n_like_t': 'Nieuwe waardering', 'push.n_like_b': '{who} waardeerde "{title}"', 'push.n_boost_t': 'Geboost', 'push.n_boost_b': '{who} boostte "{title}"', 'msg.guard_offer': 'wil je guardian worden. Bespreek dit met je ouders of verzorgers voordat je beslist.', 'msg.guard_accept': 'Accepteer', 'msg.guard_reject': 'Weiger', 'msg.guard_accepted': 'Guardian geaccepteerd. Jullie zijn nu verbonden.', 'msg.guard_rejected': 'Aanvraag geweigerd.', 'msg.guard_failed': 'Dat lukte niet; probeer het opnieuw.', 'msg.guardians_label': 'Jouw guardians', 'msg.waved_at_you': 'zwaaide naar je', 'msg.help_request': 'vroeg om hulp', 'msg.g_available': 'beschikbaar', 'msg.g_away': 'afwezig tot {date}', 'msg.g_offline': 'offline', 'msg.wave_r1': 'Wat leuk!', 'msg.wave_r2': 'Bel me even', 'msg.wave_back': '👋 Terug', 'msg.wave_sent': 'Zwaai verstuurd.', 'guardian.feed_title': 'Van je wards', 'guardian.feed_sub': 'Meelezen met wat je wards plaatsen. Alleen kijken.', 'guardian.follow_title': 'Volgverzoeken', 'guardian.follow_sub': 'Iemand wil een van je wards volgen. Jij beslist.', 'guardian.wave': '👋 Zwaai', 'guardian.waved': '👋 verstuurd', 'guardian.app_name': 'Klonkt Guardian', 'guardian.tagline': 'Wards beheren en hulpverzoeken opvangen.', 'guardian.acting_as': 'Je handelt als', 'guardian.help_title': 'Hulpverzoeken', 'guardian.help_sub': 'Als een ward de reddingsboei gebruikt, verschijnt het hier.', 'guardian.help_empty': 'Geen hulpverzoeken. Mooi zo.', 'guardian.adopt_title': 'Ward adopteren', 'guardian.adopt_sub': 'Vul de handle van het kind in (@kind@server.eu). Ze krijgen een aanvraag in hun Klonkt die ze accepteren.', 'guardian.adopt_label': 'Handle van de ward', 'guardian.adopt_btn': 'Verstuur aanvraag', 'guardian.pending_title': 'Verzonden aanvragen', 'guardian.pending_sub': 'Wacht tot de ward accepteert.', 'guardian.wards_title': 'Mijn wards', 'guardian.avail_available': 'Beschikbaar', 'guardian.avail_away': 'Afwezig tot {date}', 'guardian.avail_dormant': 'Offline', 'guardian.panel_guards': 'Guardians van dit kind', 'guardian.panel_guards_remote': 'Dit kind woont op een andere server; de beschikbaarheid wordt daar bijgehouden.', 'guardian.lapse_propose': 'Voorstel: loslaten bij afwezigheid', 'guardian.lapse_line': '{who} antwoordt niet meer als guardian van {ward}.', 'guardian.lapse_tally': '{n} van {need} akkoord; sluit {date}; het venster loopt altijd vol.', 'guardian.lapse_note': 'Elk teken van leven van hen annuleert dit meteen. Niets hier is straf.', 'guardian.lapse_agree': 'Eens', 'guardian.lapse_disagree': 'Oneens', 'guardian.voted': 'Je hebt gestemd', 'guardian.away_title': 'Even afwezig', 'guardian.away_sub': 'Meld je wards dat je er even niet bent. Besluiten wachten niet op je, en een enkel antwoord brengt je meteen terug.', 'guardian.away_week': 'Een week', 'guardian.away_month': 'Een maand', 'guardian.away_done': 'Je wards weten dat je afwezig bent tot {date}.', 'guardian.away_msg': 'Ik ben afwezig als je guardian tot {date}. Je andere guardians zijn er voor je.', 'guardian.release_title': '{who} loslaten?', 'guardian.release_effect': 'Je stopt als guardian. Je ziet hun berichten niet meer, je krijgt geen hulpvragen meer van ze, en je beoordeelt geen volgverzoeken meer voor ze. Terugkomen kan alleen met een nieuwe aanvraag die zij accepteren.', 'guardian.release_local': 'Hun server en de andere guardians krijgen dit door, dus daarna sta jij ook bij hen niet meer als guardian.', 'guardian.release_step_down': 'Zij houden hun andere guardians, dus zij blijven een ward.', 'guardian.release_last': 'Je bent hun laatste guardian. Dat is emancipatie, en volgens FEP-633c 3.4 is dat niet aan een guardian alleen: daar horen drie instemmende volwassenen bij, of een meerderheid met twee getuigen. Deze knop kan dat dus niet: je blijft hun guardian tot dat geregeld is.', 'guardian.release_unknown': 'We konden hun server niet bereiken, dus we weten niet of jij hun laatste guardian bent.', 'guardian.release_yes': 'Ja, loslaten', 'guardian.release_no': 'Nee, toch niet', 'guardian.settings_title': 'Instellingen', 'guardian.panel_open': 'Bekijken', 'guardian.panel_close': 'Sluiten', 'guardian.panel_help': 'Hulpvragen van dit kind', 'guardian.panel_help_empty': 'Nog geen hulpvragen.', 'guardian.panel_follow': 'Volgverzoeken', 'guardian.panel_follow_empty': 'Geen openstaande volgverzoeken.', 'guardian.panel_posts': 'Recente berichten', 'guardian.panel_posts_empty': 'Nog niets te zien.', 'guardian.panel_actions': 'Acties', 'guardian.badge_help': 'hulpvragen', 'guardian.badge_follow': 'volgverzoeken', 'guardian.badge_follow_one': 'volgverzoek', 'guardian.wards_empty': 'Nog geen wards. Adopteer er hierboven een.', 'guardian.push_title': 'Meldingen', 'guardian.push_sub': 'Ontvang een melding bij een hulpverzoek of voogdij-antwoord, ook als de app dicht is.', 'guardian.push_on': 'Zet meldingen aan', 'guardian.push_off': 'Meldingen staan aan; tik om uit te zetten', 'guardian.sent': 'Aanvraag verstuurd. Zie hieronder bij Verzonden aanvragen.', 'guardian.sent_retry': 'Aanvraag opgeslagen; we blijven proberen te bezorgen.', 'guardian.sending': 'Versturen…', 'guardian.not_found': 'Die handle konden we niet vinden.', 'guardian.failed': 'Mislukt', 'guardian.network': 'Netwerkfout.', 'guardian.pending': 'wacht op antwoord', 'guardian.active': 'actief', 'guardian.retract': 'Intrekken', 'guardian.release': 'Loslaten', 'guardian.embeds_on': 'Linkvoorbeelden: aan', 'guardian.embeds_off': 'Linkvoorbeelden: uit', 'guardian.embeds_propose': 'Linkvoorbeelden voorstellen', 'guardian.embeds_waiting': 'wacht op de andere guardians', 'guardian.release_confirm': '{who} loslaten?\n\nJe stopt dan als guardian. Je ziet hun berichten niet meer, je krijgt geen hulpverzoeken meer van ze, en je kunt volgverzoeken niet meer voor ze beoordelen.\n\nTerugkomen kan alleen met een nieuwe aanvraag die zij accepteren.', 'guardian.open': 'open', 'guardian.accept': 'Accepteer', 'guardian.reject': 'Weiger', 'guardian.complete': 'Voltooien', 'guardian.awaiting_others': 'wacht op de andere partijen', 'guardian.coguard': 'mede-voogdij-aanvraag', 'guardian.push_unavailable': 'Push niet beschikbaar', 'push.n_help_t': 'Hulpvraag', 'push.n_help_b': '{who} vraagt om je hulp', 'push.n_guard_offer_t': 'Voogdij-aanvraag', 'push.n_guard_offer_b': '{who} wil je guardian worden', 'push.n_guard_ward_t': 'Ward geaccepteerd', 'push.n_guard_left_t': 'Een guardian is gestopt', 'push.n_guard_left_b': '{who} is niet langer je guardian', 'push.n_guard_cogleft_t': 'Mede-guardian gestopt', 'push.n_guard_cogleft_b': '{who} heeft de guardianship beeindigd', 'push.n_guard_ward_b': '{who} accepteerde je als guardian', 'push.n_guard_cog_t': 'Mede-voogdij gevraagd', 'push.n_guard_cog_b': 'Er is een guardian-aanvraag voor {who}', 'push.n_test_t': 'Klonkt-testnotificatie', 'push.n_test_b': 'Werkt. Zo komen meldingen binnen op dit apparaat.', 70 70 'apaid.t': 'Betaalde posts', 'apaid.intro': 'Koppel je eigen Patreon-campagne. Supporters ontgrendelen betaalde posts met een passkey, zonder account en zonder cookie. Wij bewaren geen namen of e-mailadressen van supporters, alleen het versleutelde token van jouw campagne.', 'apaid.saved': 'Opgeslagen.', 'apaid.nokey': 'Let op: de encryptiesleutel kon niet worden aangemaakt of gelezen (schrijfrechten op de opslagmap?). Zonder sleutel kunnen secrets niet veilig worden opgeslagen.', 'apaid.status': 'Status:', 'apaid.connected': 'verbonden', 'apaid.campaign': 'campagne', 'apaid.configured': 'ingesteld, nog niet verbonden (vul een token in)', 'apaid.notyet': 'nog niet ingesteld', 'apaid.redirect_h': 'Zet deze redirect-URI in je Patreon-client', 'apaid.redirect_p': 'Bij je Patreon API-client, onder Redirect URIs, moet exact deze regel staan. Klopt hij niet, dan geeft Patreon een foutmelding in plaats van je supporters terug te sturen.', 'apaid.copy': 'Kopieer', 'apaid.copied': 'Gekopieerd', 'apaid.client_id': 'Patreon client id', 'apaid.client_secret': 'Patreon client secret', 'apaid.keep': 'Leeg laten = huidige waarde behouden.', 'apaid.campaign_id': 'Campagne-id', 'apaid.public_page': 'Openbare Patreon-pagina', 'apaid.public_help': 'De link waar bezoekers supporter kunnen worden. Getoond als "Word supporter" wanneer iemand nog niet doneert.', 'apaid.access': 'Creator access token', 'apaid.refresh': 'Creator refresh token', 'apaid.token_help': 'De access + refresh token krijg je op je Patreon API-clientpagina. Wij versleutelen ze en verversen automatisch.', 'apaid.min_eur': 'Standaard-steunbedrag voor een betaalde post (euro)', 'apaid.save': 'Opslaan', 'apaid.disconnect': 'Koppeling verwijderen', 'apaid.disconnect_confirm': 'Patreon-koppeling verwijderen?', 'apaid.unchanged': 'blijft ongewijzigd', 71 71 'pgate.h': 'Voor supporters', 'pgate.sub': 'Deze post is voor supporters van deze site. Word supporter en ontgrendel hem daarna met een passkey. Geen account op deze site, geen cookie.', 'pgate.sub_cents': 'Deze post is voor supporters van deze site (vanaf €{eur} per maand op Patreon). Word supporter en ontgrendel hem daarna met een passkey. Geen account op deze site, geen cookie.', 'pgate.join': 'Word supporter op Patreon', 'pgate.unlock_have': 'Al supporter? Ontgrendelen', 'pgate.unlock': 'Ontgrendelen met Patreon', 'pgate.join_short': 'Word supporter', 'pgate.confirm': 'Bevestig met je passkey…', 'pgate.failed': 'Ontgrendelen mislukt. Probeer opnieuw.', 'pgate.error': 'Er ging iets mis. Probeer opnieuw.', … … 1008 1008 'admin.b_paid': 'Paid posts', 'admin.b_push': 'Notifications', 'admin.back': 'Back to Admin', 1009 1009 'push.t': 'Notifications', 'push.intro': 'Get a notification on this device for new followers, replies and messages, even when the site is closed. Encrypted all the way to your browser; we send as little content as possible.', 'push.unavailable': 'Push is unavailable on this server (the key could not be created or the dependency is missing).', 'push.unsupported': 'This browser does not support push notifications.', 'push.ios_hint': 'On iPhone/iPad this only works when the site is on your home screen: share button, then "Add to Home Screen", and open it from there.', 'push.this_device': 'This device:', 'push.checking': 'checking…', 'push.state_on': 'notifications are on', 'push.state_off': 'notifications are off', 'push.state_denied': 'blocked in the browser settings', 'push.state_unknown': 'status unknown', 'push.state_unsupported': 'not supported', 'push.enable': 'Turn on for this device', 'push.disable': 'Turn off', 'push.test': 'Send a test notification', 'push.what': 'What do you want to be notified about?', 'push.a_follow': 'New follower', 'push.a_reply': 'Reply or mention', 'push.a_like': 'Like (star)', 'push.a_boost': 'Boost', 'push.a_dm': 'Private message', 'push.saved': 'Saved.', 'push.devices': 'Linked devices', 'push.device': 'Device', 'push.since': 'since', 'push.remove': 'Remove', 'push.enable_failed': 'turning on failed', 1010 'push.n_follow_t': 'New follower', 'push.n_follow_b': '{who} now follows you', 'push.n_reply_t': 'Reply to "{title}"', 'push.n_mention_t': 'Mention', 'push.n_dm_t': 'Private message', 'push.n_dm_b': 'New message from {who}', 'push.n_like_t': 'New like', 'push.n_like_b': '{who} liked "{title}"', 'push.n_boost_t': 'Boosted', 'push.n_boost_b': '{who} boosted "{title}"', 'msg.guard_offer': 'wants to become your guardian. Talk this over with your parents or carers before you decide.', 'msg.guard_accept': 'Accept', 'msg.guard_reject': 'Reject', 'msg.guard_accepted': 'Guardian accepted. You are now connected.', 'msg.guard_rejected': 'Offer rejected.', 'msg.guard_failed': 'That did not work; try again.', 'msg.guardians_label': 'Your guardians', 'msg.waved_at_you': 'waved at you', 'msg.help_request': 'asked for help', 'msg. wave_r1': 'Lovely!', 'msg.wave_r2': 'Call me', 'msg.wave_back': '👋 Back', 'msg.wave_sent': 'Wave sent.', 'guardian.feed_title': 'Your wards', 'guardian.feed_sub': 'Read along with what your wards post. Watch only.', 'guardian.follow_title': 'Follow requests', 'guardian.follow_sub': 'Someone wants to follow one of your wards. You decide.', 'guardian.wave': '👋 Wave', 'guardian.waved': '👋 sent', 'guardian.app_name': 'Klonkt Guardian', 'guardian.tagline': 'Manage wards and catch calls for help.', 'guardian.acting_as': 'You act as', 'guardian.help_title': 'Help requests', 'guardian.help_sub': 'When a ward uses the help buoy, it shows up here.', 'guardian.help_empty': 'No help requests. Good.', 'guardian.adopt_title': 'Adopt a ward', 'guardian.adopt_sub': 'Enter the child handle (@kid@server.eu). They get an offer in their Klonkt to accept.', 'guardian.adopt_label': 'Ward handle', 'guardian.adopt_btn': 'Send offer', 'guardian.pending_title': 'Sent offers', 'guardian.pending_sub': 'Waiting for the ward to accept.', 'guardian.wards_title': 'My wards', 'guardian.release_title': 'Release {who}?', 'guardian.release_effect': 'You stop being their guardian. You will no longer see their posts, no longer receive their calls for help, and no longer decide on follow requests for them. Coming back means a fresh offer that they accept.', 'guardian.release_local': 'Their server and the other guardians are told, so afterwards you are no longer listed as a guardian there either.', 'guardian.release_step_down': 'They keep their other guardians, so they stay a ward.', 'guardian.release_last': 'You are their last guardian. That is emancipation, and FEP-633c 3.4 is explicit that no single guardian decides it: it takes three consenting adults, or a majority plus two witnesses. So this button cannot do it: you stay their guardian until that is arranged.', 'guardian.release_unknown': 'We could not reach their server, so we do not know whether you are their last guardian.', 'guardian.release_yes': 'Yes, release', 'guardian.release_no': 'No, keep them', 'guardian.settings_title': 'Settings', 'guardian.panel_open': 'Open', 'guardian.panel_close': 'Close', 'guardian.panel_help': 'Calls for help from this child', 'guardian.panel_help_empty': 'No calls for help yet.', 'guardian.panel_follow': 'Follow requests', 'guardian.panel_follow_empty': 'No follow requests waiting.', 'guardian.panel_posts': 'Recent posts', 'guardian.panel_posts_empty': 'Nothing here yet.', 'guardian.panel_actions': 'Actions', 'guardian.badge_help': 'calls for help', 'guardian.badge_follow': 'follow requests', 'guardian.badge_follow_one': 'follow request', 'guardian.wards_empty': 'No wards yet. Adopt one above.', 'guardian.push_title': 'Notifications', 'guardian.push_sub': 'Get notified on a call for help or a guardianship answer, even with the app closed.', 'guardian.push_on': 'Turn on notifications', 'guardian.push_off': 'Notifications are on; tap to turn off', 'guardian.sent': 'Offer sent. See it below under Sent offers.', 'guardian.sent_retry': 'Offer saved; we keep trying to deliver it.', 'guardian.sending': 'Sending…', 'guardian.not_found': 'We could not find that handle.', 'guardian.failed': 'Failed', 'guardian.network': 'Network error.', 'guardian.pending': 'awaiting answer', 'guardian.active': 'active', 'guardian.retract': 'Retract', 'guardian.release': 'Release', 'guardian.embeds_on': 'Link previews: on', 'guardian.embeds_off': 'Link previews: off', 'guardian.embeds_propose': 'Propose link previews', 'guardian.embeds_waiting': 'waiting for the other guardians', 'guardian.release_confirm': 'Release {who}?\n\nYou stop being their guardian. You will no longer see their posts, no longer receive their calls for help, and no longer decide on follow requests for them.\n\nComing back means a fresh offer that they accept.', 'guardian.open': 'open', 'guardian.accept': 'Accept', 'guardian.reject': 'Reject', 'guardian.complete': 'Complete', 'guardian.awaiting_others': 'awaiting the other parties', 'guardian.coguard': 'co-guardianship offer', 'guardian.push_unavailable': 'Push unavailable', 'push.n_help_t': 'Call for help', 'push.n_help_b': '{who} is asking for your help', 'push.n_guard_offer_t': 'Guardianship offer', 'push.n_guard_offer_b': '{who} wants you as their guardian', 'push.n_guard_ward_t': 'Ward accepted', 'push.n_guard_left_t': 'A guardian has stepped down', 'push.n_guard_left_b': '{who} is no longer your guardian', 'push.n_guard_cogleft_t': 'Co-guardian stepped down', 'push.n_guard_cogleft_b': '{who} has ended their guardianship', 'push.n_guard_ward_b': '{who} accepted you as guardian', 'push.n_guard_cog_t': 'Co-guardianship asked', 'push.n_guard_cog_b': 'A guardian offer for {who} needs you', 'push.n_test_t': 'Klonkt test notification', 'push.n_test_b': 'It works. This is how notifications arrive on this device.',1010 'push.n_follow_t': 'New follower', 'push.n_follow_b': '{who} now follows you', 'push.n_reply_t': 'Reply to "{title}"', 'push.n_mention_t': 'Mention', 'push.n_dm_t': 'Private message', 'push.n_dm_b': 'New message from {who}', 'push.n_like_t': 'New like', 'push.n_like_b': '{who} liked "{title}"', 'push.n_boost_t': 'Boosted', 'push.n_boost_b': '{who} boosted "{title}"', 'msg.guard_offer': 'wants to become your guardian. Talk this over with your parents or carers before you decide.', 'msg.guard_accept': 'Accept', 'msg.guard_reject': 'Reject', 'msg.guard_accepted': 'Guardian accepted. You are now connected.', 'msg.guard_rejected': 'Offer rejected.', 'msg.guard_failed': 'That did not work; try again.', 'msg.guardians_label': 'Your guardians', 'msg.waved_at_you': 'waved at you', 'msg.help_request': 'asked for help', 'msg.g_available': 'available', 'msg.g_away': 'unavailable till {date}', 'msg.g_offline': 'offline', 'msg.wave_r1': 'Lovely!', 'msg.wave_r2': 'Call me', 'msg.wave_back': '👋 Back', 'msg.wave_sent': 'Wave sent.', 'guardian.feed_title': 'Your wards', 'guardian.feed_sub': 'Read along with what your wards post. Watch only.', 'guardian.follow_title': 'Follow requests', 'guardian.follow_sub': 'Someone wants to follow one of your wards. You decide.', 'guardian.wave': '👋 Wave', 'guardian.waved': '👋 sent', 'guardian.app_name': 'Klonkt Guardian', 'guardian.tagline': 'Manage wards and catch calls for help.', 'guardian.acting_as': 'You act as', 'guardian.help_title': 'Help requests', 'guardian.help_sub': 'When a ward uses the help buoy, it shows up here.', 'guardian.help_empty': 'No help requests. Good.', 'guardian.adopt_title': 'Adopt a ward', 'guardian.adopt_sub': 'Enter the child handle (@kid@server.eu). They get an offer in their Klonkt to accept.', 'guardian.adopt_label': 'Ward handle', 'guardian.adopt_btn': 'Send offer', 'guardian.pending_title': 'Sent offers', 'guardian.pending_sub': 'Waiting for the ward to accept.', 'guardian.wards_title': 'My wards', 'guardian.avail_available': 'Available', 'guardian.avail_away': 'Unavailable till {date}', 'guardian.avail_dormant': 'Offline', 'guardian.panel_guards': 'Guardians of this child', 'guardian.panel_guards_remote': 'This child lives on another server; availability is tracked there.', 'guardian.lapse_propose': 'Propose release in absentia', 'guardian.lapse_line': '{who} has stopped answering as a guardian of {ward}.', 'guardian.lapse_tally': '{n} of {need} agreed; closes {date}; the window always runs in full.', 'guardian.lapse_note': 'Any sign of life from them cancels this outright. Nothing here is punishment.', 'guardian.lapse_agree': 'Agree', 'guardian.lapse_disagree': 'Disagree', 'guardian.voted': 'You voted', 'guardian.away_title': 'Step away', 'guardian.away_sub': 'Tell your wards you are unavailable for a while. Decisions will not wait for you, and one answer brings you straight back.', 'guardian.away_week': 'A week', 'guardian.away_month': 'A month', 'guardian.away_done': 'Your wards know you are unavailable until {date}.', 'guardian.away_msg': 'I am unavailable as your guardian until {date}. Your other guardians are there for you.', 'guardian.release_title': 'Release {who}?', 'guardian.release_effect': 'You stop being their guardian. You will no longer see their posts, no longer receive their calls for help, and no longer decide on follow requests for them. Coming back means a fresh offer that they accept.', 'guardian.release_local': 'Their server and the other guardians are told, so afterwards you are no longer listed as a guardian there either.', 'guardian.release_step_down': 'They keep their other guardians, so they stay a ward.', 'guardian.release_last': 'You are their last guardian. That is emancipation, and FEP-633c 3.4 is explicit that no single guardian decides it: it takes three consenting adults, or a majority plus two witnesses. So this button cannot do it: you stay their guardian until that is arranged.', 'guardian.release_unknown': 'We could not reach their server, so we do not know whether you are their last guardian.', 'guardian.release_yes': 'Yes, release', 'guardian.release_no': 'No, keep them', 'guardian.settings_title': 'Settings', 'guardian.panel_open': 'Open', 'guardian.panel_close': 'Close', 'guardian.panel_help': 'Calls for help from this child', 'guardian.panel_help_empty': 'No calls for help yet.', 'guardian.panel_follow': 'Follow requests', 'guardian.panel_follow_empty': 'No follow requests waiting.', 'guardian.panel_posts': 'Recent posts', 'guardian.panel_posts_empty': 'Nothing here yet.', 'guardian.panel_actions': 'Actions', 'guardian.badge_help': 'calls for help', 'guardian.badge_follow': 'follow requests', 'guardian.badge_follow_one': 'follow request', 'guardian.wards_empty': 'No wards yet. Adopt one above.', 'guardian.push_title': 'Notifications', 'guardian.push_sub': 'Get notified on a call for help or a guardianship answer, even with the app closed.', 'guardian.push_on': 'Turn on notifications', 'guardian.push_off': 'Notifications are on; tap to turn off', 'guardian.sent': 'Offer sent. See it below under Sent offers.', 'guardian.sent_retry': 'Offer saved; we keep trying to deliver it.', 'guardian.sending': 'Sending…', 'guardian.not_found': 'We could not find that handle.', 'guardian.failed': 'Failed', 'guardian.network': 'Network error.', 'guardian.pending': 'awaiting answer', 'guardian.active': 'active', 'guardian.retract': 'Retract', 'guardian.release': 'Release', 'guardian.embeds_on': 'Link previews: on', 'guardian.embeds_off': 'Link previews: off', 'guardian.embeds_propose': 'Propose link previews', 'guardian.embeds_waiting': 'waiting for the other guardians', 'guardian.release_confirm': 'Release {who}?\n\nYou stop being their guardian. You will no longer see their posts, no longer receive their calls for help, and no longer decide on follow requests for them.\n\nComing back means a fresh offer that they accept.', 'guardian.open': 'open', 'guardian.accept': 'Accept', 'guardian.reject': 'Reject', 'guardian.complete': 'Complete', 'guardian.awaiting_others': 'awaiting the other parties', 'guardian.coguard': 'co-guardianship offer', 'guardian.push_unavailable': 'Push unavailable', 'push.n_help_t': 'Call for help', 'push.n_help_b': '{who} is asking for your help', 'push.n_guard_offer_t': 'Guardianship offer', 'push.n_guard_offer_b': '{who} wants you as their guardian', 'push.n_guard_ward_t': 'Ward accepted', 'push.n_guard_left_t': 'A guardian has stepped down', 'push.n_guard_left_b': '{who} is no longer your guardian', 'push.n_guard_cogleft_t': 'Co-guardian stepped down', 'push.n_guard_cogleft_b': '{who} has ended their guardianship', 'push.n_guard_ward_b': '{who} accepted you as guardian', 'push.n_guard_cog_t': 'Co-guardianship asked', 'push.n_guard_cog_b': 'A guardian offer for {who} needs you', 'push.n_test_t': 'Klonkt test notification', 'push.n_test_b': 'It works. This is how notifications arrive on this device.', 1011 1011 'apaid.t': 'Paid posts', 'apaid.intro': 'Connect your own Patreon campaign. Supporters unlock paid posts with a passkey, no account and no cookie. We store no supporter names or email addresses, only the encrypted token of your campaign.', 'apaid.saved': 'Saved.', 'apaid.nokey': 'Note: the encryption key could not be created or read (write permissions on the storage directory?). Without a key, secrets cannot be stored safely.', 'apaid.status': 'Status:', 'apaid.connected': 'connected', 'apaid.campaign': 'campaign', 'apaid.configured': 'configured, not connected yet (enter a token)', 'apaid.notyet': 'not configured yet', 'apaid.redirect_h': 'Put this redirect URI in your Patreon client', 'apaid.redirect_p': 'In your Patreon API client, under Redirect URIs, exactly this line must be present. If it does not match, Patreon shows an error instead of sending your supporters back.', 'apaid.copy': 'Copy', 'apaid.copied': 'Copied', 'apaid.client_id': 'Patreon client id', 'apaid.client_secret': 'Patreon client secret', 'apaid.keep': 'Leave empty = keep the current value.', 'apaid.campaign_id': 'Campaign id', 'apaid.public_page': 'Public Patreon page', 'apaid.public_help': 'The link where visitors can become a supporter. Shown as "Become a supporter" when someone does not pledge yet.', 'apaid.access': 'Creator access token', 'apaid.refresh': 'Creator refresh token', 'apaid.token_help': 'You get the access + refresh token on your Patreon API client page. We encrypt them and refresh automatically.', 'apaid.min_eur': 'Default support amount for a paid post (euro)', 'apaid.save': 'Save', 'apaid.disconnect': 'Remove connection', 'apaid.disconnect_confirm': 'Remove the Patreon connection?', 'apaid.unchanged': 'stays unchanged', 1012 1012 'pgate.h': 'For supporters', 'pgate.sub': 'This post is for supporters of this site. Become a supporter and then unlock it with a passkey. No account on this site, no cookie.', 'pgate.sub_cents': 'This post is for supporters of this site (from €{eur} per month on Patreon). Become a supporter and then unlock it with a passkey. No account on this site, no cookie.', 'pgate.join': 'Become a supporter on Patreon', 'pgate.unlock_have': 'Already a supporter? Unlock', 'pgate.unlock': 'Unlock with Patreon', 'pgate.join_short': 'Become a supporter', 'pgate.confirm': 'Confirm with your passkey…', 'pgate.failed': 'Unlocking failed. Try again.', 'pgate.error': 'Something went wrong. Try again.', … … 1943 1943 'admin.b_paid': 'Bezahlte Beiträge', 'admin.b_push': 'Benachrichtigungen', 'admin.back': 'Zurück zur Verwaltung', 1944 1944 'push.t': 'Benachrichtigungen', 'push.intro': 'Erhalte auf diesem Gerät eine Meldung bei neuen Followern, Antworten und Nachrichten, auch wenn die Seite geschlossen ist. Verschlüsselt bis in deinen Browser; wir senden so wenig Inhalt wie möglich mit.', 'push.unavailable': 'Push ist auf diesem Server nicht verfügbar (Schlüssel konnte nicht erstellt werden oder die Abhängigkeit fehlt).', 'push.unsupported': 'Dieser Browser unterstützt keine Push-Benachrichtigungen.', 'push.ios_hint': 'Auf iPhone/iPad funktioniert das nur, wenn die Seite auf deinem Home-Bildschirm liegt: Teilen-Knopf, dann "Zum Home-Bildschirm", und öffne sie danach von dort.', 'push.this_device': 'Dieses Gerät:', 'push.checking': 'prüfen…', 'push.state_on': 'Benachrichtigungen sind an', 'push.state_off': 'Benachrichtigungen sind aus', 'push.state_denied': 'in den Browser-Einstellungen blockiert', 'push.state_unknown': 'Status unbekannt', 'push.state_unsupported': 'nicht unterstützt', 'push.enable': 'Auf diesem Gerät einschalten', 'push.disable': 'Ausschalten', 'push.test': 'Testmeldung senden', 'push.what': 'Wofür möchtest du eine Meldung?', 'push.a_follow': 'Neuer Follower', 'push.a_reply': 'Antwort oder Erwähnung', 'push.a_like': 'Like (Stern)', 'push.a_boost': 'Boost', 'push.a_dm': 'Private Nachricht', 'push.saved': 'Gespeichert.', 'push.devices': 'Verbundene Geräte', 'push.device': 'Gerät', 'push.since': 'seit', 'push.remove': 'Entfernen', 'push.enable_failed': 'Einschalten fehlgeschlagen', 1945 'push.n_follow_t': 'Neuer Follower', 'push.n_follow_b': '{who} folgt dir jetzt', 'push.n_reply_t': 'Antwort auf "{title}"', 'push.n_mention_t': 'Erwähnung', 'push.n_dm_t': 'Private Nachricht', 'push.n_dm_b': 'Neue Nachricht von {who}', 'push.n_like_t': 'Neues Like', 'push.n_like_b': '{who} gefällt "{title}"', 'push.n_boost_t': 'Geboostet', 'push.n_boost_b': '{who} hat "{title}" geboostet', 'msg.guard_offer': 'möchte dein Guardian werden. Besprich das mit deinen Eltern oder Betreuern, bevor du entscheidest.', 'msg.guard_accept': 'Annehmen', 'msg.guard_reject': 'Ablehnen', 'msg.guard_accepted': 'Guardian angenommen. Ihr seid jetzt verbunden.', 'msg.guard_rejected': 'Angebot abgelehnt.', 'msg.guard_failed': 'Das hat nicht geklappt; versuch es erneut.', 'msg.guardians_label': 'Deine Guardians', 'msg.waved_at_you': 'hat dir zugewinkt', 'msg.help_request': 'hat um Hilfe gebeten', 'msg. wave_r1': 'Wie schön!', 'msg.wave_r2': 'Ruf mich an', 'msg.wave_back': '👋 Zurück', 'msg.wave_sent': 'Winken gesendet.', 'guardian.feed_title': 'Deine Wards', 'guardian.feed_sub': 'Lies mit, was deine Wards posten. Nur schauen.', 'guardian.follow_title': 'Follow-Anfragen', 'guardian.follow_sub': 'Jemand möchte einem deiner Wards folgen. Du entscheidest.', 'guardian.wave': '👋 Winken', 'guardian.waved': '👋 gesendet', 'guardian.app_name': 'Klonkt Guardian', 'guardian.tagline': 'Wards verwalten und Hilferufe auffangen.', 'guardian.acting_as': 'Du handelst als', 'guardian.help_title': 'Hilferufe', 'guardian.help_sub': 'Wenn ein Ward die Rettungsboje nutzt, erscheint es hier.', 'guardian.help_empty': 'Keine Hilferufe. Gut so.', 'guardian.adopt_title': 'Ward adoptieren', 'guardian.adopt_sub': 'Gib das Handle des Kindes ein (@kind@server.eu). Es bekommt ein Angebot in seinem Klonkt zum Annehmen.', 'guardian.adopt_label': 'Ward-Handle', 'guardian.adopt_btn': 'Angebot senden', 'guardian.pending_title': 'Gesendete Angebote', 'guardian.pending_sub': 'Warten, bis der Ward annimmt.', 'guardian.wards_title': 'Meine Wards', 'guardian.release_title': '{who} loslassen?', 'guardian.release_effect': 'Du bist dann nicht mehr Guardian. Du siehst ihre Beitraege nicht mehr, erhaeltst keine Hilferufe mehr von ihnen und entscheidest nicht mehr ueber Folgeanfragen fuer sie. Zurueck geht nur mit einem neuen Angebot, das sie annehmen.', 'guardian.release_local': 'Ihr Server und die anderen Guardians werden benachrichtigt, danach stehst du auch dort nicht mehr als Guardian.', 'guardian.release_step_down': 'Sie behalten ihre anderen Guardians und bleiben also Ward.', 'guardian.release_last': 'Du bist ihr letzter Guardian. Das ist Emanzipation, und FEP-633c 3.4 sagt ausdruecklich, dass darueber kein einzelner Guardian entscheidet: dafuer braucht es drei zustimmende Erwachsene oder eine Mehrheit plus zwei Zeugen. Dieser Knopf kann das also nicht: du bleibst ihr Guardian, bis das geregelt ist.', 'guardian.release_unknown': 'Wir konnten ihren Server nicht erreichen und wissen daher nicht, ob du ihr letzter Guardian bist.', 'guardian.release_yes': 'Ja, loslassen', 'guardian.release_no': 'Nein, doch nicht', 'guardian.settings_title': 'Einstellungen', 'guardian.panel_open': 'Ansehen', 'guardian.panel_close': 'Schliessen', 'guardian.panel_help': 'Hilferufe dieses Kindes', 'guardian.panel_help_empty': 'Noch keine Hilferufe.', 'guardian.panel_follow': 'Folgeanfragen', 'guardian.panel_follow_empty': 'Keine offenen Folgeanfragen.', 'guardian.panel_posts': 'Neueste Beitraege', 'guardian.panel_posts_empty': 'Noch nichts zu sehen.', 'guardian.panel_actions': 'Aktionen', 'guardian.badge_help': 'Hilferufe', 'guardian.badge_follow': 'Folgeanfragen', 'guardian.badge_follow_one': 'Folgeanfrage', 'guardian.wards_empty': 'Noch keine Wards. Adoptiere oben eins.', 'guardian.push_title': 'Meldungen', 'guardian.push_sub': 'Erhalte eine Meldung bei einem Hilferuf oder einer Vormundschafts-Antwort, auch bei geschlossener App.', 'guardian.push_on': 'Meldungen einschalten', 'guardian.push_off': 'Meldungen sind an; tippen zum Ausschalten', 'guardian.sent': 'Angebot gesendet. Siehe unten bei Gesendete Angebote.', 'guardian.sent_retry': 'Angebot gespeichert; wir versuchen weiter zuzustellen.', 'guardian.sending': 'Senden…', 'guardian.not_found': 'Dieses Handle konnten wir nicht finden.', 'guardian.failed': 'Fehlgeschlagen', 'guardian.network': 'Netzwerkfehler.', 'guardian.pending': 'wartet auf Antwort', 'guardian.active': 'aktiv', 'guardian.retract': 'Zurückziehen', 'guardian.release': 'Loslassen', 'guardian.embeds_on': 'Linkvorschauen: an', 'guardian.embeds_off': 'Linkvorschauen: aus', 'guardian.embeds_propose': 'Linkvorschauen vorschlagen', 'guardian.embeds_waiting': 'wartet auf die anderen Guardians', 'guardian.release_confirm': '{who} loslassen?\n\nDu bist dann nicht mehr Guardian. Du siehst ihre Beitraege nicht mehr, erhaeltst keine Hilferufe mehr von ihnen und entscheidest nicht mehr ueber Follow-Anfragen fuer sie.\n\nZurueck geht nur mit einem neuen Angebot, das sie annehmen.', 'guardian.open': 'öffnen', 'guardian.accept': 'Annehmen', 'guardian.reject': 'Ablehnen', 'guardian.complete': 'Abschließen', 'guardian.awaiting_others': 'wartet auf die anderen Parteien', 'guardian.coguard': 'Mit-Vormundschaftsangebot', 'guardian.push_unavailable': 'Push nicht verfügbar', 'push.n_help_t': 'Hilferuf', 'push.n_help_b': '{who} bittet um deine Hilfe', 'push.n_guard_offer_t': 'Vormundschaftsangebot', 'push.n_guard_offer_b': '{who} möchte dich als Guardian', 'push.n_guard_ward_t': 'Ward akzeptiert', 'push.n_guard_left_t': 'Ein Guardian ist zurueckgetreten', 'push.n_guard_left_b': '{who} ist nicht mehr dein Guardian', 'push.n_guard_cogleft_t': 'Mit-Guardian zurueckgetreten', 'push.n_guard_cogleft_b': '{who} hat die Guardianship beendet', 'push.n_guard_ward_b': '{who} hat dich als Guardian akzeptiert', 'push.n_guard_cog_t': 'Mit-Vormundschaft gefragt', 'push.n_guard_cog_b': 'Ein Guardian-Angebot für {who} braucht dich', 'push.n_test_t': 'Klonkt-Testmeldung', 'push.n_test_b': 'Funktioniert. So kommen Meldungen auf diesem Gerät an.',1945 'push.n_follow_t': 'Neuer Follower', 'push.n_follow_b': '{who} folgt dir jetzt', 'push.n_reply_t': 'Antwort auf "{title}"', 'push.n_mention_t': 'Erwähnung', 'push.n_dm_t': 'Private Nachricht', 'push.n_dm_b': 'Neue Nachricht von {who}', 'push.n_like_t': 'Neues Like', 'push.n_like_b': '{who} gefällt "{title}"', 'push.n_boost_t': 'Geboostet', 'push.n_boost_b': '{who} hat "{title}" geboostet', 'msg.guard_offer': 'möchte dein Guardian werden. Besprich das mit deinen Eltern oder Betreuern, bevor du entscheidest.', 'msg.guard_accept': 'Annehmen', 'msg.guard_reject': 'Ablehnen', 'msg.guard_accepted': 'Guardian angenommen. Ihr seid jetzt verbunden.', 'msg.guard_rejected': 'Angebot abgelehnt.', 'msg.guard_failed': 'Das hat nicht geklappt; versuch es erneut.', 'msg.guardians_label': 'Deine Guardians', 'msg.waved_at_you': 'hat dir zugewinkt', 'msg.help_request': 'hat um Hilfe gebeten', 'msg.g_available': 'verfuegbar', 'msg.g_away': 'abwesend bis {date}', 'msg.g_offline': 'offline', 'msg.wave_r1': 'Wie schön!', 'msg.wave_r2': 'Ruf mich an', 'msg.wave_back': '👋 Zurück', 'msg.wave_sent': 'Winken gesendet.', 'guardian.feed_title': 'Deine Wards', 'guardian.feed_sub': 'Lies mit, was deine Wards posten. Nur schauen.', 'guardian.follow_title': 'Follow-Anfragen', 'guardian.follow_sub': 'Jemand möchte einem deiner Wards folgen. Du entscheidest.', 'guardian.wave': '👋 Winken', 'guardian.waved': '👋 gesendet', 'guardian.app_name': 'Klonkt Guardian', 'guardian.tagline': 'Wards verwalten und Hilferufe auffangen.', 'guardian.acting_as': 'Du handelst als', 'guardian.help_title': 'Hilferufe', 'guardian.help_sub': 'Wenn ein Ward die Rettungsboje nutzt, erscheint es hier.', 'guardian.help_empty': 'Keine Hilferufe. Gut so.', 'guardian.adopt_title': 'Ward adoptieren', 'guardian.adopt_sub': 'Gib das Handle des Kindes ein (@kind@server.eu). Es bekommt ein Angebot in seinem Klonkt zum Annehmen.', 'guardian.adopt_label': 'Ward-Handle', 'guardian.adopt_btn': 'Angebot senden', 'guardian.pending_title': 'Gesendete Angebote', 'guardian.pending_sub': 'Warten, bis der Ward annimmt.', 'guardian.wards_title': 'Meine Wards', 'guardian.avail_available': 'Verfuegbar', 'guardian.avail_away': 'Abwesend bis {date}', 'guardian.avail_dormant': 'Offline', 'guardian.panel_guards': 'Guardians dieses Kindes', 'guardian.panel_guards_remote': 'Dieses Kind lebt auf einem anderen Server; die Verfuegbarkeit wird dort gefuehrt.', 'guardian.lapse_propose': 'Vorschlag: Freigabe in Abwesenheit', 'guardian.lapse_line': '{who} antwortet nicht mehr als Guardian von {ward}.', 'guardian.lapse_tally': '{n} von {need} einverstanden; schliesst {date}; das Fenster laeuft immer voll.', 'guardian.lapse_note': 'Jedes Lebenszeichen von ihnen bricht dies sofort ab. Nichts hier ist Strafe.', 'guardian.lapse_agree': 'Einverstanden', 'guardian.lapse_disagree': 'Nicht einverstanden', 'guardian.voted': 'Du hast abgestimmt', 'guardian.away_title': 'Kurz abwesend', 'guardian.away_sub': 'Sag deinen Wards, dass du eine Weile nicht da bist. Entscheidungen warten nicht auf dich, und eine einzige Antwort bringt dich sofort zurueck.', 'guardian.away_week': 'Eine Woche', 'guardian.away_month': 'Ein Monat', 'guardian.away_done': 'Deine Wards wissen, dass du bis {date} abwesend bist.', 'guardian.away_msg': 'Ich bin als dein Guardian bis {date} abwesend. Deine anderen Guardians sind fuer dich da.', 'guardian.release_title': '{who} loslassen?', 'guardian.release_effect': 'Du bist dann nicht mehr Guardian. Du siehst ihre Beitraege nicht mehr, erhaeltst keine Hilferufe mehr von ihnen und entscheidest nicht mehr ueber Folgeanfragen fuer sie. Zurueck geht nur mit einem neuen Angebot, das sie annehmen.', 'guardian.release_local': 'Ihr Server und die anderen Guardians werden benachrichtigt, danach stehst du auch dort nicht mehr als Guardian.', 'guardian.release_step_down': 'Sie behalten ihre anderen Guardians und bleiben also Ward.', 'guardian.release_last': 'Du bist ihr letzter Guardian. Das ist Emanzipation, und FEP-633c 3.4 sagt ausdruecklich, dass darueber kein einzelner Guardian entscheidet: dafuer braucht es drei zustimmende Erwachsene oder eine Mehrheit plus zwei Zeugen. Dieser Knopf kann das also nicht: du bleibst ihr Guardian, bis das geregelt ist.', 'guardian.release_unknown': 'Wir konnten ihren Server nicht erreichen und wissen daher nicht, ob du ihr letzter Guardian bist.', 'guardian.release_yes': 'Ja, loslassen', 'guardian.release_no': 'Nein, doch nicht', 'guardian.settings_title': 'Einstellungen', 'guardian.panel_open': 'Ansehen', 'guardian.panel_close': 'Schliessen', 'guardian.panel_help': 'Hilferufe dieses Kindes', 'guardian.panel_help_empty': 'Noch keine Hilferufe.', 'guardian.panel_follow': 'Folgeanfragen', 'guardian.panel_follow_empty': 'Keine offenen Folgeanfragen.', 'guardian.panel_posts': 'Neueste Beitraege', 'guardian.panel_posts_empty': 'Noch nichts zu sehen.', 'guardian.panel_actions': 'Aktionen', 'guardian.badge_help': 'Hilferufe', 'guardian.badge_follow': 'Folgeanfragen', 'guardian.badge_follow_one': 'Folgeanfrage', 'guardian.wards_empty': 'Noch keine Wards. Adoptiere oben eins.', 'guardian.push_title': 'Meldungen', 'guardian.push_sub': 'Erhalte eine Meldung bei einem Hilferuf oder einer Vormundschafts-Antwort, auch bei geschlossener App.', 'guardian.push_on': 'Meldungen einschalten', 'guardian.push_off': 'Meldungen sind an; tippen zum Ausschalten', 'guardian.sent': 'Angebot gesendet. Siehe unten bei Gesendete Angebote.', 'guardian.sent_retry': 'Angebot gespeichert; wir versuchen weiter zuzustellen.', 'guardian.sending': 'Senden…', 'guardian.not_found': 'Dieses Handle konnten wir nicht finden.', 'guardian.failed': 'Fehlgeschlagen', 'guardian.network': 'Netzwerkfehler.', 'guardian.pending': 'wartet auf Antwort', 'guardian.active': 'aktiv', 'guardian.retract': 'Zurückziehen', 'guardian.release': 'Loslassen', 'guardian.embeds_on': 'Linkvorschauen: an', 'guardian.embeds_off': 'Linkvorschauen: aus', 'guardian.embeds_propose': 'Linkvorschauen vorschlagen', 'guardian.embeds_waiting': 'wartet auf die anderen Guardians', 'guardian.release_confirm': '{who} loslassen?\n\nDu bist dann nicht mehr Guardian. Du siehst ihre Beitraege nicht mehr, erhaeltst keine Hilferufe mehr von ihnen und entscheidest nicht mehr ueber Follow-Anfragen fuer sie.\n\nZurueck geht nur mit einem neuen Angebot, das sie annehmen.', 'guardian.open': 'öffnen', 'guardian.accept': 'Annehmen', 'guardian.reject': 'Ablehnen', 'guardian.complete': 'Abschließen', 'guardian.awaiting_others': 'wartet auf die anderen Parteien', 'guardian.coguard': 'Mit-Vormundschaftsangebot', 'guardian.push_unavailable': 'Push nicht verfügbar', 'push.n_help_t': 'Hilferuf', 'push.n_help_b': '{who} bittet um deine Hilfe', 'push.n_guard_offer_t': 'Vormundschaftsangebot', 'push.n_guard_offer_b': '{who} möchte dich als Guardian', 'push.n_guard_ward_t': 'Ward akzeptiert', 'push.n_guard_left_t': 'Ein Guardian ist zurueckgetreten', 'push.n_guard_left_b': '{who} ist nicht mehr dein Guardian', 'push.n_guard_cogleft_t': 'Mit-Guardian zurueckgetreten', 'push.n_guard_cogleft_b': '{who} hat die Guardianship beendet', 'push.n_guard_ward_b': '{who} hat dich als Guardian akzeptiert', 'push.n_guard_cog_t': 'Mit-Vormundschaft gefragt', 'push.n_guard_cog_b': 'Ein Guardian-Angebot für {who} braucht dich', 'push.n_test_t': 'Klonkt-Testmeldung', 'push.n_test_b': 'Funktioniert. So kommen Meldungen auf diesem Gerät an.', 1946 1946 'apaid.t': 'Bezahlte Beiträge', 'apaid.intro': 'Verbinde deine eigene Patreon-Kampagne. Unterstützer entsperren bezahlte Beiträge mit einem Passkey, ohne Konto und ohne Cookie. Wir speichern keine Namen oder E-Mail-Adressen von Unterstützern, nur das verschlüsselte Token deiner Kampagne.', 'apaid.saved': 'Gespeichert.', 'apaid.nokey': 'Achtung: der Verschlüsselungsschlüssel konnte nicht erstellt oder gelesen werden (Schreibrechte auf dem Speicherordner?). Ohne Schlüssel können Secrets nicht sicher gespeichert werden.', 'apaid.status': 'Status:', 'apaid.connected': 'verbunden', 'apaid.campaign': 'Kampagne', 'apaid.configured': 'eingerichtet, noch nicht verbunden (Token eintragen)', 'apaid.notyet': 'noch nicht eingerichtet', 'apaid.redirect_h': 'Trage diese Redirect-URI in deinen Patreon-Client ein', 'apaid.redirect_p': 'In deinem Patreon-API-Client muss unter Redirect URIs genau diese Zeile stehen. Stimmt sie nicht, zeigt Patreon eine Fehlermeldung statt deine Unterstützer zurückzuschicken.', 'apaid.copy': 'Kopieren', 'apaid.copied': 'Kopiert', 'apaid.client_id': 'Patreon Client-ID', 'apaid.client_secret': 'Patreon Client-Secret', 'apaid.keep': 'Leer lassen = aktuellen Wert behalten.', 'apaid.campaign_id': 'Kampagnen-ID', 'apaid.public_page': 'Öffentliche Patreon-Seite', 'apaid.public_help': 'Der Link, unter dem Besucher Unterstützer werden können. Wird als "Unterstützer werden" gezeigt, wenn jemand noch nicht spendet.', 'apaid.access': 'Creator Access-Token', 'apaid.refresh': 'Creator Refresh-Token', 'apaid.token_help': 'Access- und Refresh-Token bekommst du auf deiner Patreon-API-Client-Seite. Wir verschlüsseln sie und erneuern automatisch.', 'apaid.min_eur': 'Standard-Unterstützungsbetrag für einen bezahlten Beitrag (Euro)', 'apaid.save': 'Speichern', 'apaid.disconnect': 'Verbindung entfernen', 'apaid.disconnect_confirm': 'Patreon-Verbindung entfernen?', 'apaid.unchanged': 'bleibt unverändert', 1947 1947 'pgate.h': 'Für Unterstützer', 'pgate.sub': 'Dieser Beitrag ist für Unterstützer dieser Seite. Werde Unterstützer und entsperre ihn danach mit einem Passkey. Kein Konto auf dieser Seite, kein Cookie.', 'pgate.sub_cents': 'Dieser Beitrag ist für Unterstützer dieser Seite (ab €{eur} pro Monat auf Patreon). Werde Unterstützer und entsperre ihn danach mit einem Passkey. Kein Konto auf dieser Seite, kein Cookie.', 'pgate.join': 'Unterstützer werden auf Patreon', 'pgate.unlock_have': 'Schon Unterstützer? Entsperren', 'pgate.unlock': 'Mit Patreon entsperren', 'pgate.join_short': 'Unterstützer werden', 'pgate.confirm': 'Bestätige mit deinem Passkey…', 'pgate.failed': 'Entsperren fehlgeschlagen. Versuch es erneut.', 'pgate.error': 'Etwas ist schiefgegangen. Versuch es erneut.', -
src/views/pages/guardian.ejs
r6eab7e9 r0202104 73 73 </section> 74 74 75 <!-- 4b. Even afwezig (FEP-633c 3.6.1): de verantwoordelijke handeling. 76 Wie zich afmeldt telt niet mee in de besluiten, en een enkel 77 antwoord brengt je meteen terug. Alleen zichtbaar met wards. --> 78 <section id="away-section" hidden> 79 <div class="g-sec-head"><h2><%= t('guardian.away_title') %></h2></div> 80 <p class="g-sec-sub"><%= t('guardian.away_sub') %></p> 81 <div class="g-away-row"> 82 <button id="away-week" class="quiet small"><%= t('guardian.away_week') %></button> 83 <button id="away-month" class="quiet small"><%= t('guardian.away_month') %></button> 84 </div> 85 <p id="away-msg" class="g-msg" hidden></p> 86 </section> 87 75 88 <!-- 5. Meldingen. --> 76 89 <section id="push-section"> -
src/views/pages/messages.ejs
r6eab7e9 r0202104 30 30 <div style="flex:1;min-width:200px;"> 31 31 <strong><%= t('msg.guardians_label') %></strong><br> 32 <span><%= myGuardians.map(function(g){ return g.handle; }).join(', ') %></span> 32 <%# Availability (FEP-633c 3.6): the ward sees the real size of its 33 safety net, in buddy-list language on the responsibility axis. 34 Labels are UI (Robins besluit); the wire keeps the spec terms. 35 Owner-only by construction: this page is the owner's. %> 36 <span class="msg-guardians"> 37 <% myGuardians.forEach(function(g){ 38 var _st = g.availability === 'away' ? 'away' : (g.availability === 'dormant' ? 'dormant' : 'active'); 39 var _lbl = _st === 'away' ? t('msg.g_away', { date: g.awayUntil ? formatDate(g.awayUntil) : '?' }) 40 : (_st === 'dormant' ? t('msg.g_offline') : t('msg.g_available')); %> 41 <span class="msg-guardian"> 42 <span class="msg-gdot msg-gdot-<%= _st %>" aria-hidden="true"></span> 43 <%= g.handle %> 44 <span class="msg-gstate"><%= _lbl %></span> 45 </span> 46 <% }); %> 47 </span> 33 48 </div> 34 49 </div> … … 130 145 131 146 <style> 147 /* Availability of the ward's guardians (FEP-633c 3.6): the buddy-list dot 148 on the responsibility axis. Green available, yellow declared away, grey 149 observed dormant (one answer restores). */ 150 .msg-guardians { display: flex; flex-wrap: wrap; gap: .35rem 1rem; } 151 .msg-guardian { display: inline-flex; align-items: center; gap: .35rem; white-space: nowrap; } 152 .msg-gdot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; } 153 .msg-gdot-active { background: #4caf7d; } 154 .msg-gdot-away { background: #e0a83a; } 155 .msg-gdot-dormant { background: #8a93a3; } 156 .msg-gstate { color: var(--ink-soft, #888); font-size: .82rem; } 132 157 .msg-wrap { max-width: 640px; margin: 1rem auto; padding: 0 1rem; } 133 158 .msg-title { margin: 0 0 .9rem; }
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)