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
- 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 8:00 – 12:00 -
- 12:00 – 16:00 12:00 – 16:00 12:00 – 16:00 12:00 – 16:00 12:00 – 16:00 -

Supporter timezone: Europe/Zagreb (GMT+01:00)

Tagged: 

This topic contains 9 replies, has 1 voice.

Last updated by Dražen 1 day, 4 hours ago.

Assisted by: Dražen.

Author Posts
February 21, 2025 at 1:06 pm #16733687

dmytroZ-5

Background of the issue:
I am trying to attach translated taxonomies to posts in different languages using WPML. I used the following code:

 $post_id = 1252; //main post $trid = wpml_get_content_trid( 'post_docs', $post_id ); $default_post_categories = wp_get_post_terms( $post_id, 'doc_category' ); $languages = ['de', 'ru', 'uk']; foreach ( $languages as $lang ) { $translated_post_id = wp_insert_post( [ 'post_title' => 'title', 'post_content' => 'content', 'post_status' => 'publish', 'post_type' => 'docs', ] ); if ( ! is_wp_error( $translated_post_id ) ) { do_action( 'wpml_set_element_language', 'post_docs', $translated_post_id, $lang ); do_action( 'wpml_set_element_language_details', [ 'element_id' => $translated_post_id, 'element_type' => 'post_docs', 'trid' => $trid, 'language_code' => $lang ] ); if ( ! empty( $default_post_categories ) ) { foreach ( $default_post_categories as $term ) { $object_id = apply_filters( 'wpml_object_id', $term->term_id, 'doc_category', false, $lang ); if ( $object_id ) { wp_set_post_terms( $translated_post_id, [ $object_id ], 'doc_category' ); } } } } } 

Link to a page where the issue can be seen:

Symptoms:
When a taxonomy is attached to a post in a non-default language, the taxonomy of the default language is attached instead. This happens for both custom and default taxonomies and posts. All IDs are returned correctly, but the wrong category is attached as a result. The issue seems to occur in the wp_set_post_terms() call.

Questions:
Why is the wrong category being attached to translated posts?
How can I ensure the translated category is attached instead of the main language category?

February 24, 2025 at 2:13 pm #16741507

dmytroZ-5
{
    /** main post id*/
    $post_id;

    $trid = wpml_get_content_trid( 'post_docs', $post_id );
    $default_post_categories = wp_get_post_terms( $post_id, 'doc_category' );
    $languages = [ 'de', 'ru', 'uk' ];
    foreach ( $languages as $lang ) {
        $translated_post_id = wp_insert_post( [
            'post_title'   => 'title',
            'post_content' => 'content',
            'post_status'  => 'publish',
            'post_type'    => 'docs',
        ] );
        if ( ! is_wp_error( $translated_post_id ) ) {
            do_action( 'wpml_set_element_language', 'post_docs', $translated_post_id, $lang );
            do_action( 'wpml_set_element_language_details', [
                'element_id'    => $translated_post_id,
                'element_type'  => 'post_docs',
                'trid'          => $trid,
                'language_code' => $lang
            ] );
            if ( ! empty( $default_post_categories ) ) {
                foreach ( $default_post_categories as $term ) {
                    $object_id = apply_filters( 'wpml_object_id', $term->term_id, 'doc_category', false, $lang );
                    if ( $object_id ) {
                        wp_set_post_terms( $translated_post_id, [ $object_id ], 'doc_category' );
                    }
                }
            }
        }
    }
}
February 26, 2025 at 8:42 am #16749661

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+01:00)

Hello,

thanks for contacting us.

Please note as per our policy we can not debug or provide custom code solutions, for that I advise using WPML contractor's service: https://wpml.org/contractors/

I can advise what would be the correct way to do this. Looking at your code, your approach is mostly correct, but there are a few potential issues that might be causing it not to work as expected.

1) The function wpml_get_content_trid() is not a native WPML function.
Instead, use apply_filters wpml_element_trid

2)
wpml_set_element_language should not be used.
wpml_set_element_language_details is correct

3)
apply_filters( 'wpml_object_id', $term->term_id, 'doc_category', false, $lang ) might return NULL if the translation does not exist.
Ensure that wpml_object_id is returning valid term IDs.

If you need further help, as said best would be to hire WPML contractors. If you have doubts or questions about our hooks, let me know and I would be glad to help.

Regards,
Drazen

February 26, 2025 at 9:48 am #16750031

dmytroZ-5

Thanks for the advice, but I gave this code as an example.
My code works as expected.

The problem is in wp_set_post_terms(). It assigns the wrong term.
For the sake of experimentation, I did this separately from my code.
I found the necessary ids in the database and inserted them directly into the code.
In result wp_set_post_terms() function assigned a term of the default language.
I did this not only for "doc_category" but also for regular posts and the default WordPress "category."
The result is the same, the default language "category" is assigned.
E.g.

{
    //default lang in system is 'en'

    $default_lang_term_id = 48; //ID of the category of default language (language 'en')
    $default_lang_post_id = 4418; //Post ID of default language (post type 'post', language 'en')

    $translated_term_id = 85;  //ID of the of translated category (language 'de')
    $translated_post_id = 4568; //Post ID of translated post (post type 'post', language 'de')
    wp_set_post_terms( $translated_post_id, [ $translated_term_id ], 'category' );

    //in result: post with ID: 4568 has attached category with ID: 48 (expected ID: 85)
}
February 26, 2025 at 9:58 am #16750061

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+01:00)

Hello,

thanks for getting back.

We can take a look if you think this is a WPML bug and advise on the correct approach, I have created a test site.

Please try to show us an issue with a simple example code for WP posts and share steps on what you did. Please do not add any additional extra code, plugins, or themes.

- hidden link

Regards,
Drazen

February 27, 2025 at 2:28 pm #16756697

dmytroZ-5

Hello
I added custom plugin (Test WPML) to demonstrate

Plugin page: hidden link

On this page we need to add to input "Post ID" a value of post to translate. In our case we can use: 1. Then click process.

This starts a cron task (or rather an "action-scheduler" task)

You can see when it will be executed on the page: hidden link

Here will be a task with hook: "translate_post_and_add_category". You have to wait for task to complete.

Next, go to the page hidden link and a translation in Spanish should appear there.

As a result, the Spanish post has the wrong category (category of the main post)

February 28, 2025 at 7:14 am #16759061

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+01:00)

Hello,

Thanks for getting back to me. I checked your code and found the problem, adjusted the code and it seems to work fine now.

- Use apply_filters( 'wpml_object_id', term_id, 'category', true, 'es' ) instead of false to ensure WPML returns a valid translation.

This is the correct code:

function translate_process_shedule_task( $post_id ) {
    $post = get_post( $post_id );

    if ( empty( $post ) || is_wp_error( $post ) || $post->post_type !== 'post' ) {
        throw new Exception( $post_id . ' post not found' );
    }

    $translated_post_id = apply_filters( 'wpml_object_id', $post_id, 'post', false, 'es' );

    if ( ! $translated_post_id ) {
        $args = [
            'post_title'   => $post->post_title . ' - translated',
            'post_content' => $post->post_content,
            'post_status'  => 'publish',
            'post_type'    => $post->post_type,
        ];

        $new_post_id = wp_insert_post( $args );

        if ( $new_post_id ) {
            $default_post_categories = wp_get_post_terms( $post_id, 'category' );

            do_action( 'wpml_set_element_language_details', [
                'element_id'    => $new_post_id,
                'element_type'  => 'post_' . $post->post_type,
                'trid'          => apply_filters( 'wpml_element_trid', null, $post_id, 'post_' . $post->post_type ),
                'language_code' => 'es',
            ] );

            $translated_term_ids = [];
            foreach ( $default_post_categories as $term ) {
                // Get the translated category ID
                $translated_term_id = apply_filters( 'wpml_object_id', $term->term_id, 'category', true, 'es' );

                if ( $translated_term_id ) {
                    $translated_term_ids[] = $translated_term_id;
                } else {
                    error_log( "No translated category found for term ID: " . $term->term_id );
                }
            }

            if ( !empty( $translated_term_ids ) ) {
                wp_set_post_terms( $new_post_id, $translated_term_ids, 'category' );
            } else {
                error_log( "No translated categories were set for post ID: $new_post_id" );
            }
        }
    }
}

Regards,
Drazen

February 28, 2025 at 9:36 am #16759761

dmytroZ-5

Hello.
The problem remains.
I deleted the translated post and did it again.
As you can see, there is an incorrect category. I don't even see it in the list of categories.

I don't think that true and false affect this.

THIS is:
$return_original_if_missing
(bool) (Optional) If set to true it will always return a value (the original value, if translation is missing) Default is FALSE.

I need to use false to check if there is a translated category or not.

I checked, all ids are returned correctly. Even if you do it with a hardcode, it will still be incorrect.

This is a bug. And it only appears if it is launched in the action-scheduler (on background).

Please, try again and wait for the task to be executed automatically.

Selection_384.png
Selection_383.png
February 28, 2025 at 10:13 am #16760135

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+01:00)

Hello,

thanks for explanation, I did not wait for it to finish automatically.

I have now escalated this to our 2nd tier to check and advise further.

I will update you when I have some news.

Regards,
Drazen

March 3, 2025 at 7:27 am #16767009

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+01:00)

Hello,

Our 2nd tier checked and got back with the following conclusion and suggestion:

The problem is in \WPML_Term_Adjust_Id::filter in wp-content/plugins/sitepress-multilingual-cms/classes/query-filtering/class-wpml-term-adjust-id.php
This adjusts the term to the default language or if a cookie is set to that cookie language.

Fortunately, we can remove the filter prior to setting the term, which should fix the problem:

add_filter( 'wpml_disable_term_adjust_id', '__return_true' );
  	wp_set_post_terms( $new_post_id, $translated_term_ids, 'category' );
    remove_filter( 'wpml_disable_term_adjust_id', '__return_true' )

Please try and let me know how it goes.

Regards,
Drazen