172 lines
5.7 KiB
PHP
Executable File
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);
|
|
}
|
|
} |