fix(i18n): relative-time strings vollständig lokalisiert
relativeTime() in Dashboard, relTime() in WireGuard Clients+Servers und
CertExpiry() im Cluster-Page haben bisher hardcodiertes Deutsch
(„vor 5s", „abgelaufen vor X Tagen") gerendert, unabhängig von der
gewählten UI-Sprache.
Neu: gemeinsame i18n-Keys common.relTime.{Xs,Xm,Xh,Xd,never} in EN+DE,
sowie cluster.{certDaysRemaining,certExpiredDaysAgo}. Alle Helper-
Funktionen nehmen jetzt t() als Parameter und sind damit sprachunabhängig.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,13 +39,13 @@ function fmtBytes(n: number): string {
|
||||
while (v >= 1024 && i < u.length - 1) { v /= 1024; i++ }
|
||||
return `${v.toFixed(1)} ${u[i]}`
|
||||
}
|
||||
function relTime(unix: number, never: string): string {
|
||||
if (!unix) return never
|
||||
function relTime(unix: number, t: (k: string, v?: Record<string, unknown>) => string): string {
|
||||
if (!unix) return t('common.relTime.never')
|
||||
const sec = Math.max(0, Math.floor(Date.now() / 1000) - unix)
|
||||
if (sec < 60) return `${sec}s ago`
|
||||
if (sec < 3600) return `${Math.floor(sec / 60)}m ago`
|
||||
if (sec < 86400) return `${Math.floor(sec / 3600)}h ago`
|
||||
return `${Math.floor(sec / 86400)}d ago`
|
||||
if (sec < 60) return t('common.relTime.Xs', { n: sec })
|
||||
if (sec < 3600) return t('common.relTime.Xm', { n: Math.floor(sec / 60) })
|
||||
if (sec < 86400) return t('common.relTime.Xh', { n: Math.floor(sec / 3600) })
|
||||
return t('common.relTime.Xd', { n: Math.floor(sec / 86400) })
|
||||
}
|
||||
|
||||
interface ClientForm {
|
||||
@@ -145,7 +145,7 @@ export default function ClientsTab() {
|
||||
{live && (
|
||||
<Tooltip title={`▼${fmtBytes(live.transfer_rx)} ▲${fmtBytes(live.transfer_tx)}`}>
|
||||
<Text type="secondary" style={{ fontSize: 11 }}>
|
||||
{relTime(live.last_handshake_unix, t('wg.peer.never'))}
|
||||
{relTime(live.last_handshake_unix, t)}
|
||||
</Text>
|
||||
</Tooltip>
|
||||
)}
|
||||
|
||||
@@ -79,13 +79,13 @@ function fmtBytes(n: number): string {
|
||||
while (v >= 1024 && i < u.length - 1) { v /= 1024; i++ }
|
||||
return `${v.toFixed(1)} ${u[i]}`
|
||||
}
|
||||
function relTime(unix: number, never: string): string {
|
||||
if (!unix) return never
|
||||
function relTime(unix: number, t: (k: string, v?: Record<string, unknown>) => string): string {
|
||||
if (!unix) return t('common.relTime.never')
|
||||
const sec = Math.max(0, Math.floor(Date.now() / 1000) - unix)
|
||||
if (sec < 60) return `vor ${sec}s`
|
||||
if (sec < 3600) return `vor ${Math.floor(sec / 60)}m`
|
||||
if (sec < 86400) return `vor ${Math.floor(sec / 3600)}h`
|
||||
return `vor ${Math.floor(sec / 86400)}d`
|
||||
if (sec < 60) return t('common.relTime.Xs', { n: sec })
|
||||
if (sec < 3600) return t('common.relTime.Xm', { n: Math.floor(sec / 60) })
|
||||
if (sec < 86400) return t('common.relTime.Xh', { n: Math.floor(sec / 3600) })
|
||||
return t('common.relTime.Xd', { n: Math.floor(sec / 86400) })
|
||||
}
|
||||
|
||||
interface FwZoneLite { name: string; builtin: boolean }
|
||||
@@ -405,7 +405,7 @@ function PeerDrawer({ iface, onClose }: PeerDrawerProps) {
|
||||
inactiveLabel={t('wg.peer.offline')}
|
||||
/>
|
||||
<Text type="secondary" style={{ fontSize: 11 }}>
|
||||
{live ? relTime(live.last_handshake_unix, t('wg.peer.never')) : t('wg.peer.never')}
|
||||
{live ? relTime(live.last_handshake_unix, t) : t('common.relTime.never')}
|
||||
</Text>
|
||||
</Space>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user