Polish light theme and translations

This commit is contained in:
seo
2026-06-07 18:02:10 +09:00
parent 7af96612ab
commit bafdd2d35c
2 changed files with 114 additions and 38 deletions
+101 -27
View File
@@ -85,6 +85,11 @@
systemStatus: 'System Status',
loadAvg: 'Load Avg',
activeUsers: 'Active Users',
diskRoot: 'Disk /',
memory: 'Memory',
uptime: 'Uptime',
batteryV: 'Battery V',
batterySoc: 'Battery SOC',
sensorHistory: 'Sensor History',
temperature: 'Temperature',
rp1Temp: 'RP1 Temp',
@@ -131,6 +136,23 @@
average: 'Average',
current: 'Current',
causeCandidate: 'Candidate',
hostLabel: 'Host',
ipLabel: 'IP',
created: 'Created',
encoding: 'Encoding',
endpoint: 'Endpoint',
userAgent: 'UA',
hash: 'Hash',
na: 'N/A',
max: 'MAX',
avg: 'AVG',
min: 'MIN',
minuteAgo: ({ minutes }) => `${minutes}m ago`,
health_healthy: 'Healthy',
health_watch: 'Watch',
health_stale: 'Stale',
health_failed: 'Failed',
health_pending: 'Pending',
pushSummary: ({ total, healthy, watch, stale, failed, pending }) => `Push devices: ${total} total / ${healthy} healthy / ${watch} watch / ${stale} stale / ${failed} failed / ${pending} pending`,
statusUnsupported: 'Push status: browser unsupported',
statusDenied: 'Push status: permission denied',
@@ -198,6 +220,11 @@
systemStatus: '시스템 상태',
loadAvg: '부하 평균',
activeUsers: '활성 사용자',
diskRoot: 'Disk /',
memory: '메모리',
uptime: '가동 시간',
batteryV: '배터리 전압',
batterySoc: '배터리 SOC',
sensorHistory: '센서 이력',
temperature: '온도',
rp1Temp: 'RP1 온도',
@@ -244,7 +271,24 @@
average: '평균',
current: '현재',
causeCandidate: '원인 후보',
pushSummary: ({ total, healthy, watch, stale, failed, pending }) => `Push devices: ${total} total / ${healthy} healthy / ${watch} watch / ${stale} stale / ${failed} failed / ${pending} pending`,
hostLabel: '호스트',
ipLabel: 'IP',
created: '생성',
encoding: '인코딩',
endpoint: 'Endpoint',
userAgent: 'UA',
hash: 'Hash',
na: 'N/A',
max: '최대',
avg: '평균',
min: '최소',
minuteAgo: ({ minutes }) => `${minutes}분 전`,
health_healthy: '정상',
health_watch: '주의',
health_stale: '장기 미수신',
health_failed: '실패',
health_pending: '수신 대기',
pushSummary: ({ total, healthy, watch, stale, failed, pending }) => `Push 기기: 총 ${total} / 정상 ${healthy} / 주의 ${watch} / 장기 미수신 ${stale} / 실패 ${failed} / 대기 ${pending}`,
statusUnsupported: 'Push 상태: 브라우저 미지원',
statusDenied: 'Push 상태: 권한 꺼짐',
statusUngrant: 'Push 상태: 권한 미허용',
@@ -311,6 +355,11 @@
}
window.controlT = t;
function pushHealthText(status, fallback = '') {
const key = `health_${status || 'pending'}`;
return messages[state.lang]?.[key] ?? messages.en[key] ?? fallback ?? t('pendingReceive');
}
function applyTheme(theme) {
state.theme = theme === 'light' ? 'light' : 'dark';
localStorage.setItem(storageKeys.theme, state.theme);
@@ -692,10 +741,17 @@
const secs = totalSeconds % 60;
const parts = [];
if (days > 0) parts.push(`${days}d`);
if (days > 0 || hours > 0) parts.push(`${hours}h`);
if (days > 0 || hours > 0 || minutes > 0) parts.push(`${minutes}m`);
parts.push(`${secs}s`);
if (state.lang === 'ko') {
if (days > 0) parts.push(`${days}`);
if (days > 0 || hours > 0) parts.push(`${hours}`);
if (days > 0 || hours > 0 || minutes > 0) parts.push(`${minutes}`);
parts.push(`${secs}`);
} else {
if (days > 0) parts.push(`${days}d`);
if (days > 0 || hours > 0) parts.push(`${hours}h`);
if (days > 0 || hours > 0 || minutes > 0) parts.push(`${minutes}m`);
parts.push(`${secs}s`);
}
return parts.join(' ');
}
@@ -921,27 +977,32 @@
}
els.pushDeviceList.innerHTML = devices.length
? devices.map(device => `
<div class="push-device-row ${escapeHtml(device.health_status || 'pending')}">
? devices.map(device => {
const healthStatus = device.health_status || 'pending';
const healthText = pushHealthText(healthStatus, device.health_text);
return `
<div class="push-device-row ${escapeHtml(healthStatus)}">
<div class="push-device-main">
<strong>${escapeHtml(device.device_name || t('unnamed'))}</strong>
<span class="push-device-badge ${escapeHtml(device.health_status || 'pending')}">${escapeHtml(device.health_text || t('pendingReceive'))}</span>
<span>Host: ${escapeHtml(device.host || 'unknown')}</span>
<span>IP: ${escapeHtml(device.actor_ip || '-')}</span>
<span>Created: ${escapeHtml(device.created_at || '-')}</span>
<span class="push-device-badge ${escapeHtml(healthStatus)}">${escapeHtml(healthText)}</span>
<span>${escapeHtml(t('hostLabel'))}: ${escapeHtml(device.host || 'unknown')}</span>
<span>${escapeHtml(t('ipLabel'))}: ${escapeHtml(device.actor_ip || '-')}</span>
<span>${escapeHtml(t('created'))}: ${escapeHtml(device.created_at || '-')}</span>
<span>${escapeHtml(t('registeredRefresh'))}: ${escapeHtml(device.last_seen_at || '-')} (${escapeHtml(timeAgo(device.last_seen_seconds))})</span>
<span>${escapeHtml(t('lastSendSuccess'))}: ${escapeHtml(device.last_send_success_at || '-')} (${escapeHtml(timeAgo(device.last_send_success_seconds))})</span>
<span>${escapeHtml(t('lastReceived'))}: ${escapeHtml(device.last_received_at || '-')} (${escapeHtml(timeAgo(device.last_received_seconds))})</span>
<span>${escapeHtml(t('lastShown'))}: ${escapeHtml(device.last_notification_at || '-')} (${escapeHtml(timeAgo(device.last_notification_seconds))})</span>
<span>${escapeHtml(t('lastClick'))}: ${escapeHtml(device.last_click_at || '-')}</span>
<span>${escapeHtml(t('failures'))}: ${Number(device.failure_count || 0).toLocaleString()}${device.last_failure_reason ? ` / ${escapeHtml(device.last_failure_reason)}` : ''}</span>
<span>Encoding: ${escapeHtml(device.content_encoding || '-')}</span>
<span>Hash: ${escapeHtml(device.hash || '-')}</span>
<span>Endpoint: ${escapeHtml(device.endpoint || '-')}</span>
<span>UA: ${escapeHtml(device.user_agent || t('unknownDevice'))}</span>
<span>${escapeHtml(t('encoding'))}: ${escapeHtml(device.content_encoding || '-')}</span>
<span>${escapeHtml(t('hash'))}: ${escapeHtml(device.hash || '-')}</span>
<span>${escapeHtml(t('endpoint'))}: ${escapeHtml(device.endpoint || '-')}</span>
<span>${escapeHtml(t('userAgent'))}: ${escapeHtml(device.user_agent || t('unknownDevice'))}</span>
</div>
</div>
`).join('')
`;
}).join('')
: `<div class="spike-log-empty">${escapeHtml(t('noPushDevices'))}</div>`;
}
@@ -1082,15 +1143,27 @@
const minutes = Math.floor((totalSeconds % 3600) / 60);
const parts = [];
if (days > 0) {
parts.push(`${days}`);
}
if (state.lang === 'ko') {
if (days > 0) {
parts.push(`${days}`);
}
if (days > 0 || hours > 0) {
parts.push(`${hours}`);
}
if (days > 0 || hours > 0) {
parts.push(`${hours}`);
}
parts.push(`${minutes}`);
parts.push(`${minutes}`);
} else {
if (days > 0) {
parts.push(`${days}d`);
}
if (days > 0 || hours > 0) {
parts.push(`${hours}h`);
}
parts.push(`${minutes}m`);
}
return parts.join(' ');
}
@@ -1125,7 +1198,7 @@
}
});
if (bestIndex >= 0 && bestDistance <= 15) {
xTickMarkers.set(bestIndex, `${targetAge / 60}m ago`);
xTickMarkers.set(bestIndex, t('minuteAgo', { minutes: targetAge / 60 }));
}
});
const isXGridTick = index => {
@@ -1206,9 +1279,9 @@
? '-'
: `${Number(value).toLocaleString(undefined, { maximumFractionDigits: 2 })}${suffix}`;
return [
`MAX: ${format(max)}`,
`AVG: ${format(avg)}`,
`MIN: ${format(min)}`,
`${t('max')}: ${format(max)}`,
`${t('avg')}: ${format(avg)}`,
`${t('min')}: ${format(min)}`,
];
},
label: () => null,
@@ -1538,6 +1611,7 @@
els.translateBtn?.addEventListener('click', () => {
applyLang(state.lang === 'ko' ? 'en' : 'ko');
refreshPushDevices(true);
refreshStatus();
});
els.themeBtn?.addEventListener('click', () => {
applyTheme(state.theme === 'dark' ? 'light' : 'dark');