diff --git a/client/src/pages/Alerts.jsx b/client/src/pages/Alerts.jsx index a6c0e8d..2e8b28c 100644 --- a/client/src/pages/Alerts.jsx +++ b/client/src/pages/Alerts.jsx @@ -137,19 +137,19 @@ const Alerts = () => {
- Get started by creating your first alert rule. + {t('alerts.noAlertRulesDescription')}
| Name | -Priority | -Channels | -Conditions | -Status | -Created | -Actions | +{t('alerts.name')} | +{t('alerts.priority')} | +{t('alerts.channels')} | +{t('alerts.conditions')} | +{t('alerts.status')} | +{t('alerts.created')} | +{t('alerts.actions')} | @@ -251,28 +251,28 @@ const Alerts = () => { |
{rule.min_detections > 1 && (
- Min detections: {rule.min_detections}
+ {t('alerts.minDetections')}: {rule.min_detections}
)}
{rule.time_window && (
- Time window: {rule.time_window}s
+ {t('alerts.timeWindow')}: {rule.time_window}s
)}
{rule.cooldown_period && (
- Cooldown: {rule.cooldown_period}s
+ {t('alerts.cooldown')}: {rule.cooldown_period}s
)}
{rule.min_threat_level && (
- Min threat: {rule.min_threat_level}
+ {t('alerts.minThreat')}: {rule.min_threat_level}
)}
{rule.drone_types && rule.drone_types.length > 0 && (
- Drone types:
+ {t('alerts.droneTypes')}:
{rule.drone_types.map((typeId, index) => {
- const droneTypes = {
- 0: 'Consumer',
- 1: 'Orlan',
- 2: 'Professional',
- 3: 'Racing',
- 4: 'Unknown'
+ const droneTypeKeys = {
+ 0: 'consumer',
+ 1: 'orlan',
+ 2: 'professional',
+ 3: 'racing',
+ 4: 'unknown'
};
return (
{
: 'bg-gray-100 text-gray-800'
}`}
>
- {droneTypes[typeId] || 'Unknown'}
+ {t(`alerts.${droneTypeKeys[typeId] || 'unknown'}`)}
{typeId === 1 && '⚠️'}
);
@@ -299,7 +299,7 @@ const Alerts = () => {
? 'bg-green-100 text-green-800'
: 'bg-gray-100 text-gray-800'
}`}>
- {rule.is_active ? 'Active' : 'Inactive'}
+ {rule.is_active ? t('alerts.active') : t('alerts.inactive')}
|
@@ -313,13 +313,13 @@ const Alerts = () => { onClick={() => handleEditRule(rule)} className="text-primary-600 hover:text-primary-900 text-sm" > - Edit + {t('alerts.edit')} | @@ -338,9 +338,9 @@ const Alerts = () => { {(alertLogs?.length || 0) === 0 ? (
|---|
| Status | -Type | -Recipient | -Rule | -Detection | -Message | -Sent At | +{t('alerts.status')} | +{t('alerts.type')} | +{t('alerts.recipient')} | +{t('alerts.rule')} | +{t('alerts.detection')} | +{t('alerts.message')} | +{t('alerts.sentAt')} |
- {log.rule?.name || 'Unknown Rule'}
+ {log.rule?.name || t('alerts.unknownRule')}
|
@@ -389,10 +389,10 @@ const Alerts = () => { onClick={() => handleViewDetection(log.detection_id)} className="text-primary-600 hover:text-primary-900 text-sm font-medium" > - View Details + {t('alerts.viewDetails')} ) : ( - N/A + {t('alerts.na')} )} |
diff --git a/client/src/pages/Settings.jsx b/client/src/pages/Settings.jsx
index f37ecab..255b865 100644
--- a/client/src/pages/Settings.jsx
+++ b/client/src/pages/Settings.jsx
@@ -53,10 +53,45 @@ const ALL_TABS = [
const Settings = () => {
const { user } = useAuth();
+ const { t } = useTranslation();
const [tenantConfig, setTenantConfig] = useState(null);
const [loading, setLoading] = useState(true);
const [saving, setSaving] = useState(false);
+ // Define tabs with translations inside component
+ const ALL_TABS = [
+ {
+ id: 'general',
+ name: t('settings.general'),
+ icon: CogIcon,
+ permission: 'tenant.view'
+ },
+ {
+ id: 'branding',
+ name: t('settings.branding'),
+ icon: PaintBrushIcon,
+ permission: 'branding.view'
+ },
+ {
+ id: 'security',
+ name: t('settings.security'),
+ icon: ShieldCheckIcon,
+ permission: 'security.view'
+ },
+ {
+ id: 'authentication',
+ name: t('settings.authentication'),
+ icon: KeyIcon,
+ permission: 'auth.view'
+ },
+ {
+ id: 'users',
+ name: t('settings.users'),
+ icon: UserGroupIcon,
+ permission: 'users.view'
+ }
+ ];
+
// Calculate available tabs
const availableTabs = user?.role
? ALL_TABS.filter(tab => hasPermission(user.role, tab.permission))
@@ -101,9 +136,9 @@ const Settings = () => {
Access Denied+{t('settings.accessDenied')}- You don't have permission to access tenant settings. + {t('settings.accessDeniedMessage')}
-
- General Information-
-
-
-
- {tenantConfig?.name} -
-
-
- {tenantConfig?.slug} -
-
-
-);
+ );
+};
// Branding Settings Component
const BrandingSettings = ({ tenantConfig, onRefresh }) => {
@@ -214,10 +252,10 @@ const BrandingSettings = ({ tenantConfig, onRefresh }) => {
setSaving(true);
try {
await api.put('/tenant/branding', branding);
- toast.success('Branding updated successfully');
+ toast.success(t('settings.brandingUpdated'));
if (onRefresh) onRefresh();
} catch (error) {
- toast.error('Failed to update branding');
+ toast.error(t('settings.brandingUpdateFailed'));
} finally {
setSaving(false);
}
@@ -279,7 +317,7 @@ const BrandingSettings = ({ tenantConfig, onRefresh }) => {
{tenantConfig?.auth_provider} +const GeneralSettings = ({ tenantConfig }) => { + const { t } = useTranslation(); + return ( +
+
-
+
{t('settings.generalInformation')}+
+
+
+
+ {tenantConfig?.name} +
+
+
+ {tenantConfig?.slug} +
+
+
{tenantConfig?.auth_provider} +Branding & Appearance
-
+
{
{/* Manual URL input as fallback */}
-
+
{
-
+
{
-
+
{
disabled={saving}
className="bg-primary-600 text-white px-4 py-2 rounded-md hover:bg-primary-700 disabled:opacity-50"
>
- {saving ? 'Saving...' : 'Save Branding'}
+ {saving ? t('settings.saving') : t('settings.saveBranding')}
) : (
@@ -491,11 +529,11 @@ const SecuritySettings = ({ tenantConfig, onRefresh }) => {
try {
console.log('🔒 Sending security settings:', securitySettings);
await api.put('/tenant/security', securitySettings);
- toast.success('Security settings updated successfully');
+ toast.success(t('settings.securityUpdated'));
if (onRefresh) onRefresh();
} catch (error) {
console.error('Failed to update security settings:', error);
- toast.error('Failed to update security settings');
+ toast.error(t('settings.securityUpdateFailed'));
} finally {
setSaving(false);
}
@@ -516,7 +554,7 @@ const SecuritySettings = ({ tenantConfig, onRefresh }) => {
disabled={saving || !canEdit}
className="bg-primary-600 text-white px-4 py-2 rounded-md hover:bg-primary-700 disabled:opacity-50"
>
- {saving ? 'Saving...' : 'Save Changes'}
+ {saving ? t('settings.saving') : t('settings.saveChanges')}
diff --git a/client/src/utils/tempTranslations.js b/client/src/utils/tempTranslations.js
index 2c2ce1a..e05a9a8 100644
--- a/client/src/utils/tempTranslations.js
+++ b/client/src/utils/tempTranslations.js
@@ -168,7 +168,44 @@ const translations = {
lowPriority: 'Low Priority',
active: 'Active',
inactive: 'Inactive',
- triggered: 'Triggered'
+ totalAlerts24h: 'Total Alerts (24h)',
+ sentSuccessfully: 'Sent Successfully',
+ failed: 'Failed',
+ pending: 'Pending',
+ alertRules: 'Alert Rules',
+ alertLogs: 'Alert Logs',
+ noAlertRules: 'No alert rules',
+ noAlertRulesDescription: 'Get started by creating your first alert rule.',
+ createAlertRule: 'Create Alert Rule',
+ noAlertLogs: 'No alert logs',
+ noAlertLogsDescription: 'Alert logs will appear here when alerts are triggered.',
+ name: 'Name',
+ channels: 'Channels',
+ conditions: 'Conditions',
+ edit: 'Edit',
+ delete: 'Delete',
+ recipient: 'Recipient',
+ rule: 'Rule',
+ detection: 'Detection',
+ message: 'Message',
+ sentAt: 'Sent At',
+ viewDetails: 'View Details',
+ unknownRule: 'Unknown Rule',
+ na: 'N/A',
+ minDetections: 'Min detections',
+ timeWindow: 'Time window',
+ cooldown: 'Cooldown',
+ minThreat: 'Min threat',
+ droneTypes: 'Drone types',
+ consumer: 'Consumer',
+ orlan: 'Orlan',
+ professional: 'Professional',
+ racing: 'Racing',
+ unknown: 'Unknown',
+ critical: 'Critical',
+ high: 'High',
+ medium: 'Medium',
+ low: 'Low'
},
settings: {
title: 'Settings',
@@ -187,7 +224,30 @@ const translations = {
apiKeys: 'API Keys',
dataRetention: 'Data Retention',
exportData: 'Export Data',
- deleteAccount: 'Delete Account'
+ deleteAccount: 'Delete Account',
+ loading: 'Loading settings...',
+ accessDenied: 'Access Denied',
+ accessDeniedMessage: "You don't have permission to access tenant settings.",
+ general: 'General',
+ branding: 'Branding',
+ authentication: 'Authentication',
+ users: 'Users',
+ generalInformation: 'General Information',
+ tenantName: 'Tenant Name',
+ tenantId: 'Tenant ID',
+ authenticationProvider: 'Authentication Provider',
+ companyName: 'Company Name',
+ logoUrl: 'Or enter logo URL manually',
+ primaryColor: 'Primary Color',
+ secondaryColor: 'Secondary Color',
+ save: 'Save',
+ saving: 'Saving...',
+ saveBranding: 'Save Branding',
+ saveChanges: 'Save Changes',
+ brandingUpdated: 'Branding updated successfully',
+ brandingUpdateFailed: 'Failed to update branding',
+ securityUpdated: 'Security settings updated successfully',
+ securityUpdateFailed: 'Failed to update security settings'
},
auth: {
login: 'Login',
@@ -449,7 +509,44 @@ const translations = {
lowPriority: 'Låg prioritet',
active: 'Aktiv',
inactive: 'Inaktiv',
- triggered: 'Utlöst'
+ totalAlerts24h: 'Totalt larm (24h)',
+ sentSuccessfully: 'Skickade framgångsrikt',
+ failed: 'Misslyckades',
+ pending: 'Väntande',
+ alertRules: 'Larmregler',
+ alertLogs: 'Larmloggar',
+ noAlertRules: 'Inga larmregler',
+ noAlertRulesDescription: 'Kom igång genom att skapa din första larmregel.',
+ createAlertRule: 'Skapa larmregel',
+ noAlertLogs: 'Inga larmloggar',
+ noAlertLogsDescription: 'Larmloggar kommer att visas här när larm utlöses.',
+ name: 'Namn',
+ channels: 'Kanaler',
+ conditions: 'Villkor',
+ edit: 'Redigera',
+ delete: 'Ta bort',
+ recipient: 'Mottagare',
+ rule: 'Regel',
+ detection: 'Detektion',
+ message: 'Meddelande',
+ sentAt: 'Skickat vid',
+ viewDetails: 'Visa detaljer',
+ unknownRule: 'Okänd regel',
+ na: 'Ej tillämpligt',
+ minDetections: 'Min detekteringar',
+ timeWindow: 'Tidsfönster',
+ cooldown: 'Nedkylning',
+ minThreat: 'Min hot',
+ droneTypes: 'Drönartyper',
+ consumer: 'Konsument',
+ orlan: 'Orlan',
+ professional: 'Professionell',
+ racing: 'Racing',
+ unknown: 'Okänd',
+ critical: 'Kritisk',
+ high: 'Hög',
+ medium: 'Medel',
+ low: 'Låg'
},
settings: {
title: 'Inställningar',
@@ -468,7 +565,30 @@ const translations = {
apiKeys: 'API-nycklar',
dataRetention: 'Datalagring',
exportData: 'Exportera data',
- deleteAccount: 'Ta bort konto'
+ deleteAccount: 'Ta bort konto',
+ loading: 'Laddar inställningar...',
+ accessDenied: 'Åtkomst nekad',
+ accessDeniedMessage: 'Du har inte behörighet att komma åt tenant-inställningar.',
+ general: 'Allmänt',
+ branding: 'Varumärke',
+ authentication: 'Autentisering',
+ users: 'Användare',
+ generalInformation: 'Allmän information',
+ tenantName: 'Tenant-namn',
+ tenantId: 'Tenant-ID',
+ authenticationProvider: 'Autentiseringsleverantör',
+ companyName: 'Företagsnamn',
+ logoUrl: 'Eller ange logotyp-URL manuellt',
+ primaryColor: 'Primärfärg',
+ secondaryColor: 'Sekundär färg',
+ save: 'Spara',
+ saving: 'Sparar...',
+ saveBranding: 'Spara varumärke',
+ saveChanges: 'Spara ändringar',
+ brandingUpdated: 'Varumärke uppdaterat framgångsrikt',
+ brandingUpdateFailed: 'Misslyckades med att uppdatera varumärke',
+ securityUpdated: 'Säkerhetsinställningar uppdaterade framgångsrikt',
+ securityUpdateFailed: 'Misslyckades med att uppdatera säkerhetsinställningar'
},
auth: {
login: 'Logga in',
|
|---|