class-restai-translation.php
1 <?php 2 /** 3 * Translation feature. Saves the translated copy as a draft post and links it 4 * back to the source. Polylang / WPML connectors are stubbed for now. 5 * 6 * @package RESTai 7 */ 8 9 namespace RESTai; 10 11 if ( ! defined( 'ABSPATH' ) ) { 12 exit; 13 } 14 15 class Translation { 16 17 /** @var Client */ 18 private $client; 19 20 public function __construct( Client $client ) { 21 $this->client = $client; 22 } 23 24 /** 25 * @param int $post_id 26 * @param string $language Target language name (e.g. "Spanish"). 27 * @return array|\WP_Error 28 */ 29 public function translate_post( $post_id, $language ) { 30 $post = get_post( $post_id ); 31 if ( ! $post ) { 32 return new \WP_Error( 'restai_no_post', __( 'Post not found.', 'restai' ) ); 33 } 34 35 $plugin = Plugin::instance(); 36 $project_id = $plugin->provisioner->project_for( 'translator' ); 37 if ( $project_id <= 0 ) { 38 return new \WP_Error( 'restai_no_project', __( 'Translator project not configured.', 'restai' ) ); 39 } 40 41 $prompt_title = "Translate the following text to {$language}. Return only the translated text.\n\n" . $post->post_title; 42 $prompt_body = "Translate the following HTML to {$language}. Preserve all tags. Return only the translated HTML.\n\n" . $post->post_content; 43 44 $translated_title = $this->client->ask( $project_id, $prompt_title ); 45 if ( is_wp_error( $translated_title ) ) { 46 return $translated_title; 47 } 48 $translated_body = $this->client->ask( $project_id, $prompt_body ); 49 if ( is_wp_error( $translated_body ) ) { 50 return $translated_body; 51 } 52 53 $new_id = wp_insert_post( 54 array( 55 'post_title' => wp_strip_all_tags( $translated_title ), 56 'post_content' => wp_kses_post( $translated_body ), 57 'post_status' => 'draft', 58 'post_type' => $post->post_type, 59 'post_author' => get_current_user_id(), 60 ), 61 true 62 ); 63 64 if ( is_wp_error( $new_id ) ) { 65 return $new_id; 66 } 67 68 update_post_meta( $new_id, '_restai_translated_from', $post_id ); 69 update_post_meta( $new_id, '_restai_translation_language', $language ); 70 71 // Polylang integration — register language if available. 72 if ( function_exists( 'pll_set_post_language' ) ) { 73 $lang_code = $this->language_to_code( $language ); 74 if ( $lang_code ) { 75 pll_set_post_language( $new_id, $lang_code ); 76 } 77 } 78 79 return array( 80 'new_post_id' => $new_id, 81 'edit_url' => get_edit_post_link( $new_id, '' ), 82 ); 83 } 84 85 private function language_to_code( $language ) { 86 $map = array( 87 'Spanish' => 'es', 88 'Portuguese' => 'pt', 89 'French' => 'fr', 90 'German' => 'de', 91 'Italian' => 'it', 92 'Dutch' => 'nl', 93 'Polish' => 'pl', 94 'Japanese' => 'ja', 95 'Chinese (Simplified)' => 'zh', 96 ); 97 return isset( $map[ $language ] ) ? $map[ $language ] : null; 98 } 99 }