Enhance localization and AdminBanSystem component

- Added new localization keys for settings related to punishment, traffic monitoring, and network detection in both English and Russian.
- Implemented formatting functions in AdminBanSystem to improve the display of setting keys and categories, enhancing readability and user experience.
This commit is contained in:
PEDZEO
2026-01-17 07:24:14 +03:00
parent c6e99f4685
commit 9ab53034df
3 changed files with 105 additions and 5 deletions

View File

@@ -973,7 +973,46 @@
"notifications": "Notifications",
"whitelist": "Whitelist",
"saved": "Setting saved",
"error": "Error saving"
"error": "Error saving",
"categories": {
"general": "General Settings",
"punishment": "Punishments",
"progressive_bans": "Progressive Bans",
"traffic": "Traffic Monitoring",
"network": "Network Detection",
"notifications": "Notifications",
"rate_limit": "Rate Limits"
},
"punishment_enabled": "Enable auto-ban",
"punishment_minutes": "Ban duration (minutes)",
"ip_window_seconds": "IP counting window (seconds)",
"notify_on_punishment": "Notify on bans",
"notify_on_node_status": "Notify on node status",
"daily_report_enabled": "Daily report",
"daily_report_hour": "Report hour",
"rate_limit_max": "Max requests",
"rate_limit_window": "Rate limit window (sec)",
"heartbeat_timeout": "Heartbeat timeout (sec)",
"progressive_bans_enabled": "Progressive bans",
"progressive_ban_1": "1st ban (minutes)",
"progressive_ban_2": "2nd ban (minutes)",
"progressive_ban_3": "3rd ban (minutes)",
"progressive_ban_window_hours": "Reset window (hours)",
"traffic_monitor_enabled": "Traffic monitoring",
"traffic_limit_gb": "Traffic limit (GB)",
"traffic_window_minutes": "Check window (min)",
"traffic_check_interval": "Check interval (min)",
"traffic_ban_minutes": "Traffic ban (min)",
"network_detection_enabled": "Network type detection",
"network_detection_nodes": "Detection nodes",
"network_detection_monitor_all": "Monitor all nodes",
"network_detection_collect_all": "Collect from all nodes",
"network_notify_mobile": "Notify on mobile",
"network_block_mobile": "Block mobile",
"network_block_mobile_minutes": "Block mobile (min)",
"network_notify_wifi": "Notify on WiFi",
"network_block_wifi": "Block WiFi",
"network_block_wifi_minutes": "Block WiFi (min)"
},
"health": {
"title": "System Health",

View File

@@ -973,7 +973,46 @@
"notifications": "Уведомления",
"whitelist": "Белый список",
"saved": "Настройка сохранена",
"error": "Ошибка сохранения"
"error": "Ошибка сохранения",
"categories": {
"general": "Общие настройки",
"punishment": "Наказания",
"progressive_bans": "Прогрессивные баны",
"traffic": "Мониторинг трафика",
"network": "Детекция сети",
"notifications": "Уведомления",
"rate_limit": "Лимиты запросов"
},
"punishment_enabled": "Включить автобан",
"punishment_minutes": "Длительность бана (минуты)",
"ip_window_seconds": "Окно подсчёта IP (секунды)",
"notify_on_punishment": "Уведомлять о банах",
"notify_on_node_status": "Уведомлять о статусе нод",
"daily_report_enabled": "Ежедневный отчёт",
"daily_report_hour": "Час отправки отчёта",
"rate_limit_max": "Макс. запросов",
"rate_limit_window": "Окно лимита (сек)",
"heartbeat_timeout": "Таймаут heartbeat (сек)",
"progressive_bans_enabled": "Прогрессивные баны",
"progressive_ban_1": "1-й бан (минуты)",
"progressive_ban_2": "2-й бан (минуты)",
"progressive_ban_3": "3-й бан (минуты)",
"progressive_ban_window_hours": "Окно сброса (часы)",
"traffic_monitor_enabled": "Мониторинг трафика",
"traffic_limit_gb": "Лимит трафика (ГБ)",
"traffic_window_minutes": "Окно проверки (мин)",
"traffic_check_interval": "Интервал проверки (мин)",
"traffic_ban_minutes": "Бан за трафик (мин)",
"network_detection_enabled": "Детекция типа сети",
"network_detection_nodes": "Ноды для детекции",
"network_detection_monitor_all": "Мониторить все ноды",
"network_detection_collect_all": "Собирать со всех нод",
"network_notify_mobile": "Уведомлять о мобильных",
"network_block_mobile": "Блокировать мобильные",
"network_block_mobile_minutes": "Блок мобильных (мин)",
"network_notify_wifi": "Уведомлять о WiFi",
"network_block_wifi": "Блокировать WiFi",
"network_block_wifi_minutes": "Блок WiFi (мин)"
},
"health": {
"title": "Состояние системы",

View File

@@ -1,4 +1,4 @@
import { useState, useEffect } from 'react'
import { useState, useEffect, useCallback } from 'react'
import { useTranslation } from 'react-i18next'
import {
banSystemApi,
@@ -148,6 +148,28 @@ export default function AdminBanSystem() {
const [reportHours, setReportHours] = useState(24)
const [settingLoading, setSettingLoading] = useState<string | null>(null)
const [loading, setLoading] = useState(true)
// Format snake_case to readable label
const formatSettingKey = useCallback((key: string): string => {
// Try translation first
const translated = t(`banSystem.settings.${key}`, { defaultValue: '' })
if (translated && translated !== `banSystem.settings.${key}`) {
return translated
}
// Fallback: convert snake_case to Title Case
return key
.split('_')
.map(word => word.charAt(0).toUpperCase() + word.slice(1).toLowerCase())
.join(' ')
}, [t])
const formatCategory = useCallback((category: string): string => {
const translated = t(`banSystem.settings.categories.${category}`, { defaultValue: '' })
if (translated && translated !== `banSystem.settings.categories.${category}`) {
return translated
}
return category.charAt(0).toUpperCase() + category.slice(1).replace(/_/g, ' ')
}, [t])
const [error, setError] = useState<string | null>(null)
const [searchQuery, setSearchQuery] = useState('')
const [actionLoading, setActionLoading] = useState<string | null>(null)
@@ -925,13 +947,13 @@ export default function AdminBanSystem() {
return Object.entries(grouped).map(([category, items]) => (
<div key={category} className="bg-dark-800/50 rounded-xl border border-dark-700 overflow-hidden">
<div className="p-4 border-b border-dark-700">
<h3 className="text-sm font-medium text-dark-200 capitalize">{category}</h3>
<h3 className="text-sm font-medium text-dark-200">{formatCategory(category)}</h3>
</div>
<div className="divide-y divide-dark-700">
{items.map((setting) => (
<div key={setting.key} className="p-4 flex items-center justify-between">
<div className="flex-1 min-w-0">
<div className="text-dark-100 font-medium">{setting.key}</div>
<div className="text-dark-100 font-medium">{formatSettingKey(setting.key)}</div>
{setting.description && (
<div className="text-xs text-dark-500 mt-0.5">{setting.description}</div>
)}