Ask your WordPress questions! Pay money and get answers fast! Comodo Trusted Site Seal
Official PayPal Seal

Custom Polylang function: Batch duplicate existing posts across languages WordPress


Hi all,

I'm currently using polylang on a multi-lingual website with a heavy amount of mixed content (and existing content!). I'm in need of a function to loop through our existing posts which are available in english and create the duplicated versions of them (duplication is on for certain post types, so the english version should be copied across all languages (french, german, spanish, and Italian). It works as expected for NEW posts (when clicking the plus sign in polylang to create each duplicate), but the problem is that we have a lot of existing content (in one case, 950 product descriptions) that need to be duplicated (the english version carried over across all languages), and manually creating each duplicate would be quite a task.

Apparently, the newest version of polylang makes this possible. Note from the developer below:


There is a new function which can be used as follows:

PLL()->sync_post->copy_post( $post_id, $lang, true);

$post_id is the post id of the source post.
$lang is the language code (eg 'en', 'fr', de' ) of the target post.

So executing:

PLL()->sync_post->copy_post( 99, 'de', true);

will create a new post in German which will be synchronized with the source post with id 99.

So basically, you need to apply the function on all untranslated posts in English.

Languages and translations groups are taxonomies in Polylang. So querying untranslated English posts means querying the posts with the term slug 'en' in the taxonomy 'language' and with no term in the taxonomy 'post_translations'.

These informations should give the base to a developer to make a routine to synchronize the posts programatically. He just has to take care to run the process in batches as creating so much posts is very long and cannot be run in one loop.


Getting a plugin to create the duplicates is the highest priority, but in an ideal world the script would:

- Could be run on demand to sync any posts in defined post types which did not have their translation variation created yet. In this way, this could be re-run in the future (and if we add additional languages down the road).
- Would also copy custom taxonomy terms over (currently, only categories and tags seem to copy over in duplicates, even though an instance of each term exists across all languages)
- Also enable automatic duplication of the defined post types as the english version is published, instead of requiring a content author to manually hit the plus sign & create/publish the duplicated version for each language.

Answers (1)


Hariprasad Vijayan answers:


Are you using pro version or any addon of plugin?

I didn't get the following code working on free version,

PLL()->sync_post->copy_post( $post_id, $lang, true);

I prepared a code based on the free version that i have, (its all working except copy_post function, you can try if its working on your end.)

$offset = 0; // Offest
$posts_per_page = 10; // Posts per page

// The Query
$query = new WP_Query( $args );
// WP_Query arguments
$args = array(
'post_type' => array( 'post' ),
'lang' => 'en', // Query post with language English
'offset' => $offset,
'posts_per_page' => $posts_per_page,

// The Query
$query = new WP_Query( $args );

// The Loop
if ( $query->have_posts() ) {
while ( $query->have_posts() ) {
// Get the post translation of each language
$post_id_french = pll_get_post(get_the_ID(),'fr');
$post_id_deutsche = pll_get_post(get_the_ID(),'de');
$post_id_italian = pll_get_post(get_the_ID(),'it');

// Executes if French translation of post doesn't exists
PLL()->sync_post->copy_post( get_the_ID(), 'fr', true); // Creates French tranlsation of post.
// Executes if Deutsche translation of post doesn't exists
PLL()->sync_post->copy_post( get_the_ID(), 'de', true); // Creates Deutsche tranlsation of post.
// Executes if Italian translation of post doesn't exists
PLL()->sync_post->copy_post( get_the_ID(), 'it', true); // Creates Italian tranlsation of post.
} else {
// no posts found

// Restore original Post Data

(If above code is not readable, here is the paste - )

You have around 950 product, so you might need to run the loop separately. I set $offset and $posts_per_page variables, you can change the values.

The code isn't completely tested, please test it in your demo server before executing it in live server.

Let me know if you need any help.


Hariprasad Vijayan comments:

Hi, Is that worked for you?