Translating WordPress Themes and Plugins.

Some time ago I found myself needing to internationalize wordpress plugin. I read the wordpress documentation on the matter (http://codex.wordpress.org/I18n_for_WordPress_Developers), and when I arrived a the section where it tells you how to generate your POT files, I did not quite like it.

The wordpress team offers a couple php scripts that you need to download, and run in order to generate your pot files. I wanted to just use the gettext utilities that come with linux, so I decided to just use that. It is quite simple, to do so. After I finished the translation, I meant to write a post about it, but I didn’t. A few days ago, when I had to internationalize a theme, I regretted not writing that post. This time I won’t make the same mistake.

The first thing you need to do is make sure that your strings are wrapped in one of the special functions that wordpress provides for i18n. The two most popular are __() and _e(). Once you have done that, you need to collect all your strings using the xgettext program. It is very simple to use, but you need to specify the key or keys that mark the strings fro translation. This is because the functions that wordpress uses are not the functions that are commonly used. You specify the key by using the --keyword option:


xgettext --keyword=_e --keyword=__

Do not run the command yet, you still need to specify some other options. Besides, if you run it like that, it won’t know in which file to search.

Next, we need to specify the output file name:


xgettext --keyword=_e --keyword=__ -o file_name.pot

Lastly, you need to specify the file or files in which to search:


xgettext --keyword=_e --keyword=__ -o file_name.pot *.php subdirectory/*.php ...

Note that the … indicates more files. Do not enter it literally.

Now you can run the command. This will generate a new file with the name file_name, and a pot extension. You will need to give that file to your translators, and they will give you back a file with the translated text. That file should have a po extension, not pot.

Once you get that file, you just run the msgfmt command:


msgfmt translated_file.po -o locale.mo

This will generate a binary file which is the one you use with wordpress.

You may encounter encoding problems. In my case, I did. This may be because the files where sent back and forth via email as text files. Email clients sometimes change the encoding of text files. The error I was getting when I tried to msgft the translated file was this: “invalid multibyte sequence”

To solve it, I had to change the encoding of the file to utf-8. In order to do that, you need to use the uconv program. It may not be installed in your system, so you may have to install it. In ubuntu you do that by running:


sudo apt-get install libicu-dev

That is, according to the output I got when I tried to run it the first time.

Once you have it installed. You need to know from which encoding to which encoding you want to convert the file. You could not specify a “from” encoding, but it may not work. In my case it didn’t.

To find out the encoding you can do this:


encoding=$(file -i messages.po | sed "s/.*charset=\(.*\)$/\1/")
echo $encoding

Once you know the encoding of the file, you can simply run


uconv -f ico-8859-1 -t utf-8 -o converted.po -v messages.po

We are specifying we want to encode from ico-8859-1 to utf-8, we want the output file to be converted.po, we want the program to run in verbose mode so we can see as much info as possible, and we want the conversion to be performed on the messages.po file.

Once you do that, you can run msgfmt with no problems.

That’s it!

Here are some of the links I found useful this time:
http://stackoverflow.com/questions/12866068/finding-the-encoding-of-text-files
https://mail.gnome.org/archives/gnome-i18n/2006-June/msg00081.html
http://stackoverflow.com/questions/1083518/msgfmt-invalid-multibyte-sequence-error-on-a-polish-text (not that useful, added just as a reference)

Advertisements

Links of the day 12/11/2012

Yet another list of links. The last list is also marked as 12/11/2012. When I did it it was past 12, and I forgot to subtract 1 from the date. I hope it is not too confusing.

HTML 5
http://davidwalsh.name/pointer-media-query – Quick intro to the pointer media query.

Security:
http://arstechnica.com/security/2012/12/dexter-malware-steals-credit-card-data-from-point-of-sale-terminals/ – The alert word for a malware that steals credit card data from point of sale terminals.

WordPress:
http://codex.wordpress.org/Version_3.5 – Version 3.5 is out!

Javascript:
http://rmurphey.com/blog/2012/12/10/js-conditionals/ – Nothing new about if statements, but still worth reading for a good memory refresh.

Github:
https://github.com/blog/1302-goodbye-uploads – No more uploads on github.

Other:
http://arstechnica.com/business/2012/12/netflix-says-google-fiber-is-most-consistently-fast-isp-in-america/ – Netflix says google fiber is the fastest ISP in America. Lucky those who have it.
http://alt1040.com/2012/12/google-chromebooks-sector-educativo – New $99 google laptops. (Spanish)
http://alt1040.com/2012/12/darpa-espuma-hemorragias – New foam technology to stop internal bleeding on wounded soldiers. (Spanish)

Links of the day 12/11/2012

I have been just sharing links these last few posts, and sadly, today is not the exception. I am aware there are a few posts that need to be written, and I need to continue on that series that I started about building AIR Apps, but time has just not been too kind with me lately. Anyway, I hope this links can keep you busy.

Javascript:
http://davidwalsh.name/documentfragment – Just a quick intro to document fragment.
http://davidwalsh.name/deferred – Javascript defer for a cleaner code.
http://www.sitepoint.com/get-started-with-three-js/ – Getting started with three.js
http://blog.millermedeiros.com/stop-writing-plugins-start-writing-components/ – Plugins VS Components. Interesting.
http://blog.millermedeiros.com/namespaces-are-old-school/ – Namespaces are old school, use modules.
http://blog.millermedeiros.com/amd-is-better-for-the-web-than-commonjs-modules/ – A look into why AMD is better than commonjs modules. Is it?

VIM:
blog.millermedeiros.com/tag/vim/ – Improved VIM status bar. Nice!

HTML 5
http://davidwalsh.name/phone-link-protocol – The phone link protocol.
http://davidwalsh.name/vibration-api – The vibrating API. Lets hope it does not get abused.

WordPress:
http://davidwalsh.name/ssl-wordpress – Quick and easy way to force SSL on wordpress sites.
http://dzineblog.com/2012/12/best-practices-for-keeping-wordpress-clean-secure.html – WordPress security best practices.

Interior Design:
http://www.home-designing.com/2012/12/toblerone-house-brazil
http://www.home-designing.com/2012/12/super-small-space-living-inspiration-ikea

Ubuntu
http://www.atareao.es/ubuntu/conociendo-ubuntu/quieres-aprender-a-crear-paquetes-para-ubuntu/ – How to create Ubuntu packages. (Spanish)

Design:
http://dzineblog.com/2012/11/33-new-freebie-buttons-and-icon-sets-released-in-autumn-2012.html – Free icon sets.

Ruby:
http://ruby-python.com.ar/ruby/ – A ruby tutorial that I have not yet followed, but I share in case you are interested. (Spanish)

Other:
http://davidwalsh.name/twitter-cards – Nice explanation on how to create twitter cards.
http://creativefan.com/black-and-white-backgrounds/ – Black and white backgrounds. Mostly pictures, and some of them are not really B&W, but still interesting.
http://alt1040.com/2012/12/twitter-rastrea-webs – Twitter keeps track of the sites you visit. And how to stop it. (Spanish)
http://build-podcast.com/ – A postcast about development tools.
http://www.mightydeals.com/ – A website that seems to offer good deals on resources for web professionals.

Enjoy the readings, and don’t hate me for posting nothing but links these last few rounds.

add_theme_support Generates call_user_func_array Error

While working on a theme I encountered the following error:

Warning: call_user_func_array() expects parameter 1 to be a valid callback, function ” not found or invalid function name in /path/to/themesite/wp-includes/plugin.php on line 403

At first I thought it was because of the way I’m building the theme. You may remember I’ve mentioned core a few times. core is a library I built to help speed HTML development. I have a class that makes building head elements very easy. The “problem” is that wordpress requires you to call the wp_head function on the head of your templates. I solved this by including a method on the class that can be used to call any function.

My first reaction was to change my header.php file for the one included on the twentyeleven theme, but the problem did not get solved. This hinted me that the problem was not in the way I was calling wp_head. Once I realized that, I started commenting parts of the code out. I have a line of code that takes care of including a file, which in turn includes a few more files. Each file adds a certain feature to the theme, like custom header, or background color. Commenting out the line that includes the first file solved the problem.

Once I realized that the problem was in one of the files that was being included which add features to the theme, I went on and started commenting out individual include lines to see which feature was causing the problem. This way I found out that the feature causing the problem was the custom background feature.

That file had the following code:


//Custom Background documentation: http://codex.wordpress.org/Custom_Backgrounds

$color = '1d1d1d';

$defaults = array(
        'default-color'          => $color,
        'default-image'          => '',
        'wp-head-callback'       => '',
        'admin-head-callback'    => '',
        'admin-preview-callback' => ''
);

add_theme_support('custom-background', $defaults);
?>

As you can see, the wp-head-callback is empty. Which was causing the problem, since this callback gets registered somewhere in wordpress, and then wordpress tries to call this callback, but it is empty. If you review the source code of add_theme_support you will see that it has a default callback. In this case, you have to either specify a call back or do not include that array element at all.

This is a pretty simple error, but it took me a good 20 minutes to figure out.

xkcd comic
Comic by XKCD

Instaling WordPress From the Command Line – Just for Fun

Today I decided to do a fun exercise. Lets install wordpress entirely from the command line. We will download wordpress, unzip it, and create the database and user, all from the command line.

Downloading and Setting Up wordpress

To download wordpress we are going to use wget.
wget is a non-interactive network downloader. It is a pretty neat tool. If you have never used it, I recommend you read the man page for it, and to give it a try.

In order to download wordpress we need to run the following command:

wget http://wordpress.org/latest.zip

Be sure to be on the directory in which you want wordpress to be downloaded. In my case I’m using my in-house server, so I have access to all of it. I download everything to the Downloads directory.

Once wget is finished downloading wordpress you should have a new zip file named latest.zip. We need to unzip this file:

unzip latest.zip

This will extract the zipped files. You should end up with a newly created wordpress directory. Remember that at this point I am still on the Downloads directory, so I need to move the wordpress directory to public_html, which is the directory that apache uses as root. I will also change the name of the newly created wordpress directory to something more meaningful. Since I will be using this installation to develop a theme, I will just name it as the theme:

mv wordpress/ ../public_html/cafe

We are done with this step. Now we need to create the database and mysql user for this installation of wordpress.

Creating MySQL Database and User

We need to start mysql cli in order to create the database and user:

mysql -u user_name -p

user_name is the user name that you use to connect to your MySQL server. You will be required to enter your password. Once you do, you will be logged into the MySQL server and you will be able to run commands.

Creating the Database

Creating the database is simple:
CREATE DATABASE databasename;
You will need to change database for the name you want to give to your database.

Creating the User

Creating the user is also very simple:
CREATE USER 'user'@'localhost' IDENTIFIED BY 'passwd';
You need to change user for the user name you want to use. If you will be accessing the database from a different server, then change localhost for the host name that from which you will be accessing the database.

Now we need to grant the newly created user enough privileges to manage the database:

GRANT ALL PRIVILEGES ON databasename.* TO 'user'@'localhost';

Since this is just an exercise, we are granting all privileges. On a production site, you may want to not do this, and just grant enough privileges to the user so it can function properly.

Lastly, edit the wp-config.php file, and add the database and user information.

We are done. All that is left to do is run the wordpress installation program. Just use your browser to navigate to your wordpress installation, and install wordpress as you usually do.

Some reads you may be interested on:

http://dev.mysql.com/doc/refman/5.1/en/adding-users.html
http://dev.mysql.com/doc/refman/5.5/en/creating-database.html

A Little About the setup_postdata() WordPress Function

Today I spent some minutes trying to get setup_postdata() to work. The problem I was having was that the function seemed to be setting the data for one post only. I was using it along with get_posts. If you look at the setup_postdata function documentation, you will find that it is really of not much help when it comes to finding out why it might not be working properly.

This is the situation I found myself in: I was developing a widget that takes the latest posts from the specified category and displays them. That is pretty easy to do. However, I hit an error when I was displaying the posts. The code looked like this:

function widget($args, $instance){
  //..some standard code
  $posts = get_posts($options);
  foreach($posts as $post){
    setup_postdata($post);
    //..some more code here
  }
  //..some more code here
}

I’ve got rid of the code that is not relevant to the situation.

That seemed to not work properly, and I got this output:

title1
title1
title1
title1

When I should have been getting this:

title1
title2
title3
title4

I went and checked the documentation of the functions involved and nothing seemed to be wrong. So I decided to look at the code of the function. I knew that the loop was setting the proper value for $post on each round. But for some reason setup_postdata was setting up the data for the same post over and over again.

It turns out I don’t really need to setup_postdata() at all, but I do it just to be sure. The functions I’m using to display the information are the_permalink, and the_title.

setup_postdata doesn’t really set up all the data related to a post. It sets only some of it, specifically the numeric ID, the author data, the day, the month, the current page, the content, whether the post is multi-page, the number of pages, and variable named $more that I currently am not sure what it is used for. This information is used by some functions like the_content.

The source of the problem was not really on setup_postdata, but on the_title and the_permalink. the_title, for example, relies on a function called get_the_title, which takes a single argument: a post id. This post id can be 0, which in fact is the default value. get_the_title then calls get_post, and passes the post id as parameter to that function. get_post, in turn, checks for that post id, if it is an empty value (zero is an empty value), then it uses the global $post, and that is where the problem was.

In order for functions like the_title to work properly when inside a function, you must declare a global post variable:

global $post;

you should do that, preferably at the top of your function. This overwrites the current global $post with the post that you are trying to access information from.

So, as it turns out, setup_postdata is a function that only sets some global variables that can be used by other functions like the_content. Keep in mind that you don’t always have to use setup_postdata, and if you do use it, always consider running wp_reset_postdata(); when you are done.

And finally, remember that functions like the_title, the_permalink, the_content, and so on, rely on the global $post. This means that you should always declare a global $post inside any function that uses those functions mentioned earlier. When looping through a set of posts that you got from functions like get_posts, always name the current item $post:

foreach($posts as $post)//<-That $post is important! Do not use another name, or it won't work.

WordPress en ubuntu

Ayer, antes de salir a trabajar, instale wordpress en ubuntu para empezar un sitio web que estoy desarrollando. Todo iba bien, la instalación fue exitosa, las tablas fueron creadas en la base de datos y la parte del admin funcionaba bien, pero cuando quería ir a la pagina frontal de wordpress solo me mostraba el directorio de wordpress, con todos los archivos y demas:

Como no tenia tiempo de revisar que era lo que pudiera estar pasando, decidí apagar la computadora y dejar el problema para hoy. Hoy me levante y empecé a trabajar nuevamente en el asunto. La primera pista me vino al ver que al introducir la dirección al index.php de wordpress este re-direccionaba de la siguiente manera:

http://localhost/wordpress/index.php

re-direccionaba.

http://localhost/wordpress/

yo se que mi servidor busca por index.html al ingresar en un directorio, en este caso es lo que estaba haciendo. A pesar de que yo ingresaba index.php en la barra de direcciones, wordpress re-direccionaba a simplemente / o en otras palabras, simplemente me mandaba al directorio wordpress/ donde mi server nuevamente buscaba index.html y no lo encontraba, por lo que mostraba la lista de archivos del directorio wordpress.

Para ser sincero, a pesar de saber que mi server busca por index.html y no por index.php (así lo quise desde un principio por razones personales que la verdad ya no recuerdo muy bien) no se me había ocurrido que ese fuera el problema. Estuve viendo en los archivos de wordpress y tratando de encontrar el error ahí y nada. Después de unos minutos se me ilumino el cerebro y pensé en cambiar la configuración de apache para que buscara por index.php si no encontraba index.html. Eso resolvió el problema. Así que si tienes el mismo problema, quizá quieras probar lo siguiente:

1)Abre terminal
2)Teclea lo siguiente:

gksudo gedit /usr/local/apache2/conf/httpd.conf

Si tu instalación de apache no esta en el directorio local dentro de /usr/ o si tu folder se llama algo diferente a apche2 necesitas modificar un poco la instrucción. La cosa es que pongas la ruta a tu directorio de instalación de apache o mas específicamente a tu archivo httpd.conf. Si no sabes donde está, puedes usar el buscador de archivos.

Una vez que hayas dado esa instrucción, se te abrirá gedit con un archivo (el httpd.conf). Es recomendable que hagas primero una copia por si algo sale mal.

3)Busca la siguiente linea:

<IfModule dir_module>
DirectoryIndex index.html
</IfModule>

4)y agrega index.php despues de index.html

<IfModule dir_module>
DirectoryIndex index.html index.php
</IfModule>

5)Guarda y cierra el archivo.
6)En terminal, pon la siguiente instrucción y presiona enter para re-inciar apache:
sudo /usr/local/apache2/bin/apachectl -k restart

Y eso es todo, ahora deberías poder ver wordpress sin problema alguno.

Saludos.

Nota: la linea que editamos en el httpd.conf es la que le dice a apache que archivo cargar cuando entra en un directorio.