• Lluis

    (@lluis-abello)


    I’ve seen several threads in the support forum asking how to duplicate a post into a different language using the Polylang plugin instead of having to start the translation of an existing page or post from scratch.
    I myself ran into this issue and decided to improve the Polylang plugin as follows.
    Simple post duplication
    Line numbers are for version 1.7.3 (but I had this code running on Polylang version 1.6)
    Edit wp-content\plugins\polylang\admin\admin-sync.php
    Insert the 2 new lines shown below in function add_meta_boxes:

    Line 57:	$from_post = get_post($from_post_id);
    		$post->post_title = $from_post->post_title . ' Copy_' . $_GET['new_lang'];  // NEW appends Copy_Language to original Post Title
    		$post->post_content = $from_post->post_content;                             // NEW copy the content of the original post into the new translated post
    Line 58:  	foreach (array('menu_order', 'comment_status', 'ping_status') as $property)

    You can now proceed to “Add new translations” duplicating the post or page using the standard “+” icon that Polylang sets on your pages and posts. This will copy the post from the original language into the new language and provide a new post title that you should edit. You can then start translating.

    Post Duplication with Image translation:
    If you are building a multi language site you also want your images to be translated; that is having the “alt attribute” or alternate text for the image translated for each language of your site. The first step is thus to translate the images.
    Go to WordPress Setings->Languages then the “Settings” tab and make sure the Media checkbox is checked to “Activate languages and translations for media” in Polylang.
    Then translate your images in the media library by clicking in the “+” icon that polylang displays. Make sure you translate the “Alternative Text” before clicking the “Update” button.
    Note that since Polylang version 1.7 the alt text gets copied from the original language.
    Once your images are translated you can then proceed to “Add new translations” duplicating the post or page using the standard “+” icon on your pages/post. But first read the next section…
    Polylang code changes:
    Edit wp-content\plugins\polylang\admin\admin-sync.php
    Insert the 4 new lines shown below in function add_meta_boxes:

    Line 57:	$from_post = get_post($from_post_id);
    		$post->post_title = $from_post->post_title . ' Copy_' . $_GET['new_lang'];  // NEW appends Copy_Language to original Post Title
    		$post->post_content = $from_post->post_content;                             // NEW copy the content of the original post into the new translated post
    		if ($this->options['media_support'])                                        // NEW Check if images are to be translated (as set in polylang "Settings" tab)
    		    $this->translate_images_in_duplicated_post($post,$_GET['new_lang']);    // NEW do the magic to update the images
    Line 58:  	foreach (array('menu_order', 'comment_status', 'ping_status') as $property)

    Then insert the function that does the translation of image alt attributes:
    public function translate_images_in_duplicated_post(…)
    somewhere in this same file like right after the function add_meta_boxes you just modified.
    This function parses the post_content string looking for images, extracts the ID of the image, gets the newID of the translated image (calling polylang get_translation) and then replaces the image alt=”alt text in original language” with the alt=”alt text in the translated language”.

    public function translate_images_in_duplicated_post($post, $to_lang) {
    		$content = $post->post_content;
    		$imgend = 0;
    		$translated_content = '';
    		$imgstart = strpos($content,'<img',$imgend);
    		while ($imgstart !== false) {
    			$translated_content .= substr($content,$imgend,$imgstart-$imgend);     // Keep string up to imgstart
    			$index = strpos($content,'wp-image-',$imgstart);           // Search from <img
    			$imgend = strpos($content,'/>',$imgstart);                 // Search from <img
    			$imgend += 2;                                              // Advance />
    			$image_id = 0;
    			if (sscanf(substr($content,$index,$imgend-$index),"wp-image-%d",$image_id) == 1) {
    				$translated_image_id = $this->model->get_translation('post', $image_id, $to_lang);
    				if(!$translated_image_id) {
    					echo "No translation to $to_lang exists for image $image_id";
    					$translated_content .= substr($content,$imgstart,$imgend-$imgstart);        // Keep original image
    				} else {
    					$translated_content .= substr($content,$imgstart,$index-$imgstart);         // Keep up to wp-image
    					$old_imageId = sprintf("wp-image-%d",$image_id);
    					$new_imageId = sprintf("wp-image-%d",$translated_image_id);
    					$translated_content .= $new_imageId;
    					$imgstart = $index + strlen($old_imageId);  // Skip wp-image-oldId
    					// Update the parent of the translated image if it has none
    					$image_post = get_post($translated_image_id);
    					if ($image_post->post_parent === 0) {
    						$translated_image_post = array('ID'=> $translated_image_id, 'post_parent' => $post->ID);
    						wp_update_post($translated_image_post);
    					}
    
    					$index = strpos($content,'alt="',$imgstart);
    					if ($index !== false) {  // Found alt text replace with new image if available
    						$index += 5;         // Skip alt="
    						$new_image_alt = get_post_meta($translated_image_id, '_wp_attachment_image_alt', true);
    						if (is_string($new_image_alt) AND $new_image_alt != '') {
    							$translated_content .= substr($content,$imgstart,$index-$imgstart); // Keep up to including alt="
    							$translated_content .= $new_image_alt;
    							$imgstart = strpos($content,'"',$index); // find the closing " in the original alt
    						}
    					}
    					$translated_content .= substr($content,$imgstart,$imgend-$imgstart);         // Keep the rest of img
    				}
    			} else {
    				$translated_content .= substr($content,$imgstart,$imgend-$imgstart);        // Keep original image
    			}
    			$imgstart = strpos($content,'<img',$imgend);   // look for another image
    		}
    		$translated_content .= substr($content,$imgend,strlen($content)-$imgend);
    		$post->post_content = $translated_content;
    	}

    If the post has images that are not yet translated, this function will display the ID’s (using a simple echo message not fancy at all…) to give you a chance to go back, translate the media and then duplicate the post again.

    We are using this to translate this site: fibracreativa.com from French into English and Spanish.

    Hope someone finds it useful.
    Chouby, maybe this can be incorporated in the next version of the plugin.
    Enjoy!

    https://wordpress.org/plugins/polylang/

Viewing 14 replies - 1 through 14 (of 14 total)
  • Plugin Author Chouby

    (@chouby)

    Hi!

    Thank you for sharing. I will keep a link to this post for the future. But this would need an option in the UI as not every user would need this.

    However, I am not sure that you need to hack Polylang. I believe that you could use the same WP hook I use 'add_meta_boxes' to put your code, and thus make a separate plugin. This would enable you to update Polylang without loosing your customization.

    I, for next realease it would be nice to have the option to copy the original post before translating. Tnx!

    For example, if you use some Composers like Live Composer, you can not copy the content of the post from the old one cuz it does not have any code for you to copy, so the only option is to duplicate the post.
    Thank Chouby for great plugin however we sure need the duplication feature!

    I agree that this should be an option in the plugin

    Thread Starter Lluis

    (@lluis-abello)

    Hi Chouby,
    I upgraded Polylang to Version 1.8.1 and WordPress to 4.4
    The post duplication feature is still not there…
    I was going to update the latest version of the plugin with my code above to duplicate the post and translate the images to the new language but I see the Polylang plugin has been refactored and I am quite lost.
    There is no longer ‘admin-sync.php’ or ‘add_meta_boxes’ …
    Could you please indicate the file/function where the new post is created.

    Thanks!

    Hi Lluis,

    Did you try that tiny plugin ?
    Polylang-copy-translation

    Fred

    Thread Starter Lluis

    (@lluis-abello)

    Thanks Fred,
    I inspired from your plugin to make a new one that also translates the images using the function described in the original post above.
    I updated the code to access Polylang with the new API in version 1.8 using:
    PLL()->model->post->get_translation($image_id, $to_lang)

    And now it also translates the image IDs in image galleries.

    Lluis

    Hi!
    Working about half a year with polylang and… just discovered that – there is no at all functions to copy original content! )) I used premium themes and thought that all about incompatibilities. But no – that was decided! But this is very inconveniently. Ok – I understood, that might be the reasons not to translate the content. But there are too little those reasons – and … something like switcher in admin should be (translate or not) or two “+”, or + and arrow… I am so tired about this “feature”. 3 languages – 3 times from the scratch… ufff… and original content should be visible to translate… That is not normal. Kindly asking the author – implement that needed functions.
    at Viktor Szépe : is that code working in 1.8.1? Seems to be A GREAT solution

    @dino127 That code is functional
    but insecure, unsafe and unmaintained.

    OK, but what does it mean – but insecure, unsafe? How it can be used in insecure mode?

    There will be edge cases when it’ll fail, maybe it has a vulnerability.

    It is not recommended to use it in production.

    Hi dino127,
    maybe this will help you now.
    https://de.wordpress.org/plugins/lingotek-translation/

    the last update from today will say that:

    “Improved the copy source feature by allowing manual copying when using a manual Translation Profile”

    @viktor Szépe and Kochhase
    Thanks for comments! Sure, that a couple of strings some when will fail, but it seems to be changed wp or polylang vars first)
    Vulnerability… hm… even do not imagine – what kind. Ok – will try at my projects, thanks!
    As for the lingotek.. hm… that is interesting. I have a lot projects ( properties, medical, rent) – where the source page is modificated: there are a lot of additional fields: square, price, map and so on + a lot of categories: location, status, environment and so on. The very interesting thing: if I use polylang + all metas in place and translated (location, status,) but there is no content at all ( how difficult to choose the right place at google maps twice or more!). But I do another manner: duplicate the page and then edit – ok – everything in place except… metas ) I should mark them again. Better, but… Will try also with lingotek, but I don’t use this option usually

Viewing 14 replies - 1 through 14 (of 14 total)
  • The topic ‘Polylang post duplication and media translation’ is closed to new replies.