settingService = $settingService; $this->driver = $this->settingService->get('translation_driver', config('cms.translation_driver', 'mock')); } /** * Set the driver dynamically. * * @param string $driver * @return $this */ public function setDriver(string $driver): self { $this->driver = $driver; return $this; } /** * Translate text from one language to another. * * @param string $text The text to translate. * @param string $from The source locale. * @param string $to The target locale. * @return string|null The translated text or null on failure. */ public function translate(string $text, string $from, string $to): ?string { if ($from === $to) { return $text; } return match ($this->driver) { 'google' => $this->translateWithGoogle($text, $from, $to), 'deepl' => $this->translateWithDeepL($text, $from, $to), 'openai' => $this->translateWithOpenAI($text, $from, $to), 'mock' => $this->translateWithMock($text, $from, $to), default => $this->translateWithMock($text, $from, $to), }; } /** * Mock translation for development and testing. * * @param string $text * @param string $from * @param string $to * @return string */ protected function translateWithMock(string $text, string $from, string $to): string { return "[{$to}] " . $text; } /** * Translate using Google Translate API. * Checks settings first, then falls back to config/services.php. * * @param string $text * @param string $from * @param string $to * @return string|null */ protected function translateWithGoogle(string $text, string $from, string $to): ?string { $apiKey = $this->settingService->get('google_translate_key', config('services.google.translate_key')); if (!$apiKey) { Log::error("Google Translate API key not found."); return $this->translateWithMock($text, $from, $to); } try { $response = Http::post("https://translation.googleapis.com/language/translate/v2", [ 'q' => $text, 'source' => $from, 'target' => $to, 'format' => 'text', 'key' => $apiKey, ]); if ($response->successful()) { return $response->json('data.translations.0.translatedText'); } Log::error("Google Translate API error: " . $response->body()); } catch (\Exception $e) { Log::error("Google Translate Exception: " . $e->getMessage()); } return null; } /** * Translate using DeepL API. * * @param string $text * @param string $from * @param string $to * @return string|null */ protected function translateWithDeepL(string $text, string $from, string $to): ?string { $apiKey = $this->settingService->get('deepl_api_key', config('services.deepl.key')); if (!$apiKey) { Log::error("DeepL API key not found."); return $this->translateWithMock($text, $from, $to); } // DeepL uses 'source_lang' and 'target_lang' and requires upper-case codes $from = strtoupper($from); $to = strtoupper($to); // Handle regional variants if necessary (e.g. EN -> EN-US, EN-GB) // For simplicity, we'll use the 2-letter code if it's not a variant if ($to === 'EN') $to = 'EN-US'; if ($to === 'PT') $to = 'PT-PT'; try { $response = Http::withHeaders([ 'Authorization' => 'DeepL-Auth-Key ' . $apiKey, ])->post("https://api-free.deepl.com/v2/translate", [ 'text' => [$text], 'source_lang' => $from, 'target_lang' => $to, ]); // Try the Pro API if the Free one fails with 403 or 456 if ($response->status() === 403 || $response->status() === 456) { $response = Http::withHeaders([ 'Authorization' => 'DeepL-Auth-Key ' . $apiKey, ])->post("https://api.deepl.com/v2/translate", [ 'text' => [$text], 'source_lang' => $from, 'target_lang' => $to, ]); } if ($response->successful()) { return $response->json('translations.0.text'); } Log::error("DeepL API error: " . $response->body()); } catch (\Exception $e) { Log::error("DeepL Exception: " . $e->getMessage()); } return null; } /** * Translate using OpenAI API (GPT-4o-mini). * * @param string $text * @param string $from * @param string $to * @return string|null */ protected function translateWithOpenAI(string $text, string $from, string $to): ?string { $apiKey = $this->settingService->get('openai_api_key', config('services.openai.key')); if (!$apiKey) { Log::error("OpenAI API key not found."); return $this->translateWithMock($text, $from, $to); } try { $response = Http::withToken($apiKey)->post("https://api.openai.com/v1/chat/completions", [ 'model' => 'gpt-4o-mini', 'messages' => [ ['role' => 'system', 'content' => "You are a professional translator. Translate the given text from {$from} to {$to}. Respond ONLY with the translated text."], ['role' => 'user', 'content' => $text], ], 'temperature' => 0.3, ]); if ($response->successful()) { return trim($response->json('choices.0.message.content')); } Log::error("OpenAI API error: " . $response->body()); } catch (\Exception $e) { Log::error("OpenAI Exception: " . $e->getMessage()); } return null; } }