How to Automatically Connect WPML Translations Across Multiple Languages in WordPress

connect wpml translations
Milos Lukic

When managing multilingual content in WordPress with WPML, connecting translations manually can be tedious, especially for large-scale sites. In this guide, we’ll show you how to automatically link translations across multiple languages using a custom PHP function.

Why Automate Translation Connections?

WPML manages translations using a trid (Translation Group ID), which links different language versions of a post. Manually setting these connections through the WPML interface can be time-consuming. Automating this process allows for:

  • Faster translation linking
  • Consistency across translations
  • Reduced manual errors

The Custom PHP Function

Below is a PHP function that connects translations automatically by modifying the WPML translations table.

function connect_translations_multiple_languages($original_post_ids, $translations_by_language, $default_language = 'it') {
    global $wpdb;

    // Get the correct table name with prefix
    $translations_table = $wpdb->prefix . 'icl_translations';
    
    $total_updated_count = 0; // Tracks total updates across all languages
    $debug_log = []; // Tracks debug information

    foreach ($translations_by_language as $language_code => $translated_post_ids) {
        $updated_count = 0; // Tracks updates for the current language

        foreach ($original_post_ids as $index => $original_post_id) {
            $translated_post_id = $translated_post_ids[$index] ?? null;

            // Skip if there is no translated post for this index/language
            if (!$translated_post_id) {
                continue;
            }

            // Fetch the translation group ID (`trid`) for the original post
            $trid = $wpdb->get_var(
                $wpdb->prepare(
                    "SELECT trid FROM {$translations_table} WHERE element_id = %d AND language_code = %s AND element_type = %s",
                    $original_post_id,
                    $default_language,
                    'post_s'
                )
            );

            // Log debug info
            $debug_log[$language_code][] = [
                'original_post_id' => $original_post_id,
                'translated_post_id' => $translated_post_id,
                'trid' => $trid ? $trid : 'NOT_FOUND',
            ];

            // Skip if no `trid` found
            if (!$trid) {
                continue;
            }

            // Add or update the `wp_icl_translations` table for the translated post
            $wpdb->replace(
                $translations_table,
                array(
                    'element_id'   => $translated_post_id,
                    'element_type' => 'post_s',
                    'trid'         => $trid,
                    'language_code' => $language_code,
                    'source_language_code' => $default_language,
                ),
                array(
                    '%d', '%s', '%d', '%s', '%s'
                )
            );

            // Update post meta for the translated post
            update_post_meta($translated_post_id, '_wpml_import_language_code', $language_code);
            update_post_meta($translated_post_id, '_wpml_import_source_language_code', $default_language);
            update_post_meta($translated_post_id, '_wpml_import_translation_group', $original_post_id);

            // Increment counters
            $updated_count++;
        }

        // Log the number of items updated for this language
        $total_updated_count += $updated_count;
    }

    // Return details and debug info
    $debug_message = '<br><strong>Debug Info:</strong><pre>' . print_r($debug_log, true) . '</pre>';
    return "Translations connected successfully. {$total_updated_count} items were updated in total." . $debug_message;
}

How It Works

  1. Retrieve Translation Group ID: The function fetches the trid from the wp_icl_translations table for the original post in the default language.
  2. Loop Through Translations: It iterates over the provided translations, linking them to the same trid.
  3. Update Database and Metadata:
    • It inserts or updates the translation record in wp_icl_translations.
    • It adds metadata for tracking translation assignments.

Example Usage

To execute the function automatically, you can hook it into WordPress using admin_init:

add_action('admin_init', function () {
    $original_post_ids = [11313, 11333]; // Original post IDs in the default language

    // Translations for multiple languages
    $translations_by_language = [
        'en' => [11404, 11405], // Translations for English
        'fr' => [11500, 11501], // Translations for French
        'de' => [11600, 11601] // Translations for German
    ];

    $result = connect_translations_multiple_languages($original_post_ids, $translations_by_language);

    // Show result as admin notice
    add_action('admin_notices', function () use ($result) {
        echo '<div class="notice notice-success"><p>' . $result . '</p></div>';
    });
});

Breakdown of the Hook:

  • admin_init: Runs when an admin page loads, ensuring the function executes only in the backend.
  • admin_notices: Displays a success message in the WordPress admin panel.

Conclusion

By using this approach, you can automate the process of connecting WPML translations across multiple languages, saving time and reducing errors. Whether you’re managing a multilingual blog, e-commerce store, or corporate website, this method ensures that all translations remain properly linked within WPML.

For further customization, you can modify the function to work with custom post types, WooCommerce products, or other WPML-compatible elements.