commit 4dd402b250a03e65c60f6be75264a5b2b660890c
Author: dyzulk <66510723+dyzulk@users.noreply.github.com>
Date: Mon Jan 19 10:13:06 2026 +0700
Initial commit
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..f3f07b8
--- /dev/null
+++ b/.github/workflows/release.yml
@@ -0,0 +1,52 @@
+name: Release Plugin
+
+on:
+ push:
+ tags:
+ - 'v*' # Trigger on version tags, e.g. v1.0.0
+
+jobs:
+ build:
+ name: Create Release
+ runs-on: ubuntu-latest
+ permissions:
+ contents: write # Needed to create releases
+
+ steps:
+ - name: Checkout code
+ uses: actions/checkout@v4
+
+ - name: Get Version
+ id: get_version
+ run: echo "VERSION=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
+
+ - name: Create ZIP Archive
+ run: |
+ # Create a temporary directory for the zip
+ mkdir temp_zip
+
+ # Copy files to temp directory, excluding unwanted files
+ rsync -av --progress . temp_zip --exclude .git --exclude .github --exclude .gitignore --exclude LICENSE --exclude README.md --exclude temp_zip
+
+ # Create the zip file
+ cd temp_zip
+ zip -r ../plugin-lang-es.zip .
+ cd ..
+
+ echo "Created plugin-lang-es.zip"
+
+ - name: Create Release
+ uses: softprops/action-gh-release@v1
+ with:
+ files: plugin-lang-es.zip
+ name: Release ${{ steps.get_version.outputs.VERSION }}
+ body: |
+ Automatic release for version ${{ steps.get_version.outputs.VERSION }}
+
+ **Installation:**
+ 1. Download `plugin-lang-es.zip`
+ 2. Upload in Mivo > Settings > Plugins
+ draft: false
+ prerelease: false
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..1a14372
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2026 DyzulkDev
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..ba14a01
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# Spanish Language Pack
+
+**Category:** Language Pack
+**Author:** DyzulkDev
+**Version:** 1.0.0
+
+The **Spanish Language Pack** provides full Spanish (Español) localization for the Mivo Hotspot Manager.
+
+## Features
+- **Full Translation**: Covers Dashboard, Settings, Hotspot, and System menus.
+- **Flag Icon**: Adds the Spanish flag to the language switcher.
+- **Native Terminology**: Uses accurate networking and captive portal terms.
+
+## Installation
+1. Download the plugin ZIP file.
+2. Go to **Mivo > Settings > Plugins**.
+3. Click **Upload Plugin** and select the ZIP file.
+4. The plugin will appear in your installed list.
+5. In the top navbar, click the language switcher and select **Español**.
+
+## Usage
+Simply install and activate. The language option will be available immediately to all users.
diff --git a/es.json b/es.json
new file mode 100644
index 0000000..ec2d4e0
--- /dev/null
+++ b/es.json
@@ -0,0 +1,632 @@
+{
+ "_meta": {
+ "name": "Español",
+ "flag": "es"
+ },
+ "common": {
+ "dashboard": "Tablero",
+ "save": "Guardar",
+ "cancel": "Cancelar",
+ "delete": "Eliminar",
+ "edit": "Editar",
+ "add": "Añadir",
+ "install": "Instalar",
+ "back": "Atrás",
+ "actions": "Acciones",
+ "status": "Estado",
+ "name": "Nombre",
+ "description": "Descripción",
+ "search": "Buscar",
+ "previous": "Anterior",
+ "next": "Siguiente",
+ "confirm_delete": "¿Está seguro de que desea eliminar este elemento?",
+ "page_of": "Página {current} de {total}",
+ "all_topics": "Todos los temas",
+ "open": "Abrir",
+ "session": "Sesión",
+ "table": {
+ "entries_per_page": "entradas por página",
+ "search_placeholder": "Buscar...",
+ "all": "Todo",
+ "showing": "Mostrando {start} a {end} de {total} entradas",
+ "no_match": "No se encontraron registros coincidentes"
+ },
+ "char_length": "{n} Caracteres",
+ "forms": {
+ "general": "General",
+ "required": "requerido",
+ "save_changes": "Guardar Cambios",
+ "please_wait": "Por favor espere...",
+ "none": "ninguno",
+ "enabled": "Habilitado",
+ "disabled": "Deshabilitado"
+ },
+ "warning": "Advertencia"
+ },
+ "home": {
+ "subtitle": "Un administrador de Hotspot para MikroTik moderno y ligero construido para rendimiento y simplicidad.",
+ "manage_routers": "Gestionar Routers",
+ "manage_routers_desc": "Configurar conexiones RouterOS y ver estado.",
+ "source_code": "Código Fuente",
+ "source_code_desc": "Ver el repositorio del proyecto y contribuir.",
+ "quick_access": "Acceso Rápido",
+ "session_name": "Nombre de Sesión",
+ "hotspot_name": "Nombre de Hotspot",
+ "ip_address": "Dirección IP"
+ },
+ "dashboard": {
+ "system_info": "Info del Sistema",
+ "model": "Modelo",
+ "board_name": "Nombre de Placa",
+ "router_os": "RouterOS",
+ "architecture": "Arquitectura",
+ "uptime": "Tiempo de actividad",
+ "resources": "Recursos",
+ "cpu_load": "Carga CPU",
+ "memory": "Memoria",
+ "free": "Libre",
+ "hdd": "HDD",
+ "income_today": "Ingresos Hoy",
+ "traffic_monitor": "Monitor de Tráfico",
+ "rx_download": "Rx (Descarga)",
+ "tx_upload": "Tx (Subida)"
+ },
+ "settings": {
+ "title": "Ajustes",
+ "subtitle": "Gestione sus preferencias y configuraciones de la aplicación.",
+ "system": "General",
+ "system_desc": "Configuraciones del sistema y seguridad.",
+ "admin_username": "Usuario Administrador",
+ "admin_username_desc": "Por razones de seguridad, el nombre de usuario administrador no se puede cambiar.",
+ "change_password": "Cambiar Contraseña",
+ "new_password_placeholder": "Ingrese nueva contraseña",
+ "update_password": "Actualizar Contraseña",
+ "quick_print_mode": "Modo Impresión Rápida",
+ "quick_print_mode_desc": "Habilitar impresión directa para generación de cupones.",
+ "save_global": "Guardar Ajustes Globales",
+ "data_management": "Gestión de Datos",
+ "data_management_desc": "Respalde o restaure los datos de su aplicación.",
+ "backup_data": "Respaldar Datos",
+ "backup_data_desc": "Descargue un archivo de configuración (.mivo) que contiene su base de datos y ajustes.",
+ "download_backup": "Descargar Respaldo",
+ "restore_data": "Restaurar Datos",
+ "restore_data_desc": "Suba un archivo de respaldo (.mivo). Sobrescribe o añade a los datos existentes.",
+ "restore": "Restaurar",
+ "warning_restore": "ADVERTENCIA: Esto restaurará la configuración desde el archivo y puede sobrescribir datos existentes. ¿Continuar?",
+ "routers_title": "Routers",
+ "routers_subtitle": "Gestione sus conexiones MikroTik RouterOS.",
+ "add_router": "Añadir Router",
+ "no_routers": "No se encontraron Routers",
+ "connect_first": "Conecte su primer router MikroTik para comenzar a gestionar hotspots y cupones.",
+ "delete_router_title": "¿Eliminar Sesión?",
+ "delete_router_confirm": "¿Está seguro de que desea eliminar {name}? Esta acción no se puede deshacer.",
+ "connect": "Conectar",
+ "logos_title": "Logos",
+ "logos_subtitle": "Suba y gestione logotipos para sus hotspots y cupones.",
+ "upload_new_logo": "Subir Nuevo Logo",
+ "drag_drop": "Arrastre y suelte o haga clic para seleccionar archivo",
+ "supports_formats": "Soporta PNG, JPG, SVG, GIF",
+ "no_logos": "No se han subido logotipos todavía.",
+ "id_copied": "ID Copiado",
+ "logo_id_copied_desc": "ID de Logo {id} copiado al portapapeles.",
+ "delete_logo_title": "¿Eliminar Logo?",
+ "delete_logo_confirm": "¿Está seguro de que desea eliminar el logo {id}?",
+ "templates_title": "Plantillas de Cupones",
+ "templates_subtitle": "Gestione y personalice sus diseños de impresión de cupones.",
+ "new_template": "Nueva Plantilla",
+ "edit_template": "Editar Plantilla",
+ "default_template": "Plantilla Predeterminada",
+ "system_label": "Sistema",
+ "custom_label": "Personalizado",
+ "built_in": "Incorporado",
+ "default_template_desc": "Plantilla estándar amigable con impresoras térmicas.",
+ "delete_template_title": "¿Eliminar Plantilla?",
+ "delete_template_confirm": "¿Está seguro de que desea eliminar {name}?",
+ "template_name": "Nombre de Plantilla",
+ "html_source": "Fuente HTML",
+ "docs": "Docs",
+ "live_preview": "Vista Previa",
+ "template_variables": "Variables de Plantilla",
+ "variables_desc": "Use estas variables en su fuente HTML. Serán reemplazadas con datos reales del usuario durante la impresión.",
+ "qr_code": "Código QR",
+ "qr_desc": "Genera un Código QR que contiene la URL de inicio de sesión con usuario y contraseña.",
+ "custom_attributes": "Atributos Personalizados",
+ "examples": "Ejemplos",
+ "api_cors_title": "API CORS",
+ "api_cors_subtitle": "Gestione el Intercambio de Recursos de Origen Cruzado para acceso API.",
+ "add_rule": "Añadir Regla CORS",
+ "edit_rule": "Editar Regla CORS",
+ "origin": "Origen",
+ "methods": "Métodos Permitidos",
+ "headers": "Encabezados Permitidos",
+ "max_age": "Edad Máxima (segundos)",
+ "cpu_warning": "Valores bajos (< 5s) pueden aumentar el uso de CPU en routers antiguos.",
+ "back": "Volver a Ajustes",
+ "editor_shortcuts": "Atajos del Editor & Emmet",
+ "emmet_desc": "Use abreviaciones Emmet para codificar rápido. Busque el subrayado punteado, luego presione Tab.",
+ "tip_emmet_html": "Plantilla HTML: Escriba ! luego Tab.",
+ "tip_emmet_tag": "Auto-Etiqueta: Escriba .container luego Tab para <div class=\"container\">.",
+ "tip_color_picker": "Selector de Color: Haga clic en el cuadro de color junto a los códigos hex (ej: #ff0000) para abrir el selector.",
+ "tip_syntax_error": "Error de Sintaxis: Los garabatos rojos (y puntos en el margen) muestran errores de estructura como etiquetas no cerradas.",
+ "plugins_title": "Plugins",
+ "plugins": "Plugins",
+ "plugins_desc": "Gestione y extienda la funcionalidad con plugins.",
+ "upload_plugin": "Subir Plugin",
+ "upload_plugin_desc": "Seleccione un archivo .zip de plugin para instalar.",
+ "no_plugins": "No hay Plugins Instalados",
+ "no_plugins_desc": "Suba un archivo .zip para comenzar.",
+ "plugin_installed": "Plugin Instalado",
+ "plugin_installed_desc": "El plugin \"{name}\" ha sido instalado exitosamente.",
+ "delete_plugin": "¿Eliminar Plugin?",
+ "delete_plugin_confirm": "¿Está seguro de que desea eliminar el plugin {name}? Esto no se puede deshacer.",
+ "install_failed": "Instalación Fallida"
+ },
+ "routers": {
+ "edit_router_title": "Editar Router",
+ "add_router_title": "Añadir Router",
+ "connect_desc": "Conecte Mivo a su dispositivo RouterOS.",
+ "session_settings": "Ajustes de Sesión",
+ "unique_id": "ID Único. Vista previa:",
+ "show_quick_access": "Mostrar en Acceso Rápido (Inicio)",
+ "connection_details": "Detalles de Conexión",
+ "password_hint": "Dejar vacío para mantener la contraseña existente.",
+ "hotspot_info": "Información de Hotspot",
+ "dns_name": "Nombre DNS",
+ "traffic_interface": "Interfaz de Tráfico",
+ "check_btn": "Verificar",
+ "currency": "Moneda",
+ "auto_reload": "Recarga Auto (Seg)",
+ "save_connect": "Guardar & Conectar"
+ },
+ "login": {
+ "welcome": "Bienvenido, por favor inicie sesión para continuar.",
+ "username": "Usuario",
+ "password": "Contraseña",
+ "sign_in": "Iniciar Sesión"
+ },
+ "quick_print": {
+ "title": "Impresión Rápida",
+ "subtitle": "Generación e impresión de cupones instantánea.",
+ "manage": "Gestionar Paquetes",
+ "manage_title": "Gestionar Paquetes",
+ "manage_subtitle": "Configure sus paquetes de cupones de Impresión Rápida para:",
+ "no_packages": "No se encontraron Paquetes",
+ "no_packages_found": "No se encontraron paquetes.",
+ "create_first": "Cree un paquete de Impresión Rápida para comenzar.",
+ "create_package": "Crear Paquete",
+ "add_package": "Añadir Paquete",
+ "edit_package": "Editar Paquete",
+ "save_package": "Guardar Paquete",
+ "delete_package": "Eliminar Paquete",
+ "print_voucher": "Imprimir Cupón",
+ "name": "Nombre",
+ "package_name": "Nombre del Paquete",
+ "profile": "Perfil",
+ "select_profile": "Seleccionar Perfil",
+ "prefix": "Prefijo",
+ "server": "Servidor",
+ "price": "Precio",
+ "selling_price": "Precio de Venta",
+ "time_limit": "Límite de Tiempo",
+ "data_limit": "Límite de Datos",
+ "card_color": "Color de Tarjeta",
+ "char_length": "Longitud de Carácteres",
+ "vouchers_to_generate": "Cupones a Generar",
+ "comment": "Comentario"
+ },
+ "sidebar": {
+ "dashboard": "Tablero",
+ "quick_print": "Impresión Rápida",
+ "hotspot": "Hotspot",
+ "status": "Estado",
+ "security": "Seguridad",
+ "reports": "Reportes",
+ "network": "Red",
+ "system": "Sistema",
+ "settings": "Ajustes",
+ "templates": "Plantillas",
+ "disconnect": "Desconectar",
+ "logout": "Salir de Mivo"
+ },
+ "hotspot_active": {
+ "title": "Usuarios Activos",
+ "subtitle": "Monitorear sesiones de hotspot actualmente activas",
+ "filter_server": "Todos los Servidores",
+ "server": "Servidor",
+ "user": "Usuario",
+ "address": "Dirección / MAC",
+ "uptime": "Tiempo activo / Restante",
+ "bytes_in_out": "Bytes Ent/Sal",
+ "time_left": "Queda",
+ "remove": "¿Desconectar Usuario?"
+ },
+ "hotspot_hosts": {
+ "title": "Hosts Hotspot",
+ "subtitle": "Dispositivos conectados a la red hotspot para:",
+ "mac": "Dirección MAC",
+ "address": "Dirección",
+ "to_address": "A Dirección",
+ "server": "Servidor",
+ "comment": "Comentario"
+ },
+ "hotspot_menu": {
+ "users": "Usuarios",
+ "profiles": "Perfiles de Usuario",
+ "generate": "Generar",
+ "cookies": "Cookies",
+ "active": "Activos",
+ "hosts": "Hosts",
+ "bindings": "Enlaces IP",
+ "walled_garden": "Walled Garden"
+ },
+ "reports_menu": {
+ "resume": "Resumen",
+ "selling": "Reporte de Ventas",
+ "user_log": "Registro de Usuario"
+ },
+ "network_menu": {
+ "dhcp": "Concesiones DHCP"
+ },
+ "system_menu": {
+ "scheduler": "Programador",
+ "reboot": "Reiniciar",
+ "shutdown": "Apagar"
+ },
+ "dhcp": {
+ "title": "Concesiones DHCP",
+ "subtitle": "Concesiones DHCP activas para:",
+ "all_servers": "Todos los Servidores",
+ "address": "Dirección",
+ "mac": "Dirección MAC",
+ "server": "Servidor",
+ "status": "Estado",
+ "host": "Nombre de Host"
+ },
+ "cookies": {
+ "title": "Usuarios Hotspot",
+ "subtitle": "Gestione usuarios y cupones",
+ "name": "Nombre",
+ "mac": "Dirección MAC",
+ "ip": "Dirección IP",
+ "expires": "Expira En",
+ "remove_cookie": "¿Eliminar Cookie?",
+ "remove_confirm": "¿Está seguro de que desea eliminar la cookie para {user}?"
+ },
+ "reports": {
+ "selling_title": "Reporte de Ventas",
+ "selling_subtitle": "Resumen de ventas y detalles para:",
+ "user_log_title": "Registro de Usuario",
+ "user_log_subtitle": "Historial de inicio y cierre de sesión para:",
+ "resume_title": "Reporte de Resumen",
+ "resume_subtitle": "Visión general de ingresos agregados.",
+ "total_income": "Ingreso Total",
+ "total_vouchers": "Total Cupones Vendidos",
+ "date_batch": "Fecha / Lote (Comentario)",
+ "qty": "Cant",
+ "total": "Total",
+ "no_data": "No se encontraron datos de ventas.",
+ "time": "Tiempo",
+ "topics": "Temas",
+ "message": "Mensaje",
+ "daily": "Diario",
+ "monthly": "Mensual",
+ "yearly": "Anual",
+ "date": "Fecha",
+ "month": "Mes",
+ "year": "Año",
+ "refresh": "Actualizar",
+ "print_report": "Imprimir Reporte"
+ },
+ "hotspot_profiles": {
+ "title": "Perfiles de Usuario",
+ "subtitle": "Gestione límites de velocidad y precios",
+ "add_profile": "Añadir Perfil",
+ "edit_profile": "Editar Perfil",
+ "all_modes": "Todos los Modos Expirados",
+ "name": "Nombre",
+ "shared_users": "Usuarios Compartidos",
+ "rate_limit": "Límite de Velocidad",
+ "parent_queue": "Cola Padre",
+ "expired_mode": "Modo Expirado",
+ "validity": "Validez",
+ "price": "Precio",
+ "selling_price": "Precio de Venta",
+ "lock_user": "Bloquear Usuario",
+ "form": {
+ "add_title": "Añadir Perfil",
+ "edit_title": "Editar Perfil",
+ "add_subtitle": "Crear un nuevo perfil de usuario hotspot para: {name}",
+ "edit_subtitle": "Editar perfil de usuario hotspot: {name}",
+ "settings": "Ajustes de Perfil",
+ "general": "Ajustes Generales",
+ "limits_queues": "Límites & Colas",
+ "pricing_validity": "Precios & Validez",
+ "address_pool": "Grupo de Direcciones",
+ "rate_limit_help": "Rx/Tx (Subida/Descarga). Ejemplo: 512k/1M",
+ "expired_mode_help": "Acción cuando expira la validez.",
+ "validity_help": "Días / Horas / Minutos",
+ "lock_user_help": "Bloquear usuario a una dirección MAC específica.",
+ "save": "Guardar Perfil",
+ "name_placeholder": "ej. Paquete-1Hora",
+ "quick_tips": "Consejos Rápidos",
+ "tip_rate_limit": "Límite de Velocidad: Rx/Tx (Subida/Descarga). Ejemplo: 512k/1M",
+ "tip_expired_mode": "Modo Expirado: Seleccione 'Eliminar' o 'Aviso' para habilitar Validez.",
+ "tip_parent_queue": "Cola Padre: Asigna usuarios a una cola padre específica para gestión de ancho de banda."
+ }
+ },
+ "hotspot_users": {
+ "add_user": "Añadir Usuario",
+ "edit_user": "Editar Usuario",
+ "title": "Usuarios Hotspot",
+ "subtitle": "Gestione usuarios y cupones",
+ "name": "Nombre",
+ "profile": "Perfil",
+ "uptime_limit": "Tiempo activo / Límite",
+ "bytes_in_out": "Bytes Ent/Sal",
+ "comment": "Comentario",
+ "no_users_selected": "No hay usuarios seleccionados.",
+ "form": {
+ "add_title": "Añadir Usuario",
+ "edit_title": "Editar Usuario",
+ "subtitle": "Cuenta de usuario hotspot",
+ "edit_subtitle": "Actualizar detalles de usuario para: {name}",
+ "username": "Usuario",
+ "password": "Contraseña",
+ "profile": "Perfil",
+ "server": "Servidor",
+ "time_limit": "Límite de Tiempo",
+ "data_limit": "Límite de Datos",
+ "comment": "Comentario",
+ "save": "Guardar Usuario",
+ "username_help": "Nombre de usuario único para inicio de sesión.",
+ "password_help": "Contraseña segura.",
+ "profile_help": "El perfil determina el límite de velocidad y política de compartición.",
+ "time_limit_help": "Tiempo total permitido (Días, Horas, Minutos).",
+ "data_limit_help": "Límite de uso de datos (0 para ilimitado).",
+ "comment_help": "Notas adicionales o info de contacto.",
+ "username_placeholder": "ej. cupón123",
+ "password_placeholder": "ej. 123456",
+ "comment_placeholder": "Nota opcional para este usuario",
+ "quick_tips": "Consejos Rápidos",
+ "tip_profiles": "Perfiles definen los límites de velocidad predeterminados, tiempo de sesión, y política de compartición.",
+ "tip_time_limit": "Límite de Tiempo es el tiempo total acumulado permitido para este usuario.",
+ "tip_data_limit": "Límite de Datos anulará la configuración del perfil si se especifica aquí. Ponga 0 para usar el del perfil."
+ }
+ },
+ "hotspot_generate": {
+ "title": "Generar Cupones",
+ "form": {
+ "qty": "Cantidad",
+ "server": "Servidor",
+ "user_mode": "Modo Usuario",
+ "user_length": "Longitud Usuario",
+ "prefix": "Prefijo",
+ "characters": "Caracteres",
+ "profile": "Perfil",
+ "time_limit": "Límite de Tiempo",
+ "data_limit": "Límite de Datos",
+ "comment": "Comentario",
+ "generate": "Generar Cupones",
+ "subtitle": "Crear múltiples cupones hotspot en lote para: {name}",
+ "batch_settings": "Ajustes de Generación por Lote",
+ "core_config": "Configuración Núcleo",
+ "qty_help": "Cantidad de cupones a generar.",
+ "server_help": "Instancia Hotspot objetivo.",
+ "user_mode_help": "Formato de credenciales.",
+ "comment_help": "Nota para este lote.",
+ "user_format": "Formato de Usuario",
+ "name_length_help": "Longitud de usuario/contraseña.",
+ "prefix_placeholder": "ej. VIP-",
+ "prefix_help": "Prefijo para usuarios generados.",
+ "characters_help": "Tipos de caracteres a incluir.",
+ "limits_profile": "Límites & Perfil",
+ "profile_help": "Aplicar límites de velocidad del perfil.",
+ "time_limit_help": "Tiempo máx (ej. 1h, 30m).",
+ "data_limit_help": "Transferencia máx (MB).",
+ "quick_tips": "Consejos Rápidos",
+ "tip_user_mode": "Modo Usuario: UP (separado), VC (mismo).",
+ "tip_format_examples": "Ejemplos de Formato: abcd (minúsculas), 1234 (num), Mix (mayús/minús/num).",
+ "tip_limits": "Límites: Tiempo (ej. 1h, 30m), Datos (ej. 100MB). Dejar vacío para usar predeterminado del perfil."
+ }
+ },
+ "security": {
+ "bindings": {
+ "title": "Enlaces IP",
+ "subtitle": "Gestione enlaces IP (bypass/bloqueado) para: {name}",
+ "all_types": "Todos los Tipos",
+ "regular": "Regular",
+ "bypassed": "Bypassed",
+ "blocked": "Bloqueado",
+ "table": {
+ "mac": "Dirección MAC",
+ "address": "Dirección",
+ "to_address": "A Dirección",
+ "type": "Tipo",
+ "comment": "Comentario"
+ },
+ "form": {
+ "add_title": "Añadir Enlace",
+ "mac_address": "Dirección MAC",
+ "address": "Dirección",
+ "to_address": "A Dirección",
+ "type": "Tipo",
+ "server": "Servidor",
+ "comment": "Comentario",
+ "mac_help": "Dirección MAC del dispositivo.",
+ "address_help": "Dirección IP (opcional).",
+ "to_address_help": "Traducir a esta IP (opcional).",
+ "server_help": "Aplicar a servidor Hotspot específico.",
+ "comment_help": "Nota para este enlace.",
+ "save": "Guardar & Enlazar",
+ "tip_bypassed": "Bypassed: Acceso sin login.",
+ "tip_blocked": "Bloqueado: Denegar acceso completamente.",
+ "tip_regular": "Regular: Cliente hotspot normal."
+ }
+ },
+ "walled_garden": {
+ "title": "Walled Garden",
+ "subtitle": "Gestione destinos permitidos (bypass sin login) para: {name}",
+ "all_actions": "Todas las Acciones",
+ "allow": "Permitir",
+ "deny": "Denegar",
+ "table": {
+ "host_ip": "Host / IP Dest",
+ "proto_port": "Protocolo / Puerto",
+ "action": "Acción",
+ "comment": "Comentario"
+ },
+ "form": {
+ "add_title": "Añadir Entrada",
+ "action": "Acción",
+ "dst_host": "Host Dest (Dominio)",
+ "dst_address": "Dirección Dest (IP)",
+ "protocol": "Protocolo",
+ "dst_port": "Puerto Dest",
+ "server": "Servidor",
+ "comment": "Comentario",
+ "host_help": "Dominio a permitir (comodín soportado).",
+ "addr_help": "Dirección IP Destino.",
+ "action_help": "Permitir (bypass) o Denegar acceso.",
+ "server_help": "Aplicar a servidor Hotspot específico.",
+ "comment_help": "Nota para esta regla.",
+ "save": "Guardar Entrada",
+ "tip_host": "Host Dest: Nombre de dominio (ej. *.google.com).",
+ "tip_ip": "IP Dest: Dirección IP específica.",
+ "tip_action": "Acción: Permitir para saltar autenticación."
+ }
+ }
+ },
+ "system_tools": {
+ "scheduler_subtitle": "Gestione tareas automatizadas de RouterOS para:",
+ "add_task": "Añadir Tarea",
+ "add_title": "Añadir Tarea",
+ "edit_title": "Editar Tarea",
+ "save_task": "Guardar Tarea",
+ "update_task": "Actualizar Tarea",
+ "delete_task": "Eliminar Tarea",
+ "table_name": "Nombre",
+ "name": "Nombre",
+ "interval": "Intervalo",
+ "next_run": "Próxima Ejecución",
+ "status": "Estado",
+ "enabled": "Habilitado",
+ "disabled": "Deshabilitado",
+ "start_date": "Fecha Inicio",
+ "start_time": "Hora Inicio",
+ "on_event": "En Evento (Script)",
+ "comment": "Comentario"
+ },
+ "toasts": {
+ "profile_created": "Perfil Creado",
+ "profile_created_desc": "El perfil de usuario \"{name}\" ha sido creado exitosamente.",
+ "profile_updated": "Perfil Actualizado",
+ "profile_updated_desc": "Cambios al perfil \"{name}\" han sido guardados.",
+ "profile_deleted": "Perfil Eliminado",
+ "profile_deleted_desc": "El perfil de usuario ha sido eliminado.",
+ "user_added": "Usuario Añadido",
+ "user_added_desc": "Usuario hotspot \"{name}\" ha sido creado.",
+ "user_deleted": "Usuario(s) Eliminado(s)",
+ "user_deleted_desc": "Los usuarios hotspot seleccionados han sido eliminados.",
+ "user_updated": "Usuario Actualizado",
+ "user_updated_desc": "Cambios al usuario \"{name}\" han sido guardados.",
+ "session_removed": "Sesión Eliminada",
+ "session_removed_desc": "La sesión hotspot activa ha sido terminada.",
+ "binding_added": "Enlace Añadido",
+ "binding_added_desc": "El enlace IP ha sido creado exitosamente.",
+ "binding_removed": "Enlace Eliminado",
+ "binding_removed_desc": "El enlace IP ha sido eliminado.",
+ "rule_added": "Regla Añadida",
+ "rule_added_desc": "La regla Walled Garden ha sido añadida.",
+ "rule_removed": "Regla Eliminada",
+ "rule_removed_desc": "La regla Walled Garden ha sido eliminada.",
+ "cookie_removed": "Cookie Eliminada",
+ "cookie_removed_desc": "La cookie hotspot ha sido borrada.",
+ "package_saved": "Paquete Guardado",
+ "package_saved_desc": "El paquete de impresión rápida ha sido actualizado.",
+ "package_deleted": "Paquete Eliminado",
+ "package_deleted_desc": "El paquete de impresión rápida ha sido eliminado.",
+ "vouchers_generated": "Cupones Generados",
+ "vouchers_generated_desc": "{qty} usuarios han sido creados exitosamente.",
+ "schedule_added": "Programación Añadida",
+ "schedule_added_desc": "La tarea ha sido programada.",
+ "schedule_updated": "Programación Actualizada",
+ "schedule_updated_desc": "Cambios a la tarea han sido guardados.",
+ "schedule_deleted": "Programación Eliminada",
+ "schedule_deleted_desc": "La tarea programada ha sido eliminada.",
+ "router_added": "Router Añadido",
+ "router_added_desc": "La sesión {name} ha sido creada.",
+ "router_updated": "Router Actualizado",
+ "router_updated_desc": "Ajustes para {name} han sido guardados.",
+ "router_deleted": "Router Eliminado",
+ "router_deleted_desc": "La sesión ha sido eliminada.",
+ "password_updated": "Contraseña Actualizada",
+ "password_updated_desc": "La contraseña de administrador ha sido cambiada.",
+ "settings_saved": "Ajustes Guardados",
+ "settings_saved_desc": "Preferencias globales han sido actualizadas.",
+ "restore_success": "Restauración Exitosa",
+ "restore_success_desc": "Sesiones y ajustes han sido restaurados desde el respaldo.",
+ "restore_failed": "Restauración Fallida",
+ "no_file_selected": "Ningún archivo de respaldo seleccionado.",
+ "invalid_file_type": "Tipo de archivo inválido. Por favor suba un archivo .mivo o .json.",
+ "invalid_file_type_mivo": "Tipo de archivo inválido. Por favor suba un archivo .mivo.",
+ "file_empty": "El archivo subido está vacío.",
+ "file_corrupted": "El archivo está corrupto o no es un respaldo Mivo válido.",
+ "logo_uploaded": "Logo Subido",
+ "logo_uploaded_desc": "Nuevo logo ha sido añadido exitosamente.",
+ "logo_deleted": "Logo Eliminado",
+ "logo_deleted_desc": "El logo ha sido eliminado.",
+ "template_created": "Plantilla Creada",
+ "template_created_desc": "Plantilla de cupón \"{name}\" ha sido añadida.",
+ "template_updated": "Plantilla Actualizada",
+ "template_updated_desc": "Cambios a \"{name}\" han sido guardados.",
+ "template_deleted": "Plantilla Eliminada",
+ "template_deleted_desc": "La plantilla ha sido eliminada.",
+ "test_alert": "Prueba Alerta Mivo",
+ "test_alert_desc": "Si ve esto, ¡el nuevo sistema de alertas funciona perfectamente! 🚀",
+ "cors_rule_added": "Regla CORS Añadida",
+ "cors_rule_added_desc": "La regla CORS para {origin} ha sido creada.",
+ "cors_rule_updated": "Regla CORS Actualizada",
+ "cors_rule_updated_desc": "Cambios a la regla CORS para {origin} han sido guardados.",
+ "cors_rule_deleted": "Regla CORS Eliminada",
+ "cors_rule_deleted_desc": "La regla CORS ha sido eliminada.",
+ "plugin_deleted": "Plugin Eliminado",
+ "plugin_deleted_desc": "El plugin ha sido eliminado exitosamente.",
+ "upload_failed": "Fallo al Subir",
+ "install_failed": "Instalación Fallida",
+ "invalid_plugin_desc": "Estructura de plugin inválida: plugin.php no encontrado.",
+ "zip_open_failed_desc": "Fallo al abrir el archivo zip subido."
+ },
+ "status": {
+ "check_title": "Verificar Estado de Cupón",
+ "check_desc": "Monitoree su uso de datos y validez de cupón en tiempo real sin necesidad de volver a iniciar sesión.",
+ "voucher_code_label": "Código de Cupón",
+ "voucher_code_placeholder": "Ej: QWASZX",
+ "code_placeholder": "Ej: QWASZX",
+ "check_now": "Verificar Ahora",
+ "details_title": "Detalles del Cupón",
+ "code": "Código de Cupón",
+ "data_remaining": "Datos Restantes",
+ "used": "Usado",
+ "package": "Paquete",
+ "validity": "Validez",
+ "uptime": "Tiempo activo",
+ "expires": "Expira",
+ "not_found_title": "Cupón No Encontrado",
+ "not_found_desc": "El código de cupón que ingresó no existe.",
+ "try_again": "Intentar de Nuevo"
+ },
+ "errors": {
+ "404_title": "Página No Encontrada",
+ "404_desc": "La página que busca podría haber sido eliminada, cambiado de nombre, o no está disponible temporalmente.",
+ "403_title": "Acceso Denegado",
+ "403_desc": "Usted no tiene permiso para acceder a este recurso.",
+ "500_title": "Error del Servidor",
+ "500_desc": "Algo salió mal por nuestra parte. Por favor intente de nuevo más tarde.",
+ "503_title": "Servicio No Disponible",
+ "503_desc": "El servidor no puede manejar la solicitud actualmente debido a mantenimiento o sobrecarga.",
+ "router_not_found_title": "Router No Encontrado",
+ "router_not_found_desc": "La sesión de router que intenta acceder no existe o ha sido eliminada.",
+ "return_home": "Volver a Inicio",
+ "go_back": "Retroceder"
+ }
+}
\ No newline at end of file
diff --git a/plugin.php b/plugin.php
new file mode 100644
index 0000000..d0ea93d
--- /dev/null
+++ b/plugin.php
@@ -0,0 +1,38 @@
+= 1.2.0
+ */
+
+use App\Core\Hooks;
+
+Hooks::addFilter('get_available_languages', function($languages) {
+ $languages[] = [
+ 'code' => 'es',
+ 'name' => 'Español',
+ 'flag' => 'es', // Correct ISO code
+ 'path' => '/lang/plugin/plugin-lang-es/es.json'
+ ];
+ return $languages;
+});
+
+// Register Route for Language File
+Hooks::addAction('router_init', function(\App\Core\Router $router) {
+ $router->get('/lang/plugin/plugin-lang-es/es.json', function() {
+ $path = __DIR__ . '/es.json';
+ if (file_exists($path)) {
+ header('Content-Type: application/json');
+ readfile($path);
+ exit;
+ }
+ http_response_code(404);
+ });
+});