feat: добавлена возможность ручного ввода времени и трафика

- Добавлены custom input поля для expiration (секунды) и traffic (МБ)
- Добавлена функциональность редактирования клиента
- Исправлена migration 007 (AFTER expires_at)
- Удалены дублирующиеся миграции (0025, 0044, 0053, 0057)
- Удалён старый init.sql (заменён на 001_init.sql)
- Добавлены переводы для custom полей на 6 языках
This commit is contained in:
infosave2007
2025-11-08 10:45:05 +03:00
parent b6cf9cbab7
commit bbb0fbeeb9
15 changed files with 305 additions and 816 deletions
+4
View File
@@ -208,6 +208,10 @@ INSERT INTO translations (language_code, translation_key, translation_value) VAL
('en', 'clients.traffic_limit', 'Traffic Limit'),
('en', 'clients.unlimited', 'Unlimited'),
('en', 'clients.overlimit', 'Over Limit'),
('en', 'clients.custom_seconds', 'Custom (seconds)'),
('en', 'clients.custom_mb', 'Custom (MB)'),
('en', 'clients.enter_seconds', 'Enter seconds'),
('en', 'clients.enter_megabytes', 'Enter megabytes'),
('en', 'backups.title', 'Server Backups'),
('en', 'backups.create', 'Create Backup'),
('en', 'backups.restore', 'Restore'),
-127
View File
@@ -1,127 +0,0 @@
-- Spanish translations
-- This migration adds Spanish language translations
INSERT INTO translations (language_code, translation_key, translation_value) VALUES
('es', 'auth.email', 'Correo electrónico'),
('es', 'auth.login', 'Iniciar sesión'),
('es', 'auth.name', 'Nombre'),
('es', 'auth.password', 'Contraseña'),
('es', 'auth.register', 'Registrarse'),
('es', 'backups.create', 'Crear copia de seguridad'),
('es', 'backups.create_confirm', '¿Crear copia de seguridad de todos los clientes en este servidor?'),
('es', 'backups.created_success', 'Copia de seguridad creada exitosamente'),
('es', 'backups.delete_confirm', '¿Eliminar esta copia de seguridad permanentemente?'),
('es', 'backups.deleted_success', 'Copia de seguridad eliminada exitosamente'),
('es', 'backups.login_required', 'Por favor inicie sesión vía API para gestionar copias de seguridad'),
('es', 'backups.no_backups', 'Aún no hay copias de seguridad'),
('es', 'backups.restore', 'Restaurar'),
('es', 'backups.restore_confirm', '¿Restaurar clientes desde esta copia de seguridad? Los clientes existentes no se verán afectados.'),
('es', 'backups.restored_success', 'Restaurado'),
('es', 'backups.title', 'Copias de seguridad del servidor'),
('es', 'clients.actions', 'Acciones'),
('es', 'clients.add', 'Agregar cliente'),
('es', 'clients.create', 'Crear cliente'),
('es', 'clients.delete', 'Eliminar'),
('es', 'clients.download_config', 'Descargar configuración'),
('es', 'clients.expiration', 'Vencimiento'),
('es', 'clients.expired', 'Vencido'),
('es', 'clients.ip', 'Dirección IP'),
('es', 'clients.last_handshake', 'Último contacto'),
('es', 'clients.name', 'Nombre del cliente'),
('es', 'clients.never_expires', 'Nunca vence'),
('es', 'clients.qr_code', 'Código QR'),
('es', 'clients.received', 'Recibido'),
('es', 'clients.restore', 'Restaurar'),
('es', 'clients.revoke', 'Revocar'),
('es', 'clients.sent', 'Enviado'),
('es', 'clients.server', 'Servidor'),
('es', 'clients.status', 'Estado'),
('es', 'clients.sync_stats', 'Sincronizar estadísticas'),
('es', 'clients.title', 'Clientes'),
('es', 'clients.traffic', 'Tráfico'),
('es', 'common.days', 'días'),
('es', 'dashboard.active_clients', 'Clientes activos'),
('es', 'dashboard.add_first_server', 'Agregar primer servidor'),
('es', 'dashboard.get_started', 'Comience agregando su primer servidor VPN'),
('es', 'dashboard.no_servers', 'Aún no hay servidores'),
('es', 'dashboard.quick_actions', 'Acciones rápidas'),
('es', 'dashboard.recent_servers', 'Servidores recientes'),
('es', 'dashboard.title', 'Panel de control'),
('es', 'dashboard.total_clients', 'Total de clientes'),
('es', 'dashboard.total_servers', 'Total de servidores'),
('es', 'dashboard.total_traffic', 'Tráfico total'),
('es', 'dashboard.welcome', 'Bienvenido al Panel de Gestión de Amnezia VPN'),
('es', 'form.cancel', 'Cancelar'),
('es', 'form.close', 'Cerrar'),
('es', 'form.create', 'Crear'),
('es', 'form.loading', 'Cargando...'),
('es', 'form.processing', 'Procesando...'),
('es', 'form.save', 'Guardar'),
('es', 'form.submit', 'Enviar'),
('es', 'form.update', 'Actualizar'),
('es', 'menu.clients', 'Clientes'),
('es', 'menu.dashboard', 'Panel de control'),
('es', 'menu.logout', 'Cerrar sesión'),
('es', 'menu.servers', 'Servidores'),
('es', 'menu.settings', 'Configuración'),
('es', 'menu.users', 'Usuarios'),
('es', 'message.confirm', '¿Está seguro?'),
('es', 'message.deleted', 'Eliminado exitosamente'),
('es', 'message.deployed', 'Implementado exitosamente'),
('es', 'message.error', 'Ha ocurrido un error'),
('es', 'message.saved', 'Guardado exitosamente'),
('es', 'message.success', 'Operación completada exitosamente'),
('es', 'servers.actions', 'Acciones'),
('es', 'servers.add', 'Agregar servidor'),
('es', 'servers.clients', 'Clientes'),
('es', 'servers.delete', 'Eliminar'),
('es', 'servers.deploy', 'Implementar'),
('es', 'servers.edit', 'Editar'),
('es', 'servers.host', 'Host'),
('es', 'servers.name', 'Nombre'),
('es', 'servers.port', 'Puerto'),
('es', 'servers.status', 'Estado'),
('es', 'servers.title', 'Servidores'),
('es', 'servers.view', 'Ver'),
('es', 'settings.actions', 'Acciones'),
('es', 'settings.api_key_configured', 'Clave API configurada'),
('es', 'settings.api_keys', 'Claves API'),
('es', 'settings.api_keys_desc', 'Configurar claves API para servicios externos'),
('es', 'settings.auto_translate', 'Auto-traducir'),
('es', 'settings.change_password', 'Cambiar contraseña'),
('es', 'settings.confirm_password', 'Confirmar contraseña'),
('es', 'settings.confirm_translate', '¿Iniciar traducción automática? Esto puede tomar unos minutos.'),
('es', 'settings.current_password', 'Contraseña actual'),
('es', 'settings.description', 'Gestionar configuración del panel e integraciones API'),
('es', 'settings.error_empty_key', 'La clave API no puede estar vacía'),
('es', 'settings.error_invalid_key', 'Formato de clave API inválido'),
('es', 'settings.error_key_test', 'Prueba de clave API fallida'),
('es', 'settings.for_translation', 'para auto-traducción'),
('es', 'settings.get_key_at', 'Obtenga su clave API en'),
('es', 'settings.key_saved', 'Clave API guardada exitosamente'),
('es', 'settings.keys', 'claves'),
('es', 'settings.language', 'Idioma'),
('es', 'settings.min_6_chars', 'Mínimo 6 caracteres'),
('es', 'settings.new_password', 'Nueva contraseña'),
('es', 'settings.no_api_key', 'No hay clave API configurada. La auto-traducción no funcionará.'),
('es', 'settings.profile', 'Perfil'),
('es', 'settings.progress', 'Progreso'),
('es', 'settings.skip_validation', 'Omitir validación (guardar sin probar)'),
('es', 'settings.translation_complete', 'Traducción completada'),
('es', 'settings.translation_status', 'Estado de traducción'),
('es', 'settings.translations', 'Traducciones'),
('es', 'settings.users', 'Usuarios'),
('es', 'status.active', 'Activo'),
('es', 'status.deploying', 'Implementando'),
('es', 'status.disabled', 'Deshabilitado'),
('es', 'status.error', 'Error'),
('es', 'status.inactive', 'Inactivo'),
('es', 'users.add_user', 'Agregar usuario'),
('es', 'users.administrator', 'Administrador'),
('es', 'users.all_users', 'Todos los usuarios'),
('es', 'users.created', 'Creado'),
('es', 'users.delete_confirm', '¿Eliminar {0}?'),
('es', 'users.role', 'Rol'),
('es', 'users.role_admin', 'Administrador'),
('es', 'users.role_user', 'Usuario')
ON DUPLICATE KEY UPDATE translation_value=VALUES(translation_value);
+4
View File
@@ -46,6 +46,10 @@ INSERT INTO translations (language_code, translation_key, translation_value) VAL
('ru', 'clients.traffic', 'Трафик'),
('ru', 'clients.traffic_limit', 'Лимит трафика'),
('ru', 'clients.unlimited', 'Безлимитно'),
('ru', 'clients.custom_seconds', 'Своё значение (секунды)'),
('ru', 'clients.custom_mb', 'Своё значение (МБ)'),
('ru', 'clients.enter_seconds', 'Введите секунды'),
('ru', 'clients.enter_megabytes', 'Введите мегабайты'),
('ru', 'common.days', 'дней'),
('ru', 'dashboard.active_clients', 'Активные клиенты'),
('ru', 'dashboard.add_first_server', 'Добавить первый сервер'),
+4
View File
@@ -46,6 +46,10 @@ INSERT INTO translations (language_code, translation_key, translation_value) VAL
('es', 'clients.traffic', 'Tráfico'),
('es', 'clients.traffic_limit', 'Límite de tráfico'),
('es', 'clients.unlimited', 'Ilimitado'),
('es', 'clients.custom_seconds', 'Personalizado (segundos)'),
('es', 'clients.custom_mb', 'Personalizado (MB)'),
('es', 'clients.enter_seconds', 'Ingrese segundos'),
('es', 'clients.enter_megabytes', 'Ingrese megabytes'),
('es', 'common.days', 'días'),
('es', 'dashboard.active_clients', 'Clientes activos'),
('es', 'dashboard.add_first_server', 'Agregar primer servidor'),
-127
View File
@@ -1,127 +0,0 @@
-- German translations
-- This migration adds German language translations
INSERT INTO translations (language_code, translation_key, translation_value) VALUES
('de', 'auth.email', 'E-Mail'),
('de', 'auth.login', 'Anmelden'),
('de', 'auth.name', 'Name'),
('de', 'auth.password', 'Passwort'),
('de', 'auth.register', 'Registrieren'),
('de', 'backups.create', 'Backup erstellen'),
('de', 'backups.create_confirm', 'Backup aller Clients auf diesem Server erstellen?'),
('de', 'backups.created_success', 'Backup erfolgreich erstellt'),
('de', 'backups.delete_confirm', 'Dieses Backup endgültig löschen?'),
('de', 'backups.deleted_success', 'Backup erfolgreich gelöscht'),
('de', 'backups.login_required', 'Bitte melden Sie sich über die API an, um Backups zu verwalten'),
('de', 'backups.no_backups', 'Noch keine Backups'),
('de', 'backups.restore', 'Wiederherstellen'),
('de', 'backups.restore_confirm', 'Clients aus diesem Backup wiederherstellen? Bestehende Clients bleiben unberührt.'),
('de', 'backups.restored_success', 'Wiederhergestellt'),
('de', 'backups.title', 'Server-Backups'),
('de', 'clients.actions', 'Aktionen'),
('de', 'clients.add', 'Client hinzufügen'),
('de', 'clients.create', 'Client erstellen'),
('de', 'clients.delete', 'Löschen'),
('de', 'clients.download_config', 'Konfiguration herunterladen'),
('de', 'clients.expiration', 'Ablaufdatum'),
('de', 'clients.expired', 'Abgelaufen'),
('de', 'clients.ip', 'IP-Adresse'),
('de', 'clients.last_handshake', 'Letzter Handshake'),
('de', 'clients.name', 'Client-Name'),
('de', 'clients.never_expires', 'Läuft nie ab'),
('de', 'clients.qr_code', 'QR-Code'),
('de', 'clients.received', 'Empfangen'),
('de', 'clients.restore', 'Wiederherstellen'),
('de', 'clients.revoke', 'Widerrufen'),
('de', 'clients.sent', 'Gesendet'),
('de', 'clients.server', 'Server'),
('de', 'clients.status', 'Status'),
('de', 'clients.sync_stats', 'Statistiken synchronisieren'),
('de', 'clients.title', 'Clients'),
('de', 'clients.traffic', 'Datenverkehr'),
('de', 'common.days', 'Tage'),
('de', 'dashboard.active_clients', 'Aktive Clients'),
('de', 'dashboard.add_first_server', 'Ersten Server hinzufügen'),
('de', 'dashboard.get_started', 'Beginnen Sie mit dem Hinzufügen Ihres ersten VPN-Servers'),
('de', 'dashboard.no_servers', 'Noch keine Server'),
('de', 'dashboard.quick_actions', 'Schnellaktionen'),
('de', 'dashboard.recent_servers', 'Aktuelle Server'),
('de', 'dashboard.title', 'Dashboard'),
('de', 'dashboard.total_clients', 'Gesamtzahl Clients'),
('de', 'dashboard.total_servers', 'Gesamtzahl Server'),
('de', 'dashboard.total_traffic', 'Gesamter Datenverkehr'),
('de', 'dashboard.welcome', 'Willkommen im Amnezia VPN Verwaltungspanel'),
('de', 'form.cancel', 'Abbrechen'),
('de', 'form.close', 'Schließen'),
('de', 'form.create', 'Erstellen'),
('de', 'form.loading', 'Lädt...'),
('de', 'form.processing', 'Verarbeitung...'),
('de', 'form.save', 'Speichern'),
('de', 'form.submit', 'Absenden'),
('de', 'form.update', 'Aktualisieren'),
('de', 'menu.clients', 'Clients'),
('de', 'menu.dashboard', 'Dashboard'),
('de', 'menu.logout', 'Abmelden'),
('de', 'menu.servers', 'Server'),
('de', 'menu.settings', 'Einstellungen'),
('de', 'menu.users', 'Benutzer'),
('de', 'message.confirm', 'Sind Sie sicher?'),
('de', 'message.deleted', 'Erfolgreich gelöscht'),
('de', 'message.deployed', 'Erfolgreich bereitgestellt'),
('de', 'message.error', 'Ein Fehler ist aufgetreten'),
('de', 'message.saved', 'Erfolgreich gespeichert'),
('de', 'message.success', 'Vorgang erfolgreich abgeschlossen'),
('de', 'servers.actions', 'Aktionen'),
('de', 'servers.add', 'Server hinzufügen'),
('de', 'servers.clients', 'Clients'),
('de', 'servers.delete', 'Löschen'),
('de', 'servers.deploy', 'Bereitstellen'),
('de', 'servers.edit', 'Bearbeiten'),
('de', 'servers.host', 'Host'),
('de', 'servers.name', 'Name'),
('de', 'servers.port', 'Port'),
('de', 'servers.status', 'Status'),
('de', 'servers.title', 'Server'),
('de', 'servers.view', 'Ansehen'),
('de', 'settings.actions', 'Aktionen'),
('de', 'settings.api_key_configured', 'API-Schlüssel konfiguriert'),
('de', 'settings.api_keys', 'API-Schlüssel'),
('de', 'settings.api_keys_desc', 'API-Schlüssel für externe Dienste konfigurieren'),
('de', 'settings.auto_translate', 'Automatische Übersetzung'),
('de', 'settings.change_password', 'Passwort ändern'),
('de', 'settings.confirm_password', 'Passwort bestätigen'),
('de', 'settings.confirm_translate', 'Automatische Übersetzung starten? Dies kann einige Minuten dauern.'),
('de', 'settings.current_password', 'Aktuelles Passwort'),
('de', 'settings.description', 'Panel-Konfiguration und API-Integrationen verwalten'),
('de', 'settings.error_empty_key', 'API-Schlüssel darf nicht leer sein'),
('de', 'settings.error_invalid_key', 'Ungültiges API-Schlüssel-Format'),
('de', 'settings.error_key_test', 'API-Schlüssel-Test fehlgeschlagen'),
('de', 'settings.for_translation', 'für automatische Übersetzung'),
('de', 'settings.get_key_at', 'Holen Sie sich Ihren API-Schlüssel bei'),
('de', 'settings.key_saved', 'API-Schlüssel erfolgreich gespeichert'),
('de', 'settings.keys', 'Schlüssel'),
('de', 'settings.language', 'Sprache'),
('de', 'settings.min_6_chars', 'Mindestens 6 Zeichen'),
('de', 'settings.new_password', 'Neues Passwort'),
('de', 'settings.no_api_key', 'Kein API-Schlüssel konfiguriert. Automatische Übersetzung wird nicht funktionieren.'),
('de', 'settings.profile', 'Profil'),
('de', 'settings.progress', 'Fortschritt'),
('de', 'settings.skip_validation', 'Validierung überspringen (ohne Test speichern)'),
('de', 'settings.translation_complete', 'Übersetzung abgeschlossen'),
('de', 'settings.translation_status', 'Übersetzungsstatus'),
('de', 'settings.translations', 'Übersetzungen'),
('de', 'settings.users', 'Benutzer'),
('de', 'status.active', 'Aktiv'),
('de', 'status.deploying', 'Wird bereitgestellt'),
('de', 'status.disabled', 'Deaktiviert'),
('de', 'status.error', 'Fehler'),
('de', 'status.inactive', 'Inaktiv'),
('de', 'users.add_user', 'Benutzer hinzufügen'),
('de', 'users.administrator', 'Administrator'),
('de', 'users.all_users', 'Alle Benutzer'),
('de', 'users.created', 'Erstellt'),
('de', 'users.delete_confirm', '{0} löschen?'),
('de', 'users.role', 'Rolle'),
('de', 'users.role_admin', 'Admin'),
('de', 'users.role_user', 'Benutzer')
ON DUPLICATE KEY UPDATE translation_value=VALUES(translation_value);
+4
View File
@@ -46,6 +46,10 @@ INSERT INTO translations (language_code, translation_key, translation_value) VAL
('de', 'clients.traffic', 'Datenverkehr'),
('de', 'clients.traffic_limit', 'Traffic-Limit'),
('de', 'clients.unlimited', 'Unbegrenzt'),
('de', 'clients.custom_seconds', 'Benutzerdefiniert (Sekunden)'),
('de', 'clients.custom_mb', 'Benutzerdefiniert (MB)'),
('de', 'clients.enter_seconds', 'Sekunden eingeben'),
('de', 'clients.enter_megabytes', 'Megabytes eingeben'),
('de', 'common.days', 'Tage'),
('de', 'dashboard.active_clients', 'Aktive Clients'),
('de', 'dashboard.add_first_server', 'Ersten Server hinzufügen'),
-127
View File
@@ -1,127 +0,0 @@
-- Russian translations
-- This migration adds Russian language translations
INSERT INTO translations (language_code, translation_key, translation_value) VALUES
('ru', 'auth.email', 'Email'),
('ru', 'auth.login', 'Вход'),
('ru', 'auth.name', 'Имя'),
('ru', 'auth.password', 'Пароль'),
('ru', 'auth.register', 'Регистрация'),
('ru', 'backups.create', 'Создать резервную копию'),
('ru', 'backups.create_confirm', 'Создать резервную копию всех клиентов на этом сервере?'),
('ru', 'backups.created_success', 'Резервная копия успешно создана'),
('ru', 'backups.delete_confirm', 'Удалить эту резервную копию навсегда?'),
('ru', 'backups.deleted_success', 'Резервная копия успешно удалена'),
('ru', 'backups.login_required', 'Пожалуйста, войдите через API для управления резервными копиями'),
('ru', 'backups.no_backups', 'Пока нет резервных копий'),
('ru', 'backups.restore', 'Восстановить'),
('ru', 'backups.restore_confirm', 'Восстановить клиентов из этой резервной копии? Существующие клиенты не будут затронуты.'),
('ru', 'backups.restored_success', 'Восстановлено'),
('ru', 'backups.title', 'Резервные копии сервера'),
('ru', 'clients.actions', 'Действия'),
('ru', 'clients.add', 'Добавить клиента'),
('ru', 'clients.create', 'Создать клиента'),
('ru', 'clients.delete', 'Удалить'),
('ru', 'clients.download_config', 'Скачать конфигурацию'),
('ru', 'clients.expiration', 'Срок действия'),
('ru', 'clients.expired', 'Истек'),
('ru', 'clients.ip', 'IP-адрес'),
('ru', 'clients.last_handshake', 'Последнее соединение'),
('ru', 'clients.name', 'Имя клиента'),
('ru', 'clients.never_expires', 'Бессрочно'),
('ru', 'clients.qr_code', 'QR-код'),
('ru', 'clients.received', 'Получено'),
('ru', 'clients.restore', 'Восстановить'),
('ru', 'clients.revoke', 'Отозвать'),
('ru', 'clients.sent', 'Отправлено'),
('ru', 'clients.server', 'Сервер'),
('ru', 'clients.status', 'Статус'),
('ru', 'clients.sync_stats', 'Синхронизировать статистику'),
('ru', 'clients.title', 'Клиенты'),
('ru', 'clients.traffic', 'Трафик'),
('ru', 'common.days', 'дней'),
('ru', 'dashboard.active_clients', 'Активные клиенты'),
('ru', 'dashboard.add_first_server', 'Добавить первый сервер'),
('ru', 'dashboard.get_started', 'Начните с добавления вашего первого VPN-сервера'),
('ru', 'dashboard.no_servers', 'Пока нет серверов'),
('ru', 'dashboard.quick_actions', 'Быстрые действия'),
('ru', 'dashboard.recent_servers', 'Недавние серверы'),
('ru', 'dashboard.title', 'Панель управления'),
('ru', 'dashboard.total_clients', 'Всего клиентов'),
('ru', 'dashboard.total_servers', 'Всего серверов'),
('ru', 'dashboard.total_traffic', 'Общий трафик'),
('ru', 'dashboard.welcome', 'Добро пожаловать в панель управления Amnezia VPN'),
('ru', 'form.cancel', 'Отмена'),
('ru', 'form.close', 'Закрыть'),
('ru', 'form.create', 'Создать'),
('ru', 'form.loading', 'Загрузка...'),
('ru', 'form.processing', 'Обработка...'),
('ru', 'form.save', 'Сохранить'),
('ru', 'form.submit', 'Отправить'),
('ru', 'form.update', 'Обновить'),
('ru', 'menu.clients', 'Клиенты'),
('ru', 'menu.dashboard', 'Панель управления'),
('ru', 'menu.logout', 'Выход'),
('ru', 'menu.servers', 'Серверы'),
('ru', 'menu.settings', 'Настройки'),
('ru', 'menu.users', 'Пользователи'),
('ru', 'message.confirm', 'Вы уверены?'),
('ru', 'message.deleted', 'Успешно удалено'),
('ru', 'message.deployed', 'Успешно развернуто'),
('ru', 'message.error', 'Произошла ошибка'),
('ru', 'message.saved', 'Успешно сохранено'),
('ru', 'message.success', 'Операция успешно завершена'),
('ru', 'servers.actions', 'Действия'),
('ru', 'servers.add', 'Добавить сервер'),
('ru', 'servers.clients', 'Клиенты'),
('ru', 'servers.delete', 'Удалить'),
('ru', 'servers.deploy', 'Развернуть'),
('ru', 'servers.edit', 'Редактировать'),
('ru', 'servers.host', 'Хост'),
('ru', 'servers.name', 'Имя'),
('ru', 'servers.port', 'Порт'),
('ru', 'servers.status', 'Статус'),
('ru', 'servers.title', 'Серверы'),
('ru', 'servers.view', 'Просмотр'),
('ru', 'settings.actions', 'Действия'),
('ru', 'settings.api_key_configured', 'API-ключ настроен'),
('ru', 'settings.api_keys', 'API-ключи'),
('ru', 'settings.api_keys_desc', 'Настройка API-ключей для внешних сервисов'),
('ru', 'settings.auto_translate', 'Автоперевод'),
('ru', 'settings.change_password', 'Изменить пароль'),
('ru', 'settings.confirm_password', 'Подтвердите пароль'),
('ru', 'settings.confirm_translate', 'Начать автоматический перевод? Это может занять несколько минут.'),
('ru', 'settings.current_password', 'Текущий пароль'),
('ru', 'settings.description', 'Управление конфигурацией панели и интеграциями API'),
('ru', 'settings.error_empty_key', 'API-ключ не может быть пустым'),
('ru', 'settings.error_invalid_key', 'Неверный формат API-ключа'),
('ru', 'settings.error_key_test', 'Тест API-ключа не удался'),
('ru', 'settings.for_translation', 'для автоперевода'),
('ru', 'settings.get_key_at', 'Получите ваш API-ключ на'),
('ru', 'settings.key_saved', 'API-ключ успешно сохранен'),
('ru', 'settings.keys', 'ключи'),
('ru', 'settings.language', 'Язык'),
('ru', 'settings.min_6_chars', 'Минимум 6 символов'),
('ru', 'settings.new_password', 'Новый пароль'),
('ru', 'settings.no_api_key', 'API-ключ не настроен. Автоперевод не будет работать.'),
('ru', 'settings.profile', 'Профиль'),
('ru', 'settings.progress', 'Прогресс'),
('ru', 'settings.skip_validation', 'Пропустить проверку (сохранить без тестирования)'),
('ru', 'settings.translation_complete', 'Перевод завершен'),
('ru', 'settings.translation_status', 'Статус перевода'),
('ru', 'settings.translations', 'Переводы'),
('ru', 'settings.users', 'Пользователи'),
('ru', 'status.active', 'Активен'),
('ru', 'status.deploying', 'Развертывание'),
('ru', 'status.disabled', 'Отключен'),
('ru', 'status.error', 'Ошибка'),
('ru', 'status.inactive', 'Неактивен'),
('ru', 'users.add_user', 'Добавить пользователя'),
('ru', 'users.administrator', 'Администратор'),
('ru', 'users.all_users', 'Все пользователи'),
('ru', 'users.created', 'Создан'),
('ru', 'users.delete_confirm', 'Удалить {0}?'),
('ru', 'users.role', 'Роль'),
('ru', 'users.role_admin', 'Администратор'),
('ru', 'users.role_user', 'Пользователь')
ON DUPLICATE KEY UPDATE translation_value=VALUES(translation_value);
-127
View File
@@ -1,127 +0,0 @@
-- French translations
-- This migration adds French language translations
INSERT INTO translations (language_code, translation_key, translation_value) VALUES
('fr', 'auth.email', 'Email'),
('fr', 'auth.login', 'Connexion'),
('fr', 'auth.name', 'Nom'),
('fr', 'auth.password', 'Mot de passe'),
('fr', 'auth.register', 'S''inscrire'),
('fr', 'backups.create', 'Créer une sauvegarde'),
('fr', 'backups.create_confirm', 'Créer une sauvegarde de tous les clients sur ce serveur ?'),
('fr', 'backups.created_success', 'Sauvegarde créée avec succès'),
('fr', 'backups.delete_confirm', 'Supprimer définitivement cette sauvegarde ?'),
('fr', 'backups.deleted_success', 'Sauvegarde supprimée avec succès'),
('fr', 'backups.login_required', 'Veuillez vous connecter via l''API pour gérer les sauvegardes'),
('fr', 'backups.no_backups', 'Aucune sauvegarde pour le moment'),
('fr', 'backups.restore', 'Restaurer'),
('fr', 'backups.restore_confirm', 'Restaurer les clients depuis cette sauvegarde ? Les clients existants ne seront pas affectés.'),
('fr', 'backups.restored_success', 'Restauré'),
('fr', 'backups.title', 'Sauvegardes du serveur'),
('fr', 'clients.actions', 'Actions'),
('fr', 'clients.add', 'Ajouter un client'),
('fr', 'clients.create', 'Créer un client'),
('fr', 'clients.delete', 'Supprimer'),
('fr', 'clients.download_config', 'Télécharger la configuration'),
('fr', 'clients.expiration', 'Expiration'),
('fr', 'clients.expired', 'Expiré'),
('fr', 'clients.ip', 'Adresse IP'),
('fr', 'clients.last_handshake', 'Dernière connexion'),
('fr', 'clients.name', 'Nom du client'),
('fr', 'clients.never_expires', 'N''expire jamais'),
('fr', 'clients.qr_code', 'Code QR'),
('fr', 'clients.received', 'Reçu'),
('fr', 'clients.restore', 'Restaurer'),
('fr', 'clients.revoke', 'Révoquer'),
('fr', 'clients.sent', 'Envoyé'),
('fr', 'clients.server', 'Serveur'),
('fr', 'clients.status', 'Statut'),
('fr', 'clients.sync_stats', 'Synchroniser les statistiques'),
('fr', 'clients.title', 'Clients'),
('fr', 'clients.traffic', 'Trafic'),
('fr', 'common.days', 'jours'),
('fr', 'dashboard.active_clients', 'Clients actifs'),
('fr', 'dashboard.add_first_server', 'Ajouter le premier serveur'),
('fr', 'dashboard.get_started', 'Commencez par ajouter votre premier serveur VPN'),
('fr', 'dashboard.no_servers', 'Aucun serveur pour le moment'),
('fr', 'dashboard.quick_actions', 'Actions rapides'),
('fr', 'dashboard.recent_servers', 'Serveurs récents'),
('fr', 'dashboard.title', 'Tableau de bord'),
('fr', 'dashboard.total_clients', 'Total des clients'),
('fr', 'dashboard.total_servers', 'Total des serveurs'),
('fr', 'dashboard.total_traffic', 'Trafic total'),
('fr', 'dashboard.welcome', 'Bienvenue sur le panneau de gestion Amnezia VPN'),
('fr', 'form.cancel', 'Annuler'),
('fr', 'form.close', 'Fermer'),
('fr', 'form.create', 'Créer'),
('fr', 'form.loading', 'Chargement...'),
('fr', 'form.processing', 'Traitement...'),
('fr', 'form.save', 'Enregistrer'),
('fr', 'form.submit', 'Soumettre'),
('fr', 'form.update', 'Mettre à jour'),
('fr', 'menu.clients', 'Clients'),
('fr', 'menu.dashboard', 'Tableau de bord'),
('fr', 'menu.logout', 'Déconnexion'),
('fr', 'menu.servers', 'Serveurs'),
('fr', 'menu.settings', 'Paramètres'),
('fr', 'menu.users', 'Utilisateurs'),
('fr', 'message.confirm', 'Êtes-vous sûr ?'),
('fr', 'message.deleted', 'Supprimé avec succès'),
('fr', 'message.deployed', 'Déployé avec succès'),
('fr', 'message.error', 'Une erreur est survenue'),
('fr', 'message.saved', 'Enregistré avec succès'),
('fr', 'message.success', 'Opération terminée avec succès'),
('fr', 'servers.actions', 'Actions'),
('fr', 'servers.add', 'Ajouter un serveur'),
('fr', 'servers.clients', 'Clients'),
('fr', 'servers.delete', 'Supprimer'),
('fr', 'servers.deploy', 'Déployer'),
('fr', 'servers.edit', 'Modifier'),
('fr', 'servers.host', 'Hôte'),
('fr', 'servers.name', 'Nom'),
('fr', 'servers.port', 'Port'),
('fr', 'servers.status', 'Statut'),
('fr', 'servers.title', 'Serveurs'),
('fr', 'servers.view', 'Voir'),
('fr', 'settings.actions', 'Actions'),
('fr', 'settings.api_key_configured', 'Clé API configurée'),
('fr', 'settings.api_keys', 'Clés API'),
('fr', 'settings.api_keys_desc', 'Configurer les clés API pour les services externes'),
('fr', 'settings.auto_translate', 'Traduction automatique'),
('fr', 'settings.change_password', 'Changer le mot de passe'),
('fr', 'settings.confirm_password', 'Confirmer le mot de passe'),
('fr', 'settings.confirm_translate', 'Démarrer la traduction automatique ? Cela peut prendre quelques minutes.'),
('fr', 'settings.current_password', 'Mot de passe actuel'),
('fr', 'settings.description', 'Gérer la configuration du panneau et les intégrations API'),
('fr', 'settings.error_empty_key', 'La clé API ne peut pas être vide'),
('fr', 'settings.error_invalid_key', 'Format de clé API invalide'),
('fr', 'settings.error_key_test', 'Test de la clé API échoué'),
('fr', 'settings.for_translation', 'pour la traduction automatique'),
('fr', 'settings.get_key_at', 'Obtenez votre clé API sur'),
('fr', 'settings.key_saved', 'Clé API enregistrée avec succès'),
('fr', 'settings.keys', 'clés'),
('fr', 'settings.language', 'Langue'),
('fr', 'settings.min_6_chars', 'Minimum 6 caractères'),
('fr', 'settings.new_password', 'Nouveau mot de passe'),
('fr', 'settings.no_api_key', 'Aucune clé API configurée. La traduction automatique ne fonctionnera pas.'),
('fr', 'settings.profile', 'Profil'),
('fr', 'settings.progress', 'Progression'),
('fr', 'settings.skip_validation', 'Ignorer la validation (enregistrer sans tester)'),
('fr', 'settings.translation_complete', 'Traduction terminée'),
('fr', 'settings.translation_status', 'État de la traduction'),
('fr', 'settings.translations', 'Traductions'),
('fr', 'settings.users', 'Utilisateurs'),
('fr', 'status.active', 'Actif'),
('fr', 'status.deploying', 'Déploiement'),
('fr', 'status.disabled', 'Désactivé'),
('fr', 'status.error', 'Erreur'),
('fr', 'status.inactive', 'Inactif'),
('fr', 'users.add_user', 'Ajouter un utilisateur'),
('fr', 'users.administrator', 'Administrateur'),
('fr', 'users.all_users', 'Tous les utilisateurs'),
('fr', 'users.created', 'Créé'),
('fr', 'users.delete_confirm', 'Supprimer {0} ?'),
('fr', 'users.role', 'Rôle'),
('fr', 'users.role_admin', 'Administrateur'),
('fr', 'users.role_user', 'Utilisateur')
ON DUPLICATE KEY UPDATE translation_value=VALUES(translation_value);
+4
View File
@@ -46,6 +46,10 @@ INSERT INTO translations (language_code, translation_key, translation_value) VAL
('fr', 'clients.traffic', 'Trafic'),
('fr', 'clients.traffic_limit', 'Limite de trafic'),
('fr', 'clients.unlimited', 'Illimité'),
('fr', 'clients.custom_seconds', 'Personnalisé (secondes)'),
('fr', 'clients.custom_mb', 'Personnalisé (MB)'),
('fr', 'clients.enter_seconds', 'Saisissez les secondes'),
('fr', 'clients.enter_megabytes', 'Saisissez les mégaoctets'),
('fr', 'common.days', 'jours'),
('fr', 'dashboard.active_clients', 'Clients actifs'),
('fr', 'dashboard.add_first_server', 'Ajouter le premier serveur'),
+4
View File
@@ -46,6 +46,10 @@ INSERT INTO translations (language_code, translation_key, translation_value) VAL
('zh', 'clients.traffic', '流量'),
('zh', 'clients.traffic_limit', '流量限制'),
('zh', 'clients.unlimited', '无限制'),
('zh', 'clients.custom_seconds', '自定义(秒)'),
('zh', 'clients.custom_mb', '自定义(MB'),
('zh', 'clients.enter_seconds', '输入秒数'),
('zh', 'clients.enter_megabytes', '输入兆字节'),
('zh', 'common.days', ''),
('zh', 'dashboard.active_clients', '活跃客户端'),
('zh', 'dashboard.add_first_server', '添加第一个服务器'),
+1 -1
View File
@@ -2,5 +2,5 @@
-- This migration adds traffic limit functionality to clients
ALTER TABLE vpn_clients
ADD COLUMN traffic_limit BIGINT UNSIGNED NULL COMMENT 'Traffic limit in bytes (NULL = unlimited)' AFTER traffic_received,
ADD COLUMN traffic_limit BIGINT UNSIGNED NULL COMMENT 'Traffic limit in bytes (NULL = unlimited)' AFTER expires_at,
ADD INDEX idx_traffic_limit (traffic_limit);
-300
View File
@@ -1,300 +0,0 @@
-- Amnezia VPN Panel - Complete Database Schema
-- Single migration file containing all tables and initial data
-- Users table
CREATE TABLE IF NOT EXISTS users (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
email VARCHAR(255) NOT NULL UNIQUE,
password_hash VARCHAR(255) NOT NULL,
name VARCHAR(255) NOT NULL,
role ENUM('admin', 'user') DEFAULT 'user',
preferred_language VARCHAR(10) DEFAULT 'en',
status ENUM('active', 'disabled') DEFAULT 'active',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
last_login_at TIMESTAMP NULL,
INDEX idx_email (email),
INDEX idx_role (role),
INDEX idx_language (preferred_language)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- VPN Servers table
CREATE TABLE IF NOT EXISTS vpn_servers (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
name VARCHAR(255) NOT NULL,
host VARCHAR(255) NOT NULL,
port INT UNSIGNED NOT NULL,
username VARCHAR(255) NOT NULL,
password VARCHAR(255) NOT NULL,
container_name VARCHAR(255) DEFAULT 'amnezia-awg',
vpn_port INT UNSIGNED NULL,
vpn_subnet VARCHAR(50) DEFAULT '10.8.1.0/24',
server_public_key TEXT NULL,
preshared_key TEXT NULL,
awg_params JSON NULL COMMENT 'Jc, Jmin, Jmax, S1, S2, H1-H4',
status ENUM('deploying', 'active', 'stopped', 'error') DEFAULT 'deploying',
deployed_at TIMESTAMP NULL,
last_check_at TIMESTAMP NULL,
error_message TEXT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_user_id (user_id),
INDEX idx_status (status),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- VPN Clients table
CREATE TABLE IF NOT EXISTS vpn_clients (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
server_id INT UNSIGNED NOT NULL,
user_id INT UNSIGNED NOT NULL,
name VARCHAR(255) NOT NULL,
client_ip VARCHAR(50) NOT NULL,
public_key TEXT NOT NULL,
private_key TEXT NOT NULL,
preshared_key TEXT NULL,
config TEXT NULL COMMENT 'Full WireGuard config file',
qr_code LONGTEXT NULL COMMENT 'Base64 encoded QR code image',
bytes_sent BIGINT UNSIGNED DEFAULT 0 COMMENT 'Total bytes sent by client',
bytes_received BIGINT UNSIGNED DEFAULT 0 COMMENT 'Total bytes received by client',
last_handshake TIMESTAMP NULL COMMENT 'Last successful WireGuard handshake',
last_sync_at TIMESTAMP NULL COMMENT 'Last time stats were synced from server',
status ENUM('active', 'disabled') DEFAULT 'active',
expires_at TIMESTAMP NULL COMMENT 'Client expiration date (NULL = never expires)',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_server_id (server_id),
INDEX idx_user_id (user_id),
INDEX idx_status (status),
INDEX idx_expires_at (expires_at),
INDEX idx_last_handshake (last_handshake),
UNIQUE KEY unique_server_client_ip (server_id, client_ip),
FOREIGN KEY (server_id) REFERENCES vpn_servers(id) ON DELETE CASCADE,
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- API Tokens table
CREATE TABLE IF NOT EXISTS api_tokens (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NOT NULL,
token VARCHAR(255) NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL,
last_used_at TIMESTAMP NULL,
expires_at TIMESTAMP NULL,
revoked_at TIMESTAMP NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_token (token),
INDEX idx_user_id (user_id),
FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Settings table
CREATE TABLE IF NOT EXISTS settings (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
user_id INT UNSIGNED NULL COMMENT 'NULL for global settings',
namespace VARCHAR(100) NOT NULL,
`key` VARCHAR(100) NOT NULL,
value JSON NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_setting (user_id, namespace, `key`),
INDEX idx_namespace (namespace)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Languages table
CREATE TABLE IF NOT EXISTS languages (
id INT AUTO_INCREMENT PRIMARY KEY,
code VARCHAR(10) NOT NULL UNIQUE COMMENT 'Language code (en, ru, es, de, fr, zh)',
name VARCHAR(50) NOT NULL COMMENT 'Language name in English',
native_name VARCHAR(50) NOT NULL COMMENT 'Language name in native language',
is_active TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
INDEX idx_code (code),
INDEX idx_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Translations table
CREATE TABLE IF NOT EXISTS translations (
id INT AUTO_INCREMENT PRIMARY KEY,
language_code VARCHAR(10) NOT NULL,
translation_key VARCHAR(255) NOT NULL COMMENT 'Translation key (e.g., menu.dashboard)',
translation_value TEXT NOT NULL COMMENT 'Translated text',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY unique_translation (language_code, translation_key),
FOREIGN KEY (language_code) REFERENCES languages(code) ON DELETE CASCADE,
INDEX idx_key (translation_key),
INDEX idx_language (language_code)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- API Keys table
CREATE TABLE IF NOT EXISTS api_keys (
id INT AUTO_INCREMENT PRIMARY KEY,
service_name VARCHAR(50) NOT NULL UNIQUE COMMENT 'Service name (e.g., openrouter)',
api_key TEXT NOT NULL COMMENT 'API key value',
is_active TINYINT(1) DEFAULT 1,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
INDEX idx_service (service_name),
INDEX idx_active (is_active)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Server Backups table
CREATE TABLE IF NOT EXISTS server_backups (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
server_id INT UNSIGNED NOT NULL,
backup_name VARCHAR(255) NOT NULL COMMENT 'Backup file name',
backup_path VARCHAR(500) NOT NULL COMMENT 'Path to backup file',
backup_size BIGINT UNSIGNED DEFAULT 0 COMMENT 'Backup file size in bytes',
clients_count INT UNSIGNED DEFAULT 0 COMMENT 'Number of clients in backup',
backup_type ENUM('manual', 'automatic') DEFAULT 'manual',
status ENUM('creating', 'completed', 'failed') DEFAULT 'creating',
error_message TEXT NULL COMMENT 'Error message if backup failed',
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
created_by INT UNSIGNED NULL COMMENT 'User who created the backup',
INDEX idx_server_id (server_id),
INDEX idx_status (status),
INDEX idx_created_at (created_at),
FOREIGN KEY (server_id) REFERENCES vpn_servers(id) ON DELETE CASCADE,
FOREIGN KEY (created_by) REFERENCES users(id) ON DELETE SET NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;
-- Insert default admin user
INSERT IGNORE INTO users (email, password_hash, name, role, status)
VALUES ('admin@amnez.ia', '$2y$10$SKEI6ogiWr2gsSG/nELLp.JcfpGhxsDLAAI7gdtTOI3ELz4zJzzPG', 'Administrator', 'admin', 'active');
-- Insert supported languages
INSERT INTO languages (code, name, native_name) VALUES
('en', 'English', 'English'),
('ru', 'Russian', 'Русский'),
('es', 'Spanish', 'Español'),
('de', 'German', 'Deutsch'),
('fr', 'French', 'Français'),
('zh', 'Chinese', '中文')
ON DUPLICATE KEY UPDATE name=VALUES(name);
-- Insert English translations
INSERT INTO translations (language_code, translation_key, translation_value) VALUES
('en', 'auth.email', 'Email'),
('en', 'auth.login', 'Login'),
('en', 'auth.name', 'Name'),
('en', 'auth.password', 'Password'),
('en', 'auth.register', 'Register'),
('en', 'clients.actions', 'Actions'),
('en', 'clients.add', 'Add Client'),
('en', 'clients.create', 'Create Client'),
('en', 'clients.delete', 'Delete'),
('en', 'clients.download_config', 'Download Config'),
('en', 'clients.expiration', 'Expiration'),
('en', 'clients.expired', 'Expired'),
('en', 'clients.never_expires', 'Never expires'),
('en', 'clients.ip', 'IP Address'),
('en', 'clients.last_handshake', 'Last Handshake'),
('en', 'clients.name', 'Client Name'),
('en', 'clients.qr_code', 'QR Code'),
('en', 'clients.received', 'Received'),
('en', 'clients.restore', 'Restore'),
('en', 'clients.revoke', 'Revoke'),
('en', 'clients.sent', 'Sent'),
('en', 'clients.server', 'Server'),
('en', 'clients.status', 'Status'),
('en', 'clients.sync_stats', 'Sync Stats'),
('en', 'clients.title', 'Clients'),
('en', 'clients.traffic', 'Traffic'),
('en', 'backups.title', 'Server Backups'),
('en', 'backups.create', 'Create Backup'),
('en', 'backups.restore', 'Restore'),
('en', 'backups.no_backups', 'No backups yet'),
('en', 'backups.create_confirm', 'Create backup of all clients on this server?'),
('en', 'backups.restore_confirm', 'Restore clients from this backup? Existing clients will not be affected.'),
('en', 'backups.delete_confirm', 'Delete this backup permanently?'),
('en', 'backups.created_success', 'Backup created successfully'),
('en', 'backups.restored_success', 'Restored'),
('en', 'backups.deleted_success', 'Backup deleted successfully'),
('en', 'backups.login_required', 'Please login via API to manage backups'),
('en', 'common.days', 'days'),
('en', 'dashboard.active_clients', 'Active Clients'),
('en', 'dashboard.add_first_server', 'Add First Server'),
('en', 'dashboard.get_started', 'Get started by adding your first VPN server'),
('en', 'dashboard.no_servers', 'No servers yet'),
('en', 'dashboard.quick_actions', 'Quick Actions'),
('en', 'dashboard.recent_servers', 'Recent Servers'),
('en', 'dashboard.title', 'Dashboard'),
('en', 'dashboard.total_clients', 'Total Clients'),
('en', 'dashboard.total_servers', 'Total Servers'),
('en', 'dashboard.total_traffic', 'Total Traffic'),
('en', 'dashboard.welcome', 'Welcome to Amnezia VPN Management Panel'),
('en', 'form.cancel', 'Cancel'),
('en', 'form.close', 'Close'),
('en', 'form.create', 'Create'),
('en', 'form.loading', 'Loading...'),
('en', 'form.processing', 'Processing...'),
('en', 'form.save', 'Save'),
('en', 'form.submit', 'Submit'),
('en', 'form.update', 'Update'),
('en', 'menu.clients', 'Clients'),
('en', 'menu.dashboard', 'Dashboard'),
('en', 'menu.logout', 'Logout'),
('en', 'menu.servers', 'Servers'),
('en', 'menu.settings', 'Settings'),
('en', 'menu.users', 'Users'),
('en', 'message.confirm', 'Are you sure?'),
('en', 'message.deleted', 'Deleted successfully'),
('en', 'message.deployed', 'Deployed successfully'),
('en', 'message.error', 'An error occurred'),
('en', 'message.saved', 'Saved successfully'),
('en', 'message.success', 'Operation completed successfully'),
('en', 'servers.actions', 'Actions'),
('en', 'servers.add', 'Add Server'),
('en', 'servers.clients', 'Clients'),
('en', 'servers.delete', 'Delete'),
('en', 'servers.deploy', 'Deploy'),
('en', 'servers.edit', 'Edit'),
('en', 'servers.host', 'Host'),
('en', 'servers.name', 'Name'),
('en', 'servers.port', 'Port'),
('en', 'servers.status', 'Status'),
('en', 'servers.title', 'Servers'),
('en', 'servers.view', 'View'),
('en', 'settings.actions', 'Actions'),
('en', 'settings.api_keys', 'API Keys'),
('en', 'settings.api_keys_desc', 'Configure API keys for external services'),
('en', 'settings.auto_translate', 'Auto-translate'),
('en', 'settings.change_password', 'Change Password'),
('en', 'settings.confirm_password', 'Confirm Password'),
('en', 'settings.confirm_translate', 'Start automatic translation? This may take a few minutes.'),
('en', 'settings.current_password', 'Current Password'),
('en', 'settings.description', 'Manage panel configuration and API integrations'),
('en', 'settings.error_empty_key', 'API key cannot be empty'),
('en', 'settings.error_invalid_key', 'Invalid API key format'),
('en', 'settings.error_key_test', 'API key test failed'),
('en', 'settings.for_translation', 'for auto-translation'),
('en', 'settings.get_key_at', 'Get your API key at'),
('en', 'settings.key_saved', 'API key saved successfully'),
('en', 'settings.keys', 'keys'),
('en', 'settings.language', 'Language'),
('en', 'settings.min_6_chars', 'Minimum 6 characters'),
('en', 'settings.new_password', 'New Password'),
('en', 'settings.profile', 'Profile'),
('en', 'settings.progress', 'Progress'),
('en', 'settings.translations', 'Translations'),
('en', 'settings.translation_complete', 'Translation completed'),
('en', 'settings.translation_status', 'Translation Status'),
('en', 'settings.users', 'Users'),
('en', 'status.active', 'Active'),
('en', 'status.deploying', 'Deploying'),
('en', 'status.disabled', 'Disabled'),
('en', 'status.error', 'Error'),
('en', 'status.inactive', 'Inactive'),
('en', 'users.add_user', 'Add User'),
('en', 'users.all_users', 'All Users'),
('en', 'users.administrator', 'Administrator'),
('en', 'users.created', 'Created'),
('en', 'users.delete_confirm', 'Delete {0}?'),
('en', 'users.role', 'Role'),
('en', 'users.role_admin', 'Admin'),
('en', 'users.role_user', 'User'),
('en', 'settings.api_key_configured', 'API Key Configured'),
('en', 'settings.no_api_key', 'No API key configured. Auto-translation will not work.'),
('en', 'settings.skip_validation', 'Skip validation (save without testing)')
ON DUPLICATE KEY UPDATE translation_value=VALUES(translation_value);