Have a quick script to search for untranslated pages, and then returning a translate link. (Polylang makes a new post for a translation, which is then linked to the original.)

All is working well, except the nonce:

$url = admin_url('post-new.php?post_type=product&from_post=' . $ID . '&new_lang=' . $lang);

$nonce_url = wp_nonce_url($url);

Returns a beautifully formatted url, with an invalid nonce:


The link in the admin panel reads exactly the same, but with a working nonce:


I like to think Im alright with WP, but this is breaking my head. Does anyone have any sort of idea why it is generating invalid links??

Full code:


$lang = $_POST['lang'];
if ($lang == 'nl') { $language = 'Dutch';}
elseif ($lang == 'pt') { $language = 'Portuguese';}
else { $language = 'Something is going awry, I dont know ' . $lang;}

echo '<h2>Missing ' . $language . ' translations</h2>';
// An array of all published WC_Product Objects
$products = wc_get_products( array( 'status' => 'publish', 'limit' => -1,'lang' => 'en', ) );

// Displaying the number of products in this array
echo '<p>Total number of products published: ' . sizeof( $products ) . '</p>';

// Loop through products and save some data using WC_Product and stuff in array
$tobearray = [];
$count = 0;
foreach ( $products as $product ){
    $ID = $product->get_id();
    $title = $product->get_title();

    if (!pll_get_post($ID, $lang)) {

                  $url = admin_url('post-new.php?post_type=product&from_post=' . $ID . '&new_lang=' . $lang);

                  $nonce_url = wp_nonce_url($url);
                      //wp_nonce_url( $url);  // Adding our nonce to the url with a unique id made from the expiry timestamp

        $addpostlink = '<a href="' . wp_nonce_url('/wp-admin/post-new.php?post_type=product&from_post=' . $ID . '&new_lang=' . $lang) . '" target="_blank"> click here</a>';

        $tobearray[] = ['ID' => $ID, 'Title' => $title, 'Link' => $addpostlink ];
echo '<p>Number of Products that are missing their ' . $lang . ' translation: ' . $count . '</p>';
echo 'Posts that need a ' . $language . ' translation: ';

    Click on the link in the table below to create a new translation.  After the link opens (its a bit slow, pls wait), just open the original English product to copy and paste the title and description so you can translate them.
<table border="1">
<?php foreach($tobearray as $row) {
  echo(implode('</td><td>', $row));
} ?>
  • Nonces are per-user (and possibly per-user-session). Does the script run as the same user that's trying to use the link?
    – Rup
    Commented Sep 6, 2019 at 15:54
  • Well, its a plugin so I assumed it was run by the user logged into the admin section. I cant find anything in the codex about setting a user either... Would you have any idea how to do this? Commented Sep 6, 2019 at 16:00
  • 1
    Can you tell us more about this script and how it's triggered? It is possible for things to run without any user, e.g. if it's running on a cron job, it's not clear what the script is though, it could be a WP CLI command, a Cron job, a standalone PHP file, etc. Why are you generating a nonce btw? And how is it being checked? I noticed there's no action specified for your nonce URL
    – Tom J Nowell
    Commented Sep 6, 2019 at 16:06
  • Full code added. It is a plugin file, the first page of which the (admin) user picks a language, and a POST variable is passed indicating the language. My little script then checks for products which require a translation and generates links to do so. Commented Sep 6, 2019 at 16:19
  • At first glance from code in /wp-admin/ that uses wp_nonce_url, you don't want the /wp-admin/ in the string that you pass to wp_nonce_url. i.e. '/wp-admin/' . wp_nonce_url('post-new.php?...') or admin_url(wp_nonce_url('post-new.php?...')). ... except now I've found some examples with admin_url or self_admin_url inside the wp_nonce_url. Maybe that's not it. I'd suggest you add trace to the wp_nonce_url and see what your version and the admin version are passing.
    – Rup
    Commented Sep 6, 2019 at 16:31

1 Answer 1


Found out what the problem was. Polylang plugin verifies the nonces, so you need to pass it the 'new-post-translation' arg.

The solution is: wp_nonce_url( $link, 'new-post-translation' );

it might help someone, but maybe no ;)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.