Polish light theme and translations
This commit is contained in:
+101
-27
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user