Files

172 lines
5.7 KiB
PHP
Executable File

<?php
class Translate
{
private $apiUrl;
public function __construct()
{
$this->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('<div>' . $html . '</div>', 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);
}
}