Mejora traducción bot Discord: detección de imágenes/videos y preservación de emojis
- Evita mostrar botones de traducción en mensajes con solo imágenes/videos - Detecta y traduce captions de imágenes/videos - Preserva emojis, menciones y elementos de Discord durante traducción - Soluciona problema de placeholders en emojis Unicode estándar
This commit is contained in:
107
discord_bot.php
107
discord_bot.php
@@ -104,8 +104,10 @@ try {
|
||||
return;
|
||||
}
|
||||
|
||||
// Extraer y preservar emojis, stickers y elementos de Discord
|
||||
$processedContent = preserveDiscordElements($originalContent);
|
||||
$translator = new Translate(LIBRETRANSLATE_URL);
|
||||
$sourceLang = $translator->detectLanguage($originalContent) ?? 'es';
|
||||
$sourceLang = $translator->detectLanguage($processedContent['text']) ?? 'es';
|
||||
|
||||
if ($sourceLang === $targetLang) {
|
||||
$interaction->respondWithMessage(
|
||||
@@ -115,7 +117,10 @@ try {
|
||||
return;
|
||||
}
|
||||
|
||||
$translatedText = $translator->translateText($originalContent, $sourceLang, $targetLang);
|
||||
$translatedText = $translator->translateText($processedContent['text'], $sourceLang, $targetLang);
|
||||
|
||||
// Restaurar emojis y elementos de Discord
|
||||
$finalText = restoreDiscordElements($translatedText, $processedContent['placeholders']);
|
||||
|
||||
// Obtener bandera
|
||||
$stmt = $pdo->prepare("SELECT flag_emoji FROM supported_languages WHERE language_code = ? AND is_active = 1");
|
||||
@@ -125,7 +130,7 @@ try {
|
||||
$flag = $flag !== '' ? $flag : '🏳️';
|
||||
|
||||
// Responder efímeramente con la traducción
|
||||
$response = "{$flag} **Traducción ({$sourceLang} → {$targetLang}):**\n\n" . $translatedText;
|
||||
$response = "{$flag} **Traducción ({$sourceLang} → {$targetLang}):**\n\n" . $finalText;
|
||||
$interaction->respondWithMessage(
|
||||
MessageBuilder::new()->setContent($response),
|
||||
true // Efímero - solo visible para el usuario
|
||||
@@ -154,8 +159,10 @@ try {
|
||||
return;
|
||||
}
|
||||
|
||||
// Extraer y preservar emojis, stickers y elementos de Discord
|
||||
$processedContent = preserveDiscordElements($originalContent);
|
||||
$translator = new Translate(LIBRETRANSLATE_URL);
|
||||
$sourceLang = $translator->detectLanguage($originalContent) ?? 'es';
|
||||
$sourceLang = $translator->detectLanguage($processedContent['text']) ?? 'es';
|
||||
|
||||
if ($sourceLang === $targetLang) {
|
||||
$interaction->respondWithMessage(
|
||||
@@ -165,7 +172,10 @@ try {
|
||||
return;
|
||||
}
|
||||
|
||||
$translatedText = $translator->translateText($originalContent, $sourceLang, $targetLang);
|
||||
$translatedText = $translator->translateText($processedContent['text'], $sourceLang, $targetLang);
|
||||
|
||||
// Restaurar emojis y elementos de Discord
|
||||
$finalText = restoreDiscordElements($translatedText, $processedContent['placeholders']);
|
||||
|
||||
// Obtener bandera
|
||||
$stmt = $pdo->prepare("SELECT flag_emoji FROM supported_languages WHERE language_code = ? AND is_active = 1");
|
||||
@@ -175,7 +185,7 @@ try {
|
||||
$flag = $flag !== '' ? $flag : '🏳️';
|
||||
|
||||
// Responder efímeramente con la traducción
|
||||
$response = "{$flag} **Traducción ({$sourceLang} → {$targetLang}):**\n\n" . $translatedText;
|
||||
$response = "{$flag} **Traducción ({$sourceLang} → {$targetLang}):**\n\n" . $finalText;
|
||||
$interaction->respondWithMessage(
|
||||
MessageBuilder::new()->setContent($response),
|
||||
true // Efímero - solo visible para el usuario
|
||||
@@ -550,8 +560,39 @@ function handleDiscordTranslation(Message $message, PDO $pdo, Logger $logger)
|
||||
{
|
||||
try {
|
||||
$text = $message->content;
|
||||
$attachments = $message->attachments;
|
||||
|
||||
// Verificar si el mensaje tiene contenido de texto
|
||||
$hasTextContent = !empty(trim($text));
|
||||
|
||||
// Verificar si hay texto en los attachments (captions de imágenes/videos)
|
||||
$attachmentText = '';
|
||||
if (!empty($attachments)) {
|
||||
foreach ($attachments as $attachment) {
|
||||
// Algunos attachments tienen propiedad 'description' o 'caption'
|
||||
if (!empty($attachment->description)) {
|
||||
$attachmentText .= $attachment->description . ' ';
|
||||
}
|
||||
if (!empty($attachment->caption)) {
|
||||
$attachmentText .= $attachment->caption . ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Combinar texto principal con texto de attachments
|
||||
$fullText = trim($text . ' ' . $attachmentText);
|
||||
$hasAnyText = !empty($fullText);
|
||||
|
||||
// Verificar si el mensaje tiene solo imágenes/adjuntos sin texto
|
||||
$hasOnlyAttachments = !$hasAnyText && !empty($attachments) && count($attachments) > 0;
|
||||
|
||||
// Si el mensaje no tiene texto o tiene solo imágenes, no mostrar botones de traducción
|
||||
if (!$hasAnyText || $hasOnlyAttachments) {
|
||||
$logger->info("[TRADUCCIÓN] Mensaje #{$message->id} no tiene contenido de texto, omitiendo botones de traducción.");
|
||||
return;
|
||||
}
|
||||
$translator = new Translate(LIBRETRANSLATE_URL);
|
||||
$detectedLang = $translator->detectLanguage(strip_tags($text)) ?? 'es';
|
||||
$detectedLang = $translator->detectLanguage(strip_tags($fullText)) ?? 'es';
|
||||
|
||||
// Obtener idiomas activos disponibles
|
||||
$langStmt = $pdo->query("SELECT language_code, language_name, flag_emoji FROM supported_languages WHERE is_active = 1");
|
||||
@@ -596,7 +637,7 @@ function handleDiscordTranslation(Message $message, PDO $pdo, Logger $logger)
|
||||
|
||||
// Enviar mensaje con botones efímeros
|
||||
$builder = MessageBuilder::new()
|
||||
->setContent("🌍 **Selecciona idioma para traducir:**")
|
||||
// ->setContent("🌍 **Selecciona idioma para traducir:**")
|
||||
->setComponents($components);
|
||||
|
||||
$message->reply($builder, true); // true = ephemeral (solo visible para el usuario)
|
||||
@@ -607,3 +648,53 @@ function handleDiscordTranslation(Message $message, PDO $pdo, Logger $logger)
|
||||
$logger->error("[Error Traducción Discord]", ['error' => $e->getMessage(), 'trace' => $e->getTraceAsString()]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Función para preservar emojis, stickers y elementos de Discord durante la traducción
|
||||
*/
|
||||
function preserveDiscordElements($text) {
|
||||
$placeholders = [];
|
||||
$processedText = $text;
|
||||
|
||||
// Patrones para detectar elementos de Discord (excluyendo emojis Unicode)
|
||||
$patterns = [
|
||||
// Emojis personalizados de Discord <:name:id>
|
||||
'/<a?:([a-zA-Z0-9_]+):(\d+)>/',
|
||||
// Menciones de usuarios <@id> y <@!id>
|
||||
'/<@!?(\d+)>/',
|
||||
// Menciones de canales <#id>
|
||||
'/<#(\d+)>/',
|
||||
// Menciones de roles <@&id>
|
||||
'/<@&(\d+)>/',
|
||||
// Stickers y GIFs animados (pueden venir como URLs especiales)
|
||||
'/https?:\/\/(?:media|cdn)\.discordapp\.(?:com|net)\/(stickers|attachments)\/\S+/i'
|
||||
];
|
||||
|
||||
$index = 0;
|
||||
foreach ($patterns as $pattern) {
|
||||
$processedText = preg_replace_callback($pattern, function($matches) use (&$placeholders, &$index) {
|
||||
$placeholder = "DISCORD_ELEMENT_{$index}";
|
||||
$placeholders[$placeholder] = $matches[0];
|
||||
$index++;
|
||||
return $placeholder;
|
||||
}, $processedText);
|
||||
}
|
||||
|
||||
return [
|
||||
'text' => $processedText,
|
||||
'placeholders' => $placeholders
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Función para restaurar emojis, stickers y elementos de Discord después de la traducción
|
||||
*/
|
||||
function restoreDiscordElements($translatedText, $placeholders) {
|
||||
$restoredText = $translatedText;
|
||||
|
||||
foreach ($placeholders as $placeholder => $originalElement) {
|
||||
$restoredText = str_replace($placeholder, $originalElement, $restoredText);
|
||||
}
|
||||
|
||||
return $restoredText;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user