- Implemented StreamInterface, UploadedFileInterface, and UriInterface as per PSR standards. - Added getallheaders function to retrieve HTTP headers in a compatible manner. - Included LICENSE files for ralouphie/getallheaders and symfony/deprecation-contracts. - Introduced function for triggering deprecation notices in Symfony.
1038 lines
51 KiB
PHP
1038 lines
51 KiB
PHP
<?php
|
|
|
|
use GuzzleHttp\Client;
|
|
use GuzzleHttp\Exception\RequestException;
|
|
|
|
function atfpp_render_settings_page() {
|
|
$text_domain = 'autopoly-ai-translation-for-polylang-pro';
|
|
|
|
// Define APIs configuration
|
|
$apis = [
|
|
'google' => [
|
|
'name' => 'Gemini',
|
|
'docs_url' => 'https://docs.coolplugins.net/doc/generate-gemini-api-key/?utm_source=atfp_plugin&utm_medium=inside&utm_campaign=docs&utm_content=settings_gemini_pro'
|
|
],
|
|
'openai' => [
|
|
'name' => 'OpenAI',
|
|
'docs_url' => 'https://docs.coolplugins.net/doc/generate-open-ai-api-key/?utm_source=atfp_plugin&utm_medium=inside&utm_campaign=docs&utm_content=settings_openai_pro'
|
|
],
|
|
'deepl' => [
|
|
'name' => 'DeepL',
|
|
'docs_url' => 'https://locoaddon.com/docs/how-to-generate-deepl-api-key/'
|
|
],
|
|
'context_aware' => [
|
|
'name' => 'Context Aware',
|
|
'option_key' => 'atfp_context_aware',
|
|
],
|
|
'atfpp_bulk_post_status' => [
|
|
'name' => 'Bulk Translation default Post Status',
|
|
'option_key' => 'atfp_bulk_post_status',
|
|
'options' => [
|
|
'publish' => 'Published',
|
|
'draft' => 'Draft',
|
|
],
|
|
'value' => get_option('atfp_bulk_post_status', 'draft')
|
|
],
|
|
'atfp_slug_translation_option' => [
|
|
'name' => 'Slug Translation Settings',
|
|
'option_key' => 'atfp_slug_translation_option',
|
|
'options' => [
|
|
'title_translate' => 'Use Translated Title',
|
|
'slug_translate' => 'Translate Original Slug',
|
|
'slug_keep' => 'Keep Original Slug',
|
|
],
|
|
'value' => get_option('atfp_slug_translation_option', 'title_translate')
|
|
],
|
|
'atfp_ai_request_token_per_request' => [
|
|
'name' => 'AI Token Per Request',
|
|
'option_key' => 'atfp_ai_request_token_per_request',
|
|
'value' => get_option('atfp_ai_request_token_per_request', 500)
|
|
],
|
|
'atfp_ai_request_batch_size' => [
|
|
'name' => 'AI Batch Size',
|
|
'option_key' => 'atfp_ai_request_batch_size',
|
|
'value' => get_option('atfp_ai_request_batch_size', 5)
|
|
],
|
|
'atfp_ai_request_timeout' => [
|
|
'name' => 'AI Timeout',
|
|
'option_key' => 'atfp_ai_request_timeout',
|
|
'value' => get_option('atfp_ai_request_timeout', 120)
|
|
]
|
|
];
|
|
?>
|
|
<div class="atfpp-dashboard-settings">
|
|
<div class="atfpp-dashboard-settings-container">
|
|
<div class="header">
|
|
<h1><?php echo esc_html('Polylang Addon Settings', $text_domain); ?></h1>
|
|
</div>
|
|
<p class="description">
|
|
<?php echo sprintf(esc_html__('Configure your settings for the Polylang Addon to optimize your translation experience. Start by entering your %s. Once it\'s activated, you\'ll be able to add your Gemini or OpenAI API keys and manage your preferences for seamless integration.', $text_domain), '<strong><a href="' . esc_url(admin_url('admin.php?page=polylang-atfpp-dashboard&tab=license')) . '">' . esc_html__('license key', $text_domain) . '</a></strong>') ?>
|
|
</p>
|
|
<div class="atfpp-dashboard-api-settings-container">
|
|
<div class="atfpp-dashboard-api-settings">
|
|
<?php foreach ($apis as $key => $api):
|
|
if ($key === 'context_aware'): ?>
|
|
<label for="<?php echo esc_attr($key); ?>-input">
|
|
<?php echo esc_html__('Context Aware', $text_domain); ?>
|
|
</label>
|
|
<textarea
|
|
id="<?php echo esc_attr($key); ?>-input"
|
|
placeholder="Provide optional context about WordPress page or post to enhance translation accuracy (e.g. content purpose, target audience, SEO focus, tone)..."
|
|
disabled
|
|
></textarea>
|
|
<?php elseif($key === 'atfpp_bulk_post_status'):
|
|
?>
|
|
<label for="<?php echo esc_attr($key); ?>-input">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-bulk-translation-post-status-options">
|
|
<?php
|
|
foreach($api['options'] as $option_key => $option_value):
|
|
?>
|
|
<input type="radio" name="<?php echo esc_attr($api['option_key']); ?>" id="atfpp_bulk_post_status_<?php echo esc_attr($option_key); ?>" value="<?php echo esc_attr($option_key); ?>" <?php echo esc_attr($api['value']) === $option_key ? 'checked' : ''; ?> disabled>
|
|
<label for="atfpp_bulk_post_status_<?php echo esc_attr($option_key); ?>"><?php echo esc_html($option_value); ?></label>
|
|
<?php
|
|
endforeach;
|
|
?>
|
|
</div>
|
|
<?php elseif($key === 'atfp_slug_translation_option'):
|
|
?>
|
|
<label for="<?php echo esc_attr($key); ?>-input">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-bulk-translation-post-status-options">
|
|
<?php
|
|
foreach($api['options'] as $option_key => $option_value):
|
|
?>
|
|
<input type="radio" name="<?php echo esc_attr($api['option_key']); ?>" id="atfpp_translated_slug_strategy_<?php echo esc_attr($option_key); ?>" value="<?php echo esc_attr($option_key); ?>" <?php echo esc_attr($api['value']) === $option_key ? 'checked' : ''; ?> disabled>
|
|
<label for="atfpp_translated_slug_strategy_<?php echo esc_attr($option_key); ?>"><?php echo esc_html($option_value); ?></label>
|
|
<?php
|
|
endforeach;
|
|
?>
|
|
</div>
|
|
<?php elseif($key === 'atfp_ai_request_token_per_request'):
|
|
?>
|
|
<hr style="margin: 2rem 0px;">
|
|
<div class="atfpp-dashboard-ai-request-container">
|
|
<h2><?php echo __('AI Request Performance', $text_domain); ?></h2>
|
|
<p><?php echo __('Adjust these settings to optimize the performance of your AI requests.', $text_domain); ?></p>
|
|
<div class="atfpp-dashboard-ai-token-container">
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-dashboard-ai-token-container-input">
|
|
<input type="number" min="100" max="10000" step="100" name="<?php echo esc_attr($api['option_key']); ?>" id="<?php echo esc_attr($key); ?>-input" value="<?php echo esc_attr($api['value']); ?>" disabled>
|
|
<p><?php echo sprintf(__('%sRecommended%s 500 tokens per request If model or network is slow, decrease this value', $text_domain), '<span>', '</span>'); ?></p>
|
|
</div>
|
|
</div>
|
|
<?php elseif($key === 'atfp_ai_request_batch_size'):
|
|
?>
|
|
<div class="atfpp-dashboard-ai-batch-size-container">
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-dashboard-ai-batch-container-input">
|
|
<input type="number" min="1" max="10" name="<?php echo esc_attr($api['option_key']); ?>" id="<?php echo esc_attr($key); ?>-input" value="<?php echo esc_attr($api['value']); ?>" disabled>
|
|
<p><?php echo sprintf(__('%sRecommended%s 5 posts per batch Larger batch can take longer to process If model or network is slow, decrease this value', $text_domain), '<span>', '</span>'); ?></p>
|
|
</div>
|
|
</div>
|
|
<?php elseif($key === 'atfp_ai_request_timeout'):
|
|
?>
|
|
<div class="atfpp-dashboard-ai-timeout-container">
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-dashboard-ai-timeout-container-input">
|
|
<input type="number" min="10" max="1200" step="10" name="<?php echo esc_attr($api['option_key']); ?>" id="<?php echo esc_attr($key); ?>-input" value="<?php echo esc_attr($api['value']); ?>" disabled>
|
|
<p><?php echo sprintf(__('%sRecommended%s 120 seconds minimum timeout can cause timeouts If model or network is slow, increase this value', $text_domain), '<span>', '</span>'); ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<hr style="margin: 2rem 0px 20px;">
|
|
<?php else: ?>
|
|
<label for="<?php echo esc_attr($key); ?>-api"><?php printf(__('Add %s API key', $text_domain), esc_html($api['name'])); ?></label>
|
|
<div class="input-group">
|
|
<input type="text" id="<?php echo esc_attr($key); ?>-api" placeholder="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" disabled>
|
|
</div>
|
|
<?php
|
|
printf(
|
|
esc_html__('%s to See How to Generate %s API Key', $text_domain),
|
|
'<a href="' . esc_url($api['docs_url']) . '" target="_blank">' . esc_html__('Click Here', $text_domain) . '</a>',
|
|
esc_html($api['name'])
|
|
);
|
|
endif;
|
|
endforeach; ?>
|
|
|
|
<div class="atfpp-dashboard-save-btn-container">
|
|
<button disabled class="button button-primary"><?php echo esc_html__('Save', $text_domain); ?></button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="atfpp-dashboard-geminiAPIkey">
|
|
<h3>Rate Limits of Free Gemini API Key</h3>
|
|
<ul>
|
|
<li><strong>15 RPM</strong>: This API Key allows a maximum of 15 requests per minute</li>
|
|
<li><strong>1 million TPM</strong>: With this API Key, you can process up to 1 million tokens per minute</li>
|
|
<li><strong>1,500 RPD</strong>: To ensure smooth performance, it allows up to 1,500 requests per day</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
function atfpp_render_settings_page_pro() {
|
|
$text_domain = 'autopoly-ai-translation-for-polylang-pro';
|
|
|
|
// Move API configuration to a separate function for better organization
|
|
$apis = atfpp_get_api_configurations();
|
|
|
|
// Handle form submission early
|
|
if (atfpp_check_form_submission()) {
|
|
atfpp_handle_api_key_submission();
|
|
}
|
|
|
|
atfpp_render_settings_page_html($apis, $text_domain);
|
|
}
|
|
|
|
function atfpp_get_api_configurations() {
|
|
return [
|
|
'google' => [
|
|
'name' => 'Gemini',
|
|
'option_key' => 'Atfpp_Ai_Translate_google_api_key',
|
|
'docs_url' => 'https://docs.coolplugins.net/doc/generate-gemini-api-key/?utm_source=atfp_plugin&utm_medium=inside&utm_campaign=docs&utm_content=settings_gemini_pro',
|
|
'value' => get_option('Atfpp_Ai_Translate_google_api_key', '')
|
|
],
|
|
'openai' => [
|
|
'name' => 'OpenAI',
|
|
'option_key' => 'Atfpp_Ai_Translate_openai_api_key',
|
|
'docs_url' => 'https://docs.coolplugins.net/doc/generate-open-ai-api-key/?utm_source=atfp_plugin&utm_medium=inside&utm_campaign=docs&utm_content=settings_openai_pro',
|
|
'value' => get_option('Atfpp_Ai_Translate_openai_api_key', '')
|
|
],
|
|
// 'openrouter' => [
|
|
// 'name' => 'Openrouter',
|
|
// 'option_key' => 'Atfpp_Ai_Translate_openrouter_api_key',
|
|
// 'docs_url' => 'https://locoaddon.com/docs/how-to-generate-open-api-key/',
|
|
// 'value' => get_option('Atfpp_Ai_Translate_openrouter_api_key', '')
|
|
// ],
|
|
'deepl' => [
|
|
'name' => 'DeepL',
|
|
'option_key' => 'Atfpp_Ai_Translate_deepl_api_key',
|
|
'docs_url' => 'https://locoaddon.com/docs/how-to-generate-deepl-api-key/',
|
|
'value' => get_option('Atfpp_Ai_Translate_deepl_api_key', '')
|
|
],
|
|
'context_aware' => [
|
|
'name' => 'Context Aware',
|
|
'option_key' => 'atfp_context_aware',
|
|
'value' => get_option('atfp_context_aware', '')
|
|
],
|
|
'atfpp_bulk_post_status' => [
|
|
'name' => 'Bulk Translation default Post Status',
|
|
'option_key' => 'atfp_bulk_post_status',
|
|
'value' => get_option('atfp_bulk_post_status', 'draft'),
|
|
'options' => [
|
|
'publish' => 'Published',
|
|
'draft' => 'Draft',
|
|
]
|
|
],
|
|
'atfp_slug_translation_option' => [
|
|
'name' => 'Slug Translation Settings',
|
|
'option_key' => 'atfp_slug_translation_option',
|
|
'value' => get_option('atfp_slug_translation_option', 'title_translate'),
|
|
'options' => [
|
|
'title_translate' => 'Use Translated Title',
|
|
'slug_translate' => 'Translate Original Slug',
|
|
'slug_keep' => 'Keep Original Slug',
|
|
]
|
|
],
|
|
'atfp_ai_request_token_per_request' => [
|
|
'name' => 'Token Limit',
|
|
'option_key' => 'atfp_ai_request_token_per_request',
|
|
'value' => get_option('atfp_ai_request_token_per_request', 500)
|
|
],
|
|
'atfp_ai_request_batch_size' => [
|
|
'name' => 'Batch Size',
|
|
'option_key' => 'atfp_ai_request_batch_size',
|
|
'value' => get_option('atfp_ai_request_batch_size', 5)
|
|
],
|
|
'atfp_ai_request_timeout' => [
|
|
'name' => 'Timeout Duration',
|
|
'option_key' => 'atfp_ai_request_timeout',
|
|
'value' => get_option('atfp_ai_request_timeout', 120)
|
|
]
|
|
];
|
|
}
|
|
|
|
function atfpp_check_form_submission() {
|
|
return isset($_POST['nonce']) &&
|
|
wp_verify_nonce(sanitize_text_field(wp_unslash($_POST['nonce'])), 'api_keys') &&
|
|
current_user_can('manage_options') &&
|
|
$_SERVER['REQUEST_METHOD'] === 'POST';
|
|
}
|
|
|
|
function atfpp_validate_google_api_key($key) {
|
|
if (empty($key)) return false;
|
|
|
|
if (!preg_match('/^AIza[0-9A-Za-z\-_]{35}$/', $key)) {
|
|
atfpp_show_admin_notice('error', 'Invalid Gemini API Key.');
|
|
return false;
|
|
}
|
|
|
|
$response = wp_remote_get(
|
|
'https://generativelanguage.googleapis.com/v1beta/models?key=' . $key,
|
|
[
|
|
'headers' => ['Content-Type' => 'application/json'],
|
|
'timeout' => 30,
|
|
]
|
|
);
|
|
|
|
if (is_wp_error($response)) {
|
|
atfpp_show_admin_notice('error', 'API request failed: ' . $response->get_error_message());
|
|
return false;
|
|
}
|
|
|
|
$body = json_decode(wp_remote_retrieve_body($response), true);
|
|
|
|
if (!isset($body['models']) || empty($body['models'])) {
|
|
atfpp_show_admin_notice('error', 'Invalid or unauthorized Gemini API Key.');
|
|
return false;
|
|
}
|
|
|
|
$text_models = [];
|
|
foreach ($body['models'] as $model) {
|
|
if (
|
|
empty($model['name']) ||
|
|
empty($model['supportedGenerationMethods']) ||
|
|
!is_array($model['supportedGenerationMethods']) ||
|
|
!in_array('generateContent', $model['supportedGenerationMethods'], true)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
$model_name = $model['name'];
|
|
|
|
if (
|
|
(isset($model['state']) && $model['state'] !== 'ACTIVE') ||
|
|
preg_match('/(tts|image|vision)/i', $model_name)
|
|
) {
|
|
continue;
|
|
}
|
|
|
|
$clean_name = str_replace('models/', '', $model_name);
|
|
|
|
$text_models[] = $clean_name;
|
|
}
|
|
|
|
update_option('atfpp_google_models', $text_models);
|
|
|
|
return true;
|
|
}
|
|
|
|
function atfpp_validate_openai_api_key( $key ) {
|
|
if (empty($key)) return false;
|
|
|
|
$response = wp_remote_get('https://api.openai.com/v1/models', [
|
|
'headers' => [
|
|
'Authorization' => 'Bearer ' . $key,
|
|
],
|
|
]);
|
|
|
|
if (is_wp_error($response)) {
|
|
atfpp_show_admin_notice('error', 'Unable to connect to OpenAI API.');
|
|
return false;
|
|
}
|
|
|
|
$response_data = json_decode(wp_remote_retrieve_body($response), true);
|
|
|
|
if (!empty($response_data['error'])) {
|
|
$error_message = $response_data['error']['message'] ?? 'Invalid OpenAI API Key.';
|
|
atfpp_show_admin_notice('error', str_replace('<a ', '<a target="_blank" ', make_clickable($error_message)));
|
|
return false;
|
|
}
|
|
|
|
if (empty($response_data['data'])) {
|
|
atfpp_show_admin_notice('error', 'No models found. Your API key may not have access.');
|
|
return false;
|
|
}
|
|
|
|
$model_ids = array_reduce(
|
|
$response_data['data'],
|
|
function ( array $ids, array $model_data ) {
|
|
$model_slug = $model_data['id'];
|
|
|
|
if (
|
|
( str_starts_with( $model_slug, 'gpt-' ) || str_starts_with( $model_slug, 'o1-' ) )
|
|
&& ! str_contains( $model_slug, '-instruct' )
|
|
&& ! str_contains( $model_slug, '-realtime' )
|
|
&& ! str_contains( $model_slug, '-audio' )
|
|
&& ! str_contains( $model_slug, '-tts' )
|
|
&& ! str_contains( $model_slug, '-transcribe' )
|
|
&& ! str_contains( $model_slug, '-image' )
|
|
&& $model_slug !== 'o1-pro'
|
|
&& $model_slug !== 'o1-pro-2025-03-19'
|
|
) {
|
|
$ids[] = $model_slug;
|
|
}
|
|
|
|
return $ids;
|
|
},
|
|
[]
|
|
);
|
|
|
|
update_option('atfpp_openai_models', $model_ids);
|
|
|
|
return true;
|
|
}
|
|
|
|
function atfpp_validate_deepl_api_key($key) {
|
|
if (empty($key)) return false;
|
|
|
|
$client = new Client();
|
|
|
|
$key=sanitize_text_field($key);
|
|
$key_free=str_ends_with($key, ':fx');
|
|
|
|
try {
|
|
$url=$key_free ? 'https://api-free.deepl.com/v2/usage' : 'https://api.deepl.com/v2/usage';
|
|
|
|
$response = $client->request('GET', $url, [
|
|
'headers' => [
|
|
'Authorization' => 'DeepL-Auth-Key ' . $key,
|
|
],
|
|
]);
|
|
|
|
$statusCode = $response->getStatusCode();
|
|
$reason = $response->getReasonPhrase(); // short HTTP reason like "Unauthorized"
|
|
|
|
|
|
if($statusCode === 200){
|
|
return true;
|
|
}else{
|
|
atfpp_show_admin_notice('error', str_replace('<a ', '<a target="_blank" ', make_clickable($reason)));
|
|
return false;
|
|
}
|
|
|
|
} catch (RequestException $e) {
|
|
if ($e->hasResponse()) {
|
|
// Extract error details from response body
|
|
$errorBody = (string) $e->getResponse()->getBody();
|
|
|
|
// Decode JSON response to array
|
|
$errorData = json_decode($errorBody, true);
|
|
|
|
// Get error message if available
|
|
$errorMessage = $errorData['message'] ?? $errorBody;
|
|
} else {
|
|
// Use exception message if no response body is available
|
|
$errorMessage = $e->getMessage();
|
|
}
|
|
|
|
atfpp_show_admin_notice('error', str_replace('<a ', '<a target="_blank" ', make_clickable($errorMessage)));
|
|
return false;
|
|
}
|
|
|
|
atfpp_show_admin_notice('error', 'Invalid DeepL API Key.');
|
|
return false;
|
|
}
|
|
|
|
function atfpp_validate_openrouter_api_key($key) {
|
|
if (empty($key)) return false;
|
|
$response = wp_remote_post('https://openrouter.ai/api/v1/chat/completions', [
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => 'Bearer ' . $key,
|
|
'HTTP-Referer' => site_url(),
|
|
'X-Title' => 'Polylang Addon',
|
|
'X-Organization-ID' => site_url(),
|
|
],
|
|
'body' => wp_json_encode([
|
|
'model' => 'meta-llama/llama-4-maverick:free',
|
|
'messages' => [
|
|
[
|
|
'role' => 'user',
|
|
'content' => [
|
|
[
|
|
'type' => 'text',
|
|
'text' => 'Test message'
|
|
]
|
|
]
|
|
]
|
|
]
|
|
]),
|
|
'method' => 'POST',
|
|
'timeout' => 60,
|
|
]);
|
|
|
|
if (is_wp_error($response)) {
|
|
atfpp_show_admin_notice('error', 'Invalid OpenRouter API Key.');
|
|
return false;
|
|
}
|
|
|
|
$response_data = json_decode(wp_remote_retrieve_body($response), true);
|
|
if (!empty($response_data['error'])) {
|
|
$error_message = $response_data['error']['message'] ?? 'Invalid OpenRouter API Key.';
|
|
atfpp_show_admin_notice('error', str_replace('<a ', '<a target="_blank" ', wp_kses( make_clickable($error_message), ['a' => ['href' => [], 'target' => [], 'rel' => []]]) ));
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
function atfpp_show_admin_notice($type, $message) {
|
|
if (!isset($GLOBALS['atfpp_admin_notices'])) {
|
|
$GLOBALS['atfpp_admin_notices'] = array();
|
|
}
|
|
$GLOBALS['atfpp_admin_notices'][] = wp_kses('<div class="notice notice-' . esc_attr($type) . ' is-dismissible"><p>' . wp_kses($message, ['a' => ['href' => [], 'target' => []]]) . '</p></div>', ['div' => ['class' => true], 'p' => [], 'a' => ['href' => [], 'target' => []]]);
|
|
}
|
|
|
|
function atfpp_handle_api_key_submission() {
|
|
if ( ! current_user_can('manage_options') ) {
|
|
atfpp_show_admin_notice('error', 'You are not allowed to perform this action.');
|
|
return false;
|
|
}
|
|
// Clear any existing notices at the start
|
|
$GLOBALS['atfpp_admin_notices'] = array();
|
|
|
|
if (isset($_POST['reset_google_api_key'])) {
|
|
delete_option('Atfpp_Ai_Translate_google_api_key');
|
|
delete_option('atfpp_google_models');
|
|
delete_option('atfpp_selected_google_model');
|
|
atfpp_show_admin_notice('success', 'Gemini API Key has been removed.');
|
|
return true;
|
|
}
|
|
|
|
if (isset($_POST['reset_openai_api_key'])) {
|
|
delete_option('Atfpp_Ai_Translate_openai_api_key');
|
|
delete_option('atfpp_openai_models');
|
|
delete_option('atfpp_selected_openai_model');
|
|
atfpp_show_admin_notice('success', 'OpenAI API Key has been removed.');
|
|
return true;
|
|
}
|
|
|
|
if (isset($_POST['reset_openrouter_api_key'])) {
|
|
delete_option('Atfpp_Ai_Translate_openrouter_api_key');
|
|
atfpp_show_admin_notice('success', 'OpenRouter API Key has been removed.');
|
|
return true;
|
|
}
|
|
|
|
if (isset($_POST['reset_deepl_api_key'])) {
|
|
delete_option('atfp_deepl_api_key_type');
|
|
delete_option('Atfpp_Ai_Translate_deepl_api_key');
|
|
atfpp_show_admin_notice('success', 'DeepL API Key has been removed.');
|
|
return true;
|
|
}
|
|
|
|
if (isset($_POST['submit_api_keys'])) {
|
|
return atfpp_handle_api_key_save();
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function atfpp_handle_api_key_save() {
|
|
if ( ! current_user_can('manage_options') ) {
|
|
atfpp_show_admin_notice('error', 'You are not allowed to perform this action.');
|
|
return false;
|
|
}
|
|
$success = false;
|
|
$any_validation_attempted = false;
|
|
$has_error = false;
|
|
|
|
// Handle Context Aware textarea
|
|
if (isset($_POST['atfp_context_aware'])) {
|
|
$context_aware = sanitize_textarea_field(wp_unslash($_POST['atfp_context_aware']));
|
|
update_option('atfp_context_aware', $context_aware);
|
|
// Store the new value in a global variable to use in the render function
|
|
$GLOBALS['current_context_aware'] = $context_aware;
|
|
$success = true;
|
|
}
|
|
|
|
$current_openai_model = get_option('atfpp_selected_openai_model', '');
|
|
$current_google_model = get_option('atfpp_selected_google_model', '');
|
|
|
|
// Save selected OpenAI model if set and validate
|
|
if (isset($_POST['atfpp_selected_openai_model']) && $_POST['atfpp_selected_openai_model'] !== $current_openai_model) {
|
|
|
|
$selected_model = sanitize_text_field($_POST['atfpp_selected_openai_model']);
|
|
$openai_key = get_option('Atfpp_Ai_Translate_openai_api_key', '');
|
|
$is_valid = false;
|
|
$error_message = '';
|
|
|
|
if ($selected_model === '') {
|
|
update_option('atfpp_selected_openai_model', '');
|
|
atfpp_show_admin_notice('success', 'OpenAI model selection has been cleared.');
|
|
} else {
|
|
if ($openai_key && $selected_model) {
|
|
$response = wp_remote_post('https://api.openai.com/v1/chat/completions', [
|
|
'headers' => [
|
|
'Content-Type' => 'application/json',
|
|
'Authorization' => 'Bearer ' . $openai_key,
|
|
],
|
|
'body' => wp_json_encode([
|
|
'model' => $selected_model,
|
|
'messages' => [['role' => 'user', 'content' => 'Test']],
|
|
'max_completion_tokens' => 20
|
|
]),
|
|
'timeout' => 20,
|
|
]);
|
|
|
|
if (is_wp_error($response)) {
|
|
$error_message = $response->get_error_message();
|
|
} else {
|
|
$body = json_decode(wp_remote_retrieve_body($response), true);
|
|
if (empty($body['error'])) {
|
|
$is_valid = true;
|
|
} else {
|
|
$error_message = $body['error']['message'] ?? 'Unknown error from OpenAI.';
|
|
}
|
|
}
|
|
}
|
|
|
|
if ($is_valid) {
|
|
update_option('atfpp_selected_openai_model', $selected_model);
|
|
atfpp_show_admin_notice('success', 'The OpenAI model has been successfully validated and saved.');
|
|
} else {
|
|
atfpp_show_admin_notice('error', 'OpenAI API Error: ' . esc_html($error_message));
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
if (isset($_POST['atfpp_selected_google_model']) && $_POST['atfpp_selected_google_model'] !== $current_google_model) {
|
|
|
|
$selected_model = sanitize_text_field($_POST['atfpp_selected_google_model']);
|
|
$google_key = get_option('Atfpp_Ai_Translate_google_api_key', '');
|
|
$is_valid = false;
|
|
$error_message = '';
|
|
|
|
if ($selected_model === '') {
|
|
delete_option('atfpp_selected_google_model');
|
|
atfpp_show_admin_notice('success', 'The Google Gemini model selection has been cleared.');
|
|
} else {
|
|
if ($google_key && $selected_model) {
|
|
$response = wp_remote_post(
|
|
'https://generativelanguage.googleapis.com/v1beta/models/' . $selected_model . ':generateContent?key=' . $google_key,
|
|
[
|
|
'headers' => ['Content-Type' => 'application/json'],
|
|
'body' => json_encode([
|
|
'contents' => [[ 'parts' => [['text' => 'Test']] ]]
|
|
]),
|
|
'timeout' => 60,
|
|
]
|
|
);
|
|
|
|
if (!is_wp_error($response)) {
|
|
$body = json_decode(wp_remote_retrieve_body($response), true);
|
|
if (empty($body['error'])) {
|
|
$is_valid = true;
|
|
} else if (!empty($body['error']['message'])) {
|
|
$error_message = $body['error']['message'];
|
|
}
|
|
} else {
|
|
$error_message = $response->get_error_message();
|
|
}
|
|
}
|
|
|
|
if ($is_valid) {
|
|
update_option('atfpp_selected_google_model', $selected_model);
|
|
atfpp_show_admin_notice('success', 'The Gemini model has been successfully validated and saved.');
|
|
} else {
|
|
$notice = $error_message ? $error_message : 'The selected Gemini model is not valid or not accessible with your API key.';
|
|
atfpp_show_admin_notice('error', $notice);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Handle feedback checkbox
|
|
$feedback_opt_in = null;
|
|
if (get_option('cpfm_opt_in_choice_cool_translations')) {
|
|
$feedback_opt_in = isset($_POST['atfpp-dashboard-feedback-checkbox']) ? 'yes' : 'no';
|
|
update_option('atfp_feedback_opt_in', $feedback_opt_in);
|
|
}
|
|
|
|
// If user opted out, remove the cron job
|
|
if ($feedback_opt_in === 'no' && wp_next_scheduled('atfpp_extra_data_update')) {
|
|
wp_clear_scheduled_hook('atfpp_extra_data_update');
|
|
}
|
|
|
|
if ($feedback_opt_in === 'yes' && !wp_next_scheduled('atfpp_extra_data_update')) {
|
|
|
|
wp_schedule_event(time(), 'every_30_days', 'atfpp_extra_data_update');
|
|
|
|
}
|
|
|
|
if (isset($_POST['atfp_bulk_post_status'])) {
|
|
$bulk_post_status = sanitize_text_field($_POST['atfp_bulk_post_status']);
|
|
update_option('atfp_bulk_post_status', $bulk_post_status);
|
|
$success = true;
|
|
}
|
|
|
|
if (isset($_POST['atfp_slug_translation_option'])) {
|
|
$slug_translation_option = sanitize_text_field($_POST['atfp_slug_translation_option']);
|
|
update_option('atfp_slug_translation_option', $slug_translation_option);
|
|
$success = true;
|
|
}
|
|
|
|
if (isset($_POST['atfp_ai_request_token_per_request'])) {
|
|
$ai_token_per_request = sanitize_text_field($_POST['atfp_ai_request_token_per_request']);
|
|
|
|
if($ai_token_per_request < 100 || $ai_token_per_request > 10000 || empty($ai_token_per_request) ) {
|
|
atfpp_show_admin_notice('error', 'AI Token Per Request must be between 100 and 10000.');
|
|
return false;
|
|
}
|
|
|
|
update_option('atfp_ai_request_token_per_request', $ai_token_per_request);
|
|
$success = true;
|
|
}
|
|
|
|
if (isset($_POST['atfp_ai_request_batch_size'])) {
|
|
$ai_batch_size = sanitize_text_field($_POST['atfp_ai_request_batch_size']);
|
|
|
|
if($ai_batch_size < 1 || $ai_batch_size > 10 || empty($ai_batch_size) ) {
|
|
atfpp_show_admin_notice('error', 'AI Batch Size must be between 1 and 10.');
|
|
return false;
|
|
}
|
|
|
|
update_option('atfp_ai_request_batch_size', $ai_batch_size);
|
|
$success = true;
|
|
}
|
|
|
|
if (isset($_POST['atfp_ai_request_timeout'])) {
|
|
$ai_timeout = sanitize_text_field($_POST['atfp_ai_request_timeout']);
|
|
|
|
if($ai_timeout < 10 || $ai_timeout > 1200 || empty($ai_timeout) ) {
|
|
atfpp_show_admin_notice('error', 'AI Timeout must be between 10 and 1200.');
|
|
return false;
|
|
}
|
|
|
|
update_option('atfp_ai_request_timeout', $ai_timeout);
|
|
$success = true;
|
|
}
|
|
|
|
// Validate all API keys first before saving any
|
|
$valid_keys = [];
|
|
|
|
if (!empty($_POST['Atfpp_Ai_Translate_google_api_key'])) {
|
|
$new_google_key = sanitize_text_field($_POST['Atfpp_Ai_Translate_google_api_key']);
|
|
$any_validation_attempted = true;
|
|
if (atfpp_validate_google_api_key($new_google_key)) {
|
|
$valid_keys['google'] = $new_google_key;
|
|
} else {
|
|
$has_error = true;
|
|
}
|
|
}
|
|
|
|
if (!empty($_POST['Atfpp_Ai_Translate_openai_api_key'])) {
|
|
$new_openai_key = sanitize_text_field($_POST['Atfpp_Ai_Translate_openai_api_key']);
|
|
$any_validation_attempted = true;
|
|
if (atfpp_validate_openai_api_key($new_openai_key)) {
|
|
$valid_keys['openai'] = $new_openai_key;
|
|
} else {
|
|
$has_error = true;
|
|
}
|
|
}
|
|
|
|
if (!empty($_POST['Atfpp_Ai_Translate_deepl_api_key'])) {
|
|
$new_deepl_key = sanitize_text_field($_POST['Atfpp_Ai_Translate_deepl_api_key']);
|
|
$any_validation_attempted = true;
|
|
if (atfpp_validate_deepl_api_key($new_deepl_key)) {
|
|
$valid_keys['deepl'] = $new_deepl_key;
|
|
} else {
|
|
$has_error = true;
|
|
}
|
|
}
|
|
|
|
if (!empty($_POST['Atfpp_Ai_Translate_openrouter_api_key'])) {
|
|
$new_openrouter_key = sanitize_text_field($_POST['Atfpp_Ai_Translate_openrouter_api_key']);
|
|
$any_validation_attempted = true;
|
|
if (atfpp_validate_openrouter_api_key($new_openrouter_key)) {
|
|
$valid_keys['openrouter'] = $new_openrouter_key;
|
|
} else {
|
|
$has_error = true;
|
|
}
|
|
}
|
|
|
|
// Only save and show success if there were no errors
|
|
if (!$has_error && !empty($valid_keys)) {
|
|
foreach ($valid_keys as $key => $value) {
|
|
update_option("Atfpp_Ai_Translate_{$key}_api_key", $value);
|
|
}
|
|
atfpp_show_admin_notice('success', 'Settings saved successfully.');
|
|
return true;
|
|
} elseif ($any_validation_attempted && !isset($GLOBALS['atfpp_admin_notices'])) {
|
|
atfpp_show_admin_notice('error', 'Please enter valid values.');
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
function atfpp_render_settings_page_html($apis, $text_domain) {
|
|
// Process form submission before rendering
|
|
$form_processed = false;
|
|
if (atfpp_check_form_submission()) {
|
|
$form_processed = atfpp_handle_api_key_submission();
|
|
}
|
|
|
|
// Refresh API values after form processing
|
|
if ($form_processed) {
|
|
$apis = atfpp_get_api_configurations();
|
|
}
|
|
|
|
// Update the context aware value if it was just saved
|
|
if (isset($GLOBALS['current_context_aware'])) {
|
|
$apis['context_aware']['value'] = $GLOBALS['current_context_aware'];
|
|
}
|
|
|
|
if(isset($apis['atfpp_bulk_post_status']['value'])){
|
|
$apis['atfpp_bulk_post_status']['value'] = get_option('atfp_bulk_post_status', 'draft');
|
|
}
|
|
|
|
if(isset($apis['atfp_slug_translation_option']['value'])){
|
|
$apis['atfp_slug_translation_option']['value'] = get_option('atfp_slug_translation_option', 'title_translate');
|
|
}
|
|
|
|
if(isset($apis['atfp_ai_request_token_per_request']['value'])){
|
|
$apis['atfp_ai_request_token_per_request']['value'] = get_option('atfp_ai_request_token_per_request', 500);
|
|
}
|
|
|
|
if(isset($apis['atfp_ai_request_batch_size']['value'])){
|
|
$apis['atfp_ai_request_batch_size']['value'] = get_option('atfp_ai_request_batch_size', 5);
|
|
}
|
|
|
|
if(isset($apis['atfp_ai_request_timeout']['value'])){
|
|
$apis['atfp_ai_request_timeout']['value'] = get_option('atfp_ai_request_timeout', 120);
|
|
}
|
|
|
|
$openai_models = get_option('atfpp_openai_models', []);
|
|
$current_openai_model = get_option('atfpp_selected_openai_model', '');
|
|
$google_models = get_option('atfpp_google_models', []);
|
|
$current_google_model = get_option('atfpp_selected_google_model', '');
|
|
?>
|
|
<div class="atfpp-dashboard-settings">
|
|
<div class="atfpp-dashboard-settings-container">
|
|
<?php
|
|
// Show notices at the top of the container
|
|
if (isset($GLOBALS['atfpp_admin_notices'])) {
|
|
foreach ($GLOBALS['atfpp_admin_notices'] as $notice) {
|
|
echo wp_kses_post($notice);
|
|
}
|
|
}
|
|
?>
|
|
<div class="header">
|
|
<h1><?php echo esc_html__('Polylang Addon Settings', $text_domain); ?></h1>
|
|
</div>
|
|
|
|
<p class="description">
|
|
<?php echo esc_html__('Configure your settings for the Polylang Addon to optimize your translation experience. Enter your API keys and manage your preferences for seamless integration.', $text_domain); ?>
|
|
</p>
|
|
|
|
<div class="atfpp-dashboard-api-settings-container">
|
|
<div class="atfpp-dashboard-api-settings">
|
|
<form method="post">
|
|
<?php wp_nonce_field('api_keys', 'nonce'); ?>
|
|
|
|
<?php foreach ($apis as $key => $api):
|
|
if ($key === 'context_aware'): ?>
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html__('Context Aware', $text_domain); ?>
|
|
</label>
|
|
<textarea
|
|
id="<?php echo esc_attr($key); ?>-input"
|
|
name="<?php echo esc_attr($api['option_key']); ?>"
|
|
placeholder="Provide optional context about WordPress page or post to enhance translation accuracy (e.g. content purpose, target audience, SEO focus, tone)..."
|
|
><?php echo esc_textarea($api['value']); ?></textarea>
|
|
<p class="api-settings-note" style="margin-block: 5px;">
|
|
<?php echo esc_html__('This setting only works with Gemini AI and OpenAI.', $text_domain); ?>
|
|
</p>
|
|
<?php
|
|
elseif($key === 'atfpp_bulk_post_status'):
|
|
?>
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-bulk-translation-post-status-options">
|
|
<?php
|
|
foreach($api['options'] as $option_key => $option_value):
|
|
?>
|
|
<input type="radio" name="<?php echo esc_attr($api['option_key']); ?>" id="atfpp_bulk_post_status_<?php echo esc_attr($option_key); ?>" value="<?php echo esc_attr($option_key); ?>" <?php echo esc_attr($api['value']) === $option_key ? 'checked' : ''; ?>>
|
|
<label for="atfpp_bulk_post_status_<?php echo esc_attr($option_key); ?>"><?php echo esc_html($option_value); ?></label>
|
|
<?php
|
|
endforeach;
|
|
?>
|
|
</div>
|
|
<?php
|
|
elseif($key === 'atfp_slug_translation_option'):
|
|
?>
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-bulk-translation-post-status-options">
|
|
<?php
|
|
foreach($api['options'] as $option_key => $option_value):
|
|
?>
|
|
<input type="radio" name="<?php echo esc_attr($api['option_key']); ?>" id="atfpp_translated_slug_strategy_<?php echo esc_attr($option_key); ?>" value="<?php echo esc_attr($option_key); ?>" <?php echo esc_attr($api['value']) === $option_key ? 'checked' : ''; ?>>
|
|
<label for="atfpp_translated_slug_strategy_<?php echo esc_attr($option_key); ?>"><?php echo esc_html($option_value); ?></label>
|
|
<?php
|
|
endforeach;
|
|
?>
|
|
</div>
|
|
<?php
|
|
elseif($key === 'atfp_ai_request_token_per_request'):
|
|
?>
|
|
<hr style="margin: 2rem 0px;">
|
|
<div class="atfpp-dashboard-ai-request-container">
|
|
<h2><?php echo __('AI Performance Request Settings', $text_domain); ?></h2>
|
|
<p><?php echo __('Optimize how your requests are processed for the best balance of speed, accuracy, and reliability. If your site or network is slow, you can fine-tune these options for smoother results.', $text_domain); ?></p>
|
|
<div class="atfpp-dashboard-ai-token-container">
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-dashboard-ai-token-container-input">
|
|
<input type="number" min="100" max="10000" step="100" name="<?php echo esc_attr($api['option_key']); ?>" id="<?php echo esc_attr($key); ?>-input" value="<?php echo esc_attr($api['value']); ?>">
|
|
<p><?php echo sprintf(__('Controls text size per request; higher values give detailed results but slower speed. %sRecommended: 500%s', $text_domain), '<span>(', ')</span>'); ?></p>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
elseif($key === 'atfp_ai_request_batch_size'):
|
|
?>
|
|
<div class="atfpp-dashboard-ai-batch-size-container">
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-dashboard-ai-batch-container-input">
|
|
<input type="number" min="1" max="10" name="<?php echo esc_attr($api['option_key']); ?>" id="<?php echo esc_attr($key); ?>-input" value="<?php echo esc_attr($api['value']); ?>">
|
|
<p><?php echo sprintf(__('Sets how many items process together; lower values improve speed and stability. %sRecommended: 5%s', $text_domain), '<span>(', ')</span>'); ?></p>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
elseif($key === 'atfp_ai_request_timeout'):
|
|
?>
|
|
<div class="atfpp-dashboard-ai-timeout-container">
|
|
<label for="<?php echo esc_attr($key); ?>-input" class="api-settings-label">
|
|
<?php echo esc_html($api['name']); ?>
|
|
</label>
|
|
<div class="atfpp-dashboard-ai-timeout-container-input">
|
|
<input type="number" min="10" max="1200" step="10" name="<?php echo esc_attr($api['option_key']); ?>" id="<?php echo esc_attr($key); ?>-input" value="<?php echo esc_attr($api['value']); ?>">
|
|
<p><?php echo sprintf(__('Defines wait time before stopping; increase if requests often fail or delay. %sRecommended: 120 seconds%s', $text_domain), '<span>(', ')</span>'); ?></p>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<hr style="margin: 2rem 0px 20px;">
|
|
<?php
|
|
else:
|
|
$has_key = !empty($api['value']);
|
|
$masked_value = $has_key ?
|
|
esc_attr(substr($api['value'], 0, 8) . str_repeat('*', 24) . substr($api['value'], -8) . ' ✅') :
|
|
'';
|
|
?>
|
|
<label for="<?php echo esc_attr($key); ?>-api" class="api-settings-label">
|
|
<?php printf(esc_html__('Add %s API key', $text_domain), esc_html($api['name'])); ?>
|
|
</label>
|
|
<div class="input-group">
|
|
<input type="text"
|
|
id="<?php echo esc_attr($key); ?>-api"
|
|
name="<?php echo esc_attr($api['option_key']); ?>"
|
|
value="<?php echo $masked_value; ?>"
|
|
placeholder="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
|
|
<?php echo $has_key ? 'disabled' : ''; ?>>
|
|
|
|
<?php if ($has_key): ?>
|
|
<button type="submit" name="reset_<?php echo esc_attr($key); ?>_api_key" class="button button-primary reset-button">
|
|
<?php echo esc_html__('Reset', $text_domain); ?>
|
|
</button>
|
|
<?php endif; ?>
|
|
</div>
|
|
|
|
<?php
|
|
if ($key === 'openai' && $has_key && !empty($openai_models)) : ?>
|
|
<div class="atfpp-dashboard-api-settings-openai-model">
|
|
<label for="atfpp_selected_openai_model" class="api-settings-label">
|
|
<?php _e('Select OpenAI Model', $text_domain); ?>
|
|
</label>
|
|
<select name="atfpp_selected_openai_model" class="atfpp-openai-model-select">
|
|
<option value=""><?php _e('Select model...', $text_domain); ?></option>
|
|
<?php foreach ($openai_models as $model) : ?>
|
|
<option value="<?php echo esc_attr($model); ?>" <?php selected($current_openai_model, $model); ?>>
|
|
<?php echo esc_html($model); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if ($key === 'google' && $has_key && !empty($google_models)) : ?>
|
|
<div class="atfpp-dashboard-api-settings-google-model">
|
|
<label for="atfpp_selected_google_model" class="api-settings-label">
|
|
<?php _e('Select Gemini Model', $text_domain); ?>
|
|
</label>
|
|
<select name="atfpp_selected_google_model" class="atfpp-google-model-select">
|
|
<option value=""><?php _e('Select model...', $text_domain); ?></option>
|
|
<?php foreach ($google_models as $model) : ?>
|
|
<option value="<?php echo esc_attr($model); ?>" <?php selected($current_google_model, $model); ?>>
|
|
<?php echo esc_html($model); ?>
|
|
</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<?php endif; ?>
|
|
|
|
<?php if (!$has_key): ?>
|
|
<?php
|
|
printf(
|
|
esc_html__('%s to See How to Generate %s API Key', $text_domain),
|
|
'<a href="' . esc_url($api['docs_url']) . '" target="_blank">' . esc_html__('Click Here', $text_domain) . '</a>',
|
|
esc_html($api['name'])
|
|
);
|
|
?>
|
|
<?php endif; ?>
|
|
<?php endif; ?>
|
|
<?php endforeach; ?>
|
|
<?php if (get_option('cpfm_opt_in_choice_cool_translations')) : ?>
|
|
<div class="atfpp-dashboard-feedback-container">
|
|
<div class="atfpp-dashboard-feedback-row">
|
|
<input type="checkbox"
|
|
id="atfpp-dashboard-feedback-checkbox"
|
|
name="atfpp-dashboard-feedback-checkbox"
|
|
<?php checked(get_option('atfp_feedback_opt_in'), 'yes'); ?>>
|
|
<p><?php echo esc_html__('Help us make this plugin more compatible with your site by sharing non-sensitive site data.', $text_domain); ?></p>
|
|
<a href="#" class="atfpp-see-terms">[See terms]</a>
|
|
</div>
|
|
<div id="termsBox" style="display: none;padding-left: 20px; margin-top: 10px; font-size: 12px; color: #999;">
|
|
<p><?php echo esc_html__("Opt in to receive email updates about security improvements, new features, helpful tutorials, and occasional special offers. We'll collect:", 'ccpw'); ?> <a href="https://my.coolplugins.net/terms/usage-tracking/?utm_source=atfpp_plugin&utm_medium=inside&utm_campaign=terms&utm_content=dashboard" target="_blank"><?php echo esc_html__('Click Here', $text_domain); ?></a></p>
|
|
<ul style="list-style-type:auto;">
|
|
<li><?php echo esc_html__('Your website home URL and WordPress admin email.', 'ccpw'); ?></li>
|
|
<li><?php echo esc_html__('To check plugin compatibility, we will collect the following: list of active plugins and themes, server type, MySQL version, WordPress version, memory limit, site language and database prefix.', 'ccpw'); ?></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<?php endif; ?>
|
|
<div class="atfpp-dashboard-save-btn-container">
|
|
<button type="submit" name="submit_api_keys" class="button button-primary">
|
|
<?php echo esc_html__('Save', $text_domain); ?>
|
|
</button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="atfpp-dashboard-geminiAPIkey">
|
|
<h3>Rate Limits of Free Gemini API Key</h3>
|
|
<ul>
|
|
<li><strong>15 RPM</strong>: This API Key allows a maximum of 15 requests per minute</li>
|
|
<li><strong>1 million TPM</strong>: With this API Key, you can process up to 1 million tokens per minute</li>
|
|
<li><strong>1,500 RPD</strong>: To ensure smooth performance, it allows up to 1,500 requests per day</li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
<?php
|
|
}
|
|
|
|
function atfpp_all_apis_configured($apis) {
|
|
foreach ($apis as $api) {
|
|
if (empty($api['value'])) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
|