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', ]; } }