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.

Our wait time is higher than usual, please make sure you are meeting the minimum requirement - https://wpml.org/home/minimum-requirements before you report issues, and if you can take a look at current Known Issues - https://wpml.org/known-issues/. Thank you.
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 17 replies, has 1 voice.

Last updated by Andreas W. 4 days, 5 hours ago.

Assisted by: Andreas W..

Author Posts
March 25, 2025 at 1:12 am #16854423

severinP

<b>Background of the issue: </b>
I am trying to use the example provided at https://wpml.org/wcml-hook/wcml_register_endpoints_query_vars/ which suggests using

$obj->get_endpoint_translation( 'view-subscription', isset( $wc_vars['view-subscription'] ) ? $wc_vars['view-subscription'] : 'view-subscription' );

However, $obj is an instance of WCML_Endpoints and not WPML_Endpoints_Support. The function signatures differ, causing issues.

WCML_Endpoints => 'public function get_endpoint_translation( $endpoint, $language = null )'
WPML_Endpoints_Support => 'public function get_endpoint_translation( $key, $endpoint, $language = null )'

<b>Symptoms: </b>
The language gets switched to a non-existing locale, and some translations are not being displayed. This happens because the second parameter is language and not endpoint, leading to incorrect language switching when trying to register the endpoint.

<b>Questions: </b>
Is the example provided on the website incorrect?
Has backwards compatibility been broken at some point?

March 25, 2025 at 1:16 am #16854439

severinP

I believe in WCML_Endpoints the method should be this

	public function get_endpoint_translation( $key, $endpoint, $language = null ) {
		return apply_filters( 'wpml_get_endpoint_translation', $key, $endpoint, $language );
	}

Instead of this

	public function get_endpoint_translation( $endpoint, $language = null ) {
		return apply_filters( 'wpml_get_endpoint_translation', $endpoint, $endpoint, $language );
	}
March 26, 2025 at 12:16 pm #16862669

Andreas W.
Supporter

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

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

Hello,

I suggest you stick with this example of the usage of this hook is:

/*
 * Add this code to the functions.php file of your theme.
 * This is extracted from the WCML WC Subscriptions compatibility class. 
 */
  
add_filter('wcml_register_endpoints_query_vars', 'register_endpoint', 10, 3 );
 
function register_endpoint( $query_vars, $wc_vars, $obj ){
 
    // Add the translation for the custom "view-subscription" endpoint.
    $query_vars[ 'view-subscription' ] = $obj->get_endpoint_translation( 'view-subscription',  isset( $wc_vars['view-subscription'] ) ? $wc_vars['view-subscription'] : 'view-subscription' );
 
    return $query_vars;
}

Source:
https://wpml.org/wcml-hook/wcml_register_endpoints_query_vars/

The translation is coming from WPML > String Translation. Domain: WC Endpoints.

If this example will not solve the issue, please let me know.

Best regards
Andreas

March 27, 2025 at 3:23 pm #16869342

severinP

I am (and other extensions are using it like this)

The issue lies in WCML (maybe a rewrite at some point) because as I already explained

$obj is an instance of WCML_Endpoints but it's signature does not match that of the example, it takes 2 arguments $endpoint and $language while another similar class takes $key, $endpoint and $language

That means that with the example provided, the $language parameter is set to 'view-subscription' which is obviously not a valid language code and was meant to be $key and $endpoint.
That means that it will lookup the string translation of the endpoint in the language 'view-subscription', which obviously doesn't exists (and spends a lot of time doing so as well by trying to load MO files to init the locale)

As such, the method `WCML_Endpoints::get_endpoint_translation` should be rewritten to this

public function get_endpoint_translation( $key, $endpoint = null, $language = null ) {
    return apply_filters( 'wpml_get_endpoint_translation', $key, $endpoint ?? $key, $language );
}
March 27, 2025 at 3:33 pm #16869425

Andreas W.
Supporter

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

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

Could you please recreate the issue on the following sandbox?
hidden link

Please use the File Manager plugin to access the server. Do not migrate your whole website to this sandbox. We only need a simple example that replicates the bug.

Leave me a comment on this ticket once you are done with this task.

March 28, 2025 at 4:32 pm #16873873

severinP

It appears that I broke the sandbox and I cannot access it to fix the php file, it also had outdated WPML plugin (though this is not an issue to demonstrate the bug)

March 28, 2025 at 6:20 pm #16874343

Andreas W.
Supporter

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

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

The issue is, that we do not have FTP access for those sandboxes, so we are not able to recover the site.

How would you like to proceed?

1) I could send you a new sandbox including the latest version of WPML and our add-ons.

2) You could provide me your custom code and I will try to recreate the issue on a localhost install.

March 28, 2025 at 8:10 pm #16874486

severinP

You can just add the following code in a theme or plugin

add_filter('wcml_register_endpoints_query_vars', 'register_endpoint', 10, 3);

function register_endpoint($query_vars, $wc_vars, $obj)
{
    // Add the translation for the custom "view-subscription" endpoint.
    $query_vars['view-subscription'] = $obj->get_endpoint_translation('view-subscription', isset($wc_vars['view-subscription']) ? $wc_vars['view-subscription'] : 'view-subscription');

    return $query_vars;
}

add_filter('pre_load_textdomain', function ($null, $domain, $mofile, $locale) {
    if ($locale === "view-subscription" && !isset($_GET['bypass'])) {
        echo "The 'view-subscription' locale is being loaded";
        die;
    }
    return $null;
}, 10, 4);

If you load any page you will see that the "view-subscription" locale is being loaded

March 28, 2025 at 8:42 pm #16874601

Andreas W.
Supporter

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

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

I am not sure why you are doing this but this code is not correct:

add_filter('pre_load_textdomain', function ($null, $domain, $mofile, $locale) {
    if ($locale === "view-subscription" && !isset($_GET['bypass'])) {
        echo "The 'view-subscription' locale is being loaded";
        die;
    }
    return $null;
}, 10, 4);

$locale (string|null): This is the locale being used for the translation. It is a string representing the language and regional settings (like en_US for English - United States, fr_FR for French - France, etc.). The $locale is usually set based on the language preference of the user or the site configuration.

I would suggest removing this part of the code or using it properly.

The first provided hook should be sufficient to register the endpoint and translate it with WPML String Translation.

March 29, 2025 at 9:42 am #16875069

severinP

Look, I am not here looking for feedback on a minimal reproduction.

This is a piece of code that demonstrates that YOUR example is doing something wrong. Which is using an endpoint name as a locale parameter, which obviously doesn't exist and tries to load "view-subscription" as a locale. You said it yourself, locale should be something like "en_US" or "fr_FR" not "view-subscription", so if the die does happen then there is a problem in WPML

What is not correct is either YOUR example or the WCML_Endpoints class. But this example is now widely used in other plugins. So the WCML_Endpoints class needs to be fixed.

If you don't want to implement the fix I provided which is a 2 line patch and improves the performance and reliability of WCML without breaking changes, be my guest.

March 29, 2025 at 2:11 pm #16875411

Andreas W.
Supporter

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

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

I can not confirm any issue by registering a WC endpoint and translating it with WPML String Translation while using only our code example.

It is your code that is declaring it as $locale:

add_filter('pre_load_textdomain', function ($null, $domain, $mofile, $locale) {
    if ($locale === "view-subscription" && !isset($_GET['bypass'])) {
        echo "The 'view-subscription' locale is being loaded";
        die;
    }
    return $null;
}, 10, 4);

If you remove this hook the error will not occur.

March 29, 2025 at 5:56 pm #16875685

severinP

Again my hook is just a DEMONSTRATION THAT WPML IS SWITCHING THE LOCALE TO 'view-subscription', it was just condensed into something that shows the issue and real usage differs, what is so hard to understand? I did not "invent" the locale parameter

https://developer.wordpress.org/reference/hooks/pre_load_textdomain/

Stop lecturing me about bad usage here. And actually try to understand the issue I'm reporting and if you can't then escalate the example I provided and the suggested patch to developers because they will understand.

March 29, 2025 at 6:05 pm #16875699

Andreas W.
Supporter

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

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

My apologies, reviewing this again, it looks correct. I will need to run some further tests and then get back to you.

March 29, 2025 at 7:21 pm #16875743

Andreas W.
Supporter

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

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

Inside the 'pre_load_textdomain' hook call you may find inside $locale:

NULL
NULL
string(5) "en_US"
NULL
string(5) "en_US"
string(5) "en_US"
string(5) "en_US"
NULL
NULL
NULL
NULL
string(5) "en_US"
string(5) "de_DE"
string(17) "view-subscription"
string(5) "en_US"
string(5) "en_US"
string(5) "en_US"
string(5) "en_US"
NULL
string(5) "en_US"
string(5) "en_US"
string(5) "en_US

In fact, "view-subscription" looks unexpected.

It is coming from the .mo-file wp endpoints-view-subscription.mo:

NULL
string(12) "WP Endpoints"
string(95) "D:\Work\Local Sites\wpml\app\public/wp-content/languages/wpml/wp endpoints-view-subscription.mo"
string(17) "view-subscription"

I will need to consult the second-tier support for more details.

April 2, 2025 at 3:09 pm #16887792

Andreas W.
Supporter

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

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

Creating the endpoint in this way, seems to be solving the issue:

$my_current_lang = apply_filters( 'wpml_current_language', NULL );
	$query_vars['view-subscriptions'] = $obj->get_endpoint_translation('view-subscriptions',$my_current_lang);