Add i18n, branding, user management, health checks, and cleanup for deployment

- Multi-language support (EN/DE) with i18n engine and language files
- Configurable branding (name, subtitle, logo) in Settings
- Global default language and per-user language preference
- User management router with CRUD endpoints
- Customer status sync on start/stop/restart
- Health check fixes: derive status from container state, remove broken wget healthcheck
- Caddy reverse proxy and dashboard env templates for customer stacks
- Updated README with real hardware specs, prerequisites, and new features
- Removed .claude settings (JWT tokens) and build artifacts from tracking
- Updated .gitignore for .claude/ and Windows artifacts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-02-08 17:24:05 +01:00
parent c4d68db2f4
commit 41ba835a99
28 changed files with 2550 additions and 661 deletions

285
static/lang/de.json Normal file
View File

@@ -0,0 +1,285 @@
{
"login": {
"subtitle": "Multi-Tenant Management Plattform",
"username": "Benutzername",
"password": "Passwort",
"signIn": "Anmelden",
"signInWithMicrosoft": "Mit Microsoft anmelden"
},
"nav": {
"newCustomer": "Neuer Kunde",
"settings": "Einstellungen",
"monitoring": "Monitoring",
"logout": "Abmelden"
},
"dashboard": {
"totalCustomers": "Kunden gesamt",
"active": "Aktiv",
"inactive": "Inaktiv",
"errors": "Fehler",
"searchPlaceholder": "Suche nach Name, Subdomain, E-Mail...",
"allStatuses": "Alle Status",
"statusActive": "Aktiv",
"statusInactive": "Inaktiv",
"statusDeploying": "Wird bereitgestellt",
"statusError": "Fehler",
"refresh": "Aktualisieren",
"thId": "ID",
"thName": "Name",
"thSubdomain": "Subdomain",
"thStatus": "Status",
"thDashboard": "Dashboard",
"thDevices": "Geraete",
"thCreated": "Erstellt",
"thActions": "Aktionen",
"noCustomers": "Keine Kunden gefunden. Klicken Sie auf \"Neuer Kunde\" um einen anzulegen.",
"showing": "Zeige {start}-{end} von {total}",
"showingEmpty": "Zeige 0 von 0"
},
"customer": {
"back": "Zurueck",
"customer": "Kunde",
"edit": "Bearbeiten",
"delete": "Loeschen",
"tabInfo": "Info",
"tabDeployment": "Deployment",
"tabLogs": "Logs",
"tabHealth": "Zustand",
"name": "Name:",
"company": "Firma:",
"subdomain": "Subdomain:",
"email": "E-Mail:",
"maxDevices": "Max. Geraete:",
"status": "Status:",
"created": "Erstellt:",
"updated": "Aktualisiert:",
"notes": "Notizen:",
"deploymentStatus": "Status:",
"relayUdpPort": "Relay UDP Port:",
"dashboardPort": "Dashboard Port:",
"containerPrefix": "Container-Praefix:",
"deployed": "Bereitgestellt:",
"setupUrl": "Setup URL:",
"copy": "Kopieren",
"open": "Oeffnen",
"netbirdLogin": "NetBird Login",
"notAvailable": "Nicht verfuegbar",
"showCredentials": "Zugangsdaten anzeigen",
"credEmail": "E-Mail",
"credPassword": "Passwort",
"showHide": "Anzeigen/Verbergen",
"credentialsNotAvailable": "Zugangsdaten nicht verfuegbar. Der Admin muss das Setup manuell ueber die Setup URL abschliessen.",
"start": "Starten",
"stop": "Stoppen",
"restart": "Neustarten",
"reDeploy": "Neu bereitstellen",
"noDeployment": "Kein Deployment gefunden.",
"deployNow": "Jetzt bereitstellen",
"containerLogs": "Container Logs",
"noContainerLogs": "Keine Container-Logs verfuegbar.",
"noLogsLoaded": "Keine Logs geladen.",
"healthCheck": "Zustandspruefung",
"check": "Pruefen",
"clickCheck": "Klicken Sie auf \"Pruefen\" um eine Zustandspruefung durchzufuehren.",
"healthy": "Gesund",
"unhealthy": "Fehlerhaft",
"overall": "Gesamt:",
"thContainer": "Container",
"thContainerStatus": "Status",
"thHealth": "Zustand",
"thImage": "Image",
"lastCheck": "Letzte Pruefung: {time}",
"openDashboard": "Dashboard oeffnen"
},
"customerModal": {
"newCustomer": "Neuer Kunde",
"editCustomer": "Kunde bearbeiten",
"nameLabel": "Name *",
"companyLabel": "Firma",
"subdomainLabel": "Subdomain *",
"subdomainHint": "Kleinbuchstaben, alphanumerisch + Bindestriche",
"emailLabel": "E-Mail *",
"maxDevicesLabel": "Max. Geraete",
"notesLabel": "Notizen",
"cancel": "Abbrechen",
"saveAndDeploy": "Speichern & Bereitstellen",
"saveChanges": "Aenderungen speichern"
},
"deleteModal": {
"title": "Loeschung bestaetigen",
"confirmText": "Sind Sie sicher, dass Sie den Kunden loeschen moechten",
"warning": "Alle Container, NPM-Eintraege und Daten werden entfernt. Diese Aktion kann nicht rueckgaengig gemacht werden.",
"cancel": "Abbrechen",
"delete": "Loeschen"
},
"settings": {
"title": "Systemeinstellungen",
"tabSystem": "Systemkonfiguration",
"tabNpm": "NPM Integration",
"tabImages": "Docker Images",
"tabBranding": "Branding",
"tabUsers": "Benutzer",
"tabAzure": "Azure AD",
"tabSecurity": "Sicherheit",
"baseDomain": "Basis-Domain",
"baseDomainPlaceholder": "ihredomain.com",
"baseDomainHint": "Kunden erhalten Subdomains: kunde.ihredomain.com",
"adminEmail": "Admin E-Mail",
"adminEmailPlaceholder": "admin@ihredomain.com",
"dataDir": "Datenverzeichnis",
"dataDirPlaceholder": "/opt/netbird-instances",
"dockerNetwork": "Docker Netzwerk",
"dockerNetworkPlaceholder": "npm-network",
"relayBasePort": "Relay Basis-Port",
"relayBasePortHint": "Erster UDP-Port fuer Relay. Bereich: Basis bis Basis+99",
"dashboardBasePort": "Dashboard Basis-Port",
"dashboardBasePortHint": "Basis-Port fuer Kunden-Dashboards. Kunde N erhaelt Basis+N",
"saveSystemSettings": "Systemeinstellungen speichern",
"npmDescription": "NPM verwendet JWT-Authentifizierung. Geben Sie Ihre NPM-Anmeldedaten (E-Mail + Passwort) ein. Das System meldet sich automatisch an und bezieht Tokens fuer API-Aufrufe.",
"npmApiUrl": "NPM API URL",
"npmApiUrlPlaceholder": "http://nginx-proxy-manager:81/api",
"npmApiUrlHint": "http:// oder https:// - muss /api am Ende enthalten",
"npmLoginEmail": "NPM Login E-Mail",
"npmLoginEmailPlaceholder": "Leer lassen um aktuelle beizubehalten",
"npmLoginPassword": "NPM Login Passwort",
"npmLoginPasswordPlaceholder": "Leer lassen um aktuelles beizubehalten",
"credentialsSet": "Zugangsdaten sind gesetzt (leer lassen um aktuelle beizubehalten)",
"noCredentials": "Keine NPM-Zugangsdaten konfiguriert",
"saveNpmSettings": "NPM Einstellungen speichern",
"testConnection": "Verbindung testen",
"managementImage": "Management Image",
"managementImagePlaceholder": "netbirdio/management:latest",
"signalImage": "Signal Image",
"signalImagePlaceholder": "netbirdio/signal:latest",
"relayImage": "Relay Image",
"relayImagePlaceholder": "netbirdio/relay:latest",
"dashboardImage": "Dashboard Image",
"dashboardImagePlaceholder": "netbirdio/dashboard:latest",
"saveImageSettings": "Image Einstellungen speichern",
"brandingTitle": "Branding Einstellungen",
"companyName": "Firmen- / Anwendungsname",
"companyNamePlaceholder": "NetBird MSP Appliance",
"companyNameHint": "Wird auf der Login-Seite und in der Navbar angezeigt",
"logoPreview": "Logo-Vorschau",
"defaultIcon": "Standard-Icon (kein Logo hochgeladen)",
"uploadLogo": "Logo hochladen (PNG, JPG, SVG, max 500KB)",
"uploadBtn": "Hochladen",
"removeLogo": "Logo entfernen",
"brandingSubtitle": "Untertitel",
"brandingSubtitlePlaceholder": "Multi-Tenant Management Plattform",
"brandingSubtitleHint": "Wird unter dem Titel auf der Login-Seite angezeigt",
"defaultLanguage": "Standardsprache",
"defaultLanguageHint": "Standardsprache fuer Benutzer ohne eigene Einstellung",
"systemDefault": "Systemstandard",
"saveBranding": "Branding speichern",
"userManagement": "Benutzerverwaltung",
"newUser": "Neuer Benutzer",
"thId": "ID",
"thUsername": "Benutzername",
"thEmail": "E-Mail",
"thRole": "Rolle",
"thAuth": "Auth",
"thLanguage": "Sprache",
"thStatus": "Status",
"thActions": "Aktionen",
"azureTitle": "Azure AD / Entra ID Integration",
"enableAzureSso": "Azure AD SSO aktivieren",
"tenantId": "Tenant ID",
"clientId": "Client ID (Anwendungs-ID)",
"clientSecret": "Client Secret",
"clientSecretPlaceholder": "Leer lassen um aktuelles beizubehalten",
"secretSet": "Secret ist gesetzt (leer lassen um aktuelles beizubehalten)",
"noSecret": "Kein Client Secret konfiguriert",
"saveAzureSettings": "Azure AD Einstellungen speichern",
"securityTitle": "Admin-Passwort aendern",
"currentPassword": "Aktuelles Passwort",
"newPassword": "Neues Passwort (min. 12 Zeichen)",
"confirmPassword": "Neues Passwort bestaetigen",
"changePassword": "Passwort aendern"
},
"monitoring": {
"title": "System Monitoring",
"refresh": "Aktualisieren",
"hostResources": "Host-Ressourcen",
"hostname": "Hostname",
"cpu": "CPU ({count} Kerne)",
"memory": "Speicher ({used}/{total} GB)",
"disk": "Festplatte ({used}/{total} GB)",
"allCustomerDeployments": "Alle Kunden-Deployments",
"thId": "ID",
"thName": "Name",
"thSubdomain": "Subdomain",
"thStatus": "Status",
"thDeployment": "Deployment",
"thDashboard": "Dashboard",
"thRelayPort": "Relay Port",
"thContainers": "Container",
"noCustomers": "Keine Kunden."
},
"userModal": {
"title": "Neuer Benutzer",
"usernameLabel": "Benutzername *",
"passwordLabel": "Passwort * (min. 8 Zeichen)",
"emailLabel": "E-Mail",
"languageLabel": "Standardsprache",
"cancel": "Abbrechen",
"createUser": "Benutzer erstellen"
},
"common": {
"loading": "Laden...",
"back": "Zurueck",
"save": "Speichern",
"cancel": "Abbrechen",
"delete": "Loeschen",
"edit": "Bearbeiten",
"view": "Anzeigen",
"start": "Starten",
"stop": "Stoppen",
"restart": "Neustarten",
"disable": "Deaktivieren",
"enable": "Aktivieren",
"resetPassword": "Passwort zuruecksetzen",
"open": "Oeffnen",
"active": "Aktiv",
"disabled": "Deaktiviert"
},
"errors": {
"networkError": "Netzwerkfehler \u2014 Server nicht erreichbar.",
"sessionExpired": "Sitzung abgelaufen.",
"requestFailed": "Anfrage fehlgeschlagen.",
"serverError": "Serverfehler (HTTP {status}).",
"unknownError": "Ein unbekannter Fehler ist aufgetreten.",
"uploadFailed": "Upload fehlgeschlagen.",
"deleteFailed": "Loeschen fehlgeschlagen: {error}",
"failedToLoadSettings": "Einstellungen konnten nicht geladen werden: {error}",
"failed": "Fehlgeschlagen: {error}",
"logoUploadFailed": "Logo-Upload fehlgeschlagen: {error}",
"failedToRemoveLogo": "Logo konnte nicht entfernt werden: {error}",
"updateFailed": "Aktualisierung fehlgeschlagen: {error}",
"passwordResetFailed": "Passwort-Zuruecksetzung fehlgeschlagen: {error}",
"selectFileFirst": "Bitte waehlen Sie zuerst eine Datei aus.",
"passwordsDoNotMatch": "Passwoerter stimmen nicht ueberein.",
"failedToLoadCredentials": "Zugangsdaten konnten nicht geladen werden: {error}",
"azureNotConfigured": "Azure AD ist nicht konfiguriert.",
"azureLoginFailed": "Azure AD Anmeldung fehlgeschlagen: {error}",
"actionFailed": "{action} fehlgeschlagen: {error}"
},
"messages": {
"systemSettingsSaved": "Systemeinstellungen gespeichert.",
"npmSettingsSaved": "NPM Einstellungen gespeichert.",
"imageSettingsSaved": "Image Einstellungen gespeichert.",
"brandingNameSaved": "Branding-Einstellungen gespeichert.",
"logoUploaded": "Logo erfolgreich hochgeladen.",
"logoRemoved": "Logo entfernt.",
"azureSettingsSaved": "Azure AD Einstellungen gespeichert.",
"passwordChanged": "Passwort erfolgreich geaendert.",
"setupUrlCopied": "Setup URL in die Zwischenablage kopiert.",
"copiedToClipboard": "In die Zwischenablage kopiert.",
"userCreated": "Benutzer '{username}' erstellt.",
"userDeleted": "Benutzer '{username}' geloescht.",
"passwordResetFor": "Passwort fuer '{username}' zurueckgesetzt.",
"newPasswordAlert": "Neues Passwort fuer '{username}':\n\n{password}\n\nBitte speichern Sie dieses Passwort jetzt. Es wird nicht erneut angezeigt.",
"confirmDeleteUser": "Benutzer '{username}' loeschen? Dies kann nicht rueckgaengig gemacht werden.",
"confirmResetPassword": "Passwort fuer '{username}' zuruecksetzen? Ein neues zufaelliges Passwort wird generiert."
}
}

285
static/lang/en.json Normal file
View File

@@ -0,0 +1,285 @@
{
"login": {
"subtitle": "Multi-Tenant Management Platform",
"username": "Username",
"password": "Password",
"signIn": "Sign In",
"signInWithMicrosoft": "Sign in with Microsoft"
},
"nav": {
"newCustomer": "New Customer",
"settings": "Settings",
"monitoring": "Monitoring",
"logout": "Logout"
},
"dashboard": {
"totalCustomers": "Total Customers",
"active": "Active",
"inactive": "Inactive",
"errors": "Errors",
"searchPlaceholder": "Search by name, subdomain, email...",
"allStatuses": "All Statuses",
"statusActive": "Active",
"statusInactive": "Inactive",
"statusDeploying": "Deploying",
"statusError": "Error",
"refresh": "Refresh",
"thId": "ID",
"thName": "Name",
"thSubdomain": "Subdomain",
"thStatus": "Status",
"thDashboard": "Dashboard",
"thDevices": "Devices",
"thCreated": "Created",
"thActions": "Actions",
"noCustomers": "No customers found. Click \"New Customer\" to create one.",
"showing": "Showing {start}-{end} of {total}",
"showingEmpty": "Showing 0 of 0"
},
"customer": {
"back": "Back",
"customer": "Customer",
"edit": "Edit",
"delete": "Delete",
"tabInfo": "Info",
"tabDeployment": "Deployment",
"tabLogs": "Logs",
"tabHealth": "Health",
"name": "Name:",
"company": "Company:",
"subdomain": "Subdomain:",
"email": "Email:",
"maxDevices": "Max Devices:",
"status": "Status:",
"created": "Created:",
"updated": "Updated:",
"notes": "Notes:",
"deploymentStatus": "Status:",
"relayUdpPort": "Relay UDP Port:",
"dashboardPort": "Dashboard Port:",
"containerPrefix": "Container Prefix:",
"deployed": "Deployed:",
"setupUrl": "Setup URL:",
"copy": "Copy",
"open": "Open",
"netbirdLogin": "NetBird Login",
"notAvailable": "Not available",
"showCredentials": "Show Credentials",
"credEmail": "Email",
"credPassword": "Password",
"showHide": "Show/Hide",
"credentialsNotAvailable": "Credentials not available. Admin must complete setup manually at the Setup URL.",
"start": "Start",
"stop": "Stop",
"restart": "Restart",
"reDeploy": "Re-Deploy",
"noDeployment": "No deployment found.",
"deployNow": "Deploy Now",
"containerLogs": "Container Logs",
"noContainerLogs": "No container logs available.",
"noLogsLoaded": "No logs loaded.",
"healthCheck": "Health Check",
"check": "Check",
"clickCheck": "Click \"Check\" to run a health check.",
"healthy": "Healthy",
"unhealthy": "Unhealthy",
"overall": "Overall:",
"thContainer": "Container",
"thContainerStatus": "Status",
"thHealth": "Health",
"thImage": "Image",
"lastCheck": "Last check: {time}",
"openDashboard": "Open Dashboard"
},
"customerModal": {
"newCustomer": "New Customer",
"editCustomer": "Edit Customer",
"nameLabel": "Name *",
"companyLabel": "Company",
"subdomainLabel": "Subdomain *",
"subdomainHint": "Lowercase, alphanumeric + hyphens",
"emailLabel": "Email *",
"maxDevicesLabel": "Max Devices",
"notesLabel": "Notes",
"cancel": "Cancel",
"saveAndDeploy": "Save & Deploy",
"saveChanges": "Save Changes"
},
"deleteModal": {
"title": "Confirm Deletion",
"confirmText": "Are you sure you want to delete customer",
"warning": "This will remove all containers, NPM entries, and data. This action cannot be undone.",
"cancel": "Cancel",
"delete": "Delete"
},
"settings": {
"title": "System Settings",
"tabSystem": "System Configuration",
"tabNpm": "NPM Integration",
"tabImages": "Docker Images",
"tabBranding": "Branding",
"tabUsers": "Users",
"tabAzure": "Azure AD",
"tabSecurity": "Security",
"baseDomain": "Base Domain",
"baseDomainPlaceholder": "yourdomain.com",
"baseDomainHint": "Customers get subdomains: customer.yourdomain.com",
"adminEmail": "Admin Email",
"adminEmailPlaceholder": "admin@yourdomain.com",
"dataDir": "Data Directory",
"dataDirPlaceholder": "/opt/netbird-instances",
"dockerNetwork": "Docker Network",
"dockerNetworkPlaceholder": "npm-network",
"relayBasePort": "Relay Base Port",
"relayBasePortHint": "First UDP port for relay. Range: base to base+99",
"dashboardBasePort": "Dashboard Base Port",
"dashboardBasePortHint": "Base port for customer dashboards. Customer N gets base+N",
"saveSystemSettings": "Save System Settings",
"npmDescription": "NPM uses JWT authentication. Enter your NPM login credentials (email + password). The system will automatically log in and obtain tokens for API calls.",
"npmApiUrl": "NPM API URL",
"npmApiUrlPlaceholder": "http://nginx-proxy-manager:81/api",
"npmApiUrlHint": "http:// or https:// - must include /api at the end",
"npmLoginEmail": "NPM Login Email",
"npmLoginEmailPlaceholder": "Leave empty to keep current",
"npmLoginPassword": "NPM Login Password",
"npmLoginPasswordPlaceholder": "Leave empty to keep current",
"credentialsSet": "Credentials are set (leave empty to keep current)",
"noCredentials": "No NPM credentials configured",
"saveNpmSettings": "Save NPM Settings",
"testConnection": "Test Connection",
"managementImage": "Management Image",
"managementImagePlaceholder": "netbirdio/management:latest",
"signalImage": "Signal Image",
"signalImagePlaceholder": "netbirdio/signal:latest",
"relayImage": "Relay Image",
"relayImagePlaceholder": "netbirdio/relay:latest",
"dashboardImage": "Dashboard Image",
"dashboardImagePlaceholder": "netbirdio/dashboard:latest",
"saveImageSettings": "Save Image Settings",
"brandingTitle": "Branding Settings",
"companyName": "Company / Application Name",
"companyNamePlaceholder": "NetBird MSP Appliance",
"companyNameHint": "Displayed on login page and navbar",
"logoPreview": "Logo Preview",
"defaultIcon": "Default icon (no logo uploaded)",
"uploadLogo": "Upload Logo (PNG, JPG, SVG, max 500KB)",
"uploadBtn": "Upload",
"removeLogo": "Remove Logo",
"brandingSubtitle": "Subtitle",
"brandingSubtitlePlaceholder": "Multi-Tenant Management Platform",
"brandingSubtitleHint": "Shown below the title on the login page",
"defaultLanguage": "Default Language",
"defaultLanguageHint": "Default language for users without a preference",
"systemDefault": "System Default",
"saveBranding": "Save Branding",
"userManagement": "User Management",
"newUser": "New User",
"thId": "ID",
"thUsername": "Username",
"thEmail": "Email",
"thRole": "Role",
"thAuth": "Auth",
"thLanguage": "Language",
"thStatus": "Status",
"thActions": "Actions",
"azureTitle": "Azure AD / Entra ID Integration",
"enableAzureSso": "Enable Azure AD SSO",
"tenantId": "Tenant ID",
"clientId": "Client ID (Application ID)",
"clientSecret": "Client Secret",
"clientSecretPlaceholder": "Leave empty to keep current",
"secretSet": "Secret is set (leave empty to keep current)",
"noSecret": "No client secret configured",
"saveAzureSettings": "Save Azure AD Settings",
"securityTitle": "Change Admin Password",
"currentPassword": "Current Password",
"newPassword": "New Password (min 12 chars)",
"confirmPassword": "Confirm New Password",
"changePassword": "Change Password"
},
"monitoring": {
"title": "System Monitoring",
"refresh": "Refresh",
"hostResources": "Host Resources",
"hostname": "Hostname",
"cpu": "CPU ({count} cores)",
"memory": "Memory ({used}/{total} GB)",
"disk": "Disk ({used}/{total} GB)",
"allCustomerDeployments": "All Customer Deployments",
"thId": "ID",
"thName": "Name",
"thSubdomain": "Subdomain",
"thStatus": "Status",
"thDeployment": "Deployment",
"thDashboard": "Dashboard",
"thRelayPort": "Relay Port",
"thContainers": "Containers",
"noCustomers": "No customers."
},
"userModal": {
"title": "New User",
"usernameLabel": "Username *",
"passwordLabel": "Password * (min 8 chars)",
"emailLabel": "Email",
"languageLabel": "Default Language",
"cancel": "Cancel",
"createUser": "Create User"
},
"common": {
"loading": "Loading...",
"back": "Back",
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"edit": "Edit",
"view": "View",
"start": "Start",
"stop": "Stop",
"restart": "Restart",
"disable": "Disable",
"enable": "Enable",
"resetPassword": "Reset Password",
"open": "Open",
"active": "Active",
"disabled": "Disabled"
},
"errors": {
"networkError": "Network error \u2014 server not reachable.",
"sessionExpired": "Session expired.",
"requestFailed": "Request failed.",
"serverError": "Server error (HTTP {status}).",
"unknownError": "An unknown error occurred.",
"uploadFailed": "Upload failed.",
"deleteFailed": "Delete failed: {error}",
"failedToLoadSettings": "Failed to load settings: {error}",
"failed": "Failed: {error}",
"logoUploadFailed": "Logo upload failed: {error}",
"failedToRemoveLogo": "Failed to remove logo: {error}",
"updateFailed": "Update failed: {error}",
"passwordResetFailed": "Password reset failed: {error}",
"selectFileFirst": "Please select a file first.",
"passwordsDoNotMatch": "Passwords do not match.",
"failedToLoadCredentials": "Failed to load credentials: {error}",
"azureNotConfigured": "Azure AD is not configured.",
"azureLoginFailed": "Azure AD login failed: {error}",
"actionFailed": "{action} failed: {error}"
},
"messages": {
"systemSettingsSaved": "System settings saved.",
"npmSettingsSaved": "NPM settings saved.",
"imageSettingsSaved": "Image settings saved.",
"brandingNameSaved": "Branding settings saved.",
"logoUploaded": "Logo uploaded successfully.",
"logoRemoved": "Logo removed.",
"azureSettingsSaved": "Azure AD settings saved.",
"passwordChanged": "Password changed successfully.",
"setupUrlCopied": "Setup URL copied to clipboard.",
"copiedToClipboard": "Copied to clipboard.",
"userCreated": "User '{username}' created.",
"userDeleted": "User '{username}' deleted.",
"passwordResetFor": "Password reset for '{username}'.",
"newPasswordAlert": "New password for '{username}':\n\n{password}\n\nPlease save this password now. It will not be shown again.",
"confirmDeleteUser": "Delete user '{username}'? This cannot be undone.",
"confirmResetPassword": "Reset password for '{username}'? A new random password will be generated."
}
}