Ignore:
Timestamp:
06/21/2026 02:32:39 PM (3 months ago)
Author:
roboburr <roboburr@…>
Branches:
main
Children:
4885eab
Parents:
929d98d
Message:

feat(i18n phase 5): all admin sub-pages translated (NL/EN/DE)

settings, site-edit, seo, google, audio, stats, playlists, users, sites,
comments, circle, shows, newsletter, updates, epk, help. ~520 new keys
per language. Loop-shadowing of t() resolved by fetching before the loop. 709
view-keys cross-checked against the dictionary (0 missing).

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

File:
1 edited

Legend:

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

    r929d98d rbbf9d1a  
    1010  <header class="ax-header">
    1111    <div>
    12       <h1>Playlists</h1>
     12      <h1><%= t('apl.title') %></h1>
    1313      <p class="ax-tagline">
    14         Canonieke playlists. Bewerk een playlist hier en de wijzigingen werken
    15         door in álle posts die hem gebruiken via <code>[[playlist:&lt;id&gt;]]</code>.
     14        <%= t('apl.tagline_pre') %> <code>[[playlist:&lt;id&gt;]]</code><%= t('apl.tagline_post') %>
    1615      </p>
    1716    </div>
     
    2120  <div class="ax-actions-bar">
    2221    <button type="button" class="ax-btn ax-btn-primary" id="pl-new-btn">
    23       + Nieuwe playlist
     22      + <%= t('apl.new_playlist') %>
    2423    </button>
    2524  </div>
     
    2928      <div class="ax-empty">
    3029        <div class="ax-empty-icon">📃</div>
    31         <p>Nog geen playlists.</p>
    32         <p class="ax-empty-sub">Maak er een via de knop hierboven, of via de 📃 knop in de post-editor.</p>
     30        <p><%= t('apl.none') %></p>
     31        <p class="ax-empty-sub"><%= t('apl.none_sub') %></p>
    3332      </div>
    3433    </div>
    3534  <% } else { %>
     35    <%
     36      // Pre-fetch loop labels (defensive — keep `t` calls out of the loop body).
     37      var _aplPlaylist = t('apl.pill_playlist');
     38      var _aplAlbum    = t('apl.pill_album');
     39      var _aplTrack    = t('apl.track');
     40      var _aplTracks   = t('apl.tracks');
     41      var _aplCopy     = t('apl.copy_click');
     42      var _aplEdit     = t('apl.edit');
     43      var _aplDelete   = t('apl.delete');
     44    %>
    3645    <ul class="ax-list">
    3746      <% playlists.forEach(function(p) { %>
     
    4453            <div class="ax-track-title">
    4554              <%= p.title %>
    46               <span class="ax-pill"><%= p.kind === 'playlist' ? '📃 playlist' : '💿 album' %></span>
     55              <span class="ax-pill"><%= p.kind === 'playlist' ? '📃 ' + _aplPlaylist : '💿 ' + _aplAlbum %></span>
    4756            </div>
    4857            <div class="ax-track-sub">
    49               <span><%= p.track_count %> <%= p.track_count === 1 ? 'track' : 'tracks' %></span>
     58              <span><%= p.track_count %> <%= p.track_count === 1 ? _aplTrack : _aplTracks %></span>
    5059              <% if (p.artist) { %><span class="ax-track-sep">·</span><span><%= p.artist %></span><% } %>
    5160              <% if (p.year) { %><span class="ax-track-sep">·</span><span><%= p.year %></span><% } %>
    5261            </div>
    53             <code class="ax-embed" data-copy="[[playlist:<%= p.id %>]]" title="Klik om te kopiëren">[[playlist:<%= p.id %>]]</code>
     62            <code class="ax-embed" data-copy="[[playlist:<%= p.id %>]]" title="<%= _aplCopy %>">[[playlist:<%= p.id %>]]</code>
    5463          </div>
    5564
    5665          <div class="ax-track-actions">
    57             <button type="button" class="ax-icon-btn" data-pl-edit data-id="<%= p.id %>" aria-label="Bewerken" title="Bewerken">✎</button>
    58             <button type="button" class="ax-icon-btn ax-icon-btn-danger" data-pl-delete data-id="<%= p.id %>" data-title="<%= p.title %>" aria-label="Verwijderen" title="Verwijderen">🗑</button>
     66            <button type="button" class="ax-icon-btn" data-pl-edit data-id="<%= p.id %>" aria-label="<%= _aplEdit %>" title="<%= _aplEdit %>">✎</button>
     67            <button type="button" class="ax-icon-btn ax-icon-btn-danger" data-pl-delete data-id="<%= p.id %>" data-title="<%= p.title %>" aria-label="<%= _aplDelete %>" title="<%= _aplDelete %>">🗑</button>
    5968          </div>
    6069        </li>
     
    229238        el.classList.add('is-copied');
    230239        const original = el.textContent;
    231         el.textContent = '✓ gekopieerd';
     240        el.textContent = '✓ <%= t('apl.copied') %>';
    232241        setTimeout(() => { el.classList.remove('is-copied'); el.textContent = original; }, 1200);
    233242      } catch (_) { /* fall back to selection */ }
     
    247256      const id = btn.dataset.id;
    248257      const title = btn.dataset.title || id;
    249       if (!confirm(`Playlist "${title}" verwijderen? Posts die deze playlist embedden tonen vanaf nu een placeholder.`)) return;
     258      if (!confirm('<%= t('apl.delete_confirm') %>'.replace('{title}', title))) return;
    250259      try {
    251260        const r = await fetch(`/admin/playlists/api/${encodeURIComponent(id)}/delete`, {
     
    256265        const j = await r.json();
    257266        if (j.ok) location.reload();
    258         else alert('Verwijderen mislukt: ' + (j.error || ''));
     267        else alert('<%= t('apl.delete_failed') %>: ' + (j.error || ''));
    259268      } catch (err) {
    260         alert('Verwijderen mislukt: ' + err.message);
     269        alert('<%= t('apl.delete_failed') %>: ' + err.message);
    261270      }
    262271    });
Note: See TracChangeset for help on using the changeset viewer.