November 13, 2015
Buying a WordPress theme with multilingual compatibility doesn’t necessarily mean you’ll have an easy time creating a translated version for your website. If you’re into WordPress long enough, you probably frown when you see that sought after ‘WPML ready’ tag in the description of your No.1-pick-theme, since that particular specification hasn’t exactly proven accurate. In fact, trying to create translated pages for your website could end up being a quite a time-consuming task, since it is usually more about fixing bugs than entering your client’s content.
Multilingual-ready themes are often launched with many oversights, such as a homepage that displays content from both languages, or strings that refuse to translate. Every time I’ve come across an issue like this, I’ve wasted many hours trying to fix it, looking at various sources and trying out numerous possible solutions. Gathering all those issues and their fixes in this article will hopefully save other developers the time and the frustration I’ve experienced. Below are a number of translation problems that might be giving you a headache, along with their possible solutions — at least the solutions that worked for me.
A classic case of multilingual confusion is when a page, block or shortcode element displays content in both or all languages. This issue usually occurs because of a missing 'suppress_filters' => false
in the list of parameters of the get_posts
function.
Let’s say, for example, that the services box on your homepage displays your services in both English and Greek. Locate the php file containing the template for the services box and add the suppress_filters parameter, as seen in the following example:
$args = array(
'post_type' =>'services',
'numberposts' => -1,
'tax_query' => $service_tax_query,
'suppress_filters' => false
);
$services_posts = get_posts($args);
This applies for the get_posts
function since it uses 'suppress_filters' => true
as the default. The query_posts
function, on the other hand, applies filters by default.
More info about the suppress_filters parameter at the WordPress Codex page →
Sometimes you’ll notice that a few strings here and there refuse to translate. They either remain in your primary language after you enter a translation for them or they are not listed in your String Translation tool at all. This usually happens because the theme’s author skipped adding the GetText call for the particular strings. What you need to do is locate the templates with the stubborn strings and add the GetText call accordingly, as described in the following examples. For readability, the texts in question are colored blue and the added code is in red.
Example 2.1: For echoed strings, the text needs to be wrapped in the GetText call _e()
(translatable echo).
Before:
<h2>Links</h2>
After:
<h2><?php _e('Links','theme-text-domain'); ?></h2>
Example 2.2: For phrases that include both static and dynamic text, the solution is to use the __()
GetText call, which is suitable for returned strings and doesn’t write to the output like _e()
does. The output is done by wrapping everything in a printf
call.
Before:
by <?php echo(the_author('', false)); ?>
After:
<?php printf( __( 'by %s', 'theme-text-domain' ), the_author('', false) ); ?>
The term ‘theme-text-domain’ is generic and should be replaced with your theme’s textdomain. This is a unique identifier for retrieving translated strings and can be usually found in your theme’s functions.php:
load_theme_textdomain( 'theme-text-domain', get_template_directory().'/languages' );
More info about the GetText call at the WPML Multilingual Plugin Blog →
In the following example, the GetText call must be added around strings that are defined inside functions.
Before:
register_taxonomy('portfolio_category', 'portfolio',
array(
'hierarchical' => true,
'label' => 'Portfolio Categories',
'singular_name' => 'Category',
"rewrite" => true,
"query_var" => true
)
);
After:
register_taxonomy('portfolio_category', 'portfolio',
array(
'hierarchical' => true,
'label' => __('Portfolio Categories', 'theme-text-domain'),
'singular_name' => __('Category', 'theme-text-domain'),
"rewrite" => true,
"query_var" => true
)
);
Some themes contain built-in forms that don’t allow text to be translated in their sending mail function. In the following example the GetText call needs to be wrapped around the static text of the sent message.
Before:
function sending_mail(){
$theme = get_bloginfo('name');
$subject = $_POST['subject'];
$email = $_POST['email'];
$comments = $_POST['comments'];
$name = $_POST['name'];
$to = get_bloginfo('admin_email');
$message = "Name: $name \n\nEmail: $email \n\nComments: $comments \n\nThis email has been sent from $theme";
$headers = 'From: '.$name. "\r\n" . 'Reply-To: ' . $email;
mail($to, $subject, $message, $headers);
}
After:
function sending_mail(){
$theme = get_bloginfo('name');
$subject = $_POST['subject'];
$email = $_POST['email'];
$comments = $_POST['comments'];
$name = $_POST['name'];
$to = get_bloginfo('admin_email');
$message = __("Name:" , "theme-text-domain") . " " . $name . "\n\n" . __("Email:" , "theme-text-domain") . " " . $email . "\n\n" . __("Comments:" , "theme-text-domain") . " " . $comments . "\n\n" . __("This email has been sent from" , "theme-text-domain") . " " . $theme;
$headers = 'From: '.$name. "\r\n" . 'Reply-To: ' . $email;
mail($to, $subject, $message, $headers);
}
Example 5.1
Before:
<?php comments_popup_link('No Comments', '1 Comment', '% Comments'); ?>
After:
<?php comments_popup_link(__('No Comments', 'theme-text-domain'), __('1 Comment', 'theme-text-domain'), __('% Comments', 'theme-text-domain')); ?>
Example 5.2
Before:
<a href="#"><?php next_posts_link('← Previous') ?></a>
After:
<a href="#"><?php next_posts_link(__('← Previous', 'theme-text-domain')) ?></a>
One less common case is when post thumbnails are not visible when we switch language. I came across this particular issue in a theme that used the Aqua Resizer function v1.1.3 to generate the thumbnails. To fix it, the line below, located in aq_resizer.php, had to be commented out. It was used to check if the images’ URLs are local and it probably conflicted with the addition of the language directory in the website url.
if(strpos( $url, home_url() ) === false) return false;
This issue was fixed in version 1.1.4.
Scanning the theme for strings, you may notice that while the titles of certain widgets are listed for translation, the text entered in their textareas is missing. This issue can be fixed with the use of the icl_translate()
function.
Before:
$address = $instance['address'];
After:
$address = icl_translate('wpml_custom', 'wpml_custom_' . sanitize_title( $instance["address"] ), $instance['address']);
This applies for WPML versions < 3.2.
More information on translating user input texts at the WPML Documentation →
After you make changes to the theme’s code, in order for the texts to show up in the list of strings for translation, you should rescan the theme for strings in your String Translation tool.
This article is just a partial overview of common issues regarding the translation of a WordPress website. Any updates or corrections are welcome as well as any contributions that would make it more comprehensive.
© 2024 ward fifteen | all rights reserved