Es muy fácil hacer la vista gorda respecto a otros idiomas cuando estás desarrollando un tema para WordPress, pero éste es un mal hábito que además aleja todo un mercado de usuarios de WordPress y con ello la pérdida potencial de miles de dólares en beneficios. De los 10 principales países realizando búsquedas en Google sobre «temas para WordPress», sólo uno es anglófono (los EE.UU.) y ocupa el puesto número 9 del anterior ranking. En el momento de escribir este artículo, sólo existen 269 temas en la base de datos de WordPress etiquetados como «preparados para traducción» (translation-ready), del total de 1,500 temas existentes. Esto es sólo un 18% de los temas. Te voy a enseñar cómo hacer que tu tema sea uno de ellos.
Cómo funciona
Normalmente, cuando construyes un tema, simplemente escribes junto con el código el texto que quieres mostrar en front-end del mismo, como el mensaje de error del archivo 404.php, o etiquetas como «comentarios:» o «autor:» De esta forma, aunque el usuario de WordPress sea por ejemplo alemán, estos fragmentos de texto se mostrarán en inglés. La solución a esto es devolver o repetir estas frases usando una de las cuatro funciones de WordPress diseñadas para referenciar el texto correcto ubicado en el archivo de idioma. Una vez tengas los textos a traducir dentro de estas funciones, podrás crear un archivo conteniendo todas las traducciones referenciadas cada vez que el tema se cargue. Existen tres archivos que vamos a usar para las traducciones:
- .pot (Portable Object Template) – Éste es el archivo que contiene una referencia a cada cadena de texto que aparece en tu tema y que necesita ser traducida. El archivo no contiene ninguna traducción. Es un archivo de texto plano.
- .po (Portable Object) – Obtenido a partir del archivo .pot, .po contiene todas las referencias de tus cadenas así como sus traducciones a un idioma específico. También se trata de un archivo de texto plano que puede ser editado.
- .mo (Machine Object) – Es una versión binaria del archivo .po. A través del uso de código de máquina, el archivo se puede usar mucho más rápido que la versión en texto plano alternativa.
Paso 1 Las Cuatro Funciones
Cada una de las cuatro funciones requiere al menos un argumento, que se corresponde con el texto que debe ser traducido. Las funciones son:
__()
– (dos guiones bajos) La función básica que usarás la mayoría de las veces. Devuelve el texto en el idioma correcto._e()
– Lo mismo que__()
excepto que repite el texto en lugar de devolverlo._n()
– Se usa cuando el texto tiene el potencial de estar en plural, así por ejemplo si fueses a mostrar cuantos comentarios se han hecho, podrías querer imprimir en la salida tanto «X comentarios» como «X comentario», dependiendo del número de comentarios que existan._x()
– Útil cuando la traducción de la palabra depende del contexto. «Post» podría querer significar «a post (nombre)» o «to post (verbo)» Es importante que el traductor sepa a lo que te referías para que la traducción sea correcta._x()
se usa principalmente cuando se usan palabras simples.
__() y _e()
Estas son las funciones de traducción más simples que WordPress ofrece. Veamos un ejemplo con cada una de ellas:
1 2 3 4 5 |
<?php if( is_single() ) { //If this is a "post" echo __( 'This is a post.' ); } ?> |
1 2 3 4 5 |
<?php if( is_single() ) { //If this is a "post" _e( 'This is a post.' ); } ?> |
Ambas funciones hacen exactamente lo mismo aquí. La frase «this is a post» (esto es una entrada) se revisa confrontándola con el archivo .mo en caso de que éste exista, y devuelve el resultado. __()
y _e()
sólo requieren que se les proporcione un argumento, que no es otra cosa que es el texto que queremos traducir. Un segundo argumento opcional está disponible y lo veremos más tarde. La única diferencia entre las dos es que __()
necesita aquí de echo
. Veamos un ejemplo en el que __()
funciona mejor que _e()
:
1 2 3 |
<?php the_content( __( 'Click here to read more' ) ); ?> |
En lugar de pasar una cadena a la función the_content()
, hemos usado __()
de manera que el texto pueda ser traducido. Si hubiésemos usado aquí _e()
en su lugar, habrías obtenido la traducción de «Click here to read more» repetida en el documento en lugar de haber sido enviada a the_content()
lo que hubiese ocasionado todo tipo de problemas.
_n()
¿Qué pasaría en una situación en la que el texto que debes mostrar pudiese estar potencialmente en plural o singular como el ejemplo de «X comentarios» que vimos? En lugar de darle al traductor dos cadenas de texto diferentes, puedes indicar que tienes una pieza de texto que necesita una traducción al singular y al plural. Los dos ejemplos siguientes imprimen en la salida el mismo resultado para el usuario:
1 2 3 4 5 6 7 |
<?php if(get_comments_number() == 1) { _e( 'There is a comment' ); } else { _e( 'There are comments' ); } ?> |
1 2 3 |
<?php echo _n( 'There is a comment' , 'There are comments' , get_comments_number() ); ?> |
_n()
requiere tres argumentos. El primero es la versión singular del texto, el segundo la versión en plural, y el tercero es el número al que está haciendo referencia. En este caso, get_comments_number()
está encontrando cuantos comentarios hay en el post y después _n()
elige el texto apropiado a usar.
_x() & _ex()
Digamos que estás traduciendo un archivo .pot, y llegas a un texto que dice «scroll». ¿Vas a interpretarlo como «una pieza de papel enrollado» o «desliza la página web hacia arriba o hacia abajo»? Puedes añadir algún contexto para describir cómo necesitas que algo sea traducido. Estas funciones te proporcionan la habilidad, a través del requerimiento de un segundo atributo que solicita una breve descripción para explicar la frase o palabra. Observa el ejemplo de abajo:
1 2 3 4 |
<?php echo _x( 'post link' <, 'A link to the post' ); _ex( 'post link' , 'Submit a link' ); ?> |
El ejemplo te muestra la diferencia entre _x()
y _ex()
. Es lo mismo e
, que _e
, para hacer que la función repita la salida en lugar de devolverla. Para ambas, nuestro primer parámetro es el texto que necesitamos traducir, y el segundo es un comentario o nota sobre la traducción del texto para clarificar su significado.
Técnicas avanzadas
Digamos que el texto que quieres generar es una cadena compuesta de texto con el resultado de una función o el valor de una variable ubicada en algún lugar dentro de la misma. Podrías estar tentado de hacer directamente esto:
1 2 3 4 |
<?php $color = the_color(); _e( "You have chosen the $color theme" ); ?> |
Cuando se trata de crear tu archivo .pot, POEdit ignorará lo anterior ya que no quiere usar variables en medio de la sentencia. La razón reside en que POEdit enviará la cadena You have chosen the $color theme
al archivo .po, pero cuando se trata de buscar la traducción en el momento en el que se ejecuta el script, buscará la cadena You have chosen the blue theme
, la cual no encontrará. Así que, hacemos lo siguiente en su lugar:
1 2 3 4 |
<?php $color = the_color(); echo __( 'You have chosen the ' ) . $color . __( ' theme.' ); ?> |
El script ahora será capaz de recuperar las traducciones, pero ahora es muy difícil traducirla porque la sentencia se ha roto. Necesitarás atravesar el problema de explicar que estas dos cadenas de texto individuales son parte de una, y que ese «theme» no debería traducirse por «theme» en absoluto.
La solución es usar una única cadena de texto que contiene una sola frase con una sintaxis amigable. Aquí es dónde las funciones printf()
o sprintf()
nos son útiles. Echemos un vistazo a cómo necesita verse nuestro código:
1 2 3 4 |
<?php echo sprintf( __( 'You have chosen the %s theme.' ) , the_color() ); printf( __( 'You have chosen the %s theme.' ) , the_color() ); ?> |
Esto no sólo soluciona todos los problemas que hemos tenido anteriormente, pero es más ordenado y sólo usa una línea de código. Los argumentos de las funciones printf()
o sprintf()
son la cadena que debe ser devuelta en la salida, y que contiene al menos una ubicación, en este caso %s
(que significa «cadena»), y cualquier otro argumento, son variables que se deben colocar dentro de la cadena inicial. Existen muchos marcadores diferentes que puedes usar dentro de tu cadena y puedes encontrar una lista completa bajo sprintf
en el manual de PHP. Date cuenta de que la diferencia entre printf()
y sprintf()
es similar la existente entre a _e()
y __()
respectivamente.
Lo que te queda por leer:
-
Paso 2 introducción a POEdit
-
Paso 3 traducir y crear tu archivo .po
-
Paso 4 configurar WordPress
Deja una respuesta