mirror of
https://github.com/ParrotXray/Mantis.git
synced 2026-08-24 18:50:28 +09:00
research: translate detection.tsx UI strings to English
Replace all Chinese text with English equivalents: - SOURCE_CONFIG labels: 規則->Rule, 融合->Fusion - SEVERITY_CONFIG labels: 嚴重->Critical, 高->High - Stats cards: 總警報->Total, 涉及 IP->Unique IPs, etc. - Controls: 暫停/恢復->Pause/Resume, 監控中/已暫停->Live/Paused - Filter labels: 全部->All, 來源->Source, 嚴重度->Severity - AlertDetails: all field labels, section headers, action buttons - Empty state messages: 尚無警報->No alerts, etc. - Page title and meta description - locale: zh-TW -> en-US in formatTimestamp https://claude.ai/code/session_01Wen51749mAnwBEfh7XmvUw
This commit is contained in:
parent
9dbc6424a9
commit
7b66c4719e
@ -57,13 +57,13 @@ const SOURCE_CONFIG = {
|
||||
icon: faBrain,
|
||||
},
|
||||
Rule: {
|
||||
label: '規則',
|
||||
label: 'Rule',
|
||||
color: '#2563eb',
|
||||
bgColor: 'rgba(37,99,235,0.10)',
|
||||
icon: faScroll,
|
||||
},
|
||||
Fusion: {
|
||||
label: '融合',
|
||||
label: 'Fusion',
|
||||
color: '#dc2626',
|
||||
bgColor: 'rgba(220,38,38,0.10)',
|
||||
icon: faLayerGroup,
|
||||
@ -72,13 +72,13 @@ const SOURCE_CONFIG = {
|
||||
|
||||
const SEVERITY_CONFIG = {
|
||||
Critical: {
|
||||
label: '嚴重',
|
||||
label: 'Critical',
|
||||
color: '#dc2626',
|
||||
bgColor: 'rgba(220,38,38,0.10)',
|
||||
icon: faExclamationTriangle,
|
||||
},
|
||||
High: {
|
||||
label: '高',
|
||||
label: 'High',
|
||||
color: '#d97706',
|
||||
bgColor: 'rgba(217,119,6,0.10)',
|
||||
icon: faExclamationTriangle,
|
||||
@ -97,7 +97,7 @@ const formatProtocol = (proto: number): string =>
|
||||
PROTOCOL_MAP[proto] ?? `Proto(${proto})`
|
||||
|
||||
const formatTimestamp = (unix: number): string =>
|
||||
new Date(unix * 1000).toLocaleString('zh-TW', {
|
||||
new Date(unix * 1000).toLocaleString('en-US', {
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
hour: '2-digit',
|
||||
@ -266,8 +266,8 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
putData(
|
||||
url,
|
||||
`${formatted}:${portStr}`,
|
||||
() => showNotification(`已成功添加到黑名單: ${ip}:${blockAll ? '*' : port}`, 'success'),
|
||||
(err: any) => showNotification(`添加到黑名單失敗: ${err.message}`, 'error')
|
||||
() => showNotification(`Added to blocklist: ${ip}:${blockAll ? '*' : port}`, 'success'),
|
||||
(err: any) => showNotification(`Failed to add to blocklist: ${err.message}`, 'error')
|
||||
)
|
||||
},
|
||||
[isIPv6Src, isIPv6Dst, showNotification]
|
||||
@ -284,8 +284,8 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
putData(
|
||||
url,
|
||||
`${formatted}:${portStr}`,
|
||||
() => showNotification(`已成功添加到白名單: ${ip}:${allowAll ? '*' : port}`, 'success'),
|
||||
(err: any) => showNotification(`添加到白名單失敗: ${err.message}`, 'error')
|
||||
() => showNotification(`Added to allowlist: ${ip}:${allowAll ? '*' : port}`, 'success'),
|
||||
(err: any) => showNotification(`Failed to add to allowlist: ${err.message}`, 'error')
|
||||
)
|
||||
},
|
||||
[isIPv6Src, isIPv6Dst, showNotification]
|
||||
@ -302,28 +302,28 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
onClick={() => handleBlockIP(ip, port, isSource)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faFilter} className="mr-1" />
|
||||
封鎖 :{port}
|
||||
Block :{port}
|
||||
</button>
|
||||
<button
|
||||
className="px-3 py-2 bg-red-700 text-white text-xs rounded-lg hover:bg-red-800 transition-colors"
|
||||
onClick={() => handleBlockIP(ip, port, isSource, true)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faFilter} className="mr-1" />
|
||||
封鎖所有
|
||||
Block All
|
||||
</button>
|
||||
<button
|
||||
className="px-3 py-2 bg-green-600 text-white text-xs rounded-lg hover:bg-green-700 transition-colors"
|
||||
onClick={() => handleAllowIP(ip, port, isSource)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCheck} className="mr-1" />
|
||||
允許 :{port}
|
||||
Allow :{port}
|
||||
</button>
|
||||
<button
|
||||
className="px-3 py-2 bg-green-700 text-white text-xs rounded-lg hover:bg-green-800 transition-colors"
|
||||
onClick={() => handleAllowIP(ip, port, isSource, true)}
|
||||
>
|
||||
<FontAwesomeIcon icon={faCheck} className="mr-1" />
|
||||
允許所有
|
||||
Allow All
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
@ -340,7 +340,7 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
<div className="flex items-center justify-between mb-6">
|
||||
<h3 className="text-xl font-semibold text-gray-900 flex items-center">
|
||||
<FontAwesomeIcon icon={faEye} className="mr-2 text-blue-600" />
|
||||
警報詳情
|
||||
Alert Details
|
||||
</h3>
|
||||
<button onClick={onClose} className="text-gray-400 hover:text-gray-600 transition-colors">
|
||||
<FontAwesomeIcon icon={faTimes} />
|
||||
@ -350,11 +350,11 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
{/* Basic metadata */}
|
||||
<div className="space-y-3 mb-6">
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium text-gray-600">時間:</span>
|
||||
<span className="text-sm font-medium text-gray-600">Time:</span>
|
||||
<span className="text-sm text-gray-900">{formatTimestamp(alert.timestamp)}</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium text-gray-600">來源:</span>
|
||||
<span className="text-sm font-medium text-gray-600">Source:</span>
|
||||
<span
|
||||
className="inline-flex items-center px-2 py-1 text-xs font-medium rounded-full"
|
||||
style={{ backgroundColor: srcCfg.bgColor, color: srcCfg.color }}
|
||||
@ -364,7 +364,7 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium text-gray-600">嚴重程度:</span>
|
||||
<span className="text-sm font-medium text-gray-600">Severity:</span>
|
||||
<span
|
||||
className="inline-flex items-center px-2 py-1 text-xs font-medium rounded-full"
|
||||
style={{ backgroundColor: sevCfg.bgColor, color: sevCfg.color }}
|
||||
@ -374,7 +374,7 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm font-medium text-gray-600">協議:</span>
|
||||
<span className="text-sm font-medium text-gray-600">Protocol:</span>
|
||||
<span className="text-sm font-mono text-gray-900">{formatProtocol(alert.protocol)}</span>
|
||||
</div>
|
||||
</div>
|
||||
@ -383,7 +383,7 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
{(alert.attack_type || alert.rule_msg) && (
|
||||
<div className="mb-6">
|
||||
<span className="text-sm font-medium text-gray-600">
|
||||
{alert.source === 'Ml' ? '攻擊類型' : '規則訊息'}:
|
||||
{alert.source === 'Ml' ? 'Attack Type' : 'Rule Message'}:
|
||||
</span>
|
||||
<div className="mt-1 p-3 bg-gray-50 rounded-lg">
|
||||
<p className="text-sm text-gray-900">{alert.attack_type ?? alert.rule_msg}</p>
|
||||
@ -394,9 +394,9 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
{/* ML inference metrics */}
|
||||
{(alert.source === 'Ml' || alert.source === 'Fusion') && (
|
||||
<div className="mb-6 space-y-3">
|
||||
<h4 className="text-sm font-semibold text-gray-700">AI 推論指標</h4>
|
||||
<h4 className="text-sm font-semibold text-gray-700">ML Inference Metrics</h4>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">信心度:</span>
|
||||
<span className="text-sm text-gray-600">Confidence:</span>
|
||||
<div className="flex items-center space-x-2">
|
||||
<div className="w-24 bg-gray-200 rounded-full h-2">
|
||||
<div
|
||||
@ -422,7 +422,7 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
{/* Rule SID */}
|
||||
{(alert.source === 'Rule' || alert.source === 'Fusion') && alert.rule_sid !== null && (
|
||||
<div className="mb-6">
|
||||
<h4 className="text-sm font-semibold text-gray-700 mb-2">規則資訊</h4>
|
||||
<h4 className="text-sm font-semibold text-gray-700 mb-2">Rule Info</h4>
|
||||
<div className="flex justify-between items-center">
|
||||
<span className="text-sm text-gray-600">SID:</span>
|
||||
<span className="text-sm font-mono text-gray-900">{alert.rule_sid}</span>
|
||||
@ -432,16 +432,16 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
|
||||
{/* Connection */}
|
||||
<div className="mb-6">
|
||||
<h4 className="text-sm font-semibold text-gray-700 mb-3">連線詳情</h4>
|
||||
<h4 className="text-sm font-semibold text-gray-700 mb-3">Connection Details</h4>
|
||||
<div className="flex items-center justify-between bg-gray-50 rounded-lg p-4">
|
||||
<div className="text-center">
|
||||
<div className="text-xs font-medium text-gray-500">來源</div>
|
||||
<div className="text-xs font-medium text-gray-500">Source</div>
|
||||
<div className="text-sm font-semibold text-blue-600">{alert.src_ip}</div>
|
||||
<div className="text-xs text-gray-500">:{alert.src_port}</div>
|
||||
</div>
|
||||
<FontAwesomeIcon icon={faArrowRight} className="text-gray-400" />
|
||||
<div className="text-center">
|
||||
<div className="text-xs font-medium text-gray-500">目標</div>
|
||||
<div className="text-xs font-medium text-gray-500">Destination</div>
|
||||
<div className="text-sm font-semibold text-red-600">{alert.dst_ip}</div>
|
||||
<div className="text-xs text-gray-500">:{alert.dst_port}</div>
|
||||
</div>
|
||||
@ -450,9 +450,9 @@ const AlertDetails: React.FC<AlertDetailsProps> = ({ alert, onClose, showNotific
|
||||
|
||||
{/* IP management */}
|
||||
<div className="space-y-4">
|
||||
<h4 className="text-sm font-semibold text-gray-700">IP 管理</h4>
|
||||
<IpActions ip={alert.src_ip} port={alert.src_port} isSource={true} label="來源 IP" bg="bg-blue-50" />
|
||||
<IpActions ip={alert.dst_ip} port={alert.dst_port} isSource={false} label="目標 IP" bg="bg-red-50" />
|
||||
<h4 className="text-sm font-semibold text-gray-700">IP Management</h4>
|
||||
<IpActions ip={alert.src_ip} port={alert.src_port} isSource={true} label="Source IP" bg="bg-blue-50" />
|
||||
<IpActions ip={alert.dst_ip} port={alert.dst_port} isSource={false} label="Destination IP" bg="bg-red-50" />
|
||||
</div>
|
||||
</motion.div>
|
||||
</AnimatePresence>
|
||||
@ -547,7 +547,7 @@ const Detection: React.FC = () => {
|
||||
if (isLoading) {
|
||||
return (
|
||||
<>
|
||||
<Head><title>威脅檢測 - NetGuardia</title></Head>
|
||||
<Head><title>Threat Detection - NetGuardia</title></Head>
|
||||
<Layout>
|
||||
<div className="flex items-center justify-center w-full h-full min-h-[calc(100vh-4rem)]">
|
||||
<LoadingSpinner />
|
||||
@ -560,8 +560,8 @@ const Detection: React.FC = () => {
|
||||
return (
|
||||
<>
|
||||
<Head>
|
||||
<title>威脅檢測 - NetGuardia</title>
|
||||
<meta name="description" content="NetGuardia 統一威脅檢測系統" />
|
||||
<title>Threat Detection - NetGuardia</title>
|
||||
<meta name="description" content="NetGuardia Unified Threat Detection" />
|
||||
</Head>
|
||||
|
||||
<Layout>
|
||||
@ -579,22 +579,22 @@ const Detection: React.FC = () => {
|
||||
<motion.div initial={{ opacity: 0, y: -20 }} animate={{ opacity: 1, y: 0 }} className="mb-6">
|
||||
<h1 className="text-3xl font-bold text-gray-900 mb-1 flex items-center">
|
||||
<FontAwesomeIcon icon={faShieldAlt} className="mr-3 text-blue-600" />
|
||||
威脅檢測
|
||||
Threat Detection
|
||||
</h1>
|
||||
<p className="text-gray-500 text-sm">AI 與規則引擎聯合偵測,實時監控網路威脅</p>
|
||||
<p className="text-gray-500 text-sm">Real-time threat monitoring powered by ML and rule engine</p>
|
||||
</motion.div>
|
||||
|
||||
{/* Stats cards */}
|
||||
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-7 gap-4 mb-6">
|
||||
{(
|
||||
[
|
||||
{ label: '總警報', value: stats.total, color: '#2563eb', icon: faList },
|
||||
{ label: '嚴重', value: stats.critical, color: '#dc2626', icon: faExclamationTriangle },
|
||||
{ label: '高', value: stats.high, color: '#d97706', icon: faExclamationTriangle },
|
||||
{ label: 'AI', value: stats.ml, color: '#7c3aed', icon: faBrain },
|
||||
{ label: '規則', value: stats.rule, color: '#2563eb', icon: faScroll },
|
||||
{ label: '融合', value: stats.fusion, color: '#dc2626', icon: faLayerGroup },
|
||||
{ label: '涉及 IP', value: stats.uniqueIPs, color: '#059669', icon: faGlobe },
|
||||
{ label: 'Total', value: stats.total, color: '#2563eb', icon: faList },
|
||||
{ label: 'Critical', value: stats.critical, color: '#dc2626', icon: faExclamationTriangle },
|
||||
{ label: 'High', value: stats.high, color: '#d97706', icon: faExclamationTriangle },
|
||||
{ label: 'ML', value: stats.ml, color: '#7c3aed', icon: faBrain },
|
||||
{ label: 'Rule', value: stats.rule, color: '#2563eb', icon: faScroll },
|
||||
{ label: 'Fusion', value: stats.fusion, color: '#dc2626', icon: faLayerGroup },
|
||||
{ label: 'Unique IPs', value: stats.uniqueIPs, color: '#059669', icon: faGlobe },
|
||||
] as const
|
||||
).map(({ label, value, color, icon }, i) => (
|
||||
<motion.div
|
||||
@ -632,7 +632,7 @@ const Detection: React.FC = () => {
|
||||
}`}
|
||||
>
|
||||
<FontAwesomeIcon icon={isPaused ? faPlay : faPause} />
|
||||
{isPaused ? '恢復' : '暫停'}
|
||||
{isPaused ? 'Resume' : 'Pause'}
|
||||
</button>
|
||||
|
||||
{/* Live indicator */}
|
||||
@ -643,7 +643,7 @@ const Detection: React.FC = () => {
|
||||
}`}
|
||||
/>
|
||||
<span className={`text-xs font-medium ${isPaused ? 'text-orange-600' : 'text-green-600'}`}>
|
||||
{isPaused ? '已暫停' : '監控中'}
|
||||
{isPaused ? 'Paused' : 'Live'}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@ -651,7 +651,7 @@ const Detection: React.FC = () => {
|
||||
|
||||
{/* Source filter */}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-xs text-gray-500">來源:</span>
|
||||
<span className="text-xs text-gray-500">Source:</span>
|
||||
{(['all', 'Ml', 'Rule', 'Fusion'] as const).map(s => (
|
||||
<FilterButton
|
||||
key={s}
|
||||
@ -664,7 +664,7 @@ const Detection: React.FC = () => {
|
||||
: '#dc2626'
|
||||
}
|
||||
>
|
||||
{s === 'all' ? '全部' : SOURCE_CONFIG[s].label}
|
||||
{s === 'all' ? 'All' : SOURCE_CONFIG[s].label}
|
||||
</FilterButton>
|
||||
))}
|
||||
</div>
|
||||
@ -673,7 +673,7 @@ const Detection: React.FC = () => {
|
||||
|
||||
{/* Severity filter */}
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="text-xs text-gray-500">嚴重度:</span>
|
||||
<span className="text-xs text-gray-500">Severity:</span>
|
||||
{(['all', 'Critical', 'High'] as const).map(s => (
|
||||
<FilterButton
|
||||
key={s}
|
||||
@ -683,13 +683,13 @@ const Detection: React.FC = () => {
|
||||
s === 'all' ? '#374151' : s === 'Critical' ? '#dc2626' : '#d97706'
|
||||
}
|
||||
>
|
||||
{s === 'all' ? '全部' : SEVERITY_CONFIG[s].label}
|
||||
{s === 'all' ? 'All' : SEVERITY_CONFIG[s].label}
|
||||
</FilterButton>
|
||||
))}
|
||||
</div>
|
||||
|
||||
<div className="ml-auto text-xs text-gray-400">
|
||||
{filteredAlerts.length} / {alerts.length} 筆
|
||||
{filteredAlerts.length} / {alerts.length} alerts
|
||||
</div>
|
||||
</div>
|
||||
</motion.div>
|
||||
@ -706,9 +706,9 @@ const Detection: React.FC = () => {
|
||||
<div className="px-5 py-3 border-b border-gray-100 flex items-center justify-between">
|
||||
<h2 className="text-base font-semibold text-gray-900 flex items-center gap-2">
|
||||
<FontAwesomeIcon icon={faShieldAlt} className="text-blue-600" />
|
||||
安全警報
|
||||
Security Alerts
|
||||
</h2>
|
||||
<span className="text-xs text-gray-400">{filteredAlerts.length} 條</span>
|
||||
<span className="text-xs text-gray-400">{filteredAlerts.length} alerts</span>
|
||||
</div>
|
||||
|
||||
<div className="max-h-[620px] overflow-y-auto">
|
||||
@ -716,12 +716,12 @@ const Detection: React.FC = () => {
|
||||
<div className="p-12 text-center">
|
||||
<FontAwesomeIcon icon={faShieldAlt} className="text-5xl text-gray-200 mb-4" />
|
||||
<h3 className="text-lg font-semibold text-gray-600 mb-1">
|
||||
{alerts.length === 0 ? '尚無警報' : '無符合條件的警報'}
|
||||
{alerts.length === 0 ? 'No alerts' : 'No matching alerts'}
|
||||
</h3>
|
||||
<p className="text-sm text-gray-400">
|
||||
{alerts.length === 0
|
||||
? '系統偵測到威脅時將在此顯示'
|
||||
: '請調整過濾條件'}
|
||||
? 'Alerts will appear here when threats are detected'
|
||||
: 'Try adjusting the filters'}
|
||||
</p>
|
||||
</div>
|
||||
) : (
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user