Unifi-Voucher-Tool/lang/en.php
Friederich Loheide 61810eb050 Display-Seiten: Gäste holen sich den Zugang selbst
Für Empfang, Lobby oder Tagungsraum lässt sich je Site eine öffentliche
Seite anlegen (kiosk.php), die auf einem Bildschirm oder Tablet läuft:
ein großer Knopf, ein Klick, ein Zugangscode mit QR-Code. Nach einer
einstellbaren Anzeigedauer springt der Bildschirm zurück, damit der
nächste Gast nicht den Code seines Vorgängers sieht.

Verwaltung unter Administration → Display-Seiten:
- Site und optionales Voucher-Profil (bestimmt Laufzeit, Geräte, QoS)
- eigene Überschrift und Text für den Bildschirm
- Codes pro Tag, Wartezeit zwischen zwei Codes, Anzeigedauer
- geheimer Link zum Kopieren, als QR-Code anzeigbar und jederzeit
  erneuerbar (der alte Link gilt dann sofort nicht mehr)

Absicherung: der Link ist der Zugang, deshalb Tageslimit und Wartezeit
je Display, CSRF-Token am Formular, `noindex` im Kopf und ein Eintrag im
Audit-Log für jeden ausgegebenen Code. Webhooks werden für Kiosk-Codes
bewusst nicht ausgelöst – ein Empfangsdisplay würde den Kanal fluten.

Technik:
- neue Tabelle `kiosks`, `vouchers.kiosk_id` hält die Herkunft fest
  (Migration 0005, database.sql nachgezogen)
- includes/Kiosk.php kapselt Token, Limits und Profil-Auflösung
- includes/VoucherService.php bündelt die Voucher-Erstellung, die vorher
  in index.php lag und für den Kiosk ein zweites Mal nötig gewesen wäre
- Startbildschirm zeigt zusätzlich einen QR auf sich selbst, damit Gäste
  die Seite am eigenen Handy öffnen können

Tests: 9 neue Fälle für Token-Prüfung, Wartezeit, Tageslimit und
Profil-Auflösung (38 Tests gesamt), PHPStan deckt Kiosk.php mit ab.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-23 16:51:50 +00:00

609 lines
34 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?php
return [
// Navigation
'nav_group_overview'=> 'Overview',
'nav_group_manage' => 'Management',
'nav_group_system' => 'System',
'nav_dashboard' => 'Dashboard',
'nav_sites' => 'Manage Sites',
'nav_users' => 'Manage Users',
'nav_vouchers' => 'Live Vouchers',
'nav_templates' => 'Voucher Profiles',
'nav_audit_log' => 'Audit Log',
'nav_reports' => 'Reporting',
'nav_import' => 'Voucher Import',
'nav_settings' => 'Settings',
'nav_api_keys' => 'API Keys',
'nav_security' => 'Security (2FA)',
'nav_integrations' => 'Integration & Maintenance',
'nav_backup' => 'Backup & Restore',
'nav_update' => 'System Update',
'nav_back' => 'Back to Home',
'nav_administration'=> 'Administration',
// Common buttons
'btn_save' => 'Save',
'btn_cancel' => 'Cancel',
'btn_add' => 'Add',
'btn_edit' => 'Edit',
'btn_delete' => 'Delete',
'btn_create' => 'Create',
'btn_close' => 'Close',
'btn_back' => 'Back',
'btn_login' => 'Sign In',
'btn_logout' => 'Sign Out',
'btn_refresh' => 'Refresh',
'btn_export_csv' => 'Export CSV',
'btn_print' => 'Print',
'btn_send' => 'Send',
'btn_test' => 'Test',
'btn_generate' => 'Generate',
'btn_copy' => 'Copy',
'btn_new_code' => 'Create Another Code',
// Common labels
'label_name' => 'Name',
'label_email' => 'Email',
'label_password' => 'Password',
'label_status' => 'Status',
'label_actions' => 'Actions',
'label_created' => 'Created',
'label_site' => 'Location',
'label_sites' => 'Sites',
'label_role' => 'Role',
'label_code' => 'Code',
'label_note' => 'Note',
'label_usage' => 'Usage',
'label_expires' => 'Expires',
'label_devices' => 'Devices',
'label_duration' => 'Duration',
'label_description' => 'Description',
'label_language' => 'Language',
// Status texts
'status_active' => 'Active',
'status_inactive' => 'Inactive',
'status_valid' => 'Valid',
'status_used' => 'Used',
'status_expired' => 'Expired',
'status_admin' => 'Admin',
'status_user' => 'User',
'status_public' => 'Public',
'status_all' => 'All',
// Dashboard
'dashboard_title' => 'Dashboard',
'dashboard_subtitle'=> 'Overview of your UniFi Voucher System',
'dashboard_active_sites' => 'Active Sites',
'dashboard_users' => 'Users',
'dashboard_valid' => 'Valid Vouchers',
'dashboard_used' => 'Used',
'dashboard_expired' => 'Expired',
'dashboard_total' => 'Total',
'dashboard_live_refresh' => 'Live Refresh',
'dashboard_trend' => 'Voucher Trend (Last 7 Days)',
'dashboard_top_users'=> 'Top 5 Users (Last 30 Days)',
'dashboard_recent' => 'Recent Vouchers (from Database)',
'dashboard_creator' => 'Creator',
'dashboard_public' => 'Public',
'dashboard_vouchers_per_site' => 'Live: Vouchers per Site',
'dashboard_no_data' => 'No data available yet',
'dashboard_no_vouchers' => 'No vouchers created yet',
// Voucher creation
'voucher_name_label' => 'Voucher Name *',
'voucher_name_hint' => 'e.g. Meeting Room 3, Guest John Doe',
'voucher_devices_label' => 'How many devices may connect? *',
'voucher_site_label' => 'Location *',
'voucher_site_select' => 'Please select...',
'voucher_email_send' => 'Send code via email',
'voucher_email_label' => 'Recipient email address',
'voucher_email_hint' => 'guest@example.com',
'voucher_create_btn' => 'Create Voucher',
'voucher_creating' => 'Creating Voucher...',
'voucher_success_title' => 'Access code created',
'voucher_copy_hint' => 'Tap the code to copy it',
'app_subtitle' => 'Create Wi-Fi access codes in seconds for guests, teams and events.',
'voucher_validity' => 'Valid for {minutes} minutes from creation',
'voucher_qr_label' => 'Scan QR code to connect',
'voucher_print_btn' => 'Print Code',
'voucher_no_sites' => 'No available sites found.',
'voucher_no_sites_admin'=> 'Click here to create sites',
'voucher_no_sites_user' => 'Please contact your administrator.',
'voucher_template_select'=> '-- No Profile (manual) --',
'voucher_template_label'=> 'Quick Profile (optional)',
// Bulk creation
'bulk_tab' => 'Single',
'bulk_tab_bulk' => 'Create Multiple',
'bulk_quantity' => 'Number of Vouchers',
'bulk_quantity_hint'=> 'How many vouchers should be created?',
'bulk_name_prefix' => 'Name / Prefix',
'bulk_create_btn' => 'Create {count} Vouchers',
'bulk_creating' => 'Creating {count} vouchers...',
'bulk_success' => '{count} vouchers created successfully!',
'bulk_print_all' => 'Print All',
'bulk_results' => 'Created Vouchers ({count})',
'bulk_results_hint' => 'All codes are valid immediately and can be printed or copied.',
// Templates
'templates_title' => 'Voucher Profiles',
'templates_subtitle'=> 'Predefined voucher configurations',
'templates_add' => 'New Profile',
'templates_name' => 'Profile Name',
'templates_devices' => 'Max. Devices',
'templates_duration'=> 'Validity (Minutes)',
'templates_desc' => 'Description (optional)',
'templates_none' => 'No profiles found.',
'templates_add_hint'=> 'Create profiles for frequently used voucher configurations.',
'templates_edit' => 'Edit Profile',
'templates_added' => 'Profile created successfully!',
'templates_updated' => 'Profile updated successfully!',
'templates_deleted' => 'Profile deleted successfully!',
// Users
'users_title' => 'Manage Users',
'users_add' => 'New User',
'users_all' => 'All Users',
'users_site_access' => 'Site Access',
'users_last_login' => 'Last Login',
'users_never' => 'Never',
'users_you' => 'You',
'users_all_sites' => 'All Sites',
'users_none' => 'None',
'users_add_title' => 'Create New User',
'users_edit_title' => 'Edit User',
'users_admin_check' => 'Administrator Rights',
'users_admin_hint' => 'Admins have access to all sites and settings',
'users_password_hint'=> 'At least 8 characters',
'users_site_hint' => 'Select the sites this user should have access to',
'users_no_sites' => 'No sites available. Please create sites first.',
'users_added' => 'User created successfully!',
'users_updated' => 'User updated successfully!',
'users_deleted' => 'User deleted successfully!',
'users_notified' => ' Notification sent.',
'users_none_found' => 'No users found',
'users_save' => 'Create User',
'users_save_edit' => 'Save Changes',
'users_reset_pw' => 'Send Password Reset Link',
// Sites
'sites_title' => 'Manage Sites',
'sites_add' => 'Add New Site',
'sites_add_title' => 'Add New Site',
'sites_edit_title' => 'Edit Site',
'sites_name' => 'Site Name *',
'sites_site_id' => 'UniFi Site ID *',
'sites_controller' => 'Controller URL *',
'sites_username' => 'Username *',
'sites_password' => 'Password *',
'sites_password_edit'=> 'New Password',
'sites_password_hint'=> 'Leave blank to keep current password',
'sites_public' => 'Public Access (usable without login)',
'sites_none' => 'No sites configured yet. Add your first site!',
'sites_added' => 'Site added successfully!',
'sites_updated' => 'Site updated successfully!',
'sites_deleted' => 'Site deleted successfully!',
'sites_testing' => 'Testing connection...',
'sites_deactivate' => 'Deactivate',
'sites_activate' => 'Activate',
// Voucher admin list
'vouchers_title' => 'Live Voucher Management',
'vouchers_subtitle' => 'Vouchers are fetched directly from the UniFi Controller',
'vouchers_select_site'=> 'Select Site',
'vouchers_select_hint'=> '-- Select Site --',
'vouchers_last_sync'=> 'Last Sync',
'vouchers_no_sites' => 'No active sites available',
'vouchers_search' => 'Search (code, name...)',
'vouchers_filter_all'=> 'All',
'vouchers_filter_valid'=> 'Valid',
'vouchers_filter_used'=> 'Used',
'vouchers_filter_expired'=> 'Expired',
'vouchers_none' => 'No vouchers found.',
'vouchers_per_page' => 'per page',
'vouchers_page_of' => 'Page {current} of {total}',
// Audit Log
'audit_title' => 'Audit Log',
'audit_subtitle' => 'All system actions at a glance',
'audit_action' => 'Action',
'audit_user' => 'User',
'audit_details' => 'Details',
'audit_ip' => 'IP Address',
'audit_time' => 'Time',
'audit_entity' => 'Entity',
'audit_filter_all' => 'All Actions',
'audit_none' => 'No entries found.',
'audit_filter' => 'Filter',
// Settings
'settings_title' => 'Settings',
'settings_subtitle' => 'System configuration and customization',
'settings_tab_branding' => 'Design',
'settings_branding_intro' => 'Colours and shapes for the whole interface front end and administration.',
'settings_brand_accent' => 'Accent colour (light)',
'settings_brand_accent_hint' => 'Buttons, active navigation, links. Derived shades are calculated automatically.',
'settings_brand_accent_dark' => 'Accent colour (dark mode)',
'settings_brand_accent_dark_hint' => 'Usually a lighter variant of the base colour for dark mode.',
'settings_brand_gradient_from'=> 'Brand gradient: start',
'settings_brand_gradient_to' => 'Brand gradient: end',
'settings_brand_gradient_hint'=> 'Used for the logo tile, avatars and the voucher card.',
'settings_brand_radius' => 'Corner radius',
'settings_brand_radius_sharp' => 'Sharp',
'settings_brand_radius_default'=> 'Default',
'settings_brand_radius_round' => 'Round',
'settings_brand_preview' => 'Preview',
'settings_brand_link' => 'Example link',
'settings_image_url_placeholder' => 'https://… or upload a file',
'settings_image_remove' => 'Remove image',
'settings_upload_hint' => 'PNG, JPG, WEBP, GIF or SVG 3 MB maximum.',
'upload_error_generic' => 'The file could not be uploaded.',
'upload_error_size' => 'The file is too large (3 MB maximum).',
'upload_error_type' => 'This file type is not supported.',
'upload_error_dir' => 'The uploads/ directory is not writable.',
'settings_tab_login' => 'Login page',
'settings_login_intro' => 'Appearance and wording of the sign-in page. Empty fields fall back to the defaults.',
'settings_login_panel' => 'Show left image column (split screen)',
'settings_login_brand' => 'Company name',
'settings_login_brand_hint' => 'Empty = application title is used.',
'settings_login_logo' => 'Logo (URL)',
'settings_login_logo_hint' => 'Empty = general logo from the "General" tab.',
'settings_login_claim_title' => 'Headline',
'settings_login_claim_text' => 'Description',
'settings_login_features' => 'Bullet points',
'settings_login_features_hint'=> 'One bullet per line. Leave empty to hide the list.',
'settings_login_footer' => 'Footer',
'settings_login_bg_image' => 'Background image (URL)',
'settings_login_bg_image_hint'=> 'Optional. Displayed full-bleed; without an image the gradient is used.',
'settings_login_bg_from' => 'Gradient: start colour',
'settings_login_bg_to' => 'Gradient: end colour',
'settings_login_overlay' => 'Image dimming (%)',
'settings_login_overlay_hint' => '090%. Higher values keep text readable on bright images.',
'settings_login_preview' => 'Open preview',
'api_title' => 'API keys',
'api_subtitle' => 'Access for external systems with scope and rate limit.',
'api_new_key' => 'New key',
'api_new_key_hint' => 'Copy it now for security reasons it will not be shown again.',
'api_create_title' => 'Create a new API key',
'api_label_name' => 'Label',
'api_name_placeholder' => 'e.g. booking system, lobby terminal',
'api_label_scope' => 'Permission',
'api_scope_write' => 'Read + create',
'api_scope_read' => 'Read only',
'api_scope_write_short' => 'Read+create',
'api_scope_read_short' => 'read only',
'api_label_limit' => 'Limit (req./min)',
'api_limit_title' => '0 = unlimited',
'api_existing' => 'Existing keys',
'api_none' => 'No API keys created yet.',
'api_col_prefix' => 'Prefix',
'api_col_scope' => 'Scope',
'api_col_limit' => 'Limit',
'api_col_last_used' => 'Last used',
'api_col_created_by' => 'Created by',
'api_state_active' => 'active',
'api_state_blocked' => 'blocked',
'api_action_block' => 'Block',
'api_action_unblock' => 'Activate',
'api_delete_confirm' => 'Delete key?',
'api_usage' => 'Usage',
'api_usage_hint' => 'Authenticate using header',
'api_openapi' => 'OpenAPI specification (import into Postman/Swagger):',
'api_created' => 'API key created.',
'api_deleted' => 'API key deleted.',
'api_toggled' => 'Status changed.',
'api_name_required' => 'Please enter a label.',
'api_created_once' => 'API key created. Copy it NOW it is shown only once!',
'api_status_updated' => 'Status updated.',
'int_title' => 'Integration & maintenance',
'int_subtitle' => 'SSO, webhooks, SMS delivery and retention periods.',
'int_security' => 'Security policy',
'int_security_hint' => 'Enforces two-factor authentication for all administrator accounts (local accounts). Admins without 2FA are sent to the setup on their next action.',
'int_enforce_2fa' => 'Two-factor authentication mandatory for administrators',
'int_daily_limit' => 'Daily voucher limit per non-admin user (0 = unlimited)',
'int_session_driver' => 'Session storage',
'int_session_php' => 'PHP default (files)',
'int_session_db' => 'Database (enables "sign out everywhere")',
'int_captcha' => 'Captcha in public mode',
'int_captcha_off' => 'Off',
'int_captcha_math' => 'Arithmetic question (no external service)',
'int_secret_set' => ' (set)',
'int_secret_placeholder' => '••••••• (empty = unchanged)',
'int_proxy' => 'Reverse proxy',
'int_proxy_hint' => 'IP addresses of trusted proxies (comma separated). Only then is the real client IP taken from',
'int_proxy_hint2' => 'for rate limiting and the audit log.',
'int_webhook' => 'Webhook notifications',
'int_webhook_hint' => 'Slack, Microsoft Teams or generic JSON webhook URL. Triggered when a voucher is created.',
'int_webhook_active' => 'Webhook active',
'int_webhook_url' => 'Webhook URL',
'int_webhook_test' => 'Send test',
'int_sms' => 'SMS delivery (Twilio)',
'int_sms_hint' => 'Optionally send voucher codes by SMS. Requires a Twilio account.',
'int_sms_active' => 'SMS delivery active',
'int_sms_from' => 'Sender (from)',
'int_sso' => 'Single sign-on (OpenID Connect)',
'int_sso_hint' => 'Generic OIDC provider (e.g. Keycloak, Authentik, Google, Auth0). Redirect URI:',
'int_sso_active' => 'OIDC login active',
'int_sso_button' => 'Button label',
'int_cleanup' => 'Data retention & cleanup (GDPR)',
'int_cleanup_hint' => 'Retention periods in days (0 = disabled). Executed via',
'int_cleanup_hint2' => '(daily recommended).',
'int_cleanup_last' => 'Last run:',
'int_cleanup_expired' => 'Expired vouchers',
'int_cleanup_audit' => 'Audit log',
'int_cleanup_logins' => 'Login attempts',
'int_saved' => 'Settings saved.',
'int_webhook_sent' => 'Test webhook sent.',
'int_webhook_failed' => 'Test webhook failed.',
'int_webhook_test_sent' => 'Test notification sent (provided the webhook is active and the URL valid).',
'sec_token_invalid' => 'Invalid security token',
'sec_setup_expired' => 'Setup expired, please start again.',
'sec_code_invalid' => 'Invalid code. Please try again.',
'sec_enabled' => 'Two-factor authentication is now active. Please store the recovery codes safely!',
'sec_sessions_closed' => 'All other sessions have been signed out.',
'sec_codes_new' => 'New recovery codes generated. The previous ones are now invalid.',
'sec_disabled' => 'Two-factor authentication has been disabled.',
'backup_choose_file' => 'Please choose a backup file.',
'backup_invalid_file' => 'Invalid or foreign backup file.',
'sec_title' => 'Two-factor authentication',
'sec_account' => 'Account:',
'sec_required_hint' => 'For security reasons two-factor authentication is mandatory for administrators. Please set it up now.',
'sec_recovery_codes' => 'Recovery codes',
'sec_recovery_hint' => 'Keep them somewhere safe. Each code works once if you lose access to your app.',
'sec_unavailable' => 'Not available',
'sec_m365_hint' => 'Your account signs in via Microsoft 365. Two-factor authentication is managed in your Microsoft account.',
'sec_active' => 'Active',
'sec_inactive' => 'Inactive',
'sec_active_hint' => 'Every sign-in additionally asks for a code from your authenticator app.',
'sec_codes_left' => 'Remaining recovery codes:',
'sec_regen_codes' => 'Generate new recovery codes',
'sec_disable_confirm' => 'Really disable two-factor authentication?',
'sec_disable' => 'Disable two-factor authentication',
'sec_step_1' => 'Open your authenticator app (Google Authenticator, Authy, Microsoft Authenticator …)',
'sec_step_2' => 'Scan the QR code or enter the secret manually',
'sec_step_3' => 'Enter the six-digit code shown below',
'sec_code_label' => 'Six-digit code',
'sec_enable' => 'Enable two-factor authentication',
'sec_sessions' => 'Active sessions:',
'sec_logout_others_confirm' => 'Sign out all other sessions?',
'sec_logout_others' => 'Sign out on all other devices',
'import_title' => 'Voucher import',
'import_subtitle' => 'Create several vouchers at once from a CSV list.',
'import_card_title' => 'Create several vouchers',
'import_format_hint' => 'One line per voucher:',
'import_format_hint2' => ' max. devices and minutes are optional (defaults apply). 200 lines maximum. Example:',
'import_site' => 'Site',
'import_file' => 'CSV file (optional)',
'import_paste' => '… or paste directly',
'import_confirm' => 'Start the import now?',
'import_submit' => 'Import',
'import_result' => 'Result',
'import_col_code' => 'Code / error',
'import_created' => '{count} vouchers created.',
'backup_title' => 'Backup & restore',
'backup_subtitle' => 'Back up or restore configuration and data.',
'backup_export' => 'Export',
'backup_export_hint' => 'Downloads settings, sites and voucher profiles as JSON. Site passwords stay encrypted with the',
'backup_export_hint2' => 'of this installation a restore on an installation with a different APP_KEY cannot decrypt them.',
'backup_export_btn' => 'Export configuration',
'backup_import' => 'Import / restore',
'backup_import_hint' => 'Existing sites are matched by name + site ID and updated, new ones are added. Profiles are only created if the name does not exist yet. The cron token is never overwritten.',
'backup_opt_settings' => 'Settings',
'backup_opt_sites' => 'Sites',
'backup_opt_templates' => 'Voucher profiles',
'backup_import_confirm' => 'Run the import now?',
'backup_imported' => 'Import finished: {settings} settings, {sites} sites, {templates} profiles.',
'rep_title' => 'Reporting',
'rep_subtitle' => 'Analytics by period, site and user.',
'rep_period' => 'Period',
'rep_days' => 'days',
'rep_csv_daily' => 'CSV (daily)',
'rep_csv_site' => 'CSV (per site)',
'rep_csv_user' => 'CSV (per user)',
'rep_print' => 'Print / PDF',
'rep_total' => 'Vouchers total',
'rep_in_period' => 'Created in {days} days',
'rep_chart_title' => 'Vouchers created ({days} days)',
'rep_per_site' => 'Per site',
'rep_top_users' => 'Top users',
'rep_col_created' => 'Vouchers created',
'rep_no_data' => 'No data',
'label_total' => 'Total',
'label_user' => 'User',
'js_confirm_delete_voucher' => 'Really delete this voucher?',
'js_confirm_delete_user' => 'Really delete this user?',
'js_confirm_delete_site' => 'Do you really want to delete this site?',
'js_confirm_delete_template' => 'Really delete this profile?',
'js_confirm_delete_token' => 'Really delete this token?',
'js_error' => 'Error',
'js_enter_email' => 'Please enter an email address.',
'js_running' => 'Running…',
'js_run_now' => 'Run now',
'js_copied' => 'Copied!',
'js_code_copied' => 'Code copied!',
'js_click_to_copy' => 'Click to copy',
'settings_defaults_hint' => 'These values are used as defaults in the voucher form.',
'settings_cron_what' => 'What does the cron job do?',
'settings_smtp_from_name' => 'Sender name',
'settings_tpl_voucher_mail' => 'Voucher email',
'settings_tpl_user_notify' => 'User notification',
'settings_editor_hint' => 'The editor (TinyMCE, GPL build) is served locally from',
'settings_editor_hint2' => ' no external services are called.',
'settings_print_template' => 'HTML template for voucher printing',
'settings_leave_empty' => 'Empty = leave unchanged',
'sites_id_hint' => 'Found in the UniFi controller URL',
'sites_pw_unchanged' => 'Leave empty = unchanged',
'templates_minutes_hint' => '480 = 8 hours',
'templates_desc_placeholder' => 'Short description for your team',
'audit_all_users' => 'All users',
'label_expires_at' => 'Valid until:',
'label_site_colon' => 'Site:',
'audit_action_voucher_created' => 'Voucher created',
'audit_action_voucher_bulk' => 'Bulk vouchers',
'audit_action_user_login' => 'Login',
'audit_action_user_logout' => 'Logout',
'audit_action_user_created' => 'User created',
'audit_action_user_updated' => 'User updated',
'audit_action_user_deleted' => 'User deleted',
'audit_action_site_added' => 'Site added',
'audit_action_site_updated' => 'Site updated',
'audit_action_site_deleted' => 'Site deleted',
'audit_action_settings_saved' => 'Settings saved',
'audit_action_password_reset' => 'Password reset',
'audit_action_template_created' => 'Profile created',
'audit_action_template_updated' => 'Profile updated',
'audit_action_template_deleted' => 'Profile deleted',
'audit_page_info' => 'Page {page} of {pages} ({total} entries)',
'a11y_skip' => 'Skip to content',
'a11y_theme' => 'Toggle appearance (light/dark)',
'a11y_menu' => 'Open navigation',
'a11y_language' => 'Language',
'a11y_notifications' => 'Notifications',
'audit_system_anon' => 'System/anonymous',
'vouchers_resend' => 'Send by email',
'label_minutes_short' => 'min',
'js_copy' => 'Copy',
'settings_placeholders' => 'Placeholders:',
'settings_card_hint' => '{VOUCHER_CARD} renders the code as a highlighted card in the branded layout.',
'settings_qr_hint' => '{QR_CODE} inserts a QR code containing the voucher code.',
'print_valid_until' => 'Valid until',
'print_devices' => 'devices',
'credit_by' => 'Developed by',
'kiosk_default_headline' => 'Free guest Wi-Fi',
'kiosk_default_subline' => 'Tap the button you will get your personal access code right away.',
'kiosk_button' => 'Get access code',
'kiosk_working' => 'One moment…',
'kiosk_ready' => 'Your access code',
'kiosk_scan_code' => 'Scan the QR code or type the code',
'kiosk_reset_in' => 'This screen resets in {seconds} seconds.',
'kiosk_done' => 'Done',
'kiosk_phone_hint' => 'Or scan with your phone and open it there',
'kiosk_error_cooldown' => 'A code was just issued. Please wait {seconds} seconds.',
'kiosk_error_limit' => 'No more access codes available today. Please ask at the reception desk.',
'kiosk_error_generic' => 'The access code could not be created. Please try again.',
'kiosk_unknown' => 'This page is not available',
'kiosk_unknown_hint' => 'The link is invalid or has been deactivated.',
'audit_action_voucher_kiosk' => 'Voucher taken at display',
'nav_kiosks' => 'Display pages',
'kiosks_title' => 'Display pages',
'kiosks_subtitle' => 'Public pages for screens and tablets guests get their access themselves.',
'kiosks_add' => 'Add display page',
'kiosks_edit' => 'Edit display page',
'kiosks_empty' => 'No display page created yet.',
'kiosks_no_sites' => 'Create a site first, then you can add a display page for it.',
'kiosks_name' => 'Label',
'kiosks_name_placeholder' => 'e.g. reception ground floor',
'kiosks_name_hint' => 'Appears in the audit log and as the voucher name.',
'kiosks_template' => 'Voucher profile',
'kiosks_no_template' => 'Use default values',
'kiosks_template_hint' => 'Defines duration, device count and bandwidth of the codes issued.',
'kiosks_headline' => 'Headline on screen',
'kiosks_subline' => 'Text below',
'kiosks_daily_limit' => 'Codes per day',
'kiosks_daily_limit_hint' => '0 = unlimited. Protects against misuse if the link gets shared.',
'kiosks_cooldown' => 'Cooldown (seconds)',
'kiosks_cooldown_hint' => 'Delay between two codes on this display.',
'kiosks_display' => 'Display duration (seconds)',
'kiosks_display_hint' => 'After that the screen returns to the start screen.',
'kiosks_active' => 'Display page active',
'kiosks_link' => 'Public link',
'kiosks_open' => 'Open',
'kiosks_qr' => 'QR code',
'kiosks_qr_hint' => 'Put it up next to the screen or photograph it to open the page on a tablet.',
'kiosks_today' => 'today',
'kiosks_total' => 'in total',
'kiosks_renew' => 'Renew link',
'kiosks_renew_confirm' => 'Generate a new link? The previous link will stop working.',
'kiosks_delete_confirm' => 'Really delete this display page?',
'kiosks_added' => 'Display page created.',
'kiosks_updated' => 'Display page saved.',
'kiosks_deleted' => 'Display page deleted.',
'kiosks_token_renewed' => 'New link generated the old one is no longer valid.',
'audit_action_kiosk_created' => 'Display page created',
'audit_action_kiosk_updated' => 'Display page updated',
'audit_action_kiosk_deleted' => 'Display page deleted',
'settings_tab_general' => 'General',
'settings_tab_defaults' => 'Voucher Defaults',
'settings_tab_cron' => 'Cron Sync',
'settings_tab_m365' => 'Microsoft 365',
'settings_tab_smtp' => 'SMTP',
'settings_tab_templates_email' => 'Templates',
'settings_tab_system' => 'System',
'settings_tab_password' => 'Password',
'settings_saved' => 'Settings saved successfully!',
'settings_app_title' => 'Application Title *',
'settings_logo_url' => 'Logo',
'settings_favicon_url' => 'Favicon',
'settings_favicon_hint' => 'Browser tab icon (.ico, .png, .svg)',
'settings_instr_header' => 'Instructions - Headline',
'settings_instr_text' => 'Instructions - Text',
'settings_public_access'=> 'Public Access',
'settings_default_expire' => 'Default Validity (Minutes)',
'settings_default_expire_hint'=> 'Default expiry time for new vouchers (480 = 8 hours)',
'settings_default_devices' => 'Default Device Count',
'settings_default_devices_hint'=> 'Pre-filled value in the voucher form',
'settings_max_devices' => 'Maximum Device Count',
'settings_max_devices_hint' => 'Maximum value a user can select',
'settings_pw_current' => 'Current Password',
'settings_pw_new' => 'New Password',
'settings_pw_confirm' => 'Confirm Password',
'settings_pw_changed' => 'Password changed successfully!',
'settings_pw_minlength' => 'At least 8 characters',
// Login / Auth
'login_title' => 'Sign In',
'auth_claim_title' => 'Wi-Fi guest access, centrally managed.',
'auth_claim_text' => 'Create, deliver and analyse vouchers for every UniFi site from a single interface.',
'auth_feature_1' => 'Vouchers via email, SMS or QR code',
'auth_feature_2' => 'Roles, 2FA and a complete audit log',
'auth_feature_3' => 'Live statistics per site and user',
'login_subtitle' => 'Sign in to continue',
'login_email' => 'Email',
'login_password' => 'Password',
'login_btn' => 'Sign In',
'login_ms' => 'Sign in with Microsoft',
'login_local' => 'Sign in with username and password',
'login_back' => 'Back to Code Creation',
'login_forgot' => 'Forgot password?',
'login_error_empty' => 'Please enter email and password',
'login_error_rate' => 'Too many failed attempts. Please wait 10 minutes.',
'login_error_creds' => 'Invalid email or password',
// Password Reset
'reset_title' => 'Forgot Password',
'reset_subtitle' => 'Enter your email we will send you a reset link.',
'reset_email_label' => 'Email Address',
'reset_send_btn' => 'Send Reset Link',
'reset_success' => 'If an account with this email exists, you will receive an email shortly.',
'reset_back_login' => 'Back to Login',
'reset_new_pw' => 'Set New Password',
'reset_new_pw_label'=> 'New Password',
'reset_confirm_label'=> 'Confirm Password',
'reset_set_btn' => 'Set Password',
'reset_invalid' => 'Invalid or expired reset link.',
'reset_done' => 'Your password has been changed successfully.',
// Errors
'error_csrf' => 'Invalid security token',
'error_login_req' => 'You must be logged in',
'error_no_permission'=> 'No permission for this action',
'error_not_found' => 'Not found',
'error_name_req' => 'Please enter a name',
'error_site_req' => 'Please select a location',
'error_devices_range'=> 'Device count must be between 1 and {max}',
'error_email_invalid'=> 'Invalid email address',
'error_site_no_perm'=> 'No permission for this site',
'error_site_not_found'=> 'Site not found',
'error_voucher_invalid'=> 'UniFi did not return a valid voucher',
'error_connection' => 'Connection to UniFi Controller failed',
'error_fill_all' => 'Please fill in all required fields',
// Hello / User
'hello' => 'Hello, {name}',
'minutes_short' => 'min.',
'hours_short' => 'hrs.',
'never' => 'Never',
'unknown' => 'Unknown',
'or' => 'or',
];