GNU/Linux, Open Source, Cloud Computing, DevOps y más...

Google XML Sitemaps v3 for qTranslate no funciona con Qtranslate Slug

3 comentarios

Una de las opciones más extendida para crear un sitio multi-idioma con WordPress es utilizar el plugin Qtranslate, que además de ser gratuito funciona bastante bien. Quizás el aspecto más delicado de los sitios en diferentes idiomas sea el de la traducción de las URL’s, ya que afecta a la propia arquitectura de la información de esa web y a su posicionamiento en buscadores (SEO).

Precisamente Qtranslate no ofrece soporte para la traducción de URL’s, por lo que debemos optar por la instalación de un plugin adicional, Qtranslate Slug para lograrlo. En principio todo funciona bien con estos dos plugins instalados, hasta que tenemos la necesidad de contar con un mapa de nuestro sitio en XML para subirlo a Google.

Ahí es cuando nos damos cuenta, quizás demasiado tarde, de que muchas de las URL’s que aparecen en el sitemap XML son incorrectas. Y digo demasiado tarde, porque si no detectamos el problema rápidamente, Google recibirá un montón de enlaces que acaban en un error 404 de página no encontrada, y el número de errores de indexación en las Herramientas para Webmasters de Google aumentará de forma vertiginosa, lo cual podrá tener efectos negativos en el SEO de nuestra web si no lo remediamos pronto.

Naturaleza del problema

Qtranslate logo

El origen de este problema está en que el plugin Google XML Sitemaps v3 for qTranslate no traduce la parte de la URL que muestra los nombres de los artículos (slug). Así, un enlace que debería ser /es/google-xml-sitemaps-v3-for-qtranslate-no-funciona-con-qtranslate-slug/ aparece como /es/google-xml-sitemaps-v3-for-qtranslate-doesnt-work-with-qtranslate-slug, es decir, en inglés en lugar de en español, a pesar de que la conversión de /en/ por /es/ sí se hace correctamente.

Este mal funcionamiento afecta también a categorías y etiquetas. En este caso no obtendremos errores 404 de páginas no encontradas, pues por alguna razón el plugin Qtranslate Slug sí acepta las URL’s en el idioma por defecto del sitio web y muestra el contenido en el idioma correcto, pero las URL’s tendrán una estructura errónea y no aparecerán en el idioma deseado.

¿Dónde está el error?

Haciendo un poco de ingeniería inversa he descubierto que se trata de un fallo en el fichero sitemap-qtranslate.php ubicado en plugins/google-xml-sitemaps-v3-for-qtranslate/, el cual hace una llamada desde la función qt_permalink() a la función qtrans_convertURL() cuando se trata de una URL en otro idioma distinto del que tiene configurado nuestro sitio web por defecto. Sin embargo, la función qtrans_convertURL() no realiza la traducción de la parte del slug de la URL, lo que provoca todo el problema. Esta función qtrans_convertURL() no pertenece al plugin Google XML Sitemaps, ni tan siquiera al plugin Qtranslate Slug, sino al propio plugin Qtranslate (wp-content/plugins/qtranslate/qtranslate_core.php), que como decía al principio no tiene soporte para la traducción de URL’s. Por tanto, todo indica que se trata de una mala implementación del método qt_permalink() que esperemos sea solucionado en futuras versiones por los desarrolladores del plugin.

¿Cómo solucionarlo?

Hasta que ese momento llegue, aquí os ofrezco una solución temporal que os permitirá seguir usando el plugin y tener un sitemap XML válido y libre de errores. Los ficheros implicados que deberemos modificar son 2: sitemap-qtranslate.php y sitemap-core.php, ambos ubicados en el directorio wp-content/plugins/google-xml-sitemaps-v3-for-qtranslate/.

sitemap-qtranslate.php

Sustituir todo este fragmento:

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    }

Por este otro:

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);
                                }
                        }
                }

Y no olvidemos añadir un nuevo parámetro $bean a la definición de la función qt_permalink() en el mismo fichero:

 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, $bean) {
sitemap-core.php

Añadir un último parámetro a todas las llamadas a la función qt_permalink() que se hagan en este fichero. Este parámetro será el objeto al que haga referencia la propia URL que estamos tratando de añadir a nuestro sitemap, como un post, una categoría o una etiqueta. Las líneas entre las etiquetas y son las que he modificado en este fichero:

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>

Categorías
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>

Etiquetas
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>

Por último, recuerda que es muy importante hacer una copia de seguridad de los ficheros modificados para que si actualizamos el plugin con una nueva versión que aún no aporta una solución a este problema y nuestros cambios son machacados podamos recuperarlos aunque sea de forma manual.

¿Te ha servido esta solución?



 

Sobre el autor

Daniel López Azaña
Arquitecto de soluciones Cloud

Emprendedor, generador de ideas y mente inquieta. Apasionado de las nuevas tecnologías, especialmente de los sistemas Linux y del software libre. Me gusta escribir además sobre actualidad tecnológica, Cloud Computing, DevOps, seguridad, desarrollo web y programación, SEO, ciencia, innovación, emprendimiento, etc.

DanielGoogle XML Sitemaps v3 for qTranslate no funciona con Qtranslate Slug

Artículos relacionados

3 comentarios

Unirte a la conversación
  • Xavier Prunés - 18/09/2014 responder

    Perfecto, sólo te faltaría indicar la modificación de la función qt_permalink añadiendo el parámetro $bean:
    //function qt_permalink($qt, $permalink, $post_content, $modified_time, $change_freq, $priority, &$sitemap) {
    function qt_permalink($qt, $permalink, $post_content, $modified_time, $change_freq, $priority, &$sitemap, $bean) {

    Muchas gracias

    Daniel - 23/09/2014 responder

    Es cierto Xavier, olvidé ponerlo. Ya está rectificado. ¡Gracias a ti!

  • Marc - 28/01/2015 responder

    Hola, pues amí no me funcionado me sigue generando url’s erróneas :S

Deja un comentario

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *