commit b68f904c865b734fe81ec23d0fbc89996d4c00f6
Author: dyzulk <66510723+dyzulk@users.noreply.github.com>
Date: Mon Jan 19 10:13:09 2026 +0700
Initial commit
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
new file mode 100644
index 0000000..f9c1c72
--- /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-br.zip .
+ cd ..
+
+ echo "Created plugin-lang-br.zip"
+
+ - name: Create Release
+ uses: softprops/action-gh-release@v1
+ with:
+ files: plugin-lang-br.zip
+ name: Release ${{ steps.get_version.outputs.VERSION }}
+ body: |
+ Automatic release for version ${{ steps.get_version.outputs.VERSION }}
+
+ **Installation:**
+ 1. Download `plugin-lang-br.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..2ec3a33
--- /dev/null
+++ b/README.md
@@ -0,0 +1,22 @@
+# Portuguese (Brazil) Language Pack
+
+**Category:** Language Pack
+**Author:** DyzulkDev
+**Version:** 1.0.0
+
+The **Portuguese (Brazil) Language Pack** provides full Portuguese (Português - Brasil) localization for the Mivo Hotspot Manager.
+
+## Features
+- **Full Translation**: Covers Dashboard, Settings, Hotspot, and System menus.
+- **Flag Icon**: Adds the Brazil 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 **Português (Brasil)**.
+
+## Usage
+Simply install and activate. The language option will be available immediately to all users.
diff --git a/br.json b/br.json
new file mode 100644
index 0000000..03f1aed
--- /dev/null
+++ b/br.json
@@ -0,0 +1,632 @@
+{
+ "_meta": {
+ "name": "Português (Brasil)",
+ "flag": "br"
+ },
+ "common": {
+ "dashboard": "Painel",
+ "save": "Salvar",
+ "cancel": "Cancelar",
+ "delete": "Excluir",
+ "edit": "Editar",
+ "add": "Adicionar",
+ "install": "Instalar",
+ "back": "Voltar",
+ "actions": "Ações",
+ "status": "Status",
+ "name": "Nome",
+ "description": "Descrição",
+ "search": "Buscar",
+ "previous": "Anterior",
+ "next": "Próximo",
+ "confirm_delete": "Tem certeza que deseja excluir este item?",
+ "page_of": "Página {current} de {total}",
+ "all_topics": "Todos os tópicos",
+ "open": "Abrir",
+ "session": "Sessão",
+ "table": {
+ "entries_per_page": "entradas por página",
+ "search_placeholder": "Buscar...",
+ "all": "Todos",
+ "showing": "Mostrando {start} a {end} de {total} entradas",
+ "no_match": "Nenhum registro encontrado"
+ },
+ "char_length": "{n} Caracteres",
+ "forms": {
+ "general": "Geral",
+ "required": "obrigatório",
+ "save_changes": "Salvar Alterações",
+ "please_wait": "Por favor aguarde...",
+ "none": "nenhum",
+ "enabled": "Ativado",
+ "disabled": "Desativado"
+ },
+ "warning": "Aviso"
+ },
+ "home": {
+ "subtitle": "Um gerenciador de Hotspot MikroTik moderno e leve, construído para desempenho e simplicidade.",
+ "manage_routers": "Gerenciar Roteadores",
+ "manage_routers_desc": "Configurar conexões RouterOS e ver status.",
+ "source_code": "Código Fonte",
+ "source_code_desc": "Ver o repositório do projeto e contribuir.",
+ "quick_access": "Acesso Rápido",
+ "session_name": "Nome da Sessão",
+ "hotspot_name": "Nome do Hotspot",
+ "ip_address": "Endereço IP"
+ },
+ "dashboard": {
+ "system_info": "Info do Sistema",
+ "model": "Modelo",
+ "board_name": "Nome da Placa",
+ "router_os": "RouterOS",
+ "architecture": "Arquitetura",
+ "uptime": "Tempo de Atividade",
+ "resources": "Recursos",
+ "cpu_load": "Carga CPU",
+ "memory": "Memória",
+ "free": "Livre",
+ "hdd": "HDD",
+ "income_today": "Renda Hoje",
+ "traffic_monitor": "Monitor de Tráfego",
+ "rx_download": "Rx (Download)",
+ "tx_upload": "Tx (Upload)"
+ },
+ "settings": {
+ "title": "Configurações",
+ "subtitle": "Gerencie suas preferências e configurações do aplicativo.",
+ "system": "Geral",
+ "system_desc": "Configurações do sistema e segurança.",
+ "admin_username": "Usuário Administrador",
+ "admin_username_desc": "Por razões de segurança, o nome de usuário administrador não pode ser alterado.",
+ "change_password": "Alterar Senha",
+ "new_password_placeholder": "Digite a nova senha",
+ "update_password": "Atualizar Senha",
+ "quick_print_mode": "Modo Impressão Rápida",
+ "quick_print_mode_desc": "Ativar impressão direta para geração de vouchers.",
+ "save_global": "Salvar Configurações Globais",
+ "data_management": "Gerenciamento de Dados",
+ "data_management_desc": "Faça backup ou restaure os dados do seu aplicativo.",
+ "backup_data": "Backup de Dados",
+ "backup_data_desc": "Baixe um arquivo de configuração (.mivo) contendo seu banco de dados e configurações.",
+ "download_backup": "Baixar Backup",
+ "restore_data": "Restaurar Dados",
+ "restore_data_desc": "Envie um arquivo de backup (.mivo). Substitui ou adiciona aos dados existentes.",
+ "restore": "Restaurar",
+ "warning_restore": "AVISO: Isso restaurará as configurações do arquivo e pode substituir dados existentes. Continuar?",
+ "routers_title": "Roteadores",
+ "routers_subtitle": "Gerencie suas conexões MikroTik RouterOS.",
+ "add_router": "Adicionar Roteador",
+ "no_routers": "Nenhum Roteador Encontrado",
+ "connect_first": "Conecte seu primeiro roteador MikroTik para começar a gerenciar hotspots e vouchers.",
+ "delete_router_title": "Excluir Sessão?",
+ "delete_router_confirm": "Tem certeza que deseja excluir {name}? Esta ação não pode ser desfeita.",
+ "connect": "Conectar",
+ "logos_title": "Logos",
+ "logos_subtitle": "Envie e gerencie logotipos para seus hotspots e vouchers.",
+ "upload_new_logo": "Enviar Novo Logo",
+ "drag_drop": "Arraste e solte ou clique para selecionar arquivo",
+ "supports_formats": "Suporta PNG, JPG, SVG, GIF",
+ "no_logos": "Nenhum logotipo enviado ainda.",
+ "id_copied": "ID Copiado",
+ "logo_id_copied_desc": "ID do Logo {id} copiado para a área de transferência.",
+ "delete_logo_title": "Excluir Logo?",
+ "delete_logo_confirm": "Tem certeza que deseja excluir o logo {id}?",
+ "templates_title": "Modelos de Voucher",
+ "templates_subtitle": "Gerencie e personalize seus designs de impressão de vouchers.",
+ "new_template": "Novo Modelo",
+ "edit_template": "Editar Modelo",
+ "default_template": "Modelo Padrão",
+ "system_label": "Sistema",
+ "custom_label": "Personalizado",
+ "built_in": "Integrado",
+ "default_template_desc": "Modelo padrão compatível com impressoras térmicas.",
+ "delete_template_title": "Excluir Modelo?",
+ "delete_template_confirm": "Tem certeza que deseja excluir {name}?",
+ "template_name": "Nome do Modelo",
+ "html_source": "Código HTML",
+ "docs": "Docs",
+ "live_preview": "Pré-visualização",
+ "template_variables": "Variáveis do Modelo",
+ "variables_desc": "Use estas variáveis no seu código HTML. Elas serão substituídas por dados reais do usuário durante a impressão.",
+ "qr_code": "Código QR",
+ "qr_desc": "Gera um Código QR contendo a URL de login com usuário e senha.",
+ "custom_attributes": "Atributos Personalizados",
+ "examples": "Exemplos",
+ "api_cors_title": "API CORS",
+ "api_cors_subtitle": "Gerencie o Compartilhamento de Recursos de Origem Cruzada para acesso API.",
+ "add_rule": "Adicionar Regra CORS",
+ "edit_rule": "Editar Regra CORS",
+ "origin": "Origem",
+ "methods": "Métodos Permitidos",
+ "headers": "Cabeçalhos Permitidos",
+ "max_age": "Idade Máxima (segundos)",
+ "cpu_warning": "Valores baixos (< 5s) podem aumentar o uso da CPU em roteadores antigos.",
+ "back": "Voltar para Configurações",
+ "editor_shortcuts": "Atalhos do Editor & Emmet",
+ "emmet_desc": "Use abreviações Emmet para codificar mais rápido. Procure o sublinhado pontilhado, depois pressione Tab.",
+ "tip_emmet_html": "Modelo HTML: Digite ! depois Tab.",
+ "tip_emmet_tag": "Auto-Tag: Digite .container depois Tab para <div class=\"container\">.",
+ "tip_color_picker": "Seletor de Cores: Clique na caixa de cor ao lado dos códigos hex (ex: #ff0000) para abrir o seletor.",
+ "tip_syntax_error": "Erro de Sintaxe: Os rabiscos vermelhos (e pontos na margem) mostram erros de estrutura como tags não fechadas.",
+ "plugins_title": "Plugins",
+ "plugins": "Plugins",
+ "plugins_desc": "Gerencie e estenda a funcionalidade com plugins.",
+ "upload_plugin": "Enviar Plugin",
+ "upload_plugin_desc": "Selecione um arquivo .zip de plugin para instalar.",
+ "no_plugins": "Nenhum Plugin Instalado",
+ "no_plugins_desc": "Envie um arquivo .zip para começar.",
+ "plugin_installed": "Plugin Instalado",
+ "plugin_installed_desc": "O plugin \"{name}\" foi instalado com sucesso.",
+ "delete_plugin": "Excluir Plugin?",
+ "delete_plugin_confirm": "Tem certeza que deseja excluir o plugin {name}? Esta ação não pode ser desfeita.",
+ "install_failed": "Instalação Falhou"
+ },
+ "routers": {
+ "edit_router_title": "Editar Roteador",
+ "add_router_title": "Adicionar Roteador",
+ "connect_desc": "Conecte o Mivo ao seu dispositivo RouterOS.",
+ "session_settings": "Configurações da Sessão",
+ "unique_id": "ID Único. Prévia:",
+ "show_quick_access": "Mostrar no Acesso Rápido (Início)",
+ "connection_details": "Detalhes da Conexão",
+ "password_hint": "Deixe vazio para manter a senha existente.",
+ "hotspot_info": "Informações do Hotspot",
+ "dns_name": "Nome DNS",
+ "traffic_interface": "Interface de Tráfego",
+ "check_btn": "Verificar",
+ "currency": "Moeda",
+ "auto_reload": "Recarga Auto (Seg)",
+ "save_connect": "Salvar & Conectar"
+ },
+ "login": {
+ "welcome": "Bem-vindo, por favor faça login para continuar.",
+ "username": "Usuário",
+ "password": "Senha",
+ "sign_in": "Entrar"
+ },
+ "quick_print": {
+ "title": "Impressão Rápida",
+ "subtitle": "Geração e impressão instantânea de vouchers.",
+ "manage": "Gerenciar Pacotes",
+ "manage_title": "Gerenciar Pacotes",
+ "manage_subtitle": "Configure seus pacotes de vouchers de Impressão Rápida para:",
+ "no_packages": "Nenhum Pacote Encontrado",
+ "no_packages_found": "Nenhum pacote encontrado.",
+ "create_first": "Crie um pacote de Impressão Rápida para começar.",
+ "create_package": "Criar Pacote",
+ "add_package": "Adicionar Pacote",
+ "edit_package": "Editar Pacote",
+ "save_package": "Salvar Pacote",
+ "delete_package": "Excluir Pacote",
+ "print_voucher": "Imprimir Voucher",
+ "name": "Nome",
+ "package_name": "Nome do Pacote",
+ "profile": "Perfil",
+ "select_profile": "Selecionar Perfil",
+ "prefix": "Prefixo",
+ "server": "Servidor",
+ "price": "Preço",
+ "selling_price": "Preço de Venda",
+ "time_limit": "Limite de Tempo",
+ "data_limit": "Limite de Dados",
+ "card_color": "Cor do Cartão",
+ "char_length": "Comprimento de Caracteres",
+ "vouchers_to_generate": "Vouchers a Gerar",
+ "comment": "Comentário"
+ },
+ "sidebar": {
+ "dashboard": "Painel",
+ "quick_print": "Impressão Rápida",
+ "hotspot": "Hotspot",
+ "status": "Status",
+ "security": "Segurança",
+ "reports": "Relatórios",
+ "network": "Rede",
+ "system": "Sistema",
+ "settings": "Configurações",
+ "templates": "Modelos",
+ "disconnect": "Desconectar",
+ "logout": "Sair do Mivo"
+ },
+ "hotspot_active": {
+ "title": "Usuários Ativos",
+ "subtitle": "Monitorar sessões de hotspot atualmente ativas",
+ "filter_server": "Todos os Servidores",
+ "server": "Servidor",
+ "user": "Usuário",
+ "address": "Endereço / MAC",
+ "uptime": "Tempo Ativo / Restante",
+ "bytes_in_out": "Bytes Ent/Sai",
+ "time_left": "Resta",
+ "remove": "Desconectar Usuário?"
+ },
+ "hotspot_hosts": {
+ "title": "Hosts Hotspot",
+ "subtitle": "Dispositivos conectados à rede hotspot para:",
+ "mac": "Endereço MAC",
+ "address": "Endereço",
+ "to_address": "Para Endereço",
+ "server": "Servidor",
+ "comment": "Comentário"
+ },
+ "hotspot_menu": {
+ "users": "Usuários",
+ "profiles": "Perfis de Usuário",
+ "generate": "Gerar",
+ "cookies": "Cookies",
+ "active": "Ativos",
+ "hosts": "Hosts",
+ "bindings": "IP Binding",
+ "walled_garden": "Walled Garden"
+ },
+ "reports_menu": {
+ "resume": "Resumo",
+ "selling": "Relatório de Vendas",
+ "user_log": "Log de Usuário"
+ },
+ "network_menu": {
+ "dhcp": "DHCP Lease"
+ },
+ "system_menu": {
+ "scheduler": "Agendador",
+ "reboot": "Reiniciar",
+ "shutdown": "Desligar"
+ },
+ "dhcp": {
+ "title": "DHCP Lease",
+ "subtitle": "DHCP leases ativos para:",
+ "all_servers": "Todos os Servidores",
+ "address": "Endereço",
+ "mac": "Endereço MAC",
+ "server": "Servidor",
+ "status": "Status",
+ "host": "Nome do Host"
+ },
+ "cookies": {
+ "title": "Usuários Hotspot",
+ "subtitle": "Gerencie usuários e vouchers",
+ "name": "Nome",
+ "mac": "Endereço MAC",
+ "ip": "Endereço IP",
+ "expires": "Expira Em",
+ "remove_cookie": "Remover Cookie?",
+ "remove_confirm": "Tem certeza que deseja remover o cookie para {user}?"
+ },
+ "reports": {
+ "selling_title": "Relatório de Vendas",
+ "selling_subtitle": "Resumo de vendas e detalhes para:",
+ "user_log_title": "Log de Usuário",
+ "user_log_subtitle": "Histórico de login e logout para:",
+ "resume_title": "Relatório de Resumo",
+ "resume_subtitle": "Visão geral da receita agregada.",
+ "total_income": "Renda Total",
+ "total_vouchers": "Total de Vouchers Vendidos",
+ "date_batch": "Data / Lote (Comentário)",
+ "qty": "Qtd",
+ "total": "Total",
+ "no_data": "Nenhum dado de venda encontrado.",
+ "time": "Tempo",
+ "topics": "Tópicos",
+ "message": "Mensagem",
+ "daily": "Diário",
+ "monthly": "Mensal",
+ "yearly": "Anual",
+ "date": "Data",
+ "month": "Mês",
+ "year": "Ano",
+ "refresh": "Atualizar",
+ "print_report": "Imprimir Relatório"
+ },
+ "hotspot_profiles": {
+ "title": "Perfis de Usuário",
+ "subtitle": "Gerencie limites de velocidade e preços",
+ "add_profile": "Adicionar Perfil",
+ "edit_profile": "Editar Perfil",
+ "all_modes": "Todos os Modos Expirados",
+ "name": "Nome",
+ "shared_users": "Usuários Compartilhados",
+ "rate_limit": "Limite de Velocidade",
+ "parent_queue": "Fila Pai",
+ "expired_mode": "Modo Expirado",
+ "validity": "Validade",
+ "price": "Preço",
+ "selling_price": "Preço de Venda",
+ "lock_user": "Bloquear Usuário",
+ "form": {
+ "add_title": "Adicionar Perfil",
+ "edit_title": "Editar Perfil",
+ "add_subtitle": "Criar um novo perfil de usuário hotspot para: {name}",
+ "edit_subtitle": "Editar perfil de usuário hotspot: {name}",
+ "settings": "Configurações de Perfil",
+ "general": "Configurações Gerais",
+ "limits_queues": "Limites e Filas",
+ "pricing_validity": "Preços e Validade",
+ "address_pool": "Pool de Endereços",
+ "rate_limit_help": "Rx/Tx (Download/Upload). Exemplo: 512k/1M",
+ "expired_mode_help": "Ação quando a validade expira.",
+ "validity_help": "Dias / Horas / Minutos",
+ "lock_user_help": "Bloquear usuário a um endereço MAC específico.",
+ "save": "Salvar Perfil",
+ "name_placeholder": "ex: Pacote-1Hora",
+ "quick_tips": "Dicas Rápidas",
+ "tip_rate_limit": "Limite de Velocidade: Rx/Tx (Download/Upload). Exemplo: 512k/1M",
+ "tip_expired_mode": "Modo Expirado: Selecione 'Remover' ou 'Aviso' para habilitar Validade.",
+ "tip_parent_queue": "Fila Pai: Atribui usuários a uma fila pai específica para gerenciamento de largura de banda."
+ }
+ },
+ "hotspot_users": {
+ "add_user": "Adicionar Usuário",
+ "edit_user": "Editar Usuário",
+ "title": "Usuários Hotspot",
+ "subtitle": "Gerencie usuários e vouchers",
+ "name": "Nome",
+ "profile": "Perfil",
+ "uptime_limit": "Tempo Ativo / Limite",
+ "bytes_in_out": "Bytes Ent/Sai",
+ "comment": "Comentário",
+ "no_users_selected": "Nenhum usuário selecionado.",
+ "form": {
+ "add_title": "Adicionar Usuário",
+ "edit_title": "Editar Usuário",
+ "subtitle": "Conta de usuário hotspot",
+ "edit_subtitle": "Atualizar detalhes do usuário para: {name}",
+ "username": "Usuário",
+ "password": "Senha",
+ "profile": "Perfil",
+ "server": "Servidor",
+ "time_limit": "Limite de Tempo",
+ "data_limit": "Limite de Dados",
+ "comment": "Comentário",
+ "save": "Salvar Usuário",
+ "username_help": "Nome de usuário único para login.",
+ "password_help": "Senha forte.",
+ "profile_help": "O perfil determina o limite de velocidade padrão e a política.",
+ "time_limit_help": "Tempo total permitido (Dias, Horas, Minutos).",
+ "data_limit_help": "Limite de uso de dados (0 para ilimitado).",
+ "comment_help": "Notas adicionais ou info de contato.",
+ "username_placeholder": "ex: voucher123",
+ "password_placeholder": "ex: 123456",
+ "comment_placeholder": "Nota opcional para este usuário",
+ "quick_tips": "Dicas Rápidas",
+ "tip_profiles": "Perfis definem limites de velocidade padrão, tempo de sessão e políticas.",
+ "tip_time_limit": "Limite de Tempo é o tempo total acumulado permitido para este usuário.",
+ "tip_data_limit": "Limite de Dados substituirá a configuração do perfil. Defina como 0 para usar o do perfil."
+ }
+ },
+ "hotspot_generate": {
+ "title": "Gerar Vouchers",
+ "form": {
+ "qty": "Quantidade",
+ "server": "Servidor",
+ "user_mode": "Modo de Usuário",
+ "user_length": "Comprimento do Usuário",
+ "prefix": "Prefixo",
+ "characters": "Caracteres",
+ "profile": "Perfil",
+ "time_limit": "Limite de Tempo",
+ "data_limit": "Limite de Dados",
+ "comment": "Comentário",
+ "generate": "Gerar Vouchers",
+ "subtitle": "Criar múltiplos vouchers hotspot em lote para: {name}",
+ "batch_settings": "Configurações de Geração em Lote",
+ "core_config": "Configuração Principal",
+ "qty_help": "Quantidade de vouchers a gerar.",
+ "server_help": "Instância Hotspot alvo.",
+ "user_mode_help": "Formato das credenciais.",
+ "comment_help": "Nota para este lote.",
+ "user_format": "Formato de Usuário",
+ "name_length_help": "Comprimento do usuário/senha.",
+ "prefix_placeholder": "ex: VIP-",
+ "prefix_help": "Prefixo para usuários gerados.",
+ "characters_help": "Tipos de caracteres a incluir.",
+ "limits_profile": "Limites e Perfil",
+ "profile_help": "Aplicar limites de velocidade do perfil.",
+ "time_limit_help": "Tempo máx (ex: 1h, 30m).",
+ "data_limit_help": "Transferência máx (MB).",
+ "quick_tips": "Dicas Rápidas",
+ "tip_user_mode": "Modo de Usuário: UP (separado), VC (mesmo).",
+ "tip_format_examples": "Exemplos de Formato: abcd (minúsculo), 1234 (num), Mix (maiúsc/minúsc/num).",
+ "tip_limits": "Limites: Tempo (ex: 1h, 30m), Dados (ex: 100MB). Deixe vazio para usar o padrão do perfil."
+ }
+ },
+ "security": {
+ "bindings": {
+ "title": "IP Binding",
+ "subtitle": "Gerencie IP binding (bypass/bloqueado) para: {name}",
+ "all_types": "Todos os Tipos",
+ "regular": "Regular",
+ "bypassed": "Liberado",
+ "blocked": "Bloqueado",
+ "table": {
+ "mac": "Endereço MAC",
+ "address": "Endereço",
+ "to_address": "Para Endereço",
+ "type": "Tipo",
+ "comment": "Comentário"
+ },
+ "form": {
+ "add_title": "Adicionar Binding",
+ "mac_address": "Endereço MAC",
+ "address": "Endereço",
+ "to_address": "Para Endereço",
+ "type": "Tipo",
+ "server": "Servidor",
+ "comment": "Comentário",
+ "mac_help": "Endereço MAC do dispositivo.",
+ "address_help": "Endereço IP (opcional).",
+ "to_address_help": "Traduzir para este IP (opcional).",
+ "server_help": "Aplicar a servidor Hotspot específico.",
+ "comment_help": "Nota para este binding.",
+ "save": "Salvar & Vincular",
+ "tip_bypassed": "Liberado: Acesso sem login.",
+ "tip_blocked": "Bloqueado: Negar acesso completamente.",
+ "tip_regular": "Regular: Cliente hotspot normal."
+ }
+ },
+ "walled_garden": {
+ "title": "Walled Garden",
+ "subtitle": "Gerencie destinos permitidos (bypass sem login) para: {name}",
+ "all_actions": "Todas as Ações",
+ "allow": "Permitir",
+ "deny": "Negar",
+ "table": {
+ "host_ip": "Host / IP Dest",
+ "proto_port": "Protocolo / Porta",
+ "action": "Ação",
+ "comment": "Comentário"
+ },
+ "form": {
+ "add_title": "Adicionar Entrada",
+ "action": "Ação",
+ "dst_host": "Host Dest (Domínio)",
+ "dst_address": "Endereço Dest (IP)",
+ "protocol": "Protocolo",
+ "dst_port": "Porta Dest",
+ "server": "Servidor",
+ "comment": "Comentário",
+ "host_help": "Domínio a permitir (curinga suportado).",
+ "addr_help": "Endereço IP de destino.",
+ "action_help": "Permitir (bypass) ou Negar acesso.",
+ "server_help": "Aplicar a servidor Hotspot específico.",
+ "comment_help": "Nota para esta regra.",
+ "save": "Salvar Entrada",
+ "tip_host": "Host Dest: Nome de domínio (ex: *.google.com).",
+ "tip_ip": "IP Dest: Endereço IP específico.",
+ "tip_action": "Ação: Permitir para pular autenticação."
+ }
+ }
+ },
+ "system_tools": {
+ "scheduler_subtitle": "Gerencie tarefas automatizadas do RouterOS para:",
+ "add_task": "Adicionar Tarefa",
+ "add_title": "Adicionar Tarefa",
+ "edit_title": "Editar Tarefa",
+ "save_task": "Salvar Tarefa",
+ "update_task": "Atualizar Tarefa",
+ "delete_task": "Excluir Tarefa",
+ "table_name": "Nome",
+ "name": "Nome",
+ "interval": "Intervalo",
+ "next_run": "Próxima Execução",
+ "status": "Status",
+ "enabled": "Ativado",
+ "disabled": "Desativado",
+ "start_date": "Data Início",
+ "start_time": "Hora Início",
+ "on_event": "No Evento (Script)",
+ "comment": "Comentário"
+ },
+ "toasts": {
+ "profile_created": "Perfil Criado",
+ "profile_created_desc": "O perfil de usuário \"{name}\" foi criado com sucesso.",
+ "profile_updated": "Perfil Atualizado",
+ "profile_updated_desc": "Alterações no perfil \"{name}\" foram salvas.",
+ "profile_deleted": "Perfil Excluído",
+ "profile_deleted_desc": "O perfil de usuário foi excluído.",
+ "user_added": "Usuário Adicionado",
+ "user_added_desc": "Usuário hotspot \"{name}\" foi criado.",
+ "user_deleted": "Usuário(s) Excluído(s)",
+ "user_deleted_desc": "Os usuários selecionados foram excluídos.",
+ "user_updated": "Usuário Atualizado",
+ "user_updated_desc": "Alterações no usuário \"{name}\" foram salvas.",
+ "session_removed": "Sessão Removida",
+ "session_removed_desc": "A sessão hotspot ativa foi encerrada.",
+ "binding_added": "Binding Adicionado",
+ "binding_added_desc": "IP Binding criado com sucesso.",
+ "binding_removed": "Binding Removido",
+ "binding_removed_desc": "IP Binding removido com sucesso.",
+ "rule_added": "Regra Adicionada",
+ "rule_added_desc": "Regra Walled Garden adicionada com sucesso.",
+ "rule_removed": "Regra Removida",
+ "rule_removed_desc": "Regra Walled Garden removida com sucesso.",
+ "cookie_removed": "Cookie Removido",
+ "cookie_removed_desc": "Cookie hotspot removido com sucesso.",
+ "package_saved": "Pacote Salvo",
+ "package_saved_desc": "Pacote de impressão rápida atualizado com sucesso.",
+ "package_deleted": "Pacote Excluído",
+ "package_deleted_desc": "Pacote de impressão rápida excluído com sucesso.",
+ "vouchers_generated": "Vouchers Gerados",
+ "vouchers_generated_desc": "{qty} usuários criados com sucesso.",
+ "schedule_added": "Agendamento Adicionado",
+ "schedule_added_desc": "Tarefa agendada com sucesso.",
+ "schedule_updated": "Agendamento Atualizado",
+ "schedule_updated_desc": "Alterações na tarefa salvas com sucesso.",
+ "schedule_deleted": "Agendamento Excluído",
+ "schedule_deleted_desc": "Tarefa agendada excluída com sucesso.",
+ "router_added": "Roteador Adicionado",
+ "router_added_desc": "Sessão {name} criada com sucesso.",
+ "router_updated": "Roteador Atualizado",
+ "router_updated_desc": "Configurações para {name} salvas com sucesso.",
+ "router_deleted": "Roteador Excluído",
+ "router_deleted_desc": "Sessão excluída com sucesso.",
+ "password_updated": "Senha Atualizada",
+ "password_updated_desc": "Senha do administrador alterada com sucesso.",
+ "settings_saved": "Configurações Salvas",
+ "settings_saved_desc": "Preferências globais atualizadas com sucesso.",
+ "restore_success": "Restauração com Sucesso",
+ "restore_success_desc": "Sessões e configurações restauradas do backup.",
+ "restore_failed": "Restauração Falhou",
+ "no_file_selected": "Nenhum arquivo de backup selecionado.",
+ "invalid_file_type": "Tipo de arquivo inválido. Por favor envie um arquivo .mivo ou .json.",
+ "invalid_file_type_mivo": "Tipo de arquivo inválido. Por favor envie um arquivo .mivo.",
+ "file_empty": "O arquivo enviado está vazio.",
+ "file_corrupted": "O arquivo está corrompido ou não é um backup Mivo válido.",
+ "logo_uploaded": "Logo Enviado",
+ "logo_uploaded_desc": "Novo logotipo adicionado com sucesso.",
+ "logo_deleted": "Logo Excluído",
+ "logo_deleted_desc": "Logotipo excluído com sucesso.",
+ "template_created": "Modelo Criado",
+ "template_created_desc": "Modelo de voucher \"{name}\" adicionado com sucesso.",
+ "template_updated": "Modelo Atualizado",
+ "template_updated_desc": "Alterações em \"{name}\" salvas com sucesso.",
+ "template_deleted": "Modelo Excluído",
+ "template_deleted_desc": "Modelo excluído com sucesso.",
+ "test_alert": "Teste Alerta Mivo",
+ "test_alert_desc": "Se você vê isso, o novo sistema de alertas funciona perfeitamente! 🚀",
+ "cors_rule_added": "Regra CORS Adicionada",
+ "cors_rule_added_desc": "Regra CORS para {origin} criada com sucesso.",
+ "cors_rule_updated": "Regra CORS Atualizada",
+ "cors_rule_updated_desc": "Alterações na regra CORS para {origin} salvas com sucesso.",
+ "cors_rule_deleted": "Regra CORS Excluída",
+ "cors_rule_deleted_desc": "Regra CORS excluída com sucesso.",
+ "plugin_deleted": "Plugin Excluído",
+ "plugin_deleted_desc": "Plugin excluído com sucesso.",
+ "upload_failed": "Falha no Envio",
+ "install_failed": "Instalação Falhou",
+ "invalid_plugin_desc": "Estrutura de plugin inválida: plugin.php não encontrado.",
+ "zip_open_failed_desc": "Falha ao abrir o arquivo zip enviado."
+ },
+ "status": {
+ "check_title": "Verificar Status do Voucher",
+ "check_desc": "Monitore seu uso de dados e validade do voucher em tempo real sem precisar fazer login novamente.",
+ "voucher_code_label": "Código do Voucher",
+ "voucher_code_placeholder": "Ex: QWASZX",
+ "code_placeholder": "Ex: QWASZX",
+ "check_now": "Verificar Agora",
+ "details_title": "Detalhes do Voucher",
+ "code": "Código do Voucher",
+ "data_remaining": "Dados Restantes",
+ "used": "Usado",
+ "package": "Pacote",
+ "validity": "Validade",
+ "uptime": "Tempo Ativo",
+ "expires": "Expira",
+ "not_found_title": "Voucher Não Encontrado",
+ "not_found_desc": "O código de voucher que você digitou não existe.",
+ "try_again": "Tentar Novamente"
+ },
+ "errors": {
+ "404_title": "Página Não Encontrada",
+ "404_desc": "A página que você procura pode ter sido removida, renomeada ou está temporariamente indisponível.",
+ "403_title": "Acesso Negado",
+ "403_desc": "Você não tem permissão para acessar este recurso.",
+ "500_title": "Erro no Servidor",
+ "500_desc": "Algo deu errado do nosso lado. Por favor tente novamente mais tarde.",
+ "503_title": "Serviço Indisponível",
+ "503_desc": "O servidor não consegue lidar com a solicitação no momento devido a manutenção ou sobrecarga.",
+ "router_not_found_title": "Roteador Não Encontrado",
+ "router_not_found_desc": "A sessão do roteador que você está tentando acessar não existe ou foi excluída.",
+ "return_home": "Voltar ao Início",
+ "go_back": "Voltar"
+ }
+}
\ No newline at end of file
diff --git a/plugin.php b/plugin.php
new file mode 100644
index 0000000..7f7b4d5
--- /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' => 'br',
+ 'name' => 'Português (Brasil)',
+ 'flag' => 'br', // Correct ISO code
+ 'path' => '/lang/plugin/plugin-lang-br/br.json'
+ ];
+ return $languages;
+});
+
+// Register Route for Language File
+Hooks::addAction('router_init', function(\App\Core\Router $router) {
+ $router->get('/lang/plugin/plugin-lang-br/br.json', function() {
+ $path = __DIR__ . '/br.json';
+ if (file_exists($path)) {
+ header('Content-Type: application/json');
+ readfile($path);
+ exit;
+ }
+ http_response_code(404);
+ });
+});