adicionada a opção de escolha de linguas

This commit is contained in:
Renan Bernordi 2025-01-04 15:38:33 -03:00
parent 44bd9ec959
commit 53a350c3ae
11 changed files with 260 additions and 82 deletions

View file

@ -86,6 +86,7 @@ SITE_URL=http://localhost
DNS_SERVERS=1.1.1.1, 8.8.8.8
DEBUG=true
SELENIUM_HOST=selenium-hub:4444
LANGUAGE=pt-br
```
4. Run everything:
@ -105,7 +106,10 @@ The configurations are organized in `data/`:
- `global_rules.php`: Rules that apply to all sites
- `blocked_domains.php`: List of blocked sites
- `user_agents.php`: User Agents configurations
- `messages.php`: System messages
### Translations
- `/languages/`: Each language is in its ISO id (`pt-br, en or es`) and can be defined in the `LANGUAGE` environment
### S3 Cache

View file

@ -86,6 +86,7 @@ SITE_URL=http://localhost
DNS_SERVERS=1.1.1.1, 8.8.8.8
DEBUG=true
SELENIUM_HOST=selenium-hub:4444
LANGUAGE=pt-br
```
4. Roda tudo:
@ -105,7 +106,10 @@ As configurações estão organizadas em `data/`:
- `global_rules.php`: Regras que se aplicam a todos os sites
- `blocked_domains.php`: Lista de sites bloqueados
- `user_agents.php`: Configurações de User Agents
- `messages.php`: Mensagens do sistema
### Traduções
- `/languages/`: Cada lingua está em seu ISO id (`pt-br, en ou es`) e pode ser definida no environment `LANGUAGE`
### Cache S3

View file

@ -7,6 +7,12 @@ SITE_NAME=Marreta
# Descrição do site usada em meta tags e SEO
SITE_DESCRIPTION="Chapéu de paywall é marreta!"
# Idioma do site (opções disponíveis: pt-br, en, es)
# pt-br = Português do Brasil
# en = English
# es = Español
LANGUAGE=pt-br
# URL base do site (sem barra no final)
# Use https://localhost para desenvolvimento local
SITE_URL=https://localhost

View file

@ -7,7 +7,6 @@
* - Carregamento de variáveis de ambiente
* - Definições de constantes do sistema
* - Configurações de segurança
* - Mensagens do sistema
* - Configurações de bots e user agents
* - Lista de domínios bloqueados
* - Configurações de cache S3
@ -30,6 +29,7 @@ define('DISABLE_CACHE', isset($_ENV['DISABLE_CACHE']) ? filter_var($_ENV['DISABL
define('SELENIUM_HOST', isset($_ENV['SELENIUM_HOST']) ? $_ENV['SELENIUM_HOST'] : 'localhost:4444');
define('CACHE_DIR', __DIR__ . '/cache');
define('DEBUG', isset($_ENV['DEBUG']) ? filter_var($_ENV['DEBUG'], FILTER_VALIDATE_BOOLEAN) : false);
define('LANGUAGE', isset($_ENV['LANGUAGE']) ? $_ENV['LANGUAGE'] : 'pt-br');
/**
* Configurações de Redis
@ -60,7 +60,6 @@ if (S3_CACHE_ENABLED) {
/**
* Carrega as configurações do sistema
*/
define('MESSAGES', require __DIR__ . '/data/messages.php');
define('USER_AGENTS', require __DIR__ . '/data/user_agents.php');
define('BLOCKED_DOMAINS', require __DIR__ . '/data/blocked_domains.php');
define('DOMAIN_RULES', require __DIR__ . '/data/domain_rules.php');

View file

@ -1,42 +0,0 @@
<?php
/**
* Mensagens do sistema
*
* Array associativo contendo todas as mensagens de erro e avisos
* que podem ser exibidas ao usuário durante a execução do sistema
*/
return [
'BLOCKED_DOMAIN' => [
'message' => 'Este domínio está bloqueado para extração.',
'type' => 'error'
],
'DNS_FAILURE' => [
'message' => 'Falha ao resolver DNS para o domínio. Verifique se a URL está correta.',
'type' => 'warning'
],
'HTTP_ERROR' => [
'message' => 'O servidor retornou um erro ao tentar acessar a página. Tente novamente mais tarde.',
'type' => 'warning'
],
'CONNECTION_ERROR' => [
'message' => 'Erro ao conectar com o servidor. Verifique sua conexão e tente novamente.',
'type' => 'warning'
],
'CONTENT_ERROR' => [
'message' => 'Não foi possível obter o conteúdo. Tente usar os serviços de arquivo.',
'type' => 'warning'
],
'INVALID_URL' => [
'message' => 'Formato de URL inválido',
'type' => 'error'
],
'NOT_FOUND' => [
'message' => 'Página não encontrada',
'type' => 'error'
],
'GENERIC_ERROR' => [
'message' => 'Ocorreu um erro ao processar sua solicitação.',
'type' => 'warning'
]
];

34
app/inc/Language.php Normal file
View file

@ -0,0 +1,34 @@
<?php
class Language {
private static $translations = [];
private static $currentLanguage = 'pt-br';
public static function init($language = 'pt-br') {
self::$currentLanguage = strtolower($language);
$langFile = __DIR__ . '/../languages/' . self::$currentLanguage . '.php';
if (file_exists($langFile)) {
self::$translations = require $langFile;
} else {
// Fallback to pt-br if language file doesn't exist
self::$currentLanguage = 'pt-br';
self::$translations = require __DIR__ . '/../languages/pt-br.php';
}
}
public static function get($key, $default = '') {
return self::$translations[$key] ?? $default;
}
public static function getMessage($key) {
return self::$translations['messages'][$key] ?? [
'message' => 'Unknown message',
'type' => 'error'
];
}
public static function getCurrentLanguage() {
return self::$currentLanguage;
}
}

View file

@ -13,6 +13,10 @@
require_once 'config.php';
require_once 'inc/Cache.php';
require_once 'inc/Language.php';
// Initialize language
Language::init(LANGUAGE);
// Inicialização de variáveis
$message = '';
@ -20,10 +24,11 @@ $message_type = '';
$url = '';
// Processa mensagens de erro/alerta da query string
if (isset($_GET['message']) && isset(MESSAGES[$_GET['message']])) {
if (isset($_GET['message'])) {
$message_key = $_GET['message'];
$message = MESSAGES[$message_key]['message'];
$message_type = MESSAGES[$message_key]['type'];
$messageData = Language::getMessage($message_key);
$message = $messageData['message'];
$message_type = $messageData['type'];
}
// Processa submissão do formulário
@ -33,8 +38,9 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_POST['url'])) {
header('Location: ' . SITE_URL . '/p/' . urlencode($url));
exit;
} else {
$message = MESSAGES['INVALID_URL']['message'];
$message_type = MESSAGES['INVALID_URL']['type'];
$messageData = Language::getMessage('INVALID_URL');
$message = $messageData['message'];
$message_type = $messageData['type'];
}
}
@ -43,7 +49,7 @@ $cache = new Cache();
$cache_folder = $cache->getCacheFileCount();
?>
<!DOCTYPE html>
<html lang="pt-BR">
<html lang="<?php echo Language::getCurrentLanguage(); ?>">
<head>
<meta charset="UTF-8">
@ -61,19 +67,19 @@ $cache_folder = $cache->getCacheFileCount();
<body class="bg-gray-50 min-h-screen">
<div class="container mx-auto px-4 py-8 max-w-4xl">
<!-- Cabeçalho da página -->
<div class="text-center mb-8">
<h1 class="text-4xl font-bold text-gray-800 mb-4">
<img src="assets/svg/marreta.svg" class="inline-block w-12 h-12 mb-2" alt="Marreta">
<?php echo SITE_NAME; ?>
</h1>
<p class="text-gray-600 text-lg"><?php echo SITE_DESCRIPTION; ?></p>
<p class="text-gray-600 text-lg">
<span class="font-bold text-blue-600">
<?php echo number_format($cache_folder, 0, ',', '.'); ?>
</span>
<span>paredes derrubadas!</span>
</p>
</div>
<div class="text-center mb-8">
<h1 class="text-4xl font-bold text-gray-800 mb-4">
<img src="assets/svg/marreta.svg" class="inline-block w-12 h-12 mb-2" alt="Marreta">
<?php echo SITE_NAME; ?>
</h1>
<p class="text-gray-600 text-lg"><?php echo SITE_DESCRIPTION; ?></p>
<p class="text-gray-600 text-lg">
<span class="font-bold text-blue-600">
<?php echo number_format($cache_folder, 0, ',', '.'); ?>
</span>
<span><?php echo Language::get('walls_destroyed'); ?></span>
</p>
</div>
<!-- Formulário principal de análise de URLs -->
<div class="bg-white rounded-xl shadow-lg p-8 mb-8">
@ -87,16 +93,16 @@ $cache_folder = $cache->getCacheFileCount();
name="url"
id="url"
class="flex-1 block w-full rounded-none rounded-r-lg text-lg py-4 border border-l-0 border-gray-300 bg-gray-50 focus:border-blue-500 focus:ring-blue-500 shadow-sm bg-gray-50"
placeholder="Digite a URL (ex: https://exemplo.com)"
placeholder="<?php echo Language::get('url_placeholder'); ?>"
value="<?php echo htmlspecialchars($url); ?>"
required
pattern="https?://.+"
title="Por favor, insira uma URL válida começando com http:// ou https://">
title="<?php echo Language::getMessage('INVALID_URL')['message']; ?>">
</div>
<button type="submit"
class="mt-4 w-full inline-flex justify-center items-center px-6 py-4 border border-transparent text-lg font-medium rounded-lg text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200">
<img src="assets/svg/search.svg" class="w-6 h-6 mr-3" alt="Search">
Analisar
<?php echo Language::get('analyze_button'); ?>
</button>
</div>
</form>
@ -126,7 +132,7 @@ $cache_folder = $cache->getCacheFileCount();
<div class="mt-8 text-center text-base text-gray-500">
<p>
<img src="assets/svg/code.svg" class="inline-block w-5 h-5 mr-2" alt="Acesso direito">
Acesso direto:
<?php echo Language::get('direct_access'); ?>
<pre class="bg-gray-100 p-3 rounded-lg text-sm overflow-x-auto"><?php echo SITE_URL; ?>/p/https://exemplo.com</pre>
</p>
</div>
@ -135,18 +141,18 @@ $cache_folder = $cache->getCacheFileCount();
<div class="bg-white rounded-xl shadow-lg p-8 mt-8 mb-8">
<h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center">
<img src="assets/svg/bookmark.svg" class="w-6 h-6 mr-3" alt="Favoritos">
Adicione aos Favoritos
<?php echo Language::get('bookmarklet_title'); ?>
</h2>
<div class="space-y-4">
<p class="text-gray-600">
Arraste o botão abaixo para sua barra de favoritos para acessar o <?php echo SITE_NAME; ?> rapidamente em qualquer página:
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('bookmarklet_description')); ?>
</p>
<div class="flex justify-center">
<a href="javascript:(function(){let currentUrl=window.location.href;window.location.href='<?php echo SITE_URL; ?>/p/'+encodeURIComponent(currentUrl);})()"
class="inline-flex items-center px-6 py-3 border-2 border-blue-500 font-medium rounded-lg text-blue-600 bg-white hover:bg-blue-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 transition-colors duration-200 cursor-move"
onclick="return false;">
<img src="assets/svg/marreta.svg" class="w-5 h-5 mr-2" alt="Marreta">
Abrir no <?php echo SITE_NAME; ?>
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('open_in')); ?>
</a>
</div>
</div>
@ -156,7 +162,7 @@ $cache_folder = $cache->getCacheFileCount();
<div class="bg-white rounded-xl shadow-lg p-8 mt-8">
<h2 class="text-xl font-semibold text-gray-800 mb-6">
<img src="assets/svg/refresh.svg" class="inline-block w-6 h-6 mr-3" alt="Serviços alternativos">
Serviços alternativos
<?php echo Language::get('alternative_services'); ?>
</h2>
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
<a href="https://archive.today" target="_blank"
@ -180,18 +186,18 @@ $cache_folder = $cache->getCacheFileCount();
<div class="bg-white rounded-xl shadow-lg p-8 mt-8">
<h2 class="text-xl font-semibold text-gray-800 mb-6 flex items-center">
<img src="assets/svg/code.svg" class="w-6 h-6 mr-3" alt="API REST">
API REST
<?php echo Language::get('api_title'); ?>
</h2>
<div class="space-y-4">
<p class="text-gray-600">
O <?php echo SITE_NAME; ?> disponibiliza uma API REST para integração com outros sistemas:
<?php echo str_replace('{site_name}', SITE_NAME, Language::get('api_description')); ?>
</p>
<div class="bg-gray-50 rounded-lg p-4">
<h3 class="font-medium text-gray-800 mb-2">Endpoint:</h3>
<h3 class="font-medium text-gray-800 mb-2"><?php echo Language::get('endpoint'); ?></h3>
<pre class="bg-gray-100 p-3 rounded-lg text-sm overflow-x-auto">GET <?php echo SITE_URL; ?>/api/https://exemplo.com</pre>
</div>
<div class="bg-gray-50 rounded-lg p-4">
<h3 class="font-medium text-gray-800 mb-2">Resposta de sucesso:</h3>
<h3 class="font-medium text-gray-800 mb-2"><?php echo Language::get('success_response'); ?></h3>
<pre class="bg-gray-100 p-3 rounded-lg text-sm overflow-x-auto">
{
"status": 200,
@ -199,25 +205,24 @@ $cache_folder = $cache->getCacheFileCount();
}</pre>
</div>
<div class="bg-gray-50 rounded-lg p-4">
<h3 class="font-medium text-gray-800 mb-2">Resposta de erro:</h3>
<h3 class="font-medium text-gray-800 mb-2"><?php echo Language::get('error_response'); ?></h3>
<pre class="bg-gray-100 p-3 rounded-lg text-sm overflow-x-auto">
{
"status": 400,
"error": {
"code": "INVALID_URL",
"message": "URL inválida"
"message": "<?php echo Language::getMessage('INVALID_URL')['message']; ?>"
}
}</pre>
</div>
</div>
<h2 class="text-xl font-semibold text-gray-800 mt-6 mb-6 flex items-center">
<img src="assets/svg/code.svg" class="w-6 h-6 mr-3" alt="Open Source">
Projeto Open Source
<?php echo Language::get('open_source_title'); ?>
</h2>
<div>
<p class="text-gray-600">
Este é um projeto de <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">código aberto</a> feito com ❤️!<br />
Você pode contribuir, reportar problemas ou fazer sugestões através do <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">GitHub</a>.
<?php echo Language::get('open_source_description'); ?>
</p>
</div>
</div>

55
app/languages/en.php Normal file
View file

@ -0,0 +1,55 @@
<?php
return [
'site_description' => 'Paywall hat is a sledgehammer!',
'walls_destroyed' => 'walls destroyed!',
'url_placeholder' => 'Enter URL (e.g., https://example.com)',
'analyze_button' => 'Analyze',
'direct_access' => 'Direct access:',
'bookmarklet_title' => 'Add to Bookmarks',
'bookmarklet_description' => 'Drag the button below to your bookmarks bar to quickly access {site_name} on any page:',
'open_in' => 'Open in {site_name}',
'alternative_services' => 'Alternative Services',
'api_title' => 'REST API',
'api_description' => '{site_name} provides a REST API for integration with other systems:',
'endpoint' => 'Endpoint:',
'success_response' => 'Success response:',
'error_response' => 'Error response:',
'open_source_title' => 'Open Source Project',
'open_source_description' => 'This is an <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">open source</a> project made with ❤️!<br />You can contribute, report issues, or make suggestions through <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">GitHub</a>.',
'messages' => [
'BLOCKED_DOMAIN' => [
'message' => 'This domain is blocked for extraction.',
'type' => 'error'
],
'DNS_FAILURE' => [
'message' => 'Failed to resolve DNS for the domain. Please verify if the URL is correct.',
'type' => 'warning'
],
'HTTP_ERROR' => [
'message' => 'The server returned an error while trying to access the page. Please try again later.',
'type' => 'warning'
],
'CONNECTION_ERROR' => [
'message' => 'Error connecting to the server. Check your connection and try again.',
'type' => 'warning'
],
'CONTENT_ERROR' => [
'message' => 'Could not get content. Try using archive services.',
'type' => 'warning'
],
'INVALID_URL' => [
'message' => 'Invalid URL format',
'type' => 'error'
],
'NOT_FOUND' => [
'message' => 'Page not found',
'type' => 'error'
],
'GENERIC_ERROR' => [
'message' => 'An error occurred while processing your request.',
'type' => 'warning'
]
]
];

55
app/languages/es.php Normal file
View file

@ -0,0 +1,55 @@
<?php
return [
'site_description' => '¡El sombrero del muro de pago es un martillo!',
'walls_destroyed' => '¡paredes destruidas!',
'url_placeholder' => 'Ingrese URL (ej: https://ejemplo.com)',
'analyze_button' => 'Analizar',
'direct_access' => 'Acceso directo:',
'bookmarklet_title' => 'Agregar a Favoritos',
'bookmarklet_description' => 'Arrastra el botón a tu barra de favoritos para acceder rápidamente a {site_name} en cualquier página:',
'open_in' => 'Abrir en {site_name}',
'alternative_services' => 'Servicios Alternativos',
'api_title' => 'API REST',
'api_description' => '{site_name} proporciona una API REST para integración con otros sistemas:',
'endpoint' => 'Endpoint:',
'success_response' => 'Respuesta exitosa:',
'error_response' => 'Respuesta de error:',
'open_source_title' => 'Proyecto de Código Abierto',
'open_source_description' => '¡Este es un proyecto de <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">código abierto</a> hecho con ❤️!<br />Puedes contribuir, reportar problemas o hacer sugerencias a través de <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">GitHub</a>.',
'messages' => [
'BLOCKED_DOMAIN' => [
'message' => 'Este dominio está bloqueado para extracción.',
'type' => 'error'
],
'DNS_FAILURE' => [
'message' => 'Error al resolver DNS para el dominio. Verifique si la URL es correcta.',
'type' => 'warning'
],
'HTTP_ERROR' => [
'message' => 'El servidor devolvió un error al intentar acceder a la página. Por favor, inténtelo más tarde.',
'type' => 'warning'
],
'CONNECTION_ERROR' => [
'message' => 'Error al conectar con el servidor. Verifique su conexión e inténtelo de nuevo.',
'type' => 'warning'
],
'CONTENT_ERROR' => [
'message' => 'No se pudo obtener el contenido. Intente usar los servicios de archivo.',
'type' => 'warning'
],
'INVALID_URL' => [
'message' => 'Formato de URL inválido',
'type' => 'error'
],
'NOT_FOUND' => [
'message' => 'Página no encontrada',
'type' => 'error'
],
'GENERIC_ERROR' => [
'message' => 'Ocurrió un error al procesar su solicitud.',
'type' => 'warning'
]
]
];

54
app/languages/pt-br.php Normal file
View file

@ -0,0 +1,54 @@
<?php
return [
'walls_destroyed' => 'paredes derrubadas!',
'url_placeholder' => 'Digite a URL (ex: https://exemplo.com)',
'analyze_button' => 'Analisar',
'direct_access' => 'Acesso direto:',
'bookmarklet_title' => 'Adicione aos Favoritos',
'bookmarklet_description' => 'Arraste o botão abaixo para sua barra de favoritos para acessar o {site_name} rapidamente em qualquer página:',
'open_in' => 'Abrir no {site_name}',
'alternative_services' => 'Serviços alternativos',
'api_title' => 'API REST',
'api_description' => 'O {site_name} disponibiliza uma API REST para integração com outros sistemas:',
'endpoint' => 'Endpoint:',
'success_response' => 'Resposta de sucesso:',
'error_response' => 'Resposta de erro:',
'open_source_title' => 'Projeto Open Source',
'open_source_description' => 'Este é um projeto de <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">código aberto</a> feito com ❤️!<br />Você pode contribuir, reportar problemas ou fazer sugestões através do <a href="https://github.com/manualdousuario/marreta/" class="underline" target="_blank">GitHub</a>.',
'messages' => [
'BLOCKED_DOMAIN' => [
'message' => 'Este domínio está bloqueado para extração.',
'type' => 'error'
],
'DNS_FAILURE' => [
'message' => 'Falha ao resolver DNS para o domínio. Verifique se a URL está correta.',
'type' => 'warning'
],
'HTTP_ERROR' => [
'message' => 'O servidor retornou um erro ao tentar acessar a página. Tente novamente mais tarde.',
'type' => 'warning'
],
'CONNECTION_ERROR' => [
'message' => 'Erro ao conectar com o servidor. Verifique sua conexão e tente novamente.',
'type' => 'warning'
],
'CONTENT_ERROR' => [
'message' => 'Não foi possível obter o conteúdo. Tente usar os serviços de arquivo.',
'type' => 'warning'
],
'INVALID_URL' => [
'message' => 'Formato de URL inválido',
'type' => 'error'
],
'NOT_FOUND' => [
'message' => 'Página não encontrada',
'type' => 'error'
],
'GENERIC_ERROR' => [
'message' => 'Ocorreu um erro ao processar sua solicitação.',
'type' => 'warning'
]
]
];

View file

@ -48,6 +48,10 @@ if [ -n "${SITE_URL}" ]; then
echo "SITE_URL=${SITE_URL}" >> /app/.env
fi
if [ -n "${LANGUAGE}" ]; then
echo "LANGUAGE=${LANGUAGE}" >> /app/.env
fi
if [ -n "${DNS_SERVERS}" ]; then
echo "DNS_SERVERS=${DNS_SERVERS}" >> /app/.env
fi