
Although there are different opinions about which is the best plugin to create a multilingual blog, and all of them have evolved a lot since their first versions simplifying and facilitating the task, one of the most used is Polylang.
With more than 700,000 active installations to date, it remains one of the lightest and most effective options.
Here is a small list of snippets with functions and filters that might be useful at some point. All of them work for the free version of Polylang and have been tested and/or used here.
Copy content from the original post using Polylang in its free version
If you use the free version of the Polylang plugin for WordPress, you already know that the new page or post it generates for translation does not copy the original content. This is one of the features of its paid version and in the free version you have to paste the content by hand.
To solve this and speed up the process, just add these functions in the functions.php file of your template. Now, when you add a new translation it will open with the original copied content (title and content).
// Copying content when creating a translation with Polylang
function jb_editor_content( $content ) {
// Polylang sets the 'from_post' parameter
if ( isset( $_GET['from_post'] ) ) {
$my_post = get_post( $_GET['from_post'] );
if ( $my_post )
return $my_post->post_content;
}
return $content;
}
add_filter( 'default_content', 'jb_editor_content' );
// Copy title when creating a translation with Polylang
function jb_editor_title( $title ) {
// Polylang sets the 'from_post' parameter
if ( isset( $_GET['from_post'] ) ) {
$my_post = get_post( $_GET['from_post'] );
if ( $my_post )
return $my_post->post_title;
}
return $title;
}
add_filter( 'default_title', 'jb_editor_title' );
*Thissnippet was found in a note from December 2020. Although it still works, it wouldn't hurt to keep an eye on it in case, with time and future Polylang updates, it fails.
Show the total number of posts translated with Polylang in each language
This function allows you to add a shortcode for each language that will show the total number of posts published in a language in which there are translations added with the Polylang plugin.
This function is more than tested and working properly on my statistics page and is useful for maintaining a list of counters that are automatically updated.
The snippet is added to the template's functions.php:
// Function to display number of published posts by language for Polylang
function polylang_post_count_by_language($atts) {
// Atributos del shortcode
$atts = shortcode_atts(array(
'lang' => '', // Código de idioma (ej: 'es', 'en', etc.)
), $atts, 'post_count_by_lang');
// Check if Polylang is active
if (!function_exists('pll_languages_list')) {
return 'Polylang plugin is not active.';
}
// Get the language code
$lang = $atts['lang'];
if (empty($lang)) {
return 'Language code is required.';
}
// Single key for transient
$transient_key = 'post_count_by_lang_' . $lang;
// Trying to get the count from the cache
$post_count = get_transient($transient_key);
// If there is no cache, perform the query
if (false === $post_count) {
// Configure the query to count posts by language
$args = array(
'lang' => $lang,
'post_type' => 'post', // Type of post (you can change it if necessary)
'post_status' => 'publish', // Only published posts
'fields' => 'ids', // Only obtain IDs to reduce the burden
'numberposts' => -1, // All posts
);
// Make an enquiry
$query = new WP_Query($args);
// Get the total number of posts
$post_count = $query->found_posts;
// Cache for 12 hours (43200 seconds)
set_transient($transient_key, $post_count, 43200);
}
// Return the number of posts
return $post_count;
}
add_shortcode('post_count_by_lang', 'polylang_post_count_by_language');
One of the problems we face here is that if you have a lot of posts in many different languages on your site, as is the case with this blog, the impact of the database query could slow down the loading speed. The code takes this into account and the query is optimised using WP_Query with fields => 'ids' to reduce memory overhead by not loading whole post objects.
The post count is stored using set_transient and avoids repetitive database queries. In the example, the cache is updated every 12 hours, expressed in seconds (you can adjust this time according to your needs).
To optimise the query, WP_Query is used instead of get_posts to access found_posts, which returns the total number of posts without the need to load all objects.
The fields => 'ids' parameter reduces the memory load by retrieving only the post IDs.
If at some point you need to clear the cache manually (e.g. after publishing a new post) so that it does not show stale data you can use:
delete_transient('post_count_by_lang_' . $lang);
If you prefer to automate this process, the following function will delete the transient every time a post is published, updated or deleted. If you add it in the functions.php of your template, the hook will be activated for all these actions:
//Deleting the transient when publishing, updating or deleting a post
function clear_post_count_transient($post_id) {
// Check if the post is of type 'post' (or the type you are counting).
if (get_post_type($post_id) === 'post') {
// Get the language of the post using Polylang
if (function_exists('pll_get_post_language')) {
$lang = pll_get_post_language($post_id);
// If the language is obtained, delete the corresponding transient.
if ($lang) {
delete_transient('post_count_by_lang_' . $lang);
}
}
}
}
add_action('save_post', 'clear_post_count_transient'); // When publishing or updating
add_action('delete_post', 'clear_post_count_transient'); // By deleting
And this one clears the cache automatically according to a number of different possible scenarios(including the one above):
// Function to delete the transient when necessary
function clear_post_count_transient($post_id) {
if (get_post_type($post_id) === 'post') {
if (function_exists('pll_get_post_language')) {
$lang = pll_get_post_language($post_id);
if ($lang) {
delete_transient('post_count_by_lang_' . $lang);
}
}
}
}
add_action('save_post', 'clear_post_count_transient');
add_action('delete_post', 'clear_post_count_transient');
//Function to delete transient when changing the language of a post
function clear_post_count_transient_on_language_change($post_id, $lang) {
$old_lang = pll_get_post_language($post_id);
if ($old_lang) {
delete_transient('post_count_by_lang_' . $old_lang);
}
if ($lang) {
delete_transient('post_count_by_lang_' . $lang);
}
}
add_action('pll_save_post', 'clear_post_count_transient_on_language_change', 10, 2);
// Function to delete all transients when uninstalling or deactivating Polylang
function clear_all_post_count_transients() {
if (function_exists('pll_languages_list')) {
$languages = pll_languages_list();
foreach ($languages as $lang) {
delete_transient('post_count_by_lang_' . $lang);
}
}
}
register_deactivation_hook(__FILE__, 'clear_all_post_count_transients');
register_uninstall_hook(__FILE__, 'clear_all_post_count_transients');
The numbers are displayed using the shortcode for each language with its corresponding code wherever you want to display the number. It looks like this:
For Spanish: [post_count_by_lang lang="es"]
For English: [post_count_by_lang lang="en"]
For German: [post_count_by_lang lang="de"]
For French: [post_count_by_lang lang="fr"]
etc.
You can modify the 'post_type' in the code if you want to count other types of content (pages, custom post types, etc.).
In this URL you have an example of the shortcodes working.
This article continues on page 2