One of the most widespread options to create a multi-language site with WordPress is to use the qTranslate plugin, wich works pretty well and it’s free. Perhaps the most sensitive aspect of multilingual sites is URL translation , since it affects website’s information architecture and search engine optimization (SEO).
Precisely qTranslate does not support URL’s translation, so we must choose to install an additional plugin: qTranslate Slug. At first all works well with these two plugins installed, but problems arise when we need an XML sitemap to upload to Google.
That’s when we realize, perhaps too late, that many of the URLs within the XML sitemap are incorrect. And I say too late because if we don’t detect the problem quickly, Google will get plenty of links that end in a 404 page not found error , and the number of indexing errors in Google Webmaster Tools will dramatically increase, which in turn may have side effects on SEO if we don’t fix it soon.
The problem’s root
The cause of this problem is that Google XML Sitemaps v3 for qTranslate plugin doesn’t translate the slug part of URLs. Thus, a link that should be /es/google-xml-sitemaps-v3-for-qtranslate-no-funciona-con-qtranslate-slug/ appears as /es/google-xml-sitemaps-v3-for-qtranslate-doesnt-work-with-qtranslate-slug , ie, in English rather than Spanish, although the conversion of /en/ by /es/ is done properly.
This malfunction also affects categories and tags. In that case we won’t get 404 not found errors because for some reason the qTranslate Slug plugin does accept URLs in website’s default language and displays the content in the correct language, but URLs have a the wrong structure and they don’t appear on the sitemap in the desired language.
Where is the error?
Doing some reverse engineering I found out that there is a failure inside sitemap-qtranslate.php file located at plugins/google-xml-sitemaps-v3-for-qtranslate/ directory, which makes a call from qt_permalink() function to qtrans_convertURL() when it comes to a URL in site’s non default language. However, qtrans_convertURL() function doesn’t perform the translation of the URL’s slug part , causing the entire problem. This qtrans_convertURL() method doesn’t belong to Google XML Sitemaps plugin, or even the qTranslate Slug plugin, but the qTranslate main plugin (wp-content/plugins/qtranslate/qtranslate_core.php), which as said earlier doesn’t support URL translation. Thus, it seems that this is a bad implementation of qt_permalink() method that hopefully will be fixed in future versions by plugin developers.
How to fix it?
Until that time comes, here I offer a temporary workaround that will allow you to continue using the plugin and have a valid and error free XML sitemap. Two files are involved that we must modify: sitemap-qtranslate.php and sitemap-core.php , both located in the wp-content/plugins/google-xml-sitemaps-v3-for-qtranslate/ directory.
sitemap-qtranslate.php
Replace all this excerpt:
50 // Add an extra permalink url for every non-default qTranslate language
51 foreach ($languages as $language) {
52 if ($qt["hide_default_language"] == 1 && $qt["default_language"] == $language) {
53 $sitemap->AddUrl($permalink, $modified_time, $change_freq, $priority);
54 } else {
55 $sitemap->AddUrl(qtrans_convertURL($permalink, $language, true), $modified_time, $change_freq, $priority);
56 }
57 }
With this one:
global $q_config;
$qts_options = get_option('qts_options');
$oslug = new QtranslateSlug();
foreach($q_config['enabled_languages'] as $language) {
if ($qt["hide_default_language"] == 1 && $qt["default_language"] == $language) {
$sitemap->AddUrl($permalink, $modified_time, $change_freq, $priority);
} else {
// Posts
if (isset($bean->ID))
{
$p = qtrans_convertURL($permalink, $language, true);
if(!in_array($p, array('http://', 'http:/'))) {
$def_slug = get_post_meta( $bean->ID, $oslug->get_meta_key($qt["default_language"]), true);
$slug = get_post_meta( $bean->ID, $oslug->get_meta_key($language), true);
$turl = str_replace($def_slug, $slug, $p);
$sitemap->AddUrl($turl, $modified_time, $change_freq, $priority);
}
}
// categories
else if (isset($bean->taxonomy) && $bean->taxonomy == 'category')
{
$def_taxonomy_category = $qts_options["_qts_taxonomy_category"][$qt["default_language"]];
$taxonomy_category = $qts_options["_qts_taxonomy_category"][$language];
$p = qtrans_convertURL($permalink, $language, true);
if(!in_array($p, array('http://', 'http:/'))) {
$def_slug = get_term_meta( $bean->term_id, $oslug->get_meta_key($qt["default_language"]), true);
$slug = get_term_meta( $bean->term_id, $oslug->get_meta_key($language), true);
$turl = str_replace($def_slug, $slug, $p);
$turl = str_replace($def_taxonomy_category, $taxonomy_category, $turl);
$sitemap->AddUrl($turl, $modified_time, $change_freq, $priority);
}
}
// tags
else if (isset($bean->taxonomy) && $bean->taxonomy == 'post_tag')
{
$def_taxonomy_tag = $qts_options["_qts_taxonomy_post_tag"][$qt["default_language"]];
$taxonomy_tag = $qts_options["_qts_taxonomy_post_tag"][$language];
$p = qtrans_convertURL($permalink, $language, true);
if(!in_array($p, array('http://', 'http:/'))) {
$turl = str_replace('/'.$language.'/'.$def_taxonomy_tag.'/', '/'.$language.'/'.$taxonomy_tag.'/', $p);
$sitemap->AddUrl($turl, $modified_time, $change_freq, $priority);
}
}
else
{
$sitemap->AddUrl(qtrans_convertURL($permalink, $language, true), $modified_time, $change_freq, $priority);
}
}
}
And don’t forget to add a new $bean parameter to the qt_permalink() function definition found in the same file:
34 // Add additional qTranslate language permalniks
35 //function qt_permalink($qt, $permalink, $post_content, $modified_time, $change_freq, $priority, &$sitemap) {
36 function qt_permalink($qt, $permalink, $post_content, $modified_time, $change_freq, $priority, &$sitemap, <b>$bean</b>) {
sitemap-core.php
Add a last parameter to all qt_permalink() calls inside this file. This parameter will be the object instance referenced by the URL we are trying to add to our sitemap, as a post, category or tag. The lines between [dla] and [/dla] tags are the ones I have changed in this file.
Posts
1923 // <DLA>
1924 //else qt_permalink($qt, $permalink, $post->post_content, ($post->post_modified_gmt && $post->post_modified_gmt!='0000-00-00 00:00:00'?$post->post_modified_gm t:$post->post_date_gmt), ($isPage?$cf_pages:$cf_posts), $prio, $this);
1925 else qt_permalink($qt, $permalink, $post->post_content, ($post->post_modified_gmt && $post->post_modified_gmt!='0000-00-00 00:00:00'?$post->post_modified_gmt: $post->post_date_gmt), ($isPage?$cf_pages:$cf_posts), $prio, $this, $post);
1926 // </DLA>
Categories
2013 // <DLA>
2014 //else qt_permalink($qt, get_category_link($cat->ID), null, $cat->last_mod, $this->GetOption("cf_cats"), $this->GetOption("pr_cats"), $this);
2015 else qt_permalink($qt, get_category_link($cat->ID), null, $cat->last_mod, $this->GetOption("cf_cats"), $this->GetOption("pr_cats"), $this, $cat);
2016 //</DLA>
...
2027 // <DLA>
2028 //else qt_permalink($qt, get_category_link($cat->term_id), null, 0, $this->GetOption("cf_cats"), $this->GetOption("pr_cats"), $this);
2029 else qt_permalink($qt, get_category_link($cat->term_id), null, 0, $this->GetOption("cf_cats"), $this->GetOption("pr_cats"), $this, $cat);
2030 // </DLA>
Tags
2145 // <DLA>
2146 //else qt_permalink($qt, get_tag_link($tag->term_id), null, 0, $this->GetOption("cf_tags"), $this->GetOption("pr_tags"), $this);
2147 else qt_permalink($qt, get_tag_link($tag->term_id), null, 0, $this->GetOption("cf_tags"), $this->GetOption("pr_tags"), $this, $tag);
2148 // </DLA>
Finally, remember that it’s very important to backup changed files so that a plugin update wich still doesn’t provide a fix for this issue doesn’t crush our changes and we can recover them manually.
Was this solution helpful to you?


Comments
Submit comment