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 – 14:00 8:00 – 14:00 8:00 – 14:00 8:00 – 14:00 8:00 – 14:00 -
- 15:00 – 17:00 15:00 – 17:00 15:00 – 17:00 15:00 – 17:00 15:00 – 17:00 -

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

Tagged: 

This topic contains 24 replies, has 3 voices.

Last updated by Nigel 2 months, 1 week ago.

Assigned support staff: Nigel.

Author Posts
July 20, 2022 at 6:09 am #11697711

steffenW-9

I have a german page with the path '/de/impressum/', which is translated as '/en/imprint/'. I want to get the complete permalink both in the current language and in other languages, just by starting from "impressum". As far as I can tell this is the way to go:

apply_filters('wpml_permalink', get_permalink(get_page_by_path('impressum')), apply_filters('wpml_current_language', NULL), true)

But this does not work in the frontend when I'm on the english site and trying to get the german url. This

apply_filters('wpml_permalink', get_permalink(get_page_by_path('impressum')), 'de', true)

gives me '/en/imprint/'. All other combinations work. When within /wp-json/ this always works as expected.

The root of the problem may well be get_permalink() which behaves different in the frontend and within wp-json. In the frontend it returns the url in the current language when available. There is no such transformation within wp-json. But I'm not sure how to *not* use get_permalink().

July 20, 2022 at 3:11 pm #11702837

Nigel
Supporter

Languages: English (English )

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

Hi Steffen

I've been doing some tests on my own site, and I think the difficulty arises because you include the language directory for the default language (i.e. de is the default language and your paths include a de directory, e.g. site.com/de/impressum rather than site.com/impressum).

Using apply_filters( 'wpml_permalink', 'hidden link', 'en', true ); won't return the permalink of the translated page because the /de/ in the source permalink for the default language confuses the filter.

If you used apply_filters( 'wpml_permalink', 'hidden link', 'en', true ); it would likely work.

This is in spite of the fact that it is WPML settings which specify the default language should use a directory in its URL structure.

That looks like a bug to me, but I'm double-checking with colleagues.

If you don't need your default language in a directory you could of course remove it, but once I get word back from my colleagues confirming the above, I can look into an alternative solution that works with the default language in directories.

July 21, 2022 at 5:39 am #11706515

steffenW-9

Your are right

apply_filters( 'wpml_permalink', '<em><u>hidden link</u></em>', 'en', true );

works. Using get_page_by_path() and get_permalink() makes this hard though. Let's see what the others are saying, I'm open to different approaches. Thanks for your help!

July 21, 2022 at 2:31 pm #11711577

Nigel
Supporter

Languages: English (English )

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

I have escalated the issue as a bug, so hopefully we can expect a fix before too long.

But in the meantime, given that omitting the language directory from the URL passed to the wpml_permalink filter will return the correct permalink for the translated post, I thought the easiest solution would be to strip that language directory from the URL before passing it through the filter.

Something like this:

    $slug = "impressum";

    $default_permalink = home_url( $slug );

    $default_permalink_modified = str_replace( '/de/', '/', $default_permalink );
    
    $translated_permalink = apply_filters( 'wpml_permalink', $default_permalink_modified, 'en', true );

$translated_permalink will then have the correct result.

July 22, 2022 at 1:42 pm #11719691

Nigel
Supporter

Languages: English (English )

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

My colleague set up a test site where they were able to reproduce the problem, but after re-saving the permalinks the code using the wpml_permalink filter started working as expected, without the workarounds I describe above.

Could you try that on your own site? Re-save permalinks, and then test again without any modifications?

July 25, 2022 at 1:59 pm #11733493

steffenW-9

I did a quick test on friday which I think did work but when creating a new page to test this I ran into some inconsistencies. Getting at it again today I found that both the english and the german frontend both gave me only the current language permalink, no matter which language I requested. Saving the permalinks again solved the german frontend. I could get the permalink in any of the two languages. But on the english frontend I'm now only getting the english permalink. This does not change no matter how often I save the permalinks. And two other pairs of pages I created don't exhibit this behavior.

I tried deleting "wpml_resolved_url_persist" in wp_options, but that doesn't help.

This whole thing is so confusing. I managed to recreate the problem (when in EN I cannot get the DE permalink from a german permalink) with a pair of pages "deutsche-vierte-seite" and "english-forth-page". When changing the german page slug to "blub-deutsche-vierte-seite" it was working, even after removing the "blub" again. Changing my old "deutsche-seite" to "blub-deutsche-seite" made "deutsche-seite" not working again. And get_permalink(get_page_by_path('english-forth-page')) did stop working for a time.

Not even sure anymore if that was my original problem.

What may be happening is that something get's confused with page slugs that start with the language slug. That's why "deutsche-vierte-seite" is a problem but "dritte-deutsche-seite" not. Can you maybe investigate in that direction? In the meantime I'll see if saving permalinks solves my problem on the original site.

July 26, 2022 at 5:20 am #11737675

steffenW-9

> Changing my old "deutsche-seite" to "blub-deutsche-seite" made "deutsche-seite" not working again.

That should have been:

Changing my old "deutsche-seite" to "blub-deutsche-seite" made "deutsche-vierte-seite" not working again.

July 26, 2022 at 6:02 am #11737817

steffenW-9

And another thing that is unexpected:

apply_filters('wpml_permalink', 'hidden link', null, true);
accessed via hidden link
returns hidden link

apply_filters('wpml_permalink', 'hidden link', 'en', true);
accessed via hidden link
returns hidden link

This alone should never happen. But in another environment *both* calls erroneously return the german url.

If you cannot reproduce any of this readily on your end (which I cannot imagine at the moment), what's the best way to have a shared environment for testing? I could supply a Duplicator package or I could create an installation and share ftp-access with you.

July 26, 2022 at 7:51 am #11738501

Nigel
Supporter

Languages: English (English )

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

I have been working on an online test site with my colleague where—since re-saving the permalinks—with any combination of tests I can no longer reproduce the problem.

We had set it up in Spanish and English, so let me quickly recreate it with DE and EN and I'll share the details with you.

July 26, 2022 at 12:26 pm #11742035

Nigel
Supporter

Languages: English (English )

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

With this variant of the test site with German as the default language isn't working very well at all, and I've asked a colleague to double-check things before I share it with you.

Thanks for your patience.

July 26, 2022 at 4:57 pm #11744497

Nigel
Supporter

Languages: English (English )

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

OK, my colleague has identified some problems in the plugin code in this particular scenario and is escalating the issue to the developers so that they can incorporate a solution.

I have made the suggested changes to the current plugin version, a zip file of which is available here: https://toolset.com/patches/sitepress-multilingual-cms.zip

Can you test this solution to make sure it works as expected on your own site (it is working on the test site).

Make sure you have a backup of your current site, then delete the current WPML plugin and manually upload the modified zip file.

Let me know how you get on so I can share your feedback, thanks.

July 27, 2022 at 6:12 am #11746907

steffenW-9

Thanks for the short turnaround time, I repeated my tests and the problem from #11737817 is no longer happening.

There are still problems though. Calling this on DE

apply_filters('wpml_permalink', get_permalink(get_page_by_path('deutsche-vierte-seite')), 'de', true)

gives me hidden link.

I persistently (saving permalinks does not help) have this problem with the pages 'deutsche-vierte-seite'/'english-forth-page' and 'deutsche-seite'/'english-page'. It does not happen with 'zweite-deutsche-seite'/'second-english-page'. Maybe the leading 'en'?

What I found was that I have structures like this in wp_options.wpml_resolved_url_persist:

Array
(
    [<em><u>hidden link</u></em>; => Array
        (
            [en] => 
            [de] => 
        )

    [<em><u>hidden link</u></em>; => Array
        (
            [en] => <em><u>hidden link</u></em>
        )

    [<em><u>hidden link</u></em>; => Array
        (
            [en] => <em><u>hidden link</u></em>
            [de] => 
        )

)

That's probably not supposed to happen.

July 27, 2022 at 6:35 am #11747161

steffenW-9

In parallel the *original* issue: Why is get_permalink() behaving differently when called in wp-json-context?

This reduced case:

function blank_rest_callback() {
    // 50 = /de/dritte/, translated as /en/third/
    $result = [
        'function' => 'get_permalink(50)',
        'result' => get_permalink(50)
    ];
    echo json_encode($result, JSON_PRETTY_PRINT);
}

// /de/wp-json/blank/get-url/
// /en/wp-json/blank/get-url/
add_action('rest_api_init', function() {
    register_rest_route(
        'blank',
        'get-url',
        [
            [
                'methods' => WP_REST_Server::READABLE,
                'callback' => 'blank_rest_callback',
                'args' => []
            ]
        ]
    );
});

// /de/?get-url
// /en/?get-url
if (array_key_exists('get-url', $_GET)) {

    echo '<pre>';
    blank_rest_callback();
    echo '<pre>';

    exit();

}

allows to call the same function (blank_rest_callback()) from the frontend and backend. blank_rest_callback() does nothing else as executing get_permalink(50). On the frontend this returns hidden link when called via hidden link. But accessing hidden link returns hidden link.

The automatic translation of the ID 50 only seems to work on the frontend, not within wp-json.

I found nothing in the forum about that and only started using wpml_permalink to circumvent this behavior. Is this working as intended or should both behave in the same way?

July 27, 2022 at 7:50 am #11747797

Sumit
Supporter

Languages: English (English )

Timezone: Asia/Kolkata (GMT+05:30)

Hi,

I am Sumit from 2nd tier support. Nigel is off today so I will communicate with you.
I hope it is fine.

I am not sure what is wrong with the site. But looking at the options "wpml_resolved_url_persist" this is definitely wrong. There are two entries for one URL, one with a trailing slash and another without a trailing slash.
That's why we suggest saving the permalinks after making the changes to plugin/code as saving permalinks delete that option and rebuilt again on visiting the page.
I hope you did that after uploading the patched plugin.

Since I can not check it is a local site. Will you help to reproduce the issue on our sandbox site if we share it with you?

About the REST issue:-
This is kind of expected, I am not pretty sure (have not checked it yet in logs) but we did some changes to the code to not to adjust the IDs in REST as when passing the ID the expected results should be the object of that ID. There were a number of requests for this feature.

You can adjust the IDs in the callback or before passing to the request if REST client is inside the WP too.
https://wpml.org/wpml-hook/wpml_object_id/

Since this is a different topic not related to the original issue I would suggest opening a new ticket if you need further help with this.

Thanks

July 27, 2022 at 8:36 am #11748239

steffenW-9

REST was the original issue but I could not really check this until wpml_permalinks was working. If that (no adjustment of IDs within REST) is the intended behavior then I can work with that, thank you.

---

Good catch with the missing slash, I tested both versions, so maybe it's right that both versions show up.

Yes, I'm always flushing the permalinks.

I can now further isolate it (and remove get_permalink() and get_page_by_path() from the equation):

apply_filters('wpml_permalink', '<em><u>hidden link</u></em>', 'de', true)

returns "hidden link" no matter what the current language is. It should return "hidden link". wpml_resolved_url_persist is then

Array
(
    [<em><u>hidden link</u></em>; => Array
        (
            [de] => 
        )
)

This also happens with a page called 'english-page', but not with a page called 'third'.

---

Yes, I can try to reproduce this on your sandbox. Just a note: I will be out of the office on thursday and friday.