Primer commit del sistema separado falta mejorar mucho
This commit is contained in:
172
Sistema_discord/Translate.php
Executable file
172
Sistema_discord/Translate.php
Executable file
@@ -0,0 +1,172 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user