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
- - 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00 9:00 – 18:00
- - - - - - -

Supporter timezone: America/Lima (GMT-05:00)

Tagged: 

This topic contains 19 replies, has 2 voices.

Last updated by Andreas W. 4 months, 2 weeks ago.

Assisted by: Andreas W..

Author Posts
February 7, 2025 at 11:14 am #16679232

lorenzP

Please stop sending my AI generated answers. This does not help at all. The answers are just wrong...

February 7, 2025 at 4:47 pm #16680669

Andreas W.
WPML Supporter since 12/2018

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

We ran a quick test and could not confirm an issue in a minimal setup:
hidden link

Your code works as expected here without any workaround.

---

Now, I saw you reported this issue earlier, and we have a couple of open tickets on development about this issue, which are still not solved and this is why I tried to provide a possible workaround.

My previous answer truly was not AI-generated and I have today verified the provided workaround with one of our compatibility developers, who suggested a slight change:

// Use the wpml_current_language hook to get the current language
$current_language = apply_filters( 'wpml_current_language', NULL );

// Get the permalink for a specific post in default language (replace with your post ID)
$default_language = apply_filters( 'wpml_default_language', NULL );
do_action( 'wpml_switch_language', $default_language );
$post_permalink = get_permalink( $post_id );
  
// Get the post ID from the URL (this works for the default language, based on permalink)
$post_id_in_default_language = url_to_post_id( $post_permalink );
  
// Use WPML's filter to get the translated post ID in the current language
do_action( 'wpml_switch_language', $current_language );
$translated_post_id = apply_filters( 'wpml_object_id', $post_id_in_default_language );
  
// $translated_post_id now contains the post ID for the current language
echo $translated_post_id;

---

If it works on the production site and not on the staging then this would mean both sites are not identical. Revise installed theme and plugins and their versions. Make sure that staging and production use the same custom code.

If you would like me to take a look at the staging, let me know.

---

Also, I would like to invite you to, please log into the following test site and recreate the issue, so that we can take a closer look at your code and try to find a solution:

One-Click-Login:
hidden link

February 10, 2025 at 3:31 pm #16688427

lorenzP

The code you provided assumes we know the post ID already (calls get_permalink()) but we don’t know the post ID that’s why we are using the url_to_postid() WordPress API to convert a URL to a post ID.

Last week I debugged the WPML plugin’s source code for more than 4 hours to understand what’s going wrong. The WPML hook handles language switching, URL parameter stripping and lots of other things. I found the following code was failing and a failsafe code gets executed which returns the 0 result:

In classes/query-filtering/class-wpml-get-page-by-path.php the WPML_Get_Page_By_Path::get() method uses get_page_by_path() internally and returns no WP_Post value in our case. This method gets called with $post_name as parameter but does not get the full path of the page which is in our case a child page.

In our production environment we get the correct post ID but in our staging environment this failed to work about three weeks ago.

In order to be able to launch our new website ASAP, we added a workaround which uses get_page_by_path() in cases where url_to_postid() returns 0. This works fine for now without having a fix yet for the root cause.

We also extended the test page to show the APIs we call:

hidden link

To further analyze this issue we can get you access to our staging environment or duplicate it on one of your servers as we have done before. I guess this issue is related to the database and therefore not easy to reproduce on a fresh WordPress instance.

February 11, 2025 at 8:12 am #16690218

Andreas W.
WPML Supporter since 12/2018

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

To report a bug in WPML and for further escalation I would like to invite you to, please log into the following test site and recreate the issue, so that we can take a closer look at your code and take further steps:

One-Click-Login:
hidden link

February 14, 2025 at 4:43 pm #16707520

lorenzP

I have a Duplicator backup I can upload to a server. It is important we upload the full database to showcase this error. We cloned our WordPress instance before for other WPML tickets. Can we do this again?

February 14, 2025 at 8:23 pm #16708015

Andreas W.
WPML Supporter since 12/2018

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

Hello,

I would like to offer to take a closer look and request temporary access (wp-admin and FTP) to the site to investigate the issue further.

The required fields are below the comment section when you log in to leave the next reply. The information you provide is private, meaning only you and I can see and access it.

IMPORTANT
Please be sure to back up the site and database before granting us access.

If you can't see the "wp-admin / FTP" fields, your post and site login details will be set to "PUBLIC". DO NOT publish the data unless you see the required wp-admin / FTP fields.

I may need to install a plugin called "All In One WP Migration" here to create a copy of the site that I can use to investigate the issue further.

However, I would also be very grateful if you could provide a staging site or copy of the website from your server for this purpose.

If you have any questions about creating such a staging site, you can consult your hosting provider. Please note that WPML must also be registered on this staging site at https://wpml.org/de/account/websites/.

If you are not able to provide such a copy of the website for testing, please let me know on this ticket.

The private reply form looks like this:
hidden link

The next time you reply, click on "I still need assistance".

Video:
hidden link

Please note that we are obliged to request this information individually on each ticket. We are not allowed to access any credentials that were not specifically submitted on this ticket in the private response form.

Best regards
Andreas

February 21, 2025 at 6:15 pm #16734920

Andreas W.
WPML Supporter since 12/2018

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

My apologies, but I asked you to simply recreate the issue on a test site which I provided.

You are using custom code, which is something that generally is not something that we support. We can guide you on using custom code but we do not debug such code. Our support team is not obligated to do this and I am assisting you on this matter on a voluntary base.

Further, you are asking me to take a local copy of a site that already is a staging site.
This all takes a lot of time and simply recreating your coding approach on our test site would be way more time effective.

Besides, according to what I see here, this is currently working as expected with the exception of page_by_path:
hidden link

This function will be default always get the path in the site's default language.

To get page_by_path you will need to use WPML's dedicated hook to switch the language, after getting the current language and check for all active languages.

Example:

if (ap_starts_with($permalink, $base_url)) {
    $path = substr($permalink, strlen($base_url));
    $pos = strpos($path, '?');

    // Clean up path by removing query string
    if ($pos !== false) {
        $path = substr($path, 0, $pos);
    }

    // Get the current language and all active languages
    $current_language = apply_filters('wpml_current_language', NULL);
    $languages = apply_filters('wpml_active_languages', NULL, 'orderby=id&order=asc'); // Fetch all active languages

    // Check if there is a second language available
    $second_language = '';
    foreach ($languages as $lang) {
        if ($lang['code'] !== $current_language) {
            $second_language = $lang['code']; // Set second language
            break; // Break after finding the second language
        }
    }

    if ($second_language) {
        // Switch to the second language
        do_action('wpml_switch_language', $second_language);

        // Fetch the page in the second language
        $page = get_page_by_path($path);

        // Switch back to the original language
        do_action('wpml_switch_language', $current_language);

        // Debug output
        echo '<p>';
        echo   '<div>Path: ' . esc_html($path) . '</div>';
        echo   '<div>get_page_by_path(\'' . esc_html($path) . '\'): ' . (empty($page) ? '0':$page->ID) . '</div>';
        echo '</p>';
    } else {
        echo '<p>Second language not found.</p>';
    }
}

February 25, 2025 at 4:03 pm #16746894

lorenzP

The facts are:

- our code was working for 4 years (production and staging)
- after editing many pages suddenly the English pages were broken
- this issue cannot be reproduced on other systems (except the cloned production system)
- we tried the WPML repair functions but this did not help
- we spent more than a day to debug the WPML source code
- in the meantime we implemented a workaround

Because we made no WPML update at that time we think this is a problem with one of the WPML database tables.

A failing test case is available here:

hidden link

I suggest we close this ticket as unsolved because no one is willing to look into this and we have a workaround in place.

February 25, 2025 at 6:55 pm #16747515

Andreas W.
WPML Supporter since 12/2018

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

Indeed, thank you for the feedback!

My first goal was to first provide you with a workaround.

The next step would be to consult our development team about which behavior would be expected and if we might have a bug in WPML. It might be that WPML earlier used to apply its own logic once the function was used and this was changed.

I will try to recreate the issue with a simple example, then escalate accordingly and keep you updated.

February 25, 2025 at 9:29 pm #16748222

Andreas W.
WPML Supporter since 12/2018

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

I was able to recreate the issue and it only occurs when the site URL format "Language name added as a parameter" is used.

This format is usually only for development purposes and should not be used on a live site.

It can even have a negative impact on your SEO rating and indexing of the site.

I suggest you switch the language URL format to "Different languages in directories" which solves the issue on my test.

February 26, 2025 at 5:47 pm #16752594

lorenzP

We use the language parameter on this site for many years without any issues. Because of static URLs we cannot easily switch to another URL format.

Is the SEO impact you mention documented somewhere? I could not find any references in the WPML documentation about this: https://wpml.org/documentation/getting-started-guide/language-setup/language-url-options/.

February 26, 2025 at 6:01 pm #16752743

Andreas W.
WPML Supporter since 12/2018

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

The topic is covered here:
hidden link

Google doesn't give a direct example of language parameters here, but the documentation clearly states that using too many parameters can cause problems.

Example:
The language parameter can make the URL unnecessarily complex. As you search for different terms, the URL looks longer and more difficult:

example.com/shop/?lang=de&s=Handschuhe&color=blau&size=m

This URL is difficult to understand and not as user-friendly for users as one organized by a clearer structure like a directory or subdomain.

A contribution from Chat GPT on the topic:
Although language parameters provide an easy way to change the language on a website, they can cause problems, especially in terms of SEO and usability. Using subdomains or directories to separate language versions is a better, more SEO-friendly solution.

---

If you insist, I can report the problem internally, although it is possible that our developers will come to the same conclusion.

February 26, 2025 at 6:33 pm #16752906

Andreas W.
WPML Supporter since 12/2018

Languages: English (English ) Spanish (Español ) German (Deutsch )

Timezone: America/Lima (GMT-05:00)

Reason for the issue:

The native WordPress function url_to_postid() does check for parameters inside the URL, like like p=N, page_id=N, or attachment_id=N, but it does not check for lang:

if ( preg_match( '#[?&](p|page_id|attachment_id)=(\d+)#', $url, $values ) ) {
    $id = absint( $values[2] );
    if ( $id ) {
        return $id;
    }
}

The following filter hook might be able to solve such an issue if you add it to functions.php file of a Child Theme, use a Code Snippet Plugins or create a small custom plugin:

function custom_url_to_postid_lang_filter( $url ) {
    // Check if the URL has a 'lang' parameter
    if ( preg_match( '#[?&]lang=([^&]+)#', $url, $matches ) ) {
        // Do something with the 'lang' parameter, e.g., store it, change the URL, etc.
        $lang = $matches[1];
        // You can perform further logic here, like loading language-specific content
    }

    return $url; // Return the potentially modified URL
}

add_filter( 'url_to_postid', 'custom_url_to_postid_lang_filter', 10, 1 );

The topic ‘[Closed] url_to_postid() in secondary language always returns 0 for valid URL’ is closed to new replies.