From 5d039484a1604bc1207c7e4785fa89ec8f215a5d Mon Sep 17 00:00:00 2001 From: infosave2007 Date: Fri, 7 Nov 2025 13:36:54 +0300 Subject: [PATCH] Remove tests files --- CHANGELOG.md | 135 ------------------- TESTING.md | 345 ----------------------------------------------- TRAFFIC_STATS.md | 278 -------------------------------------- TRANSLATIONS.md | 142 ------------------- test_qr.php | 59 -------- 5 files changed, 959 deletions(-) delete mode 100644 CHANGELOG.md delete mode 100644 TESTING.md delete mode 100644 TRAFFIC_STATS.md delete mode 100644 TRANSLATIONS.md delete mode 100644 test_qr.php diff --git a/CHANGELOG.md b/CHANGELOG.md deleted file mode 100644 index a8a2891..0000000 --- a/CHANGELOG.md +++ /dev/null @@ -1,135 +0,0 @@ -# Changelog - -All notable changes to Amnezia VPN Web Panel will be documented in this file. - -## [1.1.0] - 2025-11-06 - -### Added -- **Traffic Statistics Tracking** - - Real-time bandwidth monitoring (upload/download) - - Last handshake tracking - - Online/offline status detection - - Formatted stats display (B, KB, MB, GB, TB) - - Manual sync stats button on server and client pages - - Batch stats sync for all clients on server - -- **Client Access Control** - - Revoke client access (temporary disable) - - Restore revoked clients - - Improved delete with proper cleanup - - Status badges (Active/Disabled) - -- **Enhanced UI** - - Traffic columns in client list table - - Last seen timestamp display - - Revoke/Restore/Delete action buttons - - Real-time stats refresh (AJAX) - - Online status indicator (green dot) - - Improved client view page with stats panel - -- **API Endpoints** - - `GET /api/clients/{id}` - Get client with stats - - `POST /api/clients/{id}/revoke` - Revoke client access - - `POST /api/clients/{id}/restore` - Restore client access - - `GET /api/servers/{id}/clients` - Get all clients with stats - - `POST /servers/{id}/sync-stats` - Batch sync server clients - - `POST /clients/{id}/sync-stats` - Sync single client stats - -### Technical -- Database migration `002_add_traffic_stats.sql` -- New columns: `bytes_sent`, `bytes_received`, `last_handshake`, `last_sync_at` -- WireGuard stats parsing from `wg show` output -- Peer removal from wg0.conf using sed -- `wg syncconf` for live config updates - -### Documentation -- Created `TRAFFIC_STATS.md` - Complete traffic stats guide -- API usage examples -- Troubleshooting section - -## [1.0.0] - 2024-11-05 - -### Added -- Initial release of Amnezia VPN Web Management Panel -- Full VPN server deployment via SSH -- AmneziaWG container management on remote servers -- Client configuration creation and management -- QR code generation compatible with Amnezia VPN apps -- User authentication system (login/register/logout) -- Role-based access control (admin/user) -- Modern responsive UI with Tailwind CSS -- Dashboard with server and client overview -- Server CRUD operations (Create, Read, Update, Delete) -- Client management with download and QR code features -- Docker Compose deployment setup -- Database migrations system -- Twig template engine integration -- REST API foundation for future Telegram bot integration - -### Technical Details -- PHP 8.2 backend -- MySQL 8.0 database -- Endroid QR Code library v5.x integration -- Qt/QDataStream compatible QR encoding (tested with Amnezia apps) -- AWG obfuscation parameters support (Jc, Jmin, Jmax, S1, S2, H1-H4) -- Secure password hashing with bcrypt -- PDO prepared statements for SQL injection prevention -- XSS protection via Twig auto-escaping - -### Security -- Default admin account: admin@amnez.ia / admin123 (change immediately!) -- Bcrypt password hashing -- SQL injection prevention -- XSS protection -- Session-based authentication - -### Known Issues -- QR code library updated to v5.x with API compatibility fixes -- Server deletion not yet removing Docker containers from remote servers -- Client deletion not yet updating server wg0.conf file -- API authentication (JWT) not yet implemented -- Rate limiting not yet implemented - -### Infrastructure -- Docker container with PHP 8.2 Apache -- MySQL 8.0 container -- Docker Compose orchestration -- Volume persistence for database -- Composer dependency management - -## [Unreleased] - -### Planned Features -- JWT authentication for REST API -- Complete Telegram bot integration -- Server monitoring and health checks -- Bandwidth usage statistics -- Client traffic analysis -- Email notifications -- Two-factor authentication (2FA) -- Multi-language support -- Dark mode UI theme -- Automated backups -- Rate limiting for API endpoints -- Export/import configurations -- Server templates for quick deployment -- Client groups and tagging -- Advanced logging and audit trail -- User management admin panel - -### Improvements Planned -- Better error handling and user feedback -- Real-time deployment progress updates -- Server resource monitoring (CPU, RAM, bandwidth) -- Client connection status tracking -- Automatic Let's Encrypt SSL setup -- Database connection pooling -- Caching layer (Redis) -- WebSocket support for real-time updates -- Mobile-responsive improvements -- Accessibility enhancements - ---- - -The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), -and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). diff --git a/TESTING.md b/TESTING.md deleted file mode 100644 index 0819554..0000000 --- a/TESTING.md +++ /dev/null @@ -1,345 +0,0 @@ -# Testing Guide - -This document describes how to test the Amnezia VPN Web Panel. - -## Prerequisites - -- Docker and Docker Compose installed -- Test VPS server with SSH access (for full deployment testing) -- Amnezia VPN mobile app (Android/iOS) for QR code testing - -## Quick Test Setup - -### 1. Start the Application - -```bash -cd amnezia-web-panel -docker compose up -d -``` - -### 2. Access the Panel - -Open browser: `http://localhost:8082` - -### 3. Login - -Default credentials: -- Email: `admin@amnez.ia` -- Password: `admin123` - -## Unit Tests - -### Test QR Code Generation - -```bash -docker compose exec web php test_qr.php -``` - -Expected output: -``` -✅ Success! QR code generation working correctly. -``` - -This creates `test_qr.png` in the project root. - -### Verify QR Code Payload - -```bash -# Compare payload with original implementation -php /tmp/test_compare_qr.php -``` - -The payload should match exactly with the original Amnezia QR format. - -## Integration Tests - -### Test 1: User Registration - -1. Logout from admin account -2. Click "Register" -3. Fill in: - - Name: "Test User" - - Email: "test@example.com" - - Password: "testpass123" -4. Click "Register" -5. ✅ Should redirect to dashboard - -### Test 2: Server Creation (Without Deployment) - -1. Go to "Servers" → "Add Server" -2. Fill in: - - Name: "Test Server" - - Host: "192.168.1.100" - - Port: 22 - - Username: "root" - - Password: "dummy" -3. Click "Add Server" (will fail at deployment, but server record created) -4. ✅ Should see server in list with "pending" status - -### Test 3: Full Server Deployment (Requires Real VPS) - -**Prerequisites**: Remote Linux server with SSH access - -1. Go to "Servers" → "Add Server" -2. Fill in real server credentials: - - Name: "Production Server 1" - - Host: "your.server.ip" - - Port: 22 - - Username: "root" - - Password: "your_ssh_password" -3. Click "Add Server" -4. Wait for deployment (5-10 minutes) -5. ✅ Server status should change to "active" -6. ✅ Server should show public key and VPN port - -### Test 4: Client Creation - -**Prerequisites**: Active server from Test 3 - -1. Click on active server -2. In "Create Client" section, enter name: "test-client-1" -3. Click "Create" -4. ✅ Should redirect to client view page -5. ✅ Should see QR code displayed -6. ✅ "Download Config" button should work - -### Test 5: QR Code Scanning - -**Prerequisites**: Amnezia VPN app installed on phone - -1. Create a client (Test 4) -2. Open Amnezia VPN app -3. Tap "Add server" → "Scan QR code" -4. Scan the QR code from web panel -5. ✅ Configuration should be imported successfully -6. ✅ Connect to VPN should work -7. ✅ Check IP address changed (e.g., whatismyip.com) - -### Test 6: Configuration Download - -1. Go to client details page -2. Click "Download Config" -3. ✅ Should download `.conf` file -4. Open file in text editor -5. ✅ Should contain valid WireGuard config with: - - [Interface] section with PrivateKey, Address, DNS - - AWG parameters (Jc, Jmin, Jmax, S1, S2, H1-H4) - - [Peer] section with PublicKey, PresharedKey, Endpoint -6. Import manually into Amnezia VPN app -7. ✅ Should work same as QR code - -### Test 7: Multiple Clients - -1. Create 5 clients on same server -2. ✅ Each should get unique IP (10.8.1.2, 10.8.1.3, etc.) -3. ✅ Each should have unique keys -4. ✅ All QR codes should scan successfully -5. Test connections from multiple devices -6. ✅ All should connect simultaneously - -### Test 8: Client Deletion - -1. Go to client details -2. Click "Delete" -3. ✅ Client should be removed from database -4. ⚠️ **Known Issue**: Not yet removed from server wg0.conf - -### Test 9: Server Deletion - -1. Go to server list -2. Click "Delete" on a server -3. ✅ Server should be removed from database -4. ⚠️ **Known Issue**: Docker container not removed from remote server - -### Test 10: Access Control - -1. Create new user account -2. Login as new user -3. Create a server -4. Logout and login as admin -5. ✅ Admin should see all servers (including user's) -6. Login as regular user -7. ✅ Regular user should only see their own servers - -## Security Tests - -### Test 11: SQL Injection Protection - -Try creating server with malicious name: -``` -Name: Test'; DROP TABLE vpn_servers; -- -``` - -✅ Should be safely escaped, no SQL error - -### Test 12: XSS Protection - -Try creating client with script tag: -``` -Name: -``` - -✅ Should be HTML-escaped in output - -### Test 13: Authentication - -1. Logout -2. Try accessing `/dashboard` directly -3. ✅ Should redirect to login page - -### Test 14: Password Security - -1. Check database: -```bash -docker compose exec db mysql -u amnezia -pamnezia123 amnezia_panel -SELECT password FROM users LIMIT 1; -``` - -✅ Password should be bcrypt hash, not plaintext - -## Performance Tests - -### Test 15: Multiple Concurrent Requests - -```bash -# Install Apache Bench -sudo apt install apache2-utils - -# Test login endpoint -ab -n 100 -c 10 -p login.txt -T application/x-www-form-urlencoded http://localhost:8082/login -``` - -✅ Should handle 100 requests without errors - -### Test 16: Database Connection Pooling - -Create 10 clients rapidly: -```bash -for i in {1..10}; do - curl -X POST http://localhost:8082/servers/1/clients/create \ - -d "name=client$i" \ - -b cookies.txt -done -``` - -✅ Should complete without connection errors - -## Browser Compatibility - -Test in: -- ✅ Chrome/Edge (Chromium) -- ✅ Firefox -- ✅ Safari -- ✅ Mobile browsers (iOS Safari, Chrome Android) - -## Docker Tests - -### Test 17: Container Health - -```bash -docker compose ps -``` - -✅ Both containers should be "Up" and healthy - -### Test 18: Volume Persistence - -```bash -# Stop containers -docker compose down - -# Start again -docker compose up -d - -# Login -``` - -✅ All data should persist (servers, clients, users) - -### Test 19: Logs - -```bash -docker compose logs -f web -docker compose logs -f db -``` - -✅ No errors in logs during normal operation - -## Troubleshooting - -### QR Code Not Displaying - -Check: -```bash -docker compose exec web php test_qr.php -``` - -If fails, check: -- GD extension installed: `php -m | grep gd` -- Composer dependencies: `composer show endroid/qr-code` - -### Can't Connect to Database - -Check: -```bash -docker compose exec web php -r " -\$pdo = new PDO('mysql:host=db;dbname=amnezia_panel', 'amnezia', 'amnezia123'); -echo 'Connected successfully'; -" -``` - -### SSH Deployment Fails - -Test SSH manually: -```bash -sshpass -p 'yourpassword' ssh -o StrictHostKeyChecking=no root@server.ip 'echo OK' -``` - -## Test Checklist - -Before releasing or deploying: - -- [ ] All unit tests pass -- [ ] QR code generation works -- [ ] Server deployment works on real VPS -- [ ] Client creation works -- [ ] QR codes scan in Amnezia app -- [ ] VPN connection works -- [ ] Multiple clients work simultaneously -- [ ] Authentication works -- [ ] Access control works (user/admin) -- [ ] SQL injection protected -- [ ] XSS protected -- [ ] CSRF protection (if implemented) -- [ ] Password hashing verified -- [ ] All browsers work -- [ ] Mobile responsive -- [ ] Docker containers healthy -- [ ] Data persists after restart -- [ ] No errors in logs -- [ ] README instructions accurate -- [ ] Default password changed - -## Automated Testing (Future) - -Consider implementing: -- PHPUnit for unit tests -- Selenium for browser automation -- GitHub Actions for CI/CD -- Code coverage reports -- Automated security scanning - -## Reporting Issues - -When reporting bugs, include: -1. Steps to reproduce -2. Expected behavior -3. Actual behavior -4. Docker logs: `docker compose logs` -5. Browser console errors -6. PHP version: `docker compose exec web php -v` -7. MySQL version: `docker compose exec db mysql -V` - ---- - -Happy Testing! 🧪 diff --git a/TRAFFIC_STATS.md b/TRAFFIC_STATS.md deleted file mode 100644 index 11d8e91..0000000 --- a/TRAFFIC_STATS.md +++ /dev/null @@ -1,278 +0,0 @@ -# Traffic Statistics & Client Management Features - -## New Features Added (2025-11-06) - -### 1. Traffic Statistics Tracking - -**Database Changes:** -- Added `bytes_sent` - Total bytes uploaded by client -- Added `bytes_received` - Total bytes downloaded by client -- Added `last_handshake` - Last successful WireGuard connection time -- Added `last_sync_at` - Last time stats were synced from server - -**Backend Methods:** -- `VpnClient->syncStats()` - Sync single client statistics from server -- `VpnClient::syncAllStatsForServer($serverId)` - Sync all clients on a server -- `VpnClient->getFormattedStats()` - Get human-readable stats (KB, MB, GB) -- `VpnClient::getClientStatsFromServer()` - Parse `wg show` output - -**How it works:** -1. Connects to server via SSH -2. Runs `wg show wg0 dump` inside Docker container -3. Parses output to extract transfer statistics -4. Updates database with latest stats -5. Calculates "last seen" based on handshake time - -### 2. Client Access Control - -**Revoke Access:** -- Temporarily disable client without deleting -- Removes peer from server WireGuard config -- Keeps client record in database with status='disabled' -- Can be restored later - -**Restore Access:** -- Re-enable previously revoked client -- Re-adds peer to server WireGuard config -- Changes status back to 'active' - -**Delete Client:** -- Permanently removes client -- First revokes access (removes from server) -- Then deletes from database - -**Backend Methods:** -- `VpnClient->revoke()` - Disable client access -- `VpnClient->restore()` - Re-enable client access -- `VpnClient->delete()` - Permanently delete client -- `VpnClient::removeClientFromServer()` - Remove peer from wg0.conf -- `VpnClient::removeFromClientsTable()` - Remove from clientsTable JSON - -### 3. Web Interface Updates - -**Server View Page (`/servers/{id}`):** -- Added "Sync Stats" button - refreshes all client stats -- Enhanced client table with: - - Status badge (Active/Disabled) - - Traffic columns (Upload/Download) - - Last seen timestamp - - Action buttons (View, Revoke/Restore, Delete) - -**Client View Page (`/clients/{id}`):** -- Added traffic statistics panel -- Shows uploaded/downloaded/total bytes -- Displays last handshake time -- "Refresh" button to sync latest stats -- Real-time status indicator (Online if handshake < 5 min) -- Revoke/Restore button based on current status - -### 4. API Endpoints - -All endpoints require authentication (session-based, JWT planned). - -**GET `/api/clients/{id}`** -```json -{ - "success": true, - "client": { - "id": 1, - "name": "client1", - "server_id": 1, - "client_ip": "10.8.1.2", - "status": "active", - "created_at": "2025-11-06 12:00:00", - "stats": { - "sent": "1.5 GB", - "received": "3.2 GB", - "total": "4.7 GB", - "last_seen": "Online", - "is_online": true - }, - "bytes_sent": 1610612736, - "bytes_received": 3435973836, - "last_handshake": "2025-11-06 14:30:00" - } -} -``` - -**POST `/api/clients/{id}/revoke`** -```json -{ - "success": true, - "message": "Client revoked" -} -``` - -**POST `/api/clients/{id}/restore`** -```json -{ - "success": true, - "message": "Client restored" -} -``` - -**GET `/api/servers/{id}/clients`** -Returns all clients with synced stats for a server. - -```json -{ - "success": true, - "clients": [ - { - "id": 1, - "name": "client1", - "client_ip": "10.8.1.2", - "status": "active", - "stats": {...}, - ... - } - ] -} -``` - -**POST `/servers/{id}/sync-stats`** -```json -{ - "success": true, - "synced": 5 -} -``` - -**POST `/clients/{id}/sync-stats`** -```json -{ - "success": true, - "stats": { - "sent": "1.5 GB", - "received": "3.2 GB", - "total": "4.7 GB", - "last_seen": "Online" - } -} -``` - -## Usage Examples - -### Web Interface - -1. **View Client Statistics:** - - Go to server page - - Click "Sync Stats" to refresh all clients - - View traffic in table or click client for details - -2. **Revoke Client Access:** - - In server client list, click "Revoke" next to active client - - Confirm action - - Client status changes to "Disabled" - - Client can no longer connect to VPN - -3. **Restore Client Access:** - - Find disabled client in list - - Click "Restore" - - Client status changes to "Active" - - Client can connect again - -### API Usage (for Telegram Bot) - -```php -// Get client with stats -$response = $api->get('/api/clients/1'); -$client = $response['client']; - -echo "Traffic: {$client['stats']['total']}\n"; -echo "Status: {$client['stats']['last_seen']}\n"; - -// Revoke access -$api->post('/api/clients/1/revoke'); - -// Restore access -$api->post('/api/clients/1/restore'); - -// Get all server clients with stats -$response = $api->get('/api/servers/1/clients'); -foreach ($response['clients'] as $client) { - echo "{$client['name']}: {$client['stats']['total']}\n"; -} -``` - -## Technical Details - -### WireGuard Stats Format - -The `wg show wg0 dump` command returns: -``` -private_key public_key preshared_key endpoint allowed_ips latest_handshake transfer_rx transfer_tx persistent_keepalive -``` - -We parse: -- `latest_handshake` - Unix timestamp of last handshake -- `transfer_rx` - Bytes received by server (client sent) -- `transfer_tx` - Bytes sent by server (client received) - -### Peer Removal - -Removing peer from `wg0.conf`: -```bash -# Find and delete [Peer] block with matching PublicKey -sed -i '/^\[Peer\]/,/^$/{/PublicKey = /,/^$/d}' /opt/amnezia/awg/wg0.conf - -# Apply changes without restart -wg syncconf wg0 <(wg-quick strip /opt/amnezia/awg/wg0.conf) -``` - -### Client Status Logic - -- **Online:** Last handshake < 5 minutes ago -- **Recently seen:** Last handshake < 1 hour ago -- **Offline:** Last handshake > 1 hour ago -- **Never connected:** No handshake recorded - -## Database Migration - -Migration file: `migrations/002_add_traffic_stats.sql` - -To apply manually: -```bash -docker compose exec -T db mysql -u root -prootpassword amnezia_panel < migrations/002_add_traffic_stats.sql -``` - -## Performance Considerations - -- Stats sync requires SSH connection to server -- Each sync runs `wg show wg0 dump` command -- For many clients, use batch sync: `VpnClient::syncAllStatsForServer()` -- Consider caching stats and refreshing periodically (e.g., every 5 minutes) -- Stats updates are logged in `last_sync_at` column - -## Future Enhancements - -- [ ] Automatic periodic stats sync (cron job) -- [ ] Traffic usage alerts (email/Telegram) -- [ ] Bandwidth limits per client -- [ ] Historical traffic graphs -- [ ] Export stats to CSV -- [ ] Real-time WebSocket updates -- [ ] Client connection notifications - -## Troubleshooting - -**Stats not syncing:** -1. Check server SSH connection -2. Verify Docker container is running: `docker ps | grep awg` -3. Check `wg show wg0` output inside container -4. Review error logs - -**Client still connecting after revoke:** -1. Check if peer was removed from wg0.conf -2. Verify `wg syncconf` was executed -3. Restart WireGuard: `docker exec wg-quick down wg0 && wg-quick up wg0` - -**Last handshake not updating:** -1. Ensure client is actually connected -2. Check WireGuard keepalive settings (should be 25 seconds) -3. Verify server time is synchronized (NTP) - ---- - -**Last Updated:** 2025-11-06 -**Version:** 1.1.0 diff --git a/TRANSLATIONS.md b/TRANSLATIONS.md deleted file mode 100644 index 07dc9ef..0000000 --- a/TRANSLATIONS.md +++ /dev/null @@ -1,142 +0,0 @@ -# Translation Management - -## Database Reset & Setup - -All translations have been reset and reloaded with complete English keys (79 total). - -### Migration Applied -- `migrations/006_full_translations.sql` - Complete translation reset with all 79 English keys - -## Translation Keys Summary - -### Categories: -- **Authentication** (5 keys): email, login, name, password, register -- **Clients** (17 keys): actions, add, delete, download_config, ip, etc. -- **Dashboard** (5 keys): active_clients, title, total_clients, etc. -- **Forms** (6 keys): cancel, close, loading, processing, save, submit -- **Menu** (6 keys): clients, dashboard, logout, servers, settings, users -- **Messages** (6 keys): confirm, deleted, deployed, error, saved, success -- **Servers** (12 keys): actions, add, clients, delete, deploy, etc. -- **Settings** (17 keys): api_keys, auto_translate, translations, etc. -- **Status** (5 keys): active, deploying, disabled, error, inactive - -**Total: 79 keys** - -## How to Translate All Languages - -### Option 1: Via Web Interface -1. Login as admin: http://localhost:8082/login -2. Go to Settings: http://localhost:8082/settings -3. Add your OpenRouter API key -4. Click "Auto-translate" button for each language - -### Option 2: Via Command Line (Recommended) -```bash -# First, add your OpenRouter API key via Settings page - -# Then run the auto-translation script -docker compose exec app php bin/translate_all.php -``` - -This will automatically translate all 5 languages: -- 🇷🇺 Russian (ru) -- 🇪🇸 Spanish (es) -- 🇩🇪 German (de) -- 🇫🇷 French (fr) -- 🇨🇳 Chinese (zh) - -### Option 3: Translate Single Language -```bash -# Translate only Russian -docker compose exec app php bin/translate.php ru - -# Translate only Spanish -docker compose exec app php bin/translate.php es -``` - -## Current Status - -After migration: -``` -+---------------+-------+ -| language_code | count | -+---------------+-------+ -| en | 79 | -+---------------+-------+ -``` - -After auto-translation (expected): -``` -+---------------+-------+ -| language_code | count | -+---------------+-------+ -| de | 79 | -| en | 79 | -| es | 79 | -| fr | 79 | -| ru | 79 | -| zh | 79 | -+---------------+-------+ -``` - -## API Rate Limits - -OpenRouter free models have rate limits: -- **gemini-2.0-flash-exp:free** - Primary model -- **meta-llama/llama-3.2-3b-instruct:free** - Fallback 1 -- **google/gemini-flash-1.5** - Fallback 2 - -The translation script includes: -- Automatic retries with exponential backoff -- Model fallback on rate limits -- 5-second delay between languages -- Batch translation for efficiency - -## Troubleshooting - -### Error: "OpenRouter API key not found" -Add your API key via Settings page first: -1. Go to http://localhost:8082/settings -2. Enter your OpenRouter API key (format: `sk-or-v1-...`) -3. Click Save - -### Error: "Rate limit exceeded" -Wait a few minutes and try again, or: -- Use the web interface (slower but more controlled) -- Increase delay in `bin/translate_all.php` -- Get a paid OpenRouter API key - -### Check Translation Progress -```bash -docker compose exec db sh -c 'mysql -u root -p"$MYSQL_ROOT_PASSWORD" amnezia_panel -e " -SELECT - l.code, - l.name, - COUNT(t.id) as translated, - (SELECT COUNT(*) FROM translations WHERE language_code = \"en\") as total -FROM languages l -LEFT JOIN translations t ON l.code = t.language_code -GROUP BY l.code -ORDER BY l.code; -"' -``` - -## Manual Export/Import - -### Export translations to JSON -```bash -docker compose exec app php -r " -require 'vendor/autoload.php'; -require 'inc/Config.php'; -require 'inc/DB.php'; -require 'inc/Translator.php'; -Config::load('.env'); -DB::conn(); -echo Translator::exportToJson('ru'); -" > translations_ru.json -``` - -### Import from JSON -```php -Translator::importFromJson('ru', file_get_contents('translations_ru.json')); -``` diff --git a/test_qr.php b/test_qr.php deleted file mode 100644 index 19db128..0000000 --- a/test_qr.php +++ /dev/null @@ -1,59 +0,0 @@ -getMessage() . "\n"; - echo "Stack trace:\n" . $e->getTraceAsString() . "\n"; - exit(1); -}