'Source String' ) * @param string $target_locale Target language localization key * @param string $provider Dynamic identifier for the targeted AI platform * @return array|WP_Error Translated map matrix sequence on success, WP_Error on failure. */ public static function translate_batch( $strings_array, $target_locale, $provider = '' ) { $settings = get_option( 'af_translate_api_settings', array() ); // 1. Dynamically resolve active translation engine track across all unmasked tokens $provider = self::resolve_active_provider( $settings, $provider ); // 2. Sandbox Routing Interceptor if ( self::is_sandbox_mode( $settings, $provider ) ) { return self::simulate_batch_sandbox( $strings_array, $target_locale ); } // 3. Platform Request Dispatcher Pipeline switch ( $provider ) { case 'gemini': // FIXED: Now utilizes optimized batch payload pipeline instead of looping individual network calls return self::call_gemini_batch( $strings_array, $target_locale, $settings ); case 'openai': return self::call_openai_batch( $strings_array, $target_locale, $settings ); default: return new WP_Error( 'unmapped_provider', __( 'Selected batch routing engine lacks an active payload class handler.', 'af-translate' ) ); } } /** * Dynamically resolve which translation provider engine to utilize */ private static function resolve_active_provider( $settings, $explicit_provider = '' ) { if ( ! empty( $explicit_provider ) ) { return sanitize_key( $explicit_provider ); } // Check if the saved active provider actually has a configured key if ( ! empty( $settings['active_provider'] ) ) { $active = sanitize_key( $settings['active_provider'] ); $active_key_field = $active . '_key'; if ( ! empty( $settings[ $active_key_field ] ) && 'sandbox-test-key' !== $settings[ $active_key_field ] ) { return $active; } } // Fallback Sweep: Find ANY provider that has an active production key configured $supported_providers = array( 'gemini', 'openai', 'anthropic', 'grok', 'deepl', 'microsoft', 'google', 'lecto' ); foreach ( $supported_providers as $provider ) { $key_field = $provider . '_key'; if ( ! empty( $settings[ $key_field ] ) && 'sandbox-test-key' !== $settings[ $key_field ] ) { return $provider; } } // Hard default if everything is empty return 'gemini'; } /** * Determine if sandbox routing protocols should be engaged for the active provider context */ private static function is_sandbox_mode( $settings, $provider ) { if ( 'openai' === $provider ) { $legacy_key = get_option( 'af_translate_api_key', '' ); if ( 'sandbox-test-key' === $legacy_key ) { return true; } } $target_key_field = $provider . '_key'; $api_key = isset( $settings[ $target_key_field ] ) ? trim( $settings[ $target_key_field ] ) : ''; return ( empty( $api_key ) || 'sandbox-test-key' === $api_key ); } /** * ------------------------------------------------------------------ * GOOGLE GEMINI API ENGINE LAYER * ------------------------------------------------------------------ */ private static function call_gemini( $text, $target_locale, $settings ) { $api_key = isset( $settings['gemini_key'] ) ? trim( $settings['gemini_key'] ) : ''; $model = ! empty( $settings['gemini_model'] ) ? trim( $settings['gemini_model'] ) : 'gemini-2.5-flash'; $prompt = ! empty( $settings['gemini_custom_prompt'] ) ? $settings['gemini_custom_prompt'] : 'Translate this WordPress string to {target_language}. Keep code/HTML placeholders identical.'; if ( empty( $api_key ) ) { return new WP_Error( 'missing_key', __( 'Gemini API key is empty.', 'af-translate' ) ); } $resolved_prompt = str_replace( '{target_language}', $target_locale, $prompt ); $endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/' . sanitize_text_field( $model ) . ':generateContent?key=' . $api_key; $response = wp_remote_post( $endpoint, array( 'timeout' => 25, 'headers' => array( 'Content-Type' => 'application/json', ), 'body' => json_encode( array( 'contents' => array( array( 'parts' => array( array( 'text' => $text ) ) ) ), 'systemInstruction' => array( 'parts' => array( array( 'text' => $resolved_prompt ) ) ), 'generationConfig' => array( 'temperature' => 0.2 ) ) ), ) ); if ( is_wp_error( $response ) ) { return $response; } $body = json_decode( wp_remote_retrieve_body( $response ), true ); if ( isset( $body['candidates'][0]['content']['parts'][0]['text'] ) ) { return trim( $body['candidates'][0]['content']['parts'][0]['text'] ); } return new WP_Error( 'api_error', isset( $body['error']['message'] ) ? $body['error']['message'] : __( 'Gemini execution loop failed.', 'af-translate' ) ); } /** * Optimized Gemini Bulk Data Pipeline Handler (Consumes only 1 Quota Request) */ private static function call_gemini_batch( $strings_array, $target_locale, $settings ) { $api_key = isset( $settings['gemini_key'] ) ? trim( $settings['gemini_key'] ) : ''; $model = ! empty( $settings['gemini_model'] ) ? trim( $settings['gemini_model'] ) : 'gemini-2.5-flash'; $prompt = ! empty( $settings['gemini_custom_prompt'] ) ? $settings['gemini_custom_prompt'] : 'Translate this WordPress string to {target_language}. Keep code/HTML placeholders identical.'; if ( empty( $api_key ) ) { return new WP_Error( 'missing_key', __( 'Gemini API key is empty.', 'af-translate' ) ); } // Infuse absolute matrix-mapping layout requirements directly into the dynamic prompt rules $resolved_prompt = str_replace( '{target_language}', $target_locale, $prompt ) . " CRITICAL REQUIREMENT: Input will arrive as an explicitly indexed JSON object array layout matrix. You must return absolute translation output ONLY as a matching structural JSON object using the identical key assignments. Do not include markdown code wrapping blocks."; $endpoint = 'https://generativelanguage.googleapis.com/v1beta/models/' . sanitize_text_field( $model ) . ':generateContent?key=' . $api_key; $response = wp_remote_post( $endpoint, array( 'timeout' => 45, 'headers' => array( 'Content-Type' => 'application/json', ), 'body' => json_encode( array( 'contents' => array( array( 'parts' => array( array( 'text' => wp_json_encode( $strings_array ) ) ) ) ), 'systemInstruction' => array( 'parts' => array( array( 'text' => $resolved_prompt ) ) ), 'generationConfig' => array( 'temperature' => 0.2, 'responseMimeType' => 'application/json' // Forces Gemini core system engine to output raw data maps ) ) ), ) ); if ( is_wp_error( $response ) ) { return $response; } $response_code = wp_remote_retrieve_response_code( $response ); $body_text = wp_remote_retrieve_body( $response ); $body = json_decode( $body_text, true ); if ( 200 !== $response_code ) { $error_msg = isset( $body['error']['message'] ) ? $body['error']['message'] : __( 'Gemini bulk engine interface error.', 'af-translate' ); return new WP_Error( 'gemini_bulk_network_error', $error_msg ); } if ( isset( $body['candidates'][0]['content']['parts'][0]['text'] ) ) { $json_raw_string = trim( $body['candidates'][0]['content']['parts'][0]['text'] ); $decoded_output = json_decode( $json_raw_string, true ); if ( is_array( $decoded_output ) ) { return $decoded_output; } } return new WP_Error( 'gemini_batch_alignment_failed', __( 'Could not securely synchronize translated Gemini dataset matrix structural syntax layout.', 'af-translate' ) ); } /** * ------------------------------------------------------------------ * OPENAI API ENGINE LAYER * ------------------------------------------------------------------ */ private static function call_openai_single( $source_text, $target_locale, $settings ) { $api_key = ! empty( $settings['openai_key'] ) ? $settings['openai_key'] : get_option( 'af_translate_api_key', '' ); $model = ! empty( $settings['openai_model'] ) ? $settings['openai_model'] : get_option( 'af_translate_ai_model', 'gpt-4o-mini' ); $system_instruction = self::get_openai_system_prompt( $target_locale, $settings ); $payload = array( 'model' => $model, 'temperature' => 0.2, 'messages' => array( array( 'role' => 'system', 'content' => $system_instruction ), array( 'role' => 'user', 'content' => $source_text ) ) ); $response = self::execute_openai_remote_post( $api_key, $payload ); if ( is_wp_error( $response ) ) { return $response; } if ( isset( $response['choices'][0]['message']['content'] ) ) { return trim( $response['choices'][0]['message']['content'] ); } return new WP_Error( 'api_malformed_response', __( 'OpenAI core node returned an unreadable response layout.', 'af-translate' ) ); } private static function call_openai_batch( $strings_array, $target_locale, $settings ) { $api_key = ! empty( $settings['openai_key'] ) ? $settings['openai_key'] : get_option( 'af_translate_api_key', '' ); $model = ! empty( $settings['openai_model'] ) ? $settings['openai_model'] : get_option( 'af_translate_ai_model', 'gpt-4o-mini' ); $system_instruction = self::get_openai_system_prompt( $target_locale, $settings ) . " Crucial Instruction: Input will arrive as a serialized JSON object map. You must respond ONLY with a valid JSON object matching the exact key definitions. Do not include markdown wraps or ```json indicators."; $payload = array( 'model' => $model, 'temperature' => 0.2, 'response_format' => array( 'type' => 'json_object' ), 'messages' => array( array( 'role' => 'system', 'content' => $system_instruction ), array( 'role' => 'user', 'content' => wp_json_encode( $strings_array ) ) ) ); $response = self::execute_openai_remote_post( $api_key, $payload ); if ( is_wp_error( $response ) ) { return $response; } if ( isset( $response['choices'][0]['message']['content'] ) ) { $decoded_output = json_decode( $response['choices'][0]['message']['content'], true ); if ( is_array( $decoded_output ) ) { return $decoded_output; } } return new WP_Error( 'batch_alignment_failed', __( 'Could not securely synchronize translated OpenAI dataset matrix trees.', 'af-translate' ) ); } private static function get_openai_system_prompt( $target_locale, $settings ) { if ( ! empty( $settings['openai_custom_prompt'] ) ) { return str_replace( '{target_language}', $target_locale, $settings['openai_custom_prompt'] ); } return "You are a professional localization engine processing complex core WordPress gettext catalogs. " . "Translate the provided text content accurately into the target language code context: '{$target_locale}'. " . "CRITICAL: You must preserve all raw formatting parameters, HTML entities, and structural printf string layout placeholders (e.g. %s, %d, %1\$s, %2\$s) exactly as they appear in the source string. " . "Never attempt to modify, alter, translate, or rearrange these system placeholder variables."; } private static function execute_openai_remote_post( $api_key, $payload ) { $endpoint = '[https://api.openai.com/v1/chat/completions](https://api.openai.com/v1/chat/completions)'; $response = wp_remote_post( $endpoint, array( 'timeout' => 45, 'blocking' => true, 'headers' => array( 'Authorization' => 'Bearer ' . $api_key, 'Content-Type' => 'application/json', ), 'body' => wp_json_encode( $payload ), ) ); if ( is_wp_error( $response ) ) { return $response; } $response_code = wp_remote_retrieve_response_code( $response ); $response_body = wp_remote_retrieve_body( $response ); if ( 200 !== $response_code ) { $error_data = json_decode( $response_body, true ); $error_message = isset( $error_data['error']['message'] ) ? $error_data['error']['message'] : __( 'Remote OpenAI endpoint communication disruption.', 'af-translate' ); return new WP_Error( 'remote_api_handshake_error', $error_message ); } return json_decode( $response_body, true ); } /** * ------------------------------------------------------------------ * SANDBOX SIMULATION SYSTEM UTILITIES * ------------------------------------------------------------------ */ private static function simulate_single_sandbox( $text, $locale ) { usleep( 600000 ); return "[Sandbox - Language Target: " . strtoupper( esc_html( $locale ) ) . "]: " . $text; } private static function simulate_batch_sandbox( $strings_array, $locale ) { usleep( 1200000 ); $mocked_catalog = array(); foreach ( $strings_array as $index => $text ) { $mocked_catalog[ $index ] = "[Bulk Sandbox - " . strtoupper( esc_html( $locale ) ) . "]: " . $text; } return $mocked_catalog; } }