Skip Navigation

This is the technical support forum for WPML - the multilingual WordPress plugin.

Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.

Sun Mon Tue Wed Thu Fri Sat
- 10:00 – 17:00 10:00 – 17:00 10:00 – 17:00 10:00 – 17:00 10:00 – 17:00 -
- 18:00 – 19:00 18:00 – 19:00 18:00 – 19:00 18:00 – 19:00 18:00 – 19:00 -

Supporter timezone: Asia/Kathmandu (GMT+05:45)

This topic contains 1 reply, has 0 voices.

Last updated by Shekhar Bhandari 6 months, 3 weeks ago.

Assisted by: Shekhar Bhandari.

Author Posts
December 17, 2024 at 11:59 pm #16523767

Maximilian Wellner

Background of the issue:
I am trying to create a small plugin to automatically add translation versions of products to my main language products using WPML. I have included the full plugin code and error log in my message.

Below is the full revised plugin code with the delayed hook initialization to ensure the plugin loads after WPML. This includes:

The code to log debug messages to an option.
The code to add a settings page where logs can be viewed and cleared.
The delayed hook registration, so we attach our main hooks (transition_post_status) after plugins_loaded, allowing WPML to be fully loaded.
Additional logging to verify if WPML functions are available.
Make sure you have WPML and, if needed, WooCommerce Multilingual & Multicurrency (for products), installed and active. Also, adjust the $openai_api_key and language codes as needed.

1000) {
$logs = array_slice($logs, -1000);
}
update_option('ai_product_debug_logs', $logs, false);
}

function ai_clear_logs() {
update_option('ai_product_debug_logs', [], false);
}

/**
* Delay hooking into WordPress so WPML has time to load.
*/
add_action('plugins_loaded', 'ai_plugin_init', 20);
function ai_plugin_init() {
ai_debug_log("plugins_loaded action triggered, checking WPML...");

// Check if WPML function is available here
ai_debug_log("WPML function 'wpml_set_element_language_details' " . (function_exists('wpml_set_element_language_details') ? "exists" : "does not exist") . " at plugins_loaded.");

// Register main hooks now that plugins are loaded
add_action('transition_post_status', 'ai_generate_on_new_product_publish', 10, 3);
add_filter('bulk_actions-edit-product', 'ai_add_bulk_action');
add_filter('handle_bulk_actions-edit-product', 'ai_initiate_batch_processing', 10, 3);
add_action('wp_ajax_process_ai_product_batch', 'ai_process_product_batch');

// Settings and notices
add_action('admin_menu', 'ai_register_settings_page');
add_action('admin_init', 'ai_register_settings');
add_action('admin_notices', 'ai_show_error_notice');
}

/**
* AUTOMATIC FOR NEW PRODUCTS
*/
function ai_generate_on_new_product_publish($new_status, $old_status, $post) {
global $openai_api_key;
ai_debug_log("transition_post_status triggered for post ID {$post->ID}, new_status={$new_status}, old_status={$old_status}");

if ($post->post_type === 'product' && $new_status === 'publish' && $old_status !== 'publish') {
$product_id = $post->ID;
$product_title = get_the_title($product_id);
ai_debug_log("New product published: ID={$product_id}, title='{$product_title}'");

delete_option('ai_product_last_error');

// GERMAN TRANSLATION
ai_debug_log("Starting German translation and content generation for product ID {$product_id}...");
$translated_title = ai_translate_title_to_german($product_title, $openai_api_key);
if (!$translated_title) {
ai_debug_log("Failed to translate title to German for product ID {$product_id}. Aborting.");
return;
}
ai_debug_log("German translated title: '{$translated_title}'");

$generated_description = ai_generate_product_description($translated_title, $openai_api_key);
if (!$generated_description) {
ai_debug_log("Failed to generate German full description for product ID {$product_id}. Aborting.");
return;
}
ai_debug_log("German full description generated.");

$short_description = ai_generate_short_description($translated_title, $openai_api_key);
if (!$short_description) {
ai_debug_log("Failed to generate German short description for product ID {$product_id}. Aborting.");
return;
}
ai_debug_log("German short description generated.");

$current_description = get_post_field('post_content', $product_id);
$current_description = $current_description ?: '';
$new_description = $generated_description . "nn" . $current_description;

$update_result = wp_update_post([
'ID' => $product_id,
'post_title' => $translated_title,
'post_excerpt' => $short_description,
'post_content' => $new_description,
], true);

if (is_wp_error($update_result)) {
$error_msg = $update_result->get_error_message();
ai_debug_log("Failed to update product ID {$product_id} with German content: {$error_msg}");
ai_log_error_detailed('Failed to update the product: ' . $error_msg, null, null, null);
} else {
ai_debug_log("Successfully updated product ID {$product_id} with German content.");
if (function_exists('wc_delete_product_transients')) {
wc_delete_product_transients($product_id);
ai_debug_log("Cleared product transients for product ID {$product_id}.");
}
}

// ENGLISH TRANSLATION
$create_english = get_option('ai_create_english_translation', false);
ai_debug_log("Option 'create_english_translation' is set to " . ($create_english ? 'true' : 'false'));
ai_debug_log("Checking WPML function: " . (function_exists('wpml_set_element_language_details') ? 'exists' : 'does not exist'));

if ($create_english && function_exists('wpml_set_element_language_details')) {
ai_debug_log("Starting English translation creation for product ID {$product_id}...");
$english_title = ai_translate_title_to_english($product_title, $openai_api_key);
if (!$english_title) {
ai_debug_log("Failed to translate title to English for product ID {$product_id}. No English version will be created.");
return;
}
ai_debug_log("English translated title: '{$english_title}'");

$english_full_desc = ai_generate_product_description_english($english_title, $openai_api_key);
if (!$english_full_desc) {
ai_debug_log("Failed to generate English full description for product ID {$product_id}. No English version will be created.");
return;
}
ai_debug_log("English full description generated.");

$english_short_desc = ai_generate_short_description_english($english_title, $openai_api_key);
if (!$english_short_desc) {
ai_debug_log("Failed to generate English short description for product ID {$product_id}. No English version will be created.");
return;
}
ai_debug_log("English short description generated.");

$new_post_id = wp_insert_post([
'post_type' => 'product',
'post_status' => 'publish',
'post_title' => $english_title,
'post_excerpt' => $english_short_desc,
'post_content' => $english_full_desc
]);
ai_debug_log("Attempting to create English product. Resulting post ID: " . (is_wp_error($new_post_id) ? "WP_Error" : $new_post_id));

if (!is_wp_error($new_post_id)) {
$original_language_info = apply_filters('wpml_post_language_details', null, $product_id);
ai_debug_log("Original product language info: " . print_r($original_language_info, true));
if ($original_language_info && isset($original_language_info['trid'])) {
$trid = $original_language_info['trid'];
$english_code = 'en'; // adjust if needed

do_action('wpml_set_element_language_details', [
'element_id' => $new_post_id,
'element_type' => 'post_product',
'trid' => $trid,
'language_code' => $english_code,
'source_language_code' => $original_language_info['language_code']
]);
ai_debug_log("Linked English product ID {$new_post_id} to TRID {$trid} as English translation.");

if (function_exists('wc_delete_product_transients')) {
wc_delete_product_transients($new_post_id);
ai_debug_log("Cleared product transients for English product ID {$new_post_id}.");
}
} else {
ai_debug_log("No TRID found for product ID {$product_id}. Could not link English translation.");
}
} else {
$error_msg = $new_post_id->get_error_message();
ai_debug_log("Failed to create English translation product for ID {$product_id}: {$error_msg}");
ai_log_error_detailed('Failed to create English translation: ' . $error_msg, null, null, null);
}
}
}
}

/**
* BULK ACTION FOR EXISTING PRODUCTS
*/
function ai_add_bulk_action($bulk_actions) {
$bulk_actions['generate_ai_descriptions'] = 'Generate AI Descriptions';
return $bulk_actions;
}

function ai_initiate_batch_processing($redirect_to, $action, $post_ids) {
if ($action === 'generate_ai_descriptions') {
ai_debug_log("Bulk action 'generate_ai_descriptions' initiated for product IDs: " . implode(',', $post_ids));
wp_enqueue_script('ai-batch-edit', plugin_dir_url(__FILE__) . 'js/ai-batch-edit.js', ['jquery'], '1.0', true);
wp_localize_script('ai-batch-edit', 'aiBatchEdit', [
'ajax_url' => admin_url('admin-ajax.php'),
'nonce' => wp_create_nonce('ai_bulk_edit_nonce'),
'product_ids' => $post_ids,
]);

add_action('admin_notices', function () use ($post_ids) {
$total = count($post_ids);
echo "

AI Descriptions will be processed in batches. Click the button below to start.
Total products: $total

";
echo "

";
});

return remove_query_arg(['ai_generated'], $redirect_to);
}

return $redirect_to;
}

function ai_process_product_batch() {
check_ajax_referer('ai_bulk_edit_nonce', 'security');

global $openai_api_key;

$product_ids = isset($_POST['product_ids']) ? array_map('intval', $_POST['product_ids']) : [];
$batch_index = isset($_POST['batch_index']) ? intval($_POST['batch_index']) : 0;
$batch_size = 10; // adjust as needed

ai_debug_log("Processing batch index {$batch_index} for product IDs: " . implode(',', $product_ids));

$start = $batch_index * $batch_size;
$end = min($start + $batch_size, count($product_ids));
$create_english = get_option('ai_create_english_translation', false);

for ($i = $start; $i $post_id,
'post_title' => $translated_title,
'post_excerpt' => $short_description,
'post_content' => $new_description,
], true);

if (!is_wp_error($update_result)) {
ai_debug_log("Successfully updated product ID {$post_id} with German content in bulk mode.");
if (function_exists('wc_delete_product_transients')) {
wc_delete_product_transients($post_id);
ai_debug_log("Cleared product transients for product ID {$post_id} (bulk mode).");
}
} else {
$error_msg = $update_result->get_error_message();
ai_debug_log("Failed to update product ID {$post_id} (bulk): {$error_msg}");
ai_log_error_detailed('Failed to update the product: ' . $error_msg, null, null, null);
}

ai_debug_log("create_english_translation option is " . ($create_english ? 'true' : 'false'));
ai_debug_log("Checking WPML function in bulk mode: " . (function_exists('wpml_set_element_language_details') ? 'exists' : 'does not exist'));

if ($create_english && function_exists('wpml_set_element_language_details')) {
ai_debug_log("Attempting English translation for product ID {$post_id} (bulk mode).");
$english_title = ai_translate_title_to_english($product_title, $openai_api_key);
if (!$english_title) {
ai_debug_log("Failed to translate title to English for product ID {$post_id} (bulk). Skipping English version.");
continue;
}
ai_debug_log("English translated title for product ID {$post_id}: '{$english_title}'");

$english_full_desc = ai_generate_product_description_english($english_title, $openai_api_key);
if (!$english_full_desc) {
ai_debug_log("Failed to generate English full description for product ID {$post_id} (bulk). Skipping English version.");
continue;
}
ai_debug_log("English full description generated for product ID {$post_id}.");

$english_short_desc = ai_generate_short_description_english($english_title, $openai_api_key);
if (!$english_short_desc) {
ai_debug_log("Failed to generate English short description for product ID {$post_id} (bulk). Skipping English version.");
continue;
}
ai_debug_log("English short description generated for product ID {$post_id}.");

$new_post_id = wp_insert_post([
'post_type' => 'product',
'post_status' => 'publish',
'post_title' => $english_title,
'post_excerpt' => $english_short_desc,
'post_content' => $english_full_desc
]);
ai_debug_log("Attempting to create English product (bulk mode) for product ID {$post_id}. Result: " . (is_wp_error($new_post_id) ? "WP_Error" : $new_post_id));

if (!is_wp_error($new_post_id)) {
$original_language_info = apply_filters('wpml_post_language_details', null, $post_id);
ai_debug_log("Original language info for product ID {$post_id}: " . print_r($original_language_info, true));
if ($original_language_info && isset($original_language_info['trid'])) {
$trid = $original_language_info['trid'];
$english_code = 'en';

do_action('wpml_set_element_language_details', [
'element_id' => $new_post_id,
'element_type' => 'post_product',
'trid' => $trid,
'language_code' => $english_code,
'source_language_code' => $original_language_info['language_code']
]);
ai_debug_log("Linked English product ID {$new_post_id} to TRID {$trid} as English translation (bulk mode).");

if (function_exists('wc_delete_product_transients')) {
wc_delete_product_transients($new_post_id);
ai_debug_log("Cleared product transients for English product ID {$new_post_id} (bulk mode).");
}
} else {
ai_debug_log("No TRID found for product ID {$post_id} (bulk mode). Cannot link English translation.");
}
} else {
$error_msg = $new_post_id->get_error_message();
ai_debug_log("Failed to create English translation product for product ID {$post_id} (bulk): {$error_msg}");
ai_log_error_detailed('Failed to create English translation in bulk: ' . $error_msg, null, null, null);
}
}
}

wp_send_json_success([
'next_batch_index' => $batch_index + 1,
'processed' => $end - $start,
'remaining' => count($product_ids) - $end,
]);
}

/**
* PROMPTS & SETTINGS
*/
function ai_get_translation_prompt() {
return get_option('ai_translation_prompt', "Translate this product title into German. Retain proper names and commonly used English terms:nn{title}");
}

function ai_get_full_description_prompt() {
return get_option('ai_full_description_prompt', "Create a professional, detailed product description for: {title}");
}

function ai_get_short_description_prompt() {
return get_option('ai_short_description_prompt', "Create a short, concise summary for a product titled: {title}");
}

// English prompts
function ai_get_english_translation_prompt() {
return get_option('ai_english_translation_prompt', "Ensure this product title is properly expressed in English:nn{title}");
}

function ai_get_english_full_description_prompt() {
return get_option('ai_english_full_description_prompt', "Create a professional, detailed product description in English for: {title}");
}

function ai_get_english_short_description_prompt() {
return get_option('ai_english_short_description_prompt', "Create a short, concise English summary for a product titled: {title}");
}

// GERMAN
function ai_translate_title_to_german($product_title, $api_key) {
ai_debug_log("Sending request to translate title to German: '{$product_title}'");
$prompt_template = ai_get_translation_prompt();
$prompt = str_replace('{title}', $product_title, $prompt_template);
return ai_send_chat_request($api_key, $prompt, 'Translation (German)', 0.3, 100);
}

function ai_generate_product_description($translated_title, $api_key) {
ai_debug_log("Generating German full description for '{$translated_title}'");
$prompt_template = ai_get_full_description_prompt();
$prompt = str_replace('{title}', $translated_title, $prompt_template);
return ai_send_chat_request($api_key, $prompt, 'Full Description (German)', 0.7, 200);
}

function ai_generate_short_description($translated_title, $api_key) {
ai_debug_log("Generating German short description for '{$translated_title}'");
$prompt_template = ai_get_short_description_prompt();
$prompt = str_replace('{title}', $translated_title, $prompt_template);
return ai_send_chat_request($api_key, $prompt, 'Short Description (German)', 0.7, 50);
}

// ENGLISH
function ai_translate_title_to_english($product_title, $api_key) {
ai_debug_log("Sending request to translate title to English: '{$product_title}'");
$prompt_template = ai_get_english_translation_prompt();
$prompt = str_replace('{title}', $product_title, $prompt_template);
return ai_send_chat_request($api_key, $prompt, 'Translation (English)', 0.3, 100);
}

function ai_generate_product_description_english($english_title, $api_key) {
ai_debug_log("Generating English full description for '{$english_title}'");
$prompt_template = ai_get_english_full_description_prompt();
$prompt = str_replace('{title}', $english_title, $prompt_template);
return ai_send_chat_request($api_key, $prompt, 'Full Description (English)', 0.7, 200);
}

function ai_generate_short_description_english($english_title, $api_key) {
ai_debug_log("Generating English short description for '{$english_title}'");
$prompt_template = ai_get_english_short_description_prompt();
$prompt = str_replace('{title}', $english_title, $prompt_template);
return ai_send_chat_request($api_key, $prompt, 'Short Description (English)', 0.7, 50);
}

function ai_send_chat_request($api_key, $prompt, $stage, $temperature, $max_tokens) {
ai_debug_log("Sending API request: Stage={$stage}, Prompt='{$prompt}'");
$endpoint = 'hidden link';

$body = json_encode([
'model' => 'gpt-3.5-turbo',
'messages' => [
['role' => 'user', 'content' => $prompt]
],
'temperature' => $temperature,
'max_tokens' => $max_tokens,
]);

$response = wp_remote_post($endpoint, [
'headers' => [
'Content-Type' => 'application/json',
'Authorization' => 'Bearer ' . $api_key,
],
'body' => $body,
'timeout' => 30,
]);

return ai_handle_api_response($response, $stage);
}

function ai_handle_api_response($response, $stage) {
if (is_wp_error($response)) {
$error_message = 'HTTP request error during ' . $stage . ': ' . $response->get_error_message();
ai_debug_log($error_message);
ai_log_error_detailed($error_message, null, null, null);
return false;
}

$status_code = wp_remote_retrieve_response_code($response);
$raw_body = wp_remote_retrieve_body($response);
$response_body = json_decode($raw_body, true);

ai_debug_log("$stage API Response ($status_code): $raw_body");

if ($status_code = 300) {
$error_message = $stage . ' API returned HTTP ' . $status_code;
ai_debug_log($error_message);
ai_log_error_detailed($error_message, $status_code, $raw_body, $response_body);
return false;
}

if (empty($response_body['choices'][0]['message']['content'])) {
$error_message = 'No text returned by the API for ' . $stage;
ai_debug_log($error_message);
ai_log_error_detailed($error_message, $status_code, $raw_body, $response_body);
return false;
}

$result = trim($response_body['choices'][0]['message']['content']);
ai_debug_log("$stage API returned: '$result'");
return $result;
}

function ai_log_error_detailed($basic_message, $status_code, $raw_body, $response_body) {
$details = '';
if ($status_code) {
$details .= "HTTP Status: $status_coden";
}
if ($raw_body) {
$details .= "Raw Response: $raw_bodyn";
}
if ($response_body !== null) {
$details .= "Decoded Response: " . print_r($response_body, true) . "n";
}

$full_message = $basic_message . "n" . $details;
update_option('ai_product_last_error', $full_message);
ai_debug_log("ERROR: $full_message");
error_log('AI Product Auto-Description Detailed Error: ' . $full_message);
}

function ai_show_error_notice() {
$error = get_option('ai_product_last_error');
if ($error) {
echo '

AI Product Auto-Description Error: ' . esc_html($error) . '

';
delete_option('ai_product_last_error');
}
}

/**
* SETTINGS PAGE
*/
function ai_register_settings_page() {
add_options_page(
'AI Product Auto-Description',
'AI Product Auto-Description',
'manage_options',
'ai-product-auto-description',
'ai_settings_page_html'
);
}

function ai_register_settings() {
register_setting('ai_auto_description_options', 'ai_translation_prompt');
register_setting('ai_auto_description_options', 'ai_full_description_prompt');
register_setting('ai_auto_description_options', 'ai_short_description_prompt');

register_setting('ai_auto_description_options', 'ai_english_translation_prompt');
register_setting('ai_auto_description_options', 'ai_english_full_description_prompt');
register_setting('ai_auto_description_options', 'ai_english_short_description_prompt');

register_setting('ai_auto_description_options', 'ai_create_english_translation'); // boolean
register_setting('ai_auto_description_options', 'ai_product_debug_logs'); // logs storage

add_settings_section(
'ai_prompts_section',
'AI Prompts',
'ai_prompts_section_cb',
'ai-product-auto-description'
);

add_settings_field(
'ai_translation_prompt_field',
'German Translation Prompt',
'ai_translation_prompt_cb',
'ai-product-auto-description',
'ai_prompts_section'
);

add_settings_field(
'ai_full_description_prompt_field',
'German Full Description Prompt',
'ai_full_description_prompt_cb',
'ai-product-auto-description',
'ai_prompts_section'
);

add_settings_field(
'ai_short_description_prompt_field',
'German Short Description Prompt',
'ai_short_description_prompt_cb',
'ai-product-auto-description',
'ai_prompts_section'
);

add_settings_field(
'ai_english_translation_prompt_field',
'English Translation Prompt',
'ai_english_translation_prompt_cb',
'ai-product-auto-description',
'ai_prompts_section'
);

add_settings_field(
'ai_english_full_description_prompt_field',
'English Full Description Prompt',
'ai_english_full_description_prompt_cb',
'ai-product-auto-description',
'ai_prompts_section'
);

add_settings_field(
'ai_english_short_description_prompt_field',
'English Short Description Prompt',
'ai_english_short_description_prompt_cb',
'ai-product-auto-description',
'ai_prompts_section'
);

add_settings_field(
'ai_create_english_translation_field',
'Create English Translation (via WPML)',
'ai_create_english_translation_cb',
'ai-product-auto-description',
'ai_prompts_section'
);

add_settings_section(
'ai_logs_section',
'Debug Logs',
'ai_logs_section_cb',
'ai-product-auto-description'
);

add_settings_field(
'ai_debug_logs_field',
'Logs',
'ai_debug_logs_cb',
'ai-product-auto-description',
'ai_logs_section'
);
}

function ai_prompts_section_cb() {
echo '

Configure the prompts used for translation and description. Use

{title}

as a placeholder for the product title.

';
}

function ai_translation_prompt_cb() {
$value = get_option('ai_translation_prompt', "Translate this product title into German. Retain proper names and commonly used English terms:nn{title}");
echo '';
}

function ai_full_description_prompt_cb() {
$value = get_option('ai_full_description_prompt', "Create a professional, detailed product description for: {title}");
echo '';
}

function ai_short_description_prompt_cb() {
$value = get_option('ai_short_description_prompt', "Create a short, concise summary for a product titled: {title}");
echo '';
}

function ai_english_translation_prompt_cb() {
$value = get_option('ai_english_translation_prompt', "Ensure this product title is properly expressed in English:nn{title}");
echo '';
}

function ai_english_full_description_prompt_cb() {
$value = get_option('ai_english_full_description_prompt', "Create a professional, detailed product description in English for: {title}");
echo '';
}

function ai_english_short_description_prompt_cb() {
$value = get_option('ai_english_short_description_prompt', "Create a short, concise English summary for a product titled: {title}");
echo '';
}

function ai_create_english_translation_cb() {
$value = get_option('ai_create_english_translation', false);
echo ' Enable creating English translations via WPML';
}

function ai_logs_section_cb() {
echo '

Below are the debug logs for the plugin. You can review them for troubleshooting. Click "Clear Logs" to remove all entries.

';
}

function ai_debug_logs_cb() {
$logs = get_option('ai_product_debug_logs', []);
if (!is_array($logs)) {
$logs = [];
}

echo '';
echo '

';
echo '';
}

function ai_settings_page_html() {
if (!current_user_can('manage_options')) {
return;
}

// Handle clear logs action
if (isset($_POST['ai_clear_logs'])) {
ai_clear_logs();
echo '

Logs cleared.

';
}

echo '

';
echo '

AI Product Auto-Description Settings

';
echo '';
settings_fields('ai_auto_description_options');
do_settings_sections('ai-product-auto-description');
submit_button();
echo '';
echo '

';
}

/**
* FRONTEND JS FOR BATCH PROCESSING (js/ai-batch-edit.js)
*
* Make sure you create a js directory in your plugin folder and place the below JS code in a file named ai-batch-edit.js:
*
* jQuery(document).ready(function ($) {
* let batchIndex = 0;
* const batchSize = 10;
* const productIds = aiBatchEdit.product_ids;
* const totalProducts = productIds.length;
*
* function processBatch() {
* if (batchIndex * batchSize >= totalProducts) {
* $('#batch-progress').text('All products processed!');
* return;
* }
*
* $.ajax({
* url: aiBatchEdit.ajax_url,
* method: 'POST',
* data: {
* action: 'process_ai_product_batch',
* security: aiBatchEdit.nonce,
* product_ids: productIds,
* batch_index: batchIndex,
* },
* success: function (response) {
* if (response.success) {
* batchIndex = response.data.next_batch_index;
* const remaining = response.data.remaining;
* const processed = totalProducts - remaining;
* $('#batch-progress').text(`Processed: ${processed}/${totalProducts}. Remaining: ${remaining}.`);
* processBatch(); // Continue with next batch
* } else {
* $('#batch-progress').text('Error: ' + response.data);
* }
* },
* error: function (xhr, status, error) {
* $('#batch-progress').text('An error occurred: ' + error);
* },
* });
* }
*
* $('#start-batch-processing').on('click', function () {
* $('#batch-progress').text('Starting batch processing...');
* processBatch();
* });
* });
*/
With this code, the hooks are registered after plugins_loaded with a priority of 20, ensuring WPML has had a chance to load first. The logs will tell you if the WPML function is available at that point. If the function still does not exist, then WPML is likely not active or not loading correctly before the plugin runs.

Symptoms:
The issue is that WPML does not seem to load. The logs repeatedly show that the WPML function 'wpml_set_element_language_details' does not exist at the 'plugins_loaded' action.

log: [2024-12-17 23:50:35] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:35] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:43] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:43] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:44] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:44] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:46] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:46] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:48] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:48] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:49] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:49] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:50] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:50] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:54] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:54] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:56] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:56] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:58] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:58] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:50:58] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:50:58] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:02] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:02] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:05] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:05] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:14] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:14] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:20] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:20] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:21] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:21] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:22] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:22] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:23] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:23] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:26] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:26] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:26] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:26] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:32] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:32] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:32] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:32] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:35] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:35] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:36] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:36] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:39] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:39] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:44] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:44] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:45] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:45] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:47] transition_post_status triggered for post ID 1228454, new_status=draft, old_status=new
[2024-12-17 23:51:49] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:49] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:49] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:49] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:51:58] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:51:58] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:00] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:00] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:11] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:11] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:14] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:14] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:30] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:30] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:33] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:33] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:37] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:37] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:38] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:38] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:40] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:40] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.
[2024-12-17 23:52:42] transition_post_status triggered for post ID 1228485, new_status=publish, old_status=new
[2024-12-17 23:52:42] transition_post_status triggered for post ID 1228486, new_status=publish, old_status=new
[2024-12-17 23:52:43] transition_post_status triggered for post ID 1228487, new_status=publish, old_status=new
[2024-12-17 23:52:44] transition_post_status triggered for post ID 1228454, new_status=publish, old_status=draft
[2024-12-17 23:52:44] New product published: ID=1228454, title='High Quality Aoyagi Toya Shinonome Akito Cosplay Wig Heat Resistant Hair Vivid BAD SQUAD Halloween Men Anime Wigs + Wig Cap'
[2024-12-17 23:52:44] Starting German translation and content generation for product ID 1228454...
[2024-12-17 23:52:44] Sending request to translate title to German: 'High Quality Aoyagi Toya Shinonome Akito Cosplay Wig Heat Resistant Hair Vivid BAD SQUAD Halloween Men Anime Wigs + Wig Cap'
[2024-12-17 23:52:44] Sending API request: Stage=Translation (German), Prompt='Translate this product title to German, only return the translation. if some english words are usually used in German, keep them in english (For example "wig" can also be used in German, but also add "Perücke").
Make it a bit shorter by removing words that are mentioned multiple times, and also remove obscene words: ({name}).

And make it a bit shorter in general
High Quality Aoyagi Toya Shinonome Akito Cosplay Wig Heat Resistant Hair Vivid BAD SQUAD Halloween Men Anime Wigs + Wig Cap'
[2024-12-17 23:52:45] Translation (German) API Response (200): {
"id": "chatcmpl-AfbemlIhZnqp5KKPqpgoWuI2N1z4p",
"object": "chat.completion",
"created": 1734479564,
"model": "gpt-3.5-turbo-0125",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hochwertige Aoyagi Toya Shinonome Akito Cosplay Perücke hitzebeständiges Haar lebendige BAD SQUAD Halloween Männer Anime Perücken + Perückenmütze",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 121,
"completion_tokens": 45,
"total_tokens": 166,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"system_fingerprint": null
}

[2024-12-17 23:52:45] Translation (German) API returned: 'Hochwertige Aoyagi Toya Shinonome Akito Cosplay Perücke hitzebeständiges Haar lebendige BAD SQUAD Halloween Männer Anime Perücken + Perückenmütze'
[2024-12-17 23:52:45] German translated title: 'Hochwertige Aoyagi Toya Shinonome Akito Cosplay Perücke hitzebeständiges Haar lebendige BAD SQUAD Halloween Männer Anime Perücken + Perückenmütze'
[2024-12-17 23:52:45] Generating German full description for 'Hochwertige Aoyagi Toya Shinonome Akito Cosplay Perücke hitzebeständiges Haar lebendige BAD SQUAD Halloween Männer Anime Perücken + Perückenmütze'
[2024-12-17 23:52:45] Sending API request: Stage=Full Description (German), Prompt='You are Anna from the cosplay store CosplayHero. Write a long description with multiple paragraphs . Keep it in informal German language. Tell the reader in the end to buy the product from us: Hochwertige Aoyagi Toya Shinonome Akito Cosplay Perücke hitzebeständiges Haar lebendige BAD SQUAD Halloween Männer Anime Perücken + Perückenmütze'
[2024-12-17 23:52:47] Full Description (German) API Response (200): {
"id": "chatcmpl-AfbeoZESZIJrS3KtsAzuSVOEdLrdx",
"object": "chat.completion",
"created": 1734479566,
"model": "gpt-3.5-turbo-0125",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Hey Leute! Ich bin Anna von CosplayHero und ich bin hier, um euch die ultimative Aoyagi Toya Shinonome Akito Cosplay Perücke vorzustellen! Diese Perücke ist perfekt für alle Fans von BAD SQUAD und Anime im Allgemeinen. nnDie Perücke besteht aus hitzebeständigem Haar, was bedeutet, dass ihr sie nach euren Wünschen stylen könnt, ohne dass sie beschädigt wird. Das bedeutet, dass ihr euren Look immer wieder verändern könnt, um euer Cosplay zu perfektionieren. Außerdem ist das Haar super lebendig und sieht genauso aus wie im Anime, also könnt ihr sicher sein, dass euer Cosplay super authentisch aussieht.nnDie Perücke wird mit einer Perückenmütze geliefert, um sicherzustellen, dass sie perf",
"refusal": null
},
"logprobs": null,
"finish_reason": "length"
}
],
"usage": {
"prompt_tokens": 93,
"completion_tokens": 200,
"total_tokens": 293,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"system_fingerprint": null
}

[2024-12-17 23:52:47] Full Description (German) API returned: 'Hey Leute! Ich bin Anna von CosplayHero und ich bin hier, um euch die ultimative Aoyagi Toya Shinonome Akito Cosplay Perücke vorzustellen! Diese Perücke ist perfekt für alle Fans von BAD SQUAD und Anime im Allgemeinen.

Die Perücke besteht aus hitzebeständigem Haar, was bedeutet, dass ihr sie nach euren Wünschen stylen könnt, ohne dass sie beschädigt wird. Das bedeutet, dass ihr euren Look immer wieder verändern könnt, um euer Cosplay zu perfektionieren. Außerdem ist das Haar super lebendig und sieht genauso aus wie im Anime, also könnt ihr sicher sein, dass euer Cosplay super authentisch aussieht.

Die Perücke wird mit einer Perückenmütze geliefert, um sicherzustellen, dass sie perf'
[2024-12-17 23:52:47] German full description generated.
[2024-12-17 23:52:47] Generating German short description for 'Hochwertige Aoyagi Toya Shinonome Akito Cosplay Perücke hitzebeständiges Haar lebendige BAD SQUAD Halloween Männer Anime Perücken + Perückenmütze'
[2024-12-17 23:52:48] Sending API request: Stage=Short Description (German), Prompt='Generate a short and catchy description for the following product in informal German language in one sentence. It is a : Hochwertige Aoyagi Toya Shinonome Akito Cosplay Perücke hitzebeständiges Haar lebendige BAD SQUAD Halloween Männer Anime Perücken + Perückenmütze'
[2024-12-17 23:52:48] Short Description (German) API Response (200): {
"id": "chatcmpl-AfbeqazjQaFGMXSMLUtS2HBKs94yM",
"object": "chat.completion",
"created": 1734479568,
"model": "gpt-3.5-turbo-0125",
"choices": [
{
"index": 0,
"message": {
"role": "assistant",
"content": "Verwandle dich mit dieser hochwertigen, hitzebeständigen Aoyagi Toya Shinonome Akito Cosplay Perücke in einen lebendigen BAD SQUAD Halloween Anime Mann!",
"refusal": null
},
"logprobs": null,
"finish_reason": "stop"
}
],
"usage": {
"prompt_tokens": 73,
"completion_tokens": 44,
"total_tokens": 117,
"prompt_tokens_details": {
"cached_tokens": 0,
"audio_tokens": 0
},
"completion_tokens_details": {
"reasoning_tokens": 0,
"audio_tokens": 0,
"accepted_prediction_tokens": 0,
"rejected_prediction_tokens": 0
}
},
"system_fingerprint": null
}

[2024-12-17 23:52:48] Short Description (German) API returned: 'Verwandle dich mit dieser hochwertigen, hitzebeständigen Aoyagi Toya Shinonome Akito Cosplay Perücke in einen lebendigen BAD SQUAD Halloween Anime Mann!'
[2024-12-17 23:52:48] German short description generated.
[2024-12-17 23:52:48] transition_post_status triggered for post ID 1228454, new_status=publish, old_status=publish
[2024-12-17 23:52:49] Successfully updated product ID 1228454 with German content.
[2024-12-17 23:52:49] Cleared product transients for product ID 1228454.
[2024-12-17 23:52:49] Option 'create_english_translation' is set to true
[2024-12-17 23:52:49] Checking WPML function: does not exist
[2024-12-17 23:52:50] plugins_loaded action triggered, checking WPML...
[2024-12-17 23:52:50] WPML function 'wpml_set_element_language_details' does not exist at plugins_loaded.

Questions:
Why is the WPML function 'wpml_set_element_language_details' not available at 'plugins_loaded'?
How can I ensure that WPML loads correctly before my plugin?

December 18, 2024 at 5:02 am #16524063

Shekhar Bhandari
WPML Supporter since 03/2015

Languages: English (English )

Timezone: Asia/Kathmandu (GMT+05:45)

Hello,

Thank you for reaching out to WPML support. I’m here to assist you with this issue.

I reviewed the hook example provided in the documentation here: https://wpml.org/wpml-hook/wpml_set_element_language_details/. I used the code provided, modified the action to `plugin_loaded`, and found it works without any issues when implemented within a custom plugin.

Additionally, to ensure functions related to WPML load correctly, you might want to check if the plugin is active before proceeding.

Please note that, according to our support policy, we’re unable to assist with custom programming and debugging. However, based on my test, the code from the documentation appears to work with the action you mentioned. I recommend trying the documented code to see if it resolves your issue.

If you require further custom debugging assistance, I suggest reaching out to one of our certified partners listed here: http://wpml.org/documentation/support/wpml-contractors/. Before contacting them, please review these guidelines to ensure you get the best support: http://wpml.org/documentation/support/wpml-contractors/guidelines-for-people-looking-for-consulting-help/.

This should help you get the custom assistance needed to move forward with your project.

Thank you.

The topic ‘[Closed] not loaded’ is closed to new replies.