Fix jwt-token

This commit is contained in:
2025-09-19 12:58:48 +02:00
parent 0fa4771a0a
commit 13593d32b4
9 changed files with 836 additions and 2 deletions

View File

@@ -0,0 +1,72 @@
import React from 'react';
import { useTranslation } from 'react-i18next';
import { Menu, Transition } from '@headlessui/react';
import { Fragment } from 'react';
import { GlobeAltIcon, ChevronDownIcon } from '@heroicons/react/24/outline';
const languages = [
{ code: 'en', name: 'English', flag: '🇺🇸' },
{ code: 'sv', name: 'Svenska', flag: '🇸🇪' }
];
export default function LanguageSelector({ className = '' }) {
const { i18n, t } = useTranslation();
const currentLanguage = languages.find(lang => lang.code === i18n.language) || languages[0];
const changeLanguage = (languageCode) => {
i18n.changeLanguage(languageCode);
};
return (
<Menu as="div" className={`relative inline-block text-left ${className}`}>
<div>
<Menu.Button className="inline-flex items-center justify-center w-full px-3 py-2 text-sm font-medium text-gray-700 bg-white border border-gray-300 rounded-md shadow-sm hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500">
<GlobeAltIcon className="w-4 h-4 mr-2" />
<span className="mr-1">{currentLanguage.flag}</span>
<span>{currentLanguage.name}</span>
<ChevronDownIcon className="w-4 h-4 ml-2" />
</Menu.Button>
</div>
<Transition
as={Fragment}
enter="transition ease-out duration-100"
enterFrom="transform opacity-0 scale-95"
enterTo="transform opacity-100 scale-100"
leave="transition ease-in duration-75"
leaveFrom="transform opacity-100 scale-100"
leaveTo="transform opacity-0 scale-95"
>
<Menu.Items className="absolute right-0 z-10 w-48 mt-2 origin-top-right bg-white border border-gray-300 rounded-md shadow-lg ring-1 ring-black ring-opacity-5 focus:outline-none">
<div className="py-1">
{languages.map((language) => (
<Menu.Item key={language.code}>
{({ active }) => (
<button
onClick={() => changeLanguage(language.code)}
className={`${
active ? 'bg-gray-100 text-gray-900' : 'text-gray-700'
} ${
language.code === i18n.language ? 'bg-indigo-50 text-indigo-600' : ''
} group flex items-center px-4 py-2 text-sm w-full text-left`}
>
<span className="mr-3">{language.flag}</span>
<span>{language.name}</span>
{language.code === i18n.language && (
<span className="ml-auto">
<svg className="w-4 h-4" fill="currentColor" viewBox="0 0 20 20">
<path fillRule="evenodd" d="M16.707 5.293a1 1 0 010 1.414l-8 8a1 1 0 01-1.414 0l-4-4a1 1 0 011.414-1.414L8 12.586l7.293-7.293a1 1 0 011.414 0z" clipRule="evenodd" />
</svg>
</span>
)}
</button>
)}
</Menu.Item>
))}
</div>
</Menu.Items>
</Transition>
</Menu>
);
}

34
client/src/i18n/index.js Normal file
View File

@@ -0,0 +1,34 @@
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
import LanguageDetector from 'i18next-browser-languagedetector';
// Import translation files
import en from './locales/en.json';
import sv from './locales/sv.json';
const resources = {
en: {
translation: en
},
sv: {
translation: sv
}
};
i18n
.use(LanguageDetector)
.use(initReactI18next)
.init({
resources,
lng: 'en', // default language
fallbackLng: 'en',
interpolation: {
escapeValue: false // React already does escaping
},
detection: {
order: ['localStorage', 'navigator', 'htmlTag'],
caches: ['localStorage']
}
});
export default i18n;

View File

@@ -0,0 +1,142 @@
{
"app": {
"title": "UAM-ILS Drone Detection System",
"subtitle": "Real-time Unmanned Aerial Vehicle Monitoring"
},
"navigation": {
"dashboard": "Dashboard",
"detections": "Detections",
"devices": "Devices",
"alerts": "Alerts",
"settings": "Settings",
"logout": "Logout"
},
"auth": {
"login": "Login",
"username": "Username",
"password": "Password",
"loginButton": "Sign In",
"loginError": "Invalid credentials. Please try again.",
"sessionExpired": "Your session has expired. Please log in again.",
"accessDenied": "Access denied. Please contact support.",
"loggingIn": "Signing in...",
"logout": "Logout",
"logoutConfirm": "Are you sure you want to log out?"
},
"dashboard": {
"title": "System Overview",
"activeDetectors": "Active Detectors",
"recentDetections": "Recent Detections",
"threatLevel": "Threat Level",
"systemStatus": "System Status",
"online": "Online",
"offline": "Offline",
"maintenance": "Maintenance"
},
"detections": {
"title": "Drone Detections",
"noDetections": "No detections found",
"loadingDetections": "Loading detections...",
"filterByType": "Filter by Type",
"filterByThreat": "Filter by Threat Level",
"allTypes": "All Types",
"allThreats": "All Threat Levels",
"timestamp": "Timestamp",
"location": "Location",
"droneType": "Drone Type",
"threatLevel": "Threat Level",
"distance": "Distance",
"altitude": "Altitude",
"confidence": "Confidence",
"actions": "Actions",
"viewDetails": "View Details",
"deleteDetection": "Delete Detection",
"confirmDelete": "Are you sure you want to delete this detection?"
},
"devices": {
"title": "Detection Devices",
"noDevices": "No devices configured",
"loadingDevices": "Loading devices...",
"addDevice": "Add Device",
"deviceId": "Device ID",
"deviceName": "Device Name",
"status": "Status",
"lastSeen": "Last Seen",
"location": "Location",
"actions": "Actions",
"edit": "Edit",
"delete": "Delete",
"activate": "Activate",
"deactivate": "Deactivate"
},
"alerts": {
"title": "Alert Configuration",
"noAlerts": "No alert rules configured",
"loadingAlerts": "Loading alert rules...",
"addAlert": "Add Alert Rule",
"ruleName": "Rule Name",
"conditions": "Conditions",
"actions": "Actions",
"enabled": "Enabled",
"disabled": "Disabled"
},
"settings": {
"title": "Settings",
"general": "General",
"notifications": "Notifications",
"language": "Language",
"theme": "Theme",
"timezone": "Timezone",
"save": "Save Changes",
"cancel": "Cancel",
"saved": "Settings saved successfully",
"error": "Failed to save settings"
},
"common": {
"loading": "Loading...",
"error": "An error occurred",
"retry": "Retry",
"cancel": "Cancel",
"save": "Save",
"delete": "Delete",
"edit": "Edit",
"add": "Add",
"remove": "Remove",
"confirm": "Confirm",
"yes": "Yes",
"no": "No",
"ok": "OK",
"close": "Close",
"search": "Search",
"filter": "Filter",
"clear": "Clear",
"refresh": "Refresh",
"export": "Export",
"import": "Import"
},
"errors": {
"networkError": "Network connection error. Please check your internet connection.",
"serverError": "Server error. Please try again later.",
"notFound": "The requested resource was not found.",
"unauthorized": "You are not authorized to access this resource.",
"forbidden": "Access to this resource is forbidden.",
"validationError": "Please check your input and try again.",
"sessionExpired": "Your session has expired. Please log in again.",
"unknownError": "An unknown error occurred. Please try again."
},
"droneTypes": {
"unknown": "Unknown",
"consumer": "Consumer",
"commercial": "Commercial",
"military": "Military",
"surveillance": "Surveillance",
"racing": "Racing",
"educational": "Educational"
},
"threatLevels": {
"low": "Low",
"medium": "Medium",
"high": "High",
"critical": "Critical"
}
}

View File

@@ -0,0 +1,142 @@
{
"app": {
"title": "UAM-ILS Drönardetektionssystem",
"subtitle": "Realtidsövervakning av obemannade luftfarkoster"
},
"navigation": {
"dashboard": "Översikt",
"detections": "Detekteringar",
"devices": "Enheter",
"alerts": "Larm",
"settings": "Inställningar",
"logout": "Logga ut"
},
"auth": {
"login": "Logga in",
"username": "Användarnamn",
"password": "Lösenord",
"loginButton": "Logga in",
"loginError": "Ogiltiga inloggningsuppgifter. Försök igen.",
"sessionExpired": "Din session har löpt ut. Vänligen logga in igen.",
"accessDenied": "Åtkomst nekad. Vänligen kontakta support.",
"loggingIn": "Loggar in...",
"logout": "Logga ut",
"logoutConfirm": "Är du säker på att du vill logga ut?"
},
"dashboard": {
"title": "Systemöversikt",
"activeDetectors": "Aktiva detektorer",
"recentDetections": "Senaste detekteringar",
"threatLevel": "Hotnivå",
"systemStatus": "Systemstatus",
"online": "Online",
"offline": "Offline",
"maintenance": "Underhåll"
},
"detections": {
"title": "Drönardetekteringar",
"noDetections": "Inga detekteringar hittades",
"loadingDetections": "Laddar detekteringar...",
"filterByType": "Filtrera efter typ",
"filterByThreat": "Filtrera efter hotnivå",
"allTypes": "Alla typer",
"allThreats": "Alla hotnivåer",
"timestamp": "Tidsstämpel",
"location": "Plats",
"droneType": "Drönartyp",
"threatLevel": "Hotnivå",
"distance": "Avstånd",
"altitude": "Höjd",
"confidence": "Säkerhet",
"actions": "Åtgärder",
"viewDetails": "Visa detaljer",
"deleteDetection": "Ta bort detektion",
"confirmDelete": "Är du säker på att du vill ta bort denna detektion?"
},
"devices": {
"title": "Detektionsenheter",
"noDevices": "Inga enheter konfigurerade",
"loadingDevices": "Laddar enheter...",
"addDevice": "Lägg till enhet",
"deviceId": "Enhets-ID",
"deviceName": "Enhetsnamn",
"status": "Status",
"lastSeen": "Senast sedd",
"location": "Plats",
"actions": "Åtgärder",
"edit": "Redigera",
"delete": "Ta bort",
"activate": "Aktivera",
"deactivate": "Inaktivera"
},
"alerts": {
"title": "Larmkonfiguration",
"noAlerts": "Inga larmregler konfigurerade",
"loadingAlerts": "Laddar larmregler...",
"addAlert": "Lägg till larmregel",
"ruleName": "Regelnamn",
"conditions": "Villkor",
"actions": "Åtgärder",
"enabled": "Aktiverad",
"disabled": "Inaktiverad"
},
"settings": {
"title": "Inställningar",
"general": "Allmänt",
"notifications": "Notifieringar",
"language": "Språk",
"theme": "Tema",
"timezone": "Tidszon",
"save": "Spara ändringar",
"cancel": "Avbryt",
"saved": "Inställningar sparade framgångsrikt",
"error": "Misslyckades att spara inställningar"
},
"common": {
"loading": "Laddar...",
"error": "Ett fel uppstod",
"retry": "Försök igen",
"cancel": "Avbryt",
"save": "Spara",
"delete": "Ta bort",
"edit": "Redigera",
"add": "Lägg till",
"remove": "Ta bort",
"confirm": "Bekräfta",
"yes": "Ja",
"no": "Nej",
"ok": "OK",
"close": "Stäng",
"search": "Sök",
"filter": "Filtrera",
"clear": "Rensa",
"refresh": "Uppdatera",
"export": "Exportera",
"import": "Importera"
},
"errors": {
"networkError": "Nätverksanslutningsfel. Vänligen kontrollera din internetanslutning.",
"serverError": "Serverfel. Vänligen försök igen senare.",
"notFound": "Den begärda resursen hittades inte.",
"unauthorized": "Du är inte behörig att komma åt denna resurs.",
"forbidden": "Åtkomst till denna resurs är förbjuden.",
"validationError": "Vänligen kontrollera din inmatning och försök igen.",
"sessionExpired": "Din session har löpt ut. Vänligen logga in igen.",
"unknownError": "Ett okänt fel uppstod. Vänligen försök igen."
},
"droneTypes": {
"unknown": "Okänd",
"consumer": "Konsument",
"commercial": "Kommersiell",
"military": "Militär",
"surveillance": "Övervakning",
"racing": "Racing",
"educational": "Utbildning"
},
"threatLevels": {
"low": "Låg",
"medium": "Medium",
"high": "Hög",
"critical": "Kritisk"
}
}