$class, 'message' => $message, ]; }; $builtin_tpl = AIGUDE_Tools_Plugin::get_builtin_prompt_template(); $builtin_id = $builtin_tpl['id'] ?? AIGUDE_Tools_Plugin::BUILTIN_PROMPT_ID; $find_tpl_index = static function ( array $list, string $id ): int { foreach ( $list as $i => $tpl ) { if ( isset( $tpl['id'] ) && $tpl['id'] === $id ) { return (int) $i; } } return -1; }; // Provider choices (all + EU only) $provider_meta_all = AIGUDE_Tools_Plugin::get_translation_providers_metadata(); $provider_meta_eu = AIGUDE_Tools_Plugin::filter_providers_by_region( $provider_meta_all, true ); $provider_choices_all = []; foreach ( $provider_meta_all as $slug => $info ) { $languages = AIGUDE_Tools_Plugin::get_translation_languages( $slug ); $provider_choices_all[ $slug ] = [ 'label' => AIGUDE_Tools_Plugin::get_translation_provider_label( $slug ), 'languages' => $languages, 'site_language' => AIGUDE_Tools_Plugin::describe_site_language( $slug ), ]; } $provider_choices_eu = []; foreach ( $provider_meta_eu as $slug => $info ) { $languages = AIGUDE_Tools_Plugin::get_translation_languages( $slug ); $provider_choices_eu[ $slug ] = [ 'label' => AIGUDE_Tools_Plugin::get_translation_provider_label( $slug ), 'languages' => $languages, 'site_language' => AIGUDE_Tools_Plugin::describe_site_language( $slug ), ]; } // Ensure every template has a stable ID (for defaults) $changed = false; $has_builtin = false; foreach ( $templates as &$tpl ) { if ( empty( $tpl['id'] ) ) { $tpl['id'] = function_exists( 'wp_generate_uuid4' ) ? wp_generate_uuid4() : ( 'tpl_' . uniqid( '', true ) ); $changed = true; } if ( $tpl['id'] === $builtin_id ) { $has_builtin = true; $tpl['builtin'] = '1'; } elseif ( ! isset( $tpl['builtin'] ) || '0' !== $tpl['builtin'] ) { $tpl['builtin'] = '0'; $changed = true; } // Every prompt declares the language its text is written in. Legacy prompts stored // 'auto', which made AiGude ignore the target language; migrate them to a real code. $stored_plang = strtolower( (string) ( $tpl['prompt_lang'] ?? '' ) ); if ( ! AIGUDE_Native_Language_Service::is_supported( $stored_plang ) ) { $tpl['prompt_lang'] = AIGUDE_Native_Language_Service::default_prompt_lang(); $changed = true; } if ( ! isset( $tpl['eu_only_providers'] ) || ! in_array( $tpl['eu_only_providers'], array( '0', '1' ), true ) ) { $tpl['eu_only_providers'] = '0'; $changed = true; } if ( ! isset( $tpl['recent_target_langs'] ) || ! is_array( $tpl['recent_target_langs'] ) ) { $tpl['recent_target_langs'] = []; $changed = true; } } unset( $tpl ); if ( ! $has_builtin ) { $templates[] = $builtin_tpl; $changed = true; $add_notice( esc_html__( 'Default prompt added.', 'aigude-tools' ) ); } if ( $changed ) { update_option( 'aigude_prompt_templates', $templates ); } $default_id = get_option( 'aigude_prompt_default_id', '' ); if ( '' === $default_id || $find_tpl_index( $templates, $default_id ) < 0 ) { $default_id = $builtin_id; update_option( 'aigude_prompt_default_id', $default_id ); } // Duplication (immediate copy) if ( 'duplicate' === $action && check_admin_referer( $nonce_action, $nonce_name ) ) { if ( $dup_index >= 0 && isset( $templates[ $dup_index ] ) ) { $src = $templates[ $dup_index ]; $new = $src; $new['id'] = function_exists( 'wp_generate_uuid4' ) ? wp_generate_uuid4() : ( 'tpl_' . uniqid( '', true ) ); $new['title'] = trim( ( $src['title'] ?? '' ) . ' (Copy)' ); $new['builtin'] = '0'; $templates[] = $new; update_option( 'aigude_prompt_templates', $templates ); $add_notice( esc_html__( 'Prompt duplicated.', 'aigude-tools' ) ); } else { $add_notice( esc_html__( 'Prompt not found.', 'aigude-tools' ), 'error' ); } $action = ''; } // Restore built-in defaults if ( 'restore_builtin' === $action && check_admin_referer( $nonce_action, $nonce_name ) ) { $idx = $find_tpl_index( $templates, $builtin_id ); if ( $idx >= 0 ) { $templates[ $idx ] = $builtin_tpl; } else { $templates[] = $builtin_tpl; } update_option( 'aigude_prompt_templates', $templates ); if ( '' === $default_id || $default_id === $builtin_id ) { $default_id = $builtin_id; update_option( 'aigude_prompt_default_id', $builtin_id ); } $add_notice( esc_html__( 'Default prompt restored.', 'aigude-tools' ) ); $action = ''; } // Set default action if ( 'set_default' === $action && check_admin_referer( $nonce_action, $nonce_name ) ) { if ( $tpl_index >= 0 && isset( $templates[ $tpl_index ]['id'] ) ) { update_option( 'aigude_prompt_default_id', $templates[ $tpl_index ]['id'] ); $default_id = $templates[ $tpl_index ]['id']; $add_notice( esc_html__( 'Default prompt updated.', 'aigude-tools' ) ); } else { $add_notice( esc_html__( 'Prompt not found.', 'aigude-tools' ), 'error' ); } $action = ''; } // Deletion if ( 'delete' === $action && check_admin_referer( $nonce_action, $nonce_name ) ) { if ( $tpl_index >= 0 && isset( $templates[ $tpl_index ] ) ) { $deleted_id = $templates[ $tpl_index ]['id'] ?? ''; if ( $deleted_id === $builtin_id ) { $add_notice( esc_html__( 'The default prompt cannot be deleted.', 'aigude-tools' ), 'error' ); } else { unset( $templates[ $tpl_index ] ); $templates = array_values( $templates ); update_option( 'aigude_prompt_templates', $templates ); // If the deleted one was default, clear default if ( $deleted_id && get_option( 'aigude_prompt_default_id' ) === $deleted_id ) { delete_option( 'aigude_prompt_default_id' ); $default_id = ''; } $add_notice( esc_html__( 'Prompt deleted.', 'aigude-tools' ) ); } } else { $add_notice( esc_html__( 'Prompt not found.', 'aigude-tools' ), 'error' ); } $action = ''; } // Decide which view to show (list vs add/edit) $view_action = ''; if ( in_array( $action, array( 'add', 'edit', 'dupedit' ), true ) ) { check_admin_referer( $nonce_action, $nonce_name ); if ( 'edit' === $action && ( $tpl_index < 0 || ! isset( $templates[ $tpl_index ] ) ) ) { $add_notice( esc_html__( 'Prompt not found.', 'aigude-tools' ), 'error' ); } else { $view_action = $action; } } if ( '' === $default_id || $find_tpl_index( $templates, $default_id ) < 0 ) { $default_id = $builtin_id; update_option( 'aigude_prompt_default_id', $default_id ); } // Form state baseline $form_state = array( 'index' => null, 'id' => '', 'title' => '', 'prompt' => '', 'src_lang' => 'auto', // Empty so a new prompt falls through to the default language in the form. 'prompt_lang' => '', 'target_provider' => 'deepl', 'target_lang' => '', 'eu_only' => '0', 'recent_target_langs' => array(), ); if ( in_array( $view_action, array( 'edit', 'dupedit' ), true ) && isset( $templates[ $tpl_index ] ) ) { $form_state = array_merge( $form_state, array( 'index' => $tpl_index, 'id' => $templates[ $tpl_index ]['id'] ?? '', 'title' => $templates[ $tpl_index ]['title'] ?? '', 'prompt' => $templates[ $tpl_index ]['prompt'] ?? '', 'src_lang' => $templates[ $tpl_index ]['src_lang'] ?? 'auto', 'prompt_lang' => $templates[ $tpl_index ]['prompt_lang'] ?? '', 'target_provider' => $templates[ $tpl_index ]['target_provider'] ?? 'deepl', 'target_lang' => $templates[ $tpl_index ]['target_lang'] ?? '', 'eu_only' => isset( $templates[ $tpl_index ]['eu_only_providers'] ) && '1' === $templates[ $tpl_index ]['eu_only_providers'] ? '1' : '0', 'recent_target_langs' => isset( $templates[ $tpl_index ]['recent_target_langs'] ) && is_array( $templates[ $tpl_index ]['recent_target_langs'] ) ? $templates[ $tpl_index ]['recent_target_langs'] : array(), ) ); } // Save (new or update) if ( isset( $_POST['ai_tpl_submit'] ) ) { check_admin_referer( $nonce_action, $nonce_name ); $title = sanitize_text_field( wp_unslash( $_POST['ai_tpl_title'] ?? '' ) ); $prompt = sanitize_textarea_field( wp_unslash( $_POST['ai_tpl_prompt'] ?? '' ) ); $src_lang_input = 'auto'; $prompt_lang_input = sanitize_text_field( wp_unslash( $_POST['ai_tpl_prompt_lang'] ?? '' ) ); $target_provider_input = sanitize_text_field( wp_unslash( $_POST['ai_tpl_target_provider'] ?? 'deepl' ) ); $target_lang_input = sanitize_text_field( wp_unslash( $_POST['ai_tpl_target_lang'] ?? '' ) ); $eu_only_input = ! empty( $_POST['ai_tpl_eu_only'] ) ? '1' : '0'; $active_provider_choices = '1' === $eu_only_input ? $provider_choices_eu : $provider_choices_all; $provider = ''; $target_lang = ''; if ( '' !== $target_provider_input ) { $normalized_provider = AIGUDE_Translation_Service::normalize_translation_provider( $target_provider_input ); if ( isset( $active_provider_choices[ $normalized_provider ] ) ) { $provider = $normalized_provider; $languages = $active_provider_choices[ $normalized_provider ]['languages'] ?? array(); $normalized_lang = AIGUDE_Translation_Service::normalize_provider_lang_code_generic( $target_lang_input, $provider, 'target' ); if ( '' !== $normalized_lang && isset( $languages[ $normalized_lang ] ) ) { $target_lang = $normalized_lang; } } } $src_lang_placeholders = 'auto'; if ( $provider && isset( $active_provider_choices[ $provider ] ) ) { $src_lang_placeholders = 'auto' === $src_lang_input ? 'auto' : AIGUDE_Translation_Service::normalize_provider_lang_code_generic( $src_lang_input, $provider, 'source' ); if ( '' === $src_lang_placeholders ) { $src_lang_placeholders = 'auto'; } } // prompt_lang is validated against AiGude's native generation languages, // independent of the translation provider. $prompt_lang = AIGUDE_Native_Language_Service::base_code( $prompt_lang_input ); if ( ! AIGUDE_Native_Language_Service::is_supported( $prompt_lang ) ) { $prompt_lang = AIGUDE_Native_Language_Service::default_prompt_lang(); } if ( '' === $provider ) { $provider = isset( $active_provider_choices['deepl'] ) ? 'deepl' : (string) array_key_first( $active_provider_choices ); } if ( '' === $target_lang && $provider && isset( $active_provider_choices[ $provider ]['languages'] ) ) { $site_info = $active_provider_choices[ $provider ]['site_language'] ?? array(); $prov_langs = $active_provider_choices[ $provider ]['languages']; if ( ! empty( $site_info['supported'] ) && ! empty( $site_info['code'] ) && isset( $prov_langs[ $site_info['code'] ] ) ) { $target_lang = $site_info['code']; } elseif ( isset( $prov_langs['EN'] ) ) { $target_lang = 'EN'; } elseif ( ! empty( $prov_langs ) ) { $target_lang = (string) array_key_first( $prov_langs ); } } // Keep ID if editing; otherwise make one $tpl_id = ''; if ( ! empty( $_POST['ai_tpl_id'] ) ) { $tpl_id = sanitize_text_field( wp_unslash( $_POST['ai_tpl_id'] ) ); } else { $tpl_id = function_exists( 'wp_generate_uuid4' ) ? wp_generate_uuid4() : ( 'tpl_' . uniqid( '', true ) ); } // Prepare per-prompt recents (persist last 5) $existing_recents = array(); if ( ! empty( $_POST['ai_tpl_index'] ) ) { $existing_index = (int) $_POST['ai_tpl_index']; if ( isset( $templates[ $existing_index ]['recent_target_langs'] ) && is_array( $templates[ $existing_index ]['recent_target_langs'] ) ) { $existing_recents = $templates[ $existing_index ]['recent_target_langs']; } } $recent_target_langs_map = array(); if ( is_array( $existing_recents ) ) { foreach ( $existing_recents as $provKey => $list ) { if ( ! is_array( $list ) ) { continue; } $recent_target_langs_map[ $provKey ] = array_slice( array_values( array_unique( array_filter( $list, 'is_string' ) ) ), 0, 5 ); } } if ( $provider && $target_lang ) { $provKey = $provider; $valid_langs = $active_provider_choices[ $provider ]['languages'] ?? array(); $current_list = isset( $recent_target_langs_map[ $provKey ] ) && is_array( $recent_target_langs_map[ $provKey ] ) ? $recent_target_langs_map[ $provKey ] : array(); $current_list = array_values( array_unique( array_merge( array( $target_lang ), $current_list ) ) ); $current_list = array_slice( $current_list, 0, 5 ); $current_list = array_values( array_filter( $current_list, static function ( $code ) use ( $valid_langs ) { return isset( $valid_langs[ $code ] ); } ) ); $recent_target_langs_map[ $provKey ] = $current_list; } $data = [ 'id' => $tpl_id, 'title' => $title, 'prompt' => $prompt, 'src_lang' => $src_lang_placeholders, 'prompt_lang' => $prompt_lang, 'target_provider' => $provider, 'target_lang' => $target_lang, 'eu_only_providers' => $eu_only_input, 'recent_target_langs' => $recent_target_langs_map, ]; $data['builtin'] = ( $tpl_id === $builtin_id ) ? '1' : '0'; $make_default = ! empty( $_POST['ai_tpl_is_default'] ); $errors = []; if ( '' === $title ) { $errors[] = __( 'Please enter a title.', 'aigude-tools' ); } if ( '' === $prompt ) { $errors[] = __( 'Please enter a prompt.', 'aigude-tools' ); } if ( '' === $provider ) { $errors[] = __( 'Please select a translation provider.', 'aigude-tools' ); } if ( '' === $target_lang ) { $errors[] = __( 'Please select a target language.', 'aigude-tools' ); } if ( ! empty( $errors ) ) { foreach ( $errors as $msg ) { $add_notice( $msg, 'error' ); } // Keep user input visible after validation errors. $form_state = array( 'index' => isset( $_POST['ai_tpl_index'] ) && '' !== $_POST['ai_tpl_index'] ? (int) $_POST['ai_tpl_index'] : null, 'id' => $tpl_id, 'title' => $title, 'prompt' => $prompt, 'src_lang' => $src_lang_placeholders, 'prompt_lang' => $prompt_lang, 'target_provider' => $provider, 'target_lang' => $target_lang, 'eu_only' => $eu_only_input, 'recent_target_langs' => $recent_target_langs_map, ); $view_action = ( isset( $_POST['ai_tpl_index'] ) && '' !== $_POST['ai_tpl_index'] ) ? 'edit' : 'add'; } else { if ( isset( $_POST['ai_tpl_index'] ) && '' !== $_POST['ai_tpl_index'] ) { $idx = (int) $_POST['ai_tpl_index']; if ( isset( $templates[ $idx ] ) ) { $templates[ $idx ] = $data; $add_notice( esc_html__( 'Prompt updated.', 'aigude-tools' ) ); } else { $add_notice( esc_html__( 'Prompt not found.', 'aigude-tools' ), 'error' ); } } else { $templates[] = $data; $add_notice( esc_html__( 'Prompt saved.', 'aigude-tools' ) ); } update_option( 'aigude_prompt_templates', $templates ); // Track recents for prompt and placeholder language selections if ( $make_default && empty( $errors ) ) { update_option( 'aigude_prompt_default_id', $tpl_id ); $default_id = $tpl_id; } $view_action = ''; $action = ''; $tpl_index = -1; } } // Prepare JSON for dynamic selects $provider_choices_all_json = wp_json_encode( $provider_choices_all ); $provider_choices_eu_json = wp_json_encode( $provider_choices_eu ); $add_url = wp_nonce_url( add_query_arg( array( 'action' => 'add' ), $page_url ), $nonce_action, $nonce_name ); // Sorting for list view $orderby = isset( $_GET['orderby'] ) ? sanitize_key( wp_unslash( $_GET['orderby'] ) ) : ''; $order = isset( $_GET['order'] ) ? strtolower( sanitize_text_field( wp_unslash( $_GET['order'] ) ) ) : 'asc'; if ( ! in_array( $order, array( 'asc', 'desc' ), true ) ) { $order = 'asc'; } $sort_fields = array( 'title', 'prompt', 'target' ); if ( '' !== $orderby && in_array( $orderby, $sort_fields, true ) && $templates ) { $templates = array_values( $templates ); usort( $templates, static function ( $a, $b ) use ( $orderby, $order ) { $direction = ( 'desc' === $order ) ? -1 : 1; if ( 'title' === $orderby ) { $va = strtolower( $a['title'] ?? '' ); $vb = strtolower( $b['title'] ?? '' ); } elseif ( 'prompt' === $orderby ) { $va = strtolower( $a['prompt'] ?? '' ); $vb = strtolower( $b['prompt'] ?? '' ); } else { $pa = strtolower( $a['target_provider'] ?? '' ); $pb = strtolower( $b['target_provider'] ?? '' ); $la = strtolower( $a['target_lang'] ?? '' ); $lb = strtolower( $b['target_lang'] ?? '' ); $va = $pa . '|' . $la; $vb = $pb . '|' . $lb; } return $direction * strcmp( $va, $vb ); } ); } else { $orderby = ''; } ?>


' . esc_html( $site_name ) . '' ); ?>

' . esc_html( $site_name ) . '', '' . esc_html( $bridge_label ) . '' ); ?>

__( 'Title', 'aigude-tools' ), 'prompt' => __( 'Prompt', 'aigude-tools' ), 'target' => __( 'Target language', 'aigude-tools' ), ); foreach ( $cols as $key => $label ) { $is_active = ( $orderby === $key ); $next_order = ( $is_active && 'asc' === $order ) ? 'desc' : 'asc'; $arrow = ''; if ( $is_active ) { $arrow = 'asc' === $order ? ' ▲' : ' ▼'; } $link = esc_url( add_query_arg( array( 'orderby' => $key, 'order' => $next_order, ), $page_url ) ); printf( '', esc_url( $link ), esc_html( $label ), esc_html( $arrow ) ); } ?> $tpl ) : $is_default = ! empty( $tpl['id'] ) && $tpl['id'] === $default_id; $is_builtin = ! empty( $tpl['builtin'] ) || ( isset( $tpl['id'] ) && $tpl['id'] === $builtin_id ); $base = $page_url; $edit_url = wp_nonce_url( add_query_arg( ['action'=>'edit','tpl_index'=>$i], $base ), $nonce_action, $nonce_name ); $dup_url = wp_nonce_url( add_query_arg( ['action'=>'duplicate','dup_index'=>$i], $base ), $nonce_action, $nonce_name ); $del_url = wp_nonce_url( add_query_arg( ['action'=>'delete','tpl_index'=>$i], $base ), $nonce_action, $nonce_name ); $def_url = wp_nonce_url( add_query_arg( ['action'=>'set_default','tpl_index'=>$i], $base ), $nonce_action, $nonce_name ); $restore_url= wp_nonce_url( add_query_arg( array( 'action' => 'restore_builtin' ), $base ), $nonce_action, $nonce_name ); $target_info = AIGUDE_Tools_Plugin::describe_target_language_choice( $tpl['target_provider'] ?? '', $tpl['target_lang'] ?? '' ); ?>
%s%s
%s', esc_url( $edit_url ), esc_html__( 'Edit', 'aigude-tools' ) ), sprintf( '%s', esc_url( $dup_url ), esc_html__( 'Duplicate', 'aigude-tools' ) ), ); if ( $is_builtin ) { $actions[] = sprintf( '%s', esc_url( $restore_url ), esc_html__( 'Restore defaults', 'aigude-tools' ) ); } else { $actions[] = sprintf( '%s', esc_url( $del_url ), esc_attr__( 'Really delete?', 'aigude-tools' ), esc_html__( 'Delete', 'aigude-tools' ) ); } echo implode( ' | ', array_map( 'wp_kses_post', $actions ) ); ?>


= 5 ) { break; } } ?>

%filename%, %filename_no_ext%, %title%, %current_alt%, %caption%, %description%, %mime%, %width%, %height%.




%title|trim|ucfirst%, %filename_no_ext|lower%, %current_alt|raw%, %title|translatable%, %current_alt|untranslatable%