Daniel López Azaña

Theme

Social Media

Blog

GNU/Linux, Open Source, Cloud Computing, DevOps and more...

Fixing Qtranslate slug problems

Wordpress multilingual site

There are basically two options when creating a multi-language website based on WordPress. One involves duplicating posts and pages by creating one different post for each language, wich is the approach followed by some plugins like WPML, Polylang or xili-language. Another approach is to introduce all the translations into the same post , separated by meta-tags within the content itself.

Note:

The issues and fixes described in this post are applicable to these plugin versions:

  • Qtranslate 2.5.39
  • Qtranslate Slug 1.1.7

Each translation is displayed in different tabs within the HTML editor of a single post. This is the case of Qtranslate , which happens to be the simplest solution from my point of view, as it is not necessary to modify the WordPress database in order to create relationships between a post or page and their translations, as well as among other WordPress objects like categories, tags, widgets, menus, etc. Therefore Qtranslate is my favorite choice when it comes to creating a multilingual website based on WordPress.

However, Qtranslate is not without complications as it has some bugs and lack of features that we need to overcome in order to make our site truly multilingual:

1. Qtranslate doesn’t support URL’s slug translation

The main impediment we find is that Qtranslate doesn’t translate our site’s URLs properly , which is a major limitation that can completely invalidate its use and force us to choose another alternative. Fortunately there is an additional plugin that will allow full URL translation: Qtranslate Slug. It supports not only posts and pages slug translation, but also categories and tags.

Qtranslate Slug

2. Qtranslate Slug causes duplicate content

However, Qtranslate does not solve another awkward problem: although our URLs are properly translated by Qtranslate Slug, when we request any post, page or category using the slug in our site’s default language, no matter what variable or subdirectory language we indicate , the same content is always displayed. So, being English our default language, if you request an URL like /es/ article-name-in-english you’ll get exactly the same result as if you request /en/ article-name-in-english, which is wrong, because the post’s address in Spanish is /es/nombre-del-articulo-en-espanol. The /es/ article-name-in-english URL makes no sense and should always return a 404 not found error. However the same post in English is displayed with exactly the same content as in the case of /en/article-name-in-english, which results in duplicate content that Google and other search engines can index and even flag as duplicate content and create us problems.

The same applies to pages, categories and tags. For example, the address /es/ category/programming shows the same content as /en/ category/programming.

To fix this issue and force WordPress to display 404 errors when bad URLs are requested it is necessary to make some changes to the wp-content/plugins/qtranslate-slug/qtranslate-slug.php file of Qtranslate Slug plugin:

882                         // <DLA>
883                         if (!$post)
884                         {
885                                 $query['name'] = 'dladladladla';
886                                 return $query;
887                         }
888                         // </DLA>

...

900                         // <DLA>
901                         if (!$term)
902                         {
903                                 $query['category_name'] = 'dladladladla';
904                                 return $query;
905                         }
906                         // </DLA>

...

1068                     /*} else {
1069                         $last_part = array_pop($parts);
1070                         $page_id = $wpdb->get_var( "SELECT ID FROM $wpdb->posts WHERE post_name = '$last_part' AND (post_type = '$post_type_sql' OR post_type = 'attachment')" );
1071 
1072                         if ( $page_id )
1073                                 return $page_id;
1074                     }*/

...

1560                 /*if ( !$term && 'slug' == $original_field ) {
1561                         $field = 't.slug';
1562                         $term = $wpdb->get_row( $wpdb->prepare( "SELECT t.*, tt.* FROM $wpdb->terms AS t INNER JOIN $wpdb->term_taxonomy AS tt ON t.term_id = tt.term_id WHERE tt.taxonomy = %s AND $field = %     s LIMIT 1", $taxonomy, $value) );
1563                 }*/

3. Pagination doesn’t work properly

When we are in an internal page of the blog, category or archived posts and we select another language from the change language widget the paging information is lost and always takes us to the main page, so we can never see the translated version of that page in other languages ​​available. That is, if we point to /es/blog/page/2 and change language to English, the page /en/blog is displayed instead of /en/blog/page/2.

I solved it adding the following lines at the end of the filter_request() function in qtranslate-slug.php file, although there is probably a better way to achieve this if we dive deeper into qTranslate Slug’s code:

972                 // <DLA>
 973                 // Add support for pagination to qtranslate slug widget
 974                 if (isset($query['paged']))
 975                 {
 976                         if ($this->current_url == null)
 977                         {
 978                                 global $q_config;
 979                                 foreach ($q_config['enabled_languages'] as $lang)
 980                                 {
 981                                         $this->current_url[$lang] = '/'.$lang . str_replace('/'.qtrans_getLanguage().'/', '/'.$lang.'/', $_SERVER['REQUEST_URI']);
 982                                 }
 983                         }
 984                         else
 985                         {
 986                                 foreach ($this->current_url as $lang => $language_url)
 987                                 {
 988                                         $this->current_url[$lang] .= 'page/'.$query['paged'];
 989                                 }
 990                         }
 991                 }
 992                 // </DLA>

Another undesirable side effect caused by Qtranslate not supporting slug translation is that wrong hreflang links are created inside HEAD section within all site’s pages. Thus, the URL of this post you are reading would be rendered as /en/ solucionando-problemas-qtranslate-slug/ instead of /es/solucionando-problemas-qtranslate-slug/ in the Spanish version, while in the English version would be rendered as /es/ fixing-qtranslate-slug-problems/ instead of /en/fixing-qtranslate-slug-problems/ , resulting in a lot of 404 page not found errors in Google Webmaster Tools.

This can be solved by making a small change to the wp-content/plugins/qtranslate/qtranslate_hooks.php file:

Before:
41         foreach($q_config['enabled_languages'] as $language) {
 42                 if($language != qtrans_getLanguage())
 43                         echo '<link hreflang="'.$language.'" href="'.qtrans_convertURL('',$language).'" rel="alternate" />'."\n";
 44         }
After:
41         foreach($q_config['enabled_languages'] as $language) {
 42                 if($language != qtrans_getLanguage())
 43                 // <DLA>
 44                 {       
 45                         global $qtranslate_slug;
 46                         $language_url = $qtranslate_slug->get_current_url($language);
 47                         //echo '<link hreflang="'.$language.'" href="'.qtrans_convertURL('',$language).'" rel="alternate" />'."\n";
 48                         echo '<link hreflang="'.$language.'" href="'.$language_url.'" rel="alternate" />'."\n";
 49                 }
 50                 // </DLA>
 51         }

Each post comment normally includes a «Reply» link wich is not filtered by Qtranslate in order to add the language variable or subdirectory to href’s URL. This causes that links that should be like /en/ fixing-qtranslate-slug-problems/?replytocom=1868#respond appear like / fixing-qtranslate-slug-problems/?replytocom=1868#respond, wich also causes 404 errors on Google Webmaster Tools.

Fix qtranslate-slug.php file like this:

533                 // <DLA>
 534                 add_filter( 'comment_reply_link', array(&$this, 'fix_comment_reply_link'));
 535                 add_filter( 'cancel_comment_reply_link', array(&$this, 'fix_cancel_comment_reply_link'));
 536                 // </DLA>
 537 
 538         }
 539 
 540         // <DLA>
 541         /*
 542          * fixes comments reply link adding language subdirectory to href URL
 543          */
 544         function fix_comment_reply_link($link)
 545         {
 546                 preg_match('/href=\'([^\']*)\'/', $link, $href);
 547 
 548                 return str_replace($href[1], qtrans_convertURL($href[1]), $link);
 549         }
 550         /*
 551          * Fixes cancel comment reply link by adding language subdirectory to href URL
 552          */
 553         function fix_cancel_comment_reply_link($link)
 554         {
 555                 preg_match('/href=\"([^\']*)\"/', $link, $href);
 556 
 557                 return str_replace($href[1], qtrans_convertURL($href[1]), $link);
 558         }
 559         // </DLA>

6. Google XML Sitemaps v3 for Qtranslate doesn’t work with Qtranslate Slug

This problem causes wrong URLs are generated in our sitemap, which results in a sitemap riddled of wrong URLs returning 404 errors. I describe better this problem and its resolution in another article: Google XML Sitemaps v3 for Qtranslate doesn’t work with Qtranslate Slug.

qTranslate qTranslate Slug Wordpress
Daniel López Azaña

About the author

Daniel López Azaña

Tech entrepreneur and cloud architect with over 20 years of experience transforming infrastructures and automating processes.

Specialist in AI/LLM integration, Rust and Python development, and AWS & GCP architecture. Restless mind, idea generator, and passionate about technological innovation and AI.

Related articles

Wordpress multilanguage icon

Google XML Sitemaps v3 for qTranslate doesn’t work with Qtranslate Slug

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.

September 4, 2014
Xorg icon

How to prevent the .xsession-errors file from growing to a huge size

The .xsession-errors file is where the X Window system logs all errors that occur within the Linux graphical environment. All desktop environments, whether Gnome, KDE, Cinnamon, XFCE, LXDE, etc., and all lighter window managers like FVWM, IceWM or Window Maker make use of the X Window system. Therefore any graphical application running on your computer can cause that error messages are written to the .xsession-errors file, reason why it can grow wildly until reaching very big sizes of tens of GB or even hundreds if your disk capacity allows it.

June 25, 2017
Ctrl+S

Unlock Linux command line after pressing Ctrl+s in Bash

Since the key combination Control+s is widely used as a shortcut to save files in GUI applications such as text editors, image editors, web browsers, etc. sometimes you are betrayed by your subconscious when you are working from the Linux command line and you use that same key combination when you are for example editing a Vim document when trying to save it. Then you notice that no key answers, the shell is locked and you can no longer do anything else in it.  Even worse, you get a cold sweat because you can’t continue editing your document and you can’t save the changes.

April 27, 2017

Comments

Alex October 25, 2016
Hi Daniel, very interesting your article. I would try to customize qTraslate slug plugin as you have shown in your post. In particoular, I'm interested in the first snipped of code: I don't understand how to insert that code inside qtranslate-slug.php. At what point do I have to insert that code? And then, I see you have put some dummy text, what I have to put inside $query['name'] = '...'; for example? The same thing, for other snippets. Than you very much
Jörg April 30, 2017
Hi Alex, thank’s for the detailed explanation but I’m having the same issue as Alex. Could you please provide us with an update? Thank you very much in advance!
Prihod June 13, 2018
Hi Daniel! Now this code I need (without /ru) Russian version by delault. Can u help me?
Prihod June 13, 2018
cut code _https://prntscr.com/jufzxx screenshot
Daniel August 2, 2018
Sorry, but the version of Qtranslate in the article is now too old and I am not aware of the problems of the most recent versions, as I switched to WPML - The WordPress Multilingual Plugin.

Submit comment