182 lines
6.1 KiB
PHP
182 lines
6.1 KiB
PHP
<?php
|
|
require_once __DIR__ . '/../ai/LocalAIApi.php';
|
|
|
|
if (!function_exists('app_translate_text')) {
|
|
function app_translate_text(string $text, string $target): array
|
|
{
|
|
$cleanText = trim($text);
|
|
$cleanTarget = strtolower(trim($target)) === 'en' ? 'en' : 'ar';
|
|
|
|
if ($cleanText === '') {
|
|
return [
|
|
'success' => false,
|
|
'error' => 'No text provided',
|
|
];
|
|
}
|
|
|
|
if (function_exists('mb_substr')) {
|
|
$cleanText = mb_substr($cleanText, 0, 500);
|
|
} else {
|
|
$cleanText = substr($cleanText, 0, 500);
|
|
}
|
|
|
|
$skipAiUntil = isset($_SESSION['translation_ai_disabled_until']) ? (int) $_SESSION['translation_ai_disabled_until'] : 0;
|
|
$shouldTryAi = $skipAiUntil <= time();
|
|
$aiResult = [
|
|
'success' => false,
|
|
'error' => 'AI translation unavailable',
|
|
'provider' => 'ai',
|
|
];
|
|
|
|
if ($shouldTryAi) {
|
|
$aiResult = app_translate_text_with_ai($cleanText, $cleanTarget);
|
|
if (!empty($aiResult['success']) && !empty($aiResult['translated'])) {
|
|
unset($_SESSION['translation_ai_disabled_until']);
|
|
return $aiResult;
|
|
}
|
|
|
|
$aiError = strtolower((string) ($aiResult['error'] ?? ''));
|
|
if ($aiError !== '' && (strpos($aiError, '401') !== false || strpos($aiError, 'unauthorized') !== false || strpos($aiError, 'timeout') !== false)) {
|
|
$_SESSION['translation_ai_disabled_until'] = time() + 900;
|
|
}
|
|
}
|
|
|
|
$fallbackResult = app_translate_text_with_google($cleanText, $cleanTarget);
|
|
if (!empty($fallbackResult['success']) && !empty($fallbackResult['translated'])) {
|
|
if (!empty($aiResult['error']) && $aiResult['error'] !== 'AI translation unavailable') {
|
|
$fallbackResult['warning'] = (string) $aiResult['error'];
|
|
}
|
|
return $fallbackResult;
|
|
}
|
|
|
|
if (!empty($aiResult['error']) && $aiResult['error'] !== 'AI translation unavailable') {
|
|
return $aiResult;
|
|
}
|
|
|
|
return $fallbackResult;
|
|
}
|
|
}
|
|
|
|
if (!function_exists('app_translate_text_with_ai')) {
|
|
function app_translate_text_with_ai(string $text, string $target): array
|
|
{
|
|
$prompt = "Translate the following product name to " . ($target === 'ar' ? 'Arabic' : 'English') . ". Return ONLY the translation, no extra text or explanations.\n\nText: " . $text;
|
|
|
|
$resp = LocalAIApi::createResponse([
|
|
'input' => [
|
|
['role' => 'system', 'content' => 'You are a translation assistant. You translate product names between English and Arabic. Keep brand names, sizes, numbers, and SKUs accurate. Return only the translated text.'],
|
|
['role' => 'user', 'content' => $prompt],
|
|
],
|
|
], [
|
|
'poll_interval' => 1,
|
|
'poll_timeout' => 12,
|
|
'timeout' => 20,
|
|
]);
|
|
|
|
if (!empty($resp['success'])) {
|
|
$translated = trim(LocalAIApi::extractText($resp));
|
|
if ($translated !== '') {
|
|
return [
|
|
'success' => true,
|
|
'translated' => $translated,
|
|
'provider' => 'ai',
|
|
];
|
|
}
|
|
}
|
|
|
|
return [
|
|
'success' => false,
|
|
'error' => (string) ($resp['error'] ?? 'AI translation failed'),
|
|
'provider' => 'ai',
|
|
];
|
|
}
|
|
}
|
|
|
|
if (!function_exists('app_translate_text_with_google')) {
|
|
function app_translate_text_with_google(string $text, string $target): array
|
|
{
|
|
if (!function_exists('curl_init')) {
|
|
return [
|
|
'success' => false,
|
|
'error' => 'Translation service unavailable: PHP cURL is missing',
|
|
'provider' => 'fallback',
|
|
];
|
|
}
|
|
|
|
$query = http_build_query([
|
|
'client' => 'gtx',
|
|
'sl' => 'auto',
|
|
'tl' => $target,
|
|
'dt' => 't',
|
|
'q' => $text,
|
|
]);
|
|
$url = 'https://translate.googleapis.com/translate_a/single?' . $query;
|
|
|
|
$ch = curl_init($url);
|
|
curl_setopt_array($ch, [
|
|
CURLOPT_RETURNTRANSFER => true,
|
|
CURLOPT_TIMEOUT => 15,
|
|
CURLOPT_CONNECTTIMEOUT => 5,
|
|
CURLOPT_HTTPGET => true,
|
|
CURLOPT_FAILONERROR => false,
|
|
CURLOPT_HTTPHEADER => [
|
|
'Accept: application/json',
|
|
'User-Agent: Mozilla/5.0',
|
|
],
|
|
]);
|
|
|
|
$body = curl_exec($ch);
|
|
if ($body === false) {
|
|
$error = curl_error($ch) ?: 'Unknown translation request error';
|
|
curl_close($ch);
|
|
return [
|
|
'success' => false,
|
|
'error' => $error,
|
|
'provider' => 'fallback',
|
|
];
|
|
}
|
|
|
|
$status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
|
|
curl_close($ch);
|
|
|
|
if ($status < 200 || $status >= 300 || $body === '' || $body === null) {
|
|
return [
|
|
'success' => false,
|
|
'error' => 'Fallback translation request failed',
|
|
'provider' => 'fallback',
|
|
];
|
|
}
|
|
|
|
$decoded = json_decode($body, true);
|
|
if (!is_array($decoded) || empty($decoded[0]) || !is_array($decoded[0])) {
|
|
return [
|
|
'success' => false,
|
|
'error' => 'Fallback translation returned an unexpected response',
|
|
'provider' => 'fallback',
|
|
];
|
|
}
|
|
|
|
$parts = [];
|
|
foreach ($decoded[0] as $segment) {
|
|
if (is_array($segment) && isset($segment[0]) && is_string($segment[0])) {
|
|
$parts[] = $segment[0];
|
|
}
|
|
}
|
|
|
|
$translated = trim(implode('', $parts));
|
|
if ($translated === '') {
|
|
return [
|
|
'success' => false,
|
|
'error' => 'Fallback translation returned empty text',
|
|
'provider' => 'fallback',
|
|
];
|
|
}
|
|
|
|
return [
|
|
'success' => true,
|
|
'translated' => $translated,
|
|
'provider' => 'fallback',
|
|
];
|
|
}
|
|
}
|