apiUrl = rtrim($_ENV['LIBRETRANSLATE_URL'], '/'); } public function detectLanguage($text) { if (empty(trim($text))) { return null; } $response = $this->request('/detect', ['q' => $text]); if (isset($response[0]['language'])) { return $response[0]['language']; } return null; } public function translateText($text, $source, $target) { if (empty(trim($text))) { return null; } $response = $this->request('/translate', [ 'q' => $text, 'source' => $source, 'target' => $target, 'format' => 'text' ]); return $response['translatedText'] ?? null; } public function translateHtml($html, $source, $target) { if (empty(trim($html))) { return null; } $maxLength = 4000; // Límite de caracteres para LibreTranslate $translatedHtml = ''; custom_log("translateHtml: Original HTML length: " . mb_strlen($html)); // Dividir el HTML en bloques para evitar exceder el límite de LibreTranslate $chunks = $this->splitHtmlIntoChunks($html, $maxLength); custom_log("translateHtml: Number of chunks: " . count($chunks)); foreach ($chunks as $index => $chunk) { custom_log("translateHtml: Processing chunk " . ($index + 1) . "/" . count($chunks) . ", length: " . mb_strlen($chunk)); $response = $this->request('/translate', [ 'q' => $chunk, 'source' => $source, 'target' => $target, 'format' => 'html' ]); $translatedChunk = $response['translatedText'] ?? null; if ($translatedChunk) { $translatedHtml .= $translatedChunk; custom_log("translateHtml: Chunk " . ($index + 1) . " translated successfully."); } else { // Si una parte falla, devolver la parte original para no perder contenido $translatedHtml .= $chunk; custom_log("translateHtml: Chunk " . ($index + 1) . " failed to translate. Appending original chunk."); } } return $translatedHtml; } private function splitHtmlIntoChunks($html, $maxLength) { $chunks = []; $currentChunk = ''; $dom = new DOMDocument(); // Suprimir errores de HTML mal formado @$dom->loadHTML('
' . $html . '
', LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); $xpath = new DOMXPath($dom); // Query all direct children of the body (or the implied div) $nodes = $xpath->query('//body/*'); if ($nodes->length === 0) { // If no block-level elements, treat the whole HTML as one chunk $nodes = $xpath->query('//body/text()'); if ($nodes->length === 0) { // Fallback if no text nodes either, just return the original HTML as one chunk return [$html]; } } foreach ($nodes as $node) { $nodeHtml = $dom->saveHTML($node); custom_log("splitHtmlIntoChunks: Processing node, length: " . mb_strlen($nodeHtml) . ", HTML: " . substr($nodeHtml, 0, 100) . "..."); if (mb_strlen($currentChunk . $nodeHtml) <= $maxLength) { $currentChunk .= $nodeHtml; } else { if (!empty($currentChunk)) { $chunks[] = $currentChunk; custom_log("splitHtmlIntoChunks: Added chunk, length: " . mb_strlen($currentChunk)); } $currentChunk = $nodeHtml; } } if (!empty($currentChunk)) { $chunks[] = $currentChunk; custom_log("splitHtmlIntoChunks: Added final chunk, length: " . mb_strlen($currentChunk)); } return $chunks; } public function translateTextBatch($texts, $source, $target) { if (empty($texts)) { return null; } $response = $this->request('/translate', [ 'q' => $texts, 'source' => $source, 'target' => $target, 'format' => 'text' ]); return $response['translatedText'] ?? null; } public function getSupportedLanguages() { $response = $this->request('/languages', [], 'GET'); return $response ?? []; } private function request($endpoint, $data, $method = 'POST') { $url = $this->apiUrl . $endpoint; $ch = curl_init($url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // Considera la seguridad de esto if ($method === 'POST') { custom_log("LibreTranslate POST Request: URL=" . $url . " | Data=" . json_encode($data)); curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($data)); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']); } else { custom_log("LibreTranslate GET Request: URL=" . $url); // Para GET, los datos (si los hubiera) se añadirían a la URL, pero /languages no requiere } $response_body = curl_exec($ch); $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE); curl_close($ch); custom_log("LibreTranslate Response: HTTP Code=" . $http_code . " | Body=" . $response_body); if ($http_code >= 400) { return null; // Devolver null si hay un error de cliente o servidor } return json_decode($response_body, true); } }