feat(i18n): Progress-Popup + Pipeline-Stati lokalisieren

- components._getStepLabel und progress-popup-title nutzen T()
  fuer Erste Recherche laeuft / Aktualisierung laeuft / In Warteschlange
  / Wird abgebrochen.
- pipeline._formatHeader / _relativeTime / _formatCount lokalisiert:
  Status-Texte (erledigt/laeuft/Fehler), Zeitangaben (gerade eben,
  vor X Min/Std/Tagen), Aktualisierung-laeuft-Header.
- dashboard.html: data-i18n auf pipeline-empty, progress-popup-title,
  progress-check-label (4 Stueck).
- Cache-Buster fuer components.js + pipeline.js auf v=20260513d.
Dieser Commit ist enthalten in:
Claude Code
2026-05-13 21:45:18 +00:00
Ursprung b214249a34
Commit 9e3c9559d9
5 geänderte Dateien mit 114 neuen und 31 gelöschten Zeilen

Datei anzeigen

@@ -254,7 +254,8 @@ const Pipeline = {
// Brandneue Lage ohne Refresh
if (!this._lastRefreshHeader) {
this._renderEmpty('Noch nie aktualisiert. Starte den ersten Refresh.');
const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
this._renderEmpty(_t('pipeline.empty', 'Noch nie aktualisiert. Starte den ersten Refresh.'));
return;
}
@@ -502,20 +503,22 @@ const Pipeline = {
_formatHeader() {
const r = this._lastRefreshHeader;
if (!r) return '';
const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
const lastLabel = _t('pipeline.last_refresh', 'Letzter Refresh');
let parts = [];
if (r.started_at) {
const rel = this._relativeTime(r.started_at);
parts.push(rel ? `Letzter Refresh: ${rel}` : `Letzter Refresh: ${r.started_at}`);
parts.push(rel ? `${lastLabel}: ${rel}` : `${lastLabel}: ${r.started_at}`);
}
if (r.duration_sec != null) {
parts.push(`Dauer: ${r.duration_sec} s`);
parts.push(`${_t('pipeline.duration_prefix', 'Dauer:')} ${r.duration_sec} s`);
}
if (r.status === 'running') {
parts = ['Aktualisierung läuft...'];
parts = [_t('pipeline.running', 'Aktualisierung läuft...')];
} else if (r.status === 'cancelled') {
parts.push('abgebrochen');
parts.push(_t('pipeline.cancelled', 'abgebrochen'));
} else if (r.status === 'error') {
parts.push('mit Fehler beendet');
parts.push(_t('pipeline.with_errors', 'mit Fehler beendet'));
}
return parts.join(' · ');
},
@@ -527,28 +530,34 @@ const Pipeline = {
if (isNaN(d.getTime())) return '';
const diffMs = Date.now() - d.getTime();
const min = Math.floor(diffMs / 60000);
if (min < 1) return 'gerade eben';
if (min < 60) return `vor ${min} Min`;
const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
if (min < 1) return _t('time.just_now', 'gerade eben');
if (min < 60) return _t('time.minutes_ago', 'vor {n} Min').replace('{n}', min);
const h = Math.floor(min / 60);
if (h < 24) return `vor ${h} Std`;
if (h < 24) return _t('time.hours_ago', 'vor {n} Std').replace('{n}', h);
const days = Math.floor(h / 24);
return `vor ${days} Tag${days === 1 ? '' : 'en'}`;
if (days === 1) return _t('time.day_ago', 'vor 1 Tag');
return _t('time.days_ago', 'vor {n} Tagen').replace('{n}', days);
} catch (e) {
return '';
}
},
_formatCount(stepKey, cv, cs, status) {
const _t = (k, fb) => (typeof T === 'function') ? T(k, fb) : fb;
const sDone = _t('pipeline.status.done', 'erledigt');
const sRun = _t('pipeline.status.running', 'läuft...');
const sErr = _t('pipeline.status.error', 'Fehler');
// Qualitaetscheck: KEINE Zahlen, nur Status (Anforderung 3 vom User)
if (stepKey === 'qc' || stepKey === 'summary') {
if (status === 'done') return '<span class="count-status">erledigt</span>';
if (status === 'active') return '<span class="count-status">läuft...</span>';
if (status === 'error') return '<span class="count-status">Fehler</span>';
if (status === 'done') return `<span class="count-status">${sDone}</span>`;
if (status === 'active') return `<span class="count-status">${sRun}</span>`;
if (status === 'error') return `<span class="count-status">${sErr}</span>`;
return '<span class="count-status">-</span>';
}
if (status === 'pending') return '<span class="count-status">-</span>';
if (status === 'active') return '<span class="count-status">läuft...</span>';
if (status === 'error') return '<span class="count-status">Fehler</span>';
if (status === 'active') return `<span class="count-status">${sRun}</span>`;
if (status === 'error') return `<span class="count-status">${sErr}</span>`;
if (cv == null) return '<span class="count-status">-</span>';
switch (stepKey) {