A la hora de crear un sitio web multi-idioma basado en WordPress son básicamente dos las opciones que tenemos. Una implica crear páginas y artículos distintos, cada uno en su idioma, usando plugins del tipo de WPML, Polylang o xili-language. Otra introduce el contenido traducido en todos los idiomas que manejemos en el mismo post, separado por unas meta-etiquetas dentro del propio contenido, y es el propio plugin el que los separa en pestañas distintas dentro del editor de un único post existente.
Nota:
Los problemas y las soluciones descritas en este artículo son aplicables a estas versiones de los plugins:
- Qtranslate 2.5.39
- Qtranslate Slug 1.1.7
Este es el caso de Qtranslate, que resulta ser la solución más sencilla desde mi punto de vista, pues no es necesario modificar la base de datos de WordPress para crear relaciones entre un artículo y sus traducciones, al igual que para el resto de objetos de WordPress: etiquetas, categorías, widgets, menús, etc. Por eso Qtranslate es mi opción preferida a la hora de crear un sitio web multi-idioma en WordPress.
Sin embargo, Qtranslate no está exento de complicaciones, pues tiene algunos fallos que es necesario solventar para que nuestro sitio sea realmente multi-idioma:
1. Qtranslate no ofrece soporte para traducción de URL’s y slugs
El principal impedimento que encontramos es que Qtranslate no ofrece soporte para la traducción de las URL’s de nuestro sitio, lo cual supone una gran limitación que puede invalidar completamente su uso y forzarnos a optar por otra alternativa. Afortunadamente existe un plugin complementario que nos permitirá traducir nuestras URL’s: Qtranslate Slug. Soporta la traducción no sólo de los slugs de nuestros artículos y páginas, sino también de etiquetas y categorías.
2. Qtranslate Slug provoca que se genere contenido duplicado en nuestro sitio
Sin embargo, Qtranslate no resuelve otro incómodo problema: aunque nuestras URL’s sean traducidas correctamente con Qtranslate Slug, cuando solicitemos cualquier artículo, página o categoría empleando el slug en el idioma por defecto de nuestro sitio, da igual qué variable o subdirectorio de idioma indiquemos en nuestra URL, pues se mostrará el mismo contenido siempre. Así, siendo el idioma por defecto de nuestro sitio el inglés, si solicitamos la URL /en/article-name obtendremos exactamente el mismo resultado que si solicitamos /es/article-name, lo cual es erróneo, pues la dirección del artículo en español es /es/nombre-articulo. La dirección /es/article-name no tiene sentido y debería devolver un error 404: no encontrado. Sin embargo se nos muestra el artículo en inglés, con exactamente el mismo contenido que en el caso de /en/article-name, lo cual es contenido duplicado que Google y otros buscadores pueden llegar a indexar o al menos marcar como contenido duplicado y crearnos problemas.
Esto mismo ocurre con páginas, categorías y etiquetas. Por ejemplo, la dirección /es/category/programming mostrará el mismo contenido que /en/category/programming.
Para solventar esto y mostrar errores 404 de página no encontrada cuando solicitamos URL’s incorrectas debemos hacer algunas modificaciones en el fichero wp-content/plugins/qtranslate-slug/qtranslate-slug.php del plugin Qtranslate Slug.
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. La paginación no funciona correctamente
Cuando nos encontramos en una página interna del blog, de una categoría o de posts archivados y seleccionamos otro idioma desde el widget de cambio de idioma la información de paginación se pierde y siempre nos lleva a la página principal, con lo cual nunca podemos ver la versión de dicha página en los otros idiomas disponibles de nuestro sitio web. Es decir, si accedemos a /es/blog/page/2 y cambiamos el idioma a inglés, en lugar de mostrarse la página /en/blog/page/2 se muestra /en/blog.
Error: Your Requested widget " ai_widget-6" is not in the widget list.
- [do_widget_area above-nav-left]
- [do_widget_area above-nav-right]
- [do_widget_area footer-1]
- [do_widget id="wpp-4"]
- [do_widget_area footer-2]
- [do_widget id="recent-posts-4"]
- [do_widget_area footer-3]
- [do_widget id="recent-comments-3"]
- [do_widget_area footer-4]
- [do_widget id="archives-4"]
- [do_widget_area logo-bar]
- [do_widget id="oxywidgetwpml-3"]
- [do_widget_area menu-bar]
- [do_widget id="search-3"]
- [do_widget_area sidebar]
- [do_widget id="search-4"]
- [do_widget id="ai_widget-2"]
- [do_widget id="categories-5"]
- [do_widget id="ai_widget-3"]
- [do_widget id="ai_widget-4"]
- [do_widget id="ai_widget-5"]
- [do_widget_area sub-footer-1]
- [do_widget id="text-4"]
- [do_widget_area sub-footer-2]
- [do_widget_area sub-footer-3]
- [do_widget_area sub-footer-4]
- [do_widget_area upper-footer-1]
- [do_widget id="search-2"]
- [do_widget id="recent-posts-2"]
- [do_widget id="recent-comments-2"]
- [do_widget id="archives-2"]
- [do_widget id="categories-2"]
- [do_widget id="meta-2"]
- [do_widget_area upper-footer-2]
- [do_widget_area upper-footer-3]
- [do_widget_area upper-footer-4]
- [do_widget_area widgets_for_shortcodes]
- [do_widget id="search-5"]
- [do_widget id="ai_widget-6"]
- [do_widget_area wp_inactive_widgets]
- [do_widget id="wpp-2"]
- [do_widget id="text-1"]
- [do_widget id="recent-posts-3"]
- [do_widget id="categories-3"]
- [do_widget id="archives-3"]
- [do_widget id="icl_lang_sel_widget-3"]
Yo lo he solucionado añadiendo las siguientes líneas al final de la función filter_request() del fichero qtranslate-slug.php, aunque probablemente haya una forma mejor si buceamos más en el código de Qtranslate Slug:
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>
4. Qtranslate genera enlaces hreflang erróneos
Otro efecto colateral indeseable que sufriremos por no ofrecer Qtranslate soporte para traducir el slug de las URL’s es el de que se creen enlaces hreflang erróneos en la sección HEAD de todas nuestras páginas. Así, la URL de este mismo post aparecería como /en/solucionando-problemas-qtranslate-slug/ en lugar de /es/solucionando-problemas-qtranslate-slug/ en la versión en español, mientras que en la versión en inglés aparecería como /es/fixing-qtranslate-slug-problems/ en lugar de /en/fixing-qtranslate-slug-problems/, lo que resulta en un montón de errores 404 de página no encontrada en las Webmaster Tools de Google.
Podemos solucionar esto realizando una pequeña modificación en el fichero wp-content/plugins/qtranslate/qtranslate_hooks.php:
Antes:
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 }
Después:
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 }
5. Comments reply links doesn’t include language
Todos los comentarios de un post incluyen normalmente un enlace «Responder» que no es filtrado por Qtranslate para añadir la variable o subdirectorio de idioma a la URL que aparece en el atributo href de dicho enlace. Esto provoca que enlaces que deberían ser como /es/solucionando-problemas-de-qtranslate-con-la-traduccion-del-slug/?replytocom=1868#respond aparezcan como /solucionando-problemas-de-qtranslate-con-la-traduccion-del-slug/?replytocom=1868#respond, lo que provoca también más errores 404 en las Herramientas para Webmasters de Google.
Podemos solucionarlo añadiendo estas líneas al fichero qtranslate-slug.php:
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 no funciona con Qtranslate Slug
Este problema hace que se generen URL’s incorrectas en nuestro mapa del sitio, las cuales provocarán que se genere un sitemap plagado de URL’s que devuelven un error 404 de página no encontrada. En este otro artículo describo mejor la problemática y su resolución: Google XML Sitemaps v3 for Qtranslate no funciona con Qtranslate Slug.
3 comentarios
Unirte a la conversaciónsara - 27/12/2016
Buenas,
Esto ya no funciona así, verdad?
Tengo el problema nº4 y estoy usando las versiones:
QTranslate Slug 1.1.18
QTranslate X 3.4.6.8
He colocado el código que indicas en q-translate-hooks.php pero me devuelve error 500.
¿Alguien sabe cómo solucionarlo?
Muchas gracias
José - 30/04/2017
Hola Daniel,
En mi opinión generar un error 404 para resolver el problema de contenido duplicado no es una opción aceptable, ya que puede generar una cantidad importante de rebotes de usuarios que se encuentran que una página que puede que exista en su idioma local devuelve un error 404.
Lo ideal sería que si el idioma actual no coincide con el del slug, se produzca una redirección al contenido correcto. Por poner un ejemplo, si un usuario accede a /es/en-slug redireccionara a /es/es-slug.
¿Sería posible modificando el plugin añadir esta funcionalidad?
Un saludo.
Daniel - 23/05/2017
Gracias José. Yo creo que nuestra web nunca debería generar una URL tipo /es/en-slug, ya que si no está traducida no existirá tampoco /en/en-slug, y si lo está debería tener también traducido el slug, por lo que poner un idioma y el slug en otro idioma yo lo considero un error. En cualquier caso, antes esta situación puede perfectamente redirigirse al usuario al slug correcto en el idioma seleccionado en lugar de mostrarse un error 404, pero creo que esto que tú planteas es más costoso de implementar. No obstante, el código puede modificarse todo lo que se quiera, por lo que sí creo que es posible modificar el plugin para obtener esa funcionalidad.