A partir de este momento y por algunas ediciones estaré presentando algunos trucos para PHP y Wordpress esperando que sean de su agrado. Wordpress es un sistema de gestión de contenidos o CMS (por sus siglas en inglés) que se encarga de crearnos un sitio web completo en minutos,1 dentro de sus ventajas es que puede ser traducido de un idioma a otro gracias a los archivos PO que acompañan a muchos temas y plugins diseñados para Wordpress.
Este recurso te va a mostrar como leer un archivo PO directamente desde PHP (sin pasar por Wordpress que tiene soporte nativo), te invito a que sigas leyendo por favor.
Este recurso te va a mostrar como leer un archivo PO directamente desde PHP (sin pasar por Wordpress que tiene soporte nativo), te invito a que sigas leyendo por favor.
Veamos antes que nada que son los archivos PO. Los archivos PO (Portable Object) son simples archivos de texto que nos proporcionan información de una interfaz en diferentes idiomas, dentro de ellos encontramos una llave y su respectivo valor a mostrar como traducido, ejemplo:
#: includes/api/class-wc-rest-system-status-controller.php:491
msgid "Terms in the product visibility taxonomy."
msgstr "Los términos en la taxonomía de visibilidad del producto."
Donde la primer línea (comienza con #) es un comentario sobre la funcionalidad de la sección en cuestión, la segunda línea es la llave y la tercera la traducción respectiva de esa llave.
Así de un modo simple podemos traducir temas, plugins y demás material para nuestra plantilla de Wordpress, una vez editado nuestro archivo hay que generar el archivo MO (Machine Object, podemos usar Poedit para agilizar el trabajo), luego dentro de Wordpress hay que copiar esos dos archivos a la carpeta wp-content/languages/plugins o wp-content/languages/themes respectivamente (dependiendo del tipo de componente), de lo contrario Wordpress no puede encontrarlos y no se puede efectuar la traducción.
Pero, el problema es que si queremos usar esos archivos (concretamente el archivo PO) desde un archivo PHP que no tenga ninguna relación, no podremos, ¿porqué no?, porque para leer los archivos PO necesitamos de las funciones _e o translate de Wordpress, esas funciones no existen de forma nativa en PHP. Así que podemos hacer dos cosas para remediar el problema:
Con respecto a la segunda opción, presento a ustedes la función "getTranslatedStringFromPOFile", esta función retorna una cadena de texto que es el valor traducido (desde un archivo PO usando como referencia una llave) y acepta dos parámetros para funcionar: la ruta del archivo PO a leer y el ID o llave a leer.
El código fuente es el siguiente:
//thanks to http://www.desarrolloweb.com/articulos/893.php
function getTranslatedStringFromPOFile($pofile, $msgid)
{
$found = false;
if(trim($pofile) == "")
return $msgid;
else
{
if(!file_exists(trim($pofile)))
return $msgid;
else
{
if(trim($msgid) == "")
return "";
else
{
$line = "";
$fp = fopen(trim($pofile), "r");
while(!feof($fp) || $found == false)
{
$line = trim(fgets($fp, 1024));
if(trim($line) != "")
{
if(startWith(strtolower(trim($line)), "msgid", false) == true)
{
$start = strpos(strtolower($line), "msgid");
$msgidvalue = substr($line, $start, strlen($line));
$start = strpos(strtolower($msgidvalue), " ");
$msgidvalue = substr($msgidvalue, $start + 1, strlen($line));
if(startWith(strtolower(trim($msgidvalue)), chr(34), false) == true)
$msgidvalue = substr($msgidvalue, 1, strlen($msgidvalue) - 1);
if(endWith(strtolower(trim($msgidvalue)), chr(34), false) == true)
$msgidvalue = substr($msgidvalue, 0, strlen($msgidvalue) - 1);
if(trim(strtolower($msgidvalue)) == trim(strtolower($msgid)))
{
$found = true;
$line = trim(fgets($fp, 1024));
if(trim($line) != "")
{
$start = strpos(strtolower($line), "msgstr");
$msgstrvalue = substr($line, $start, strlen($line));
$start = strpos(strtolower($msgstrvalue), " ");
$msgstrvalue = substr($msgstrvalue, $start + 1, strlen($line));
if(startWith(strtolower(trim($msgstrvalue)), chr(34), false) == true)
$msgstrvalue = substr($msgstrvalue, 1, strlen($msgstrvalue) - 1);
if(endWith(strtolower(trim($msgstrvalue)), chr(34), false) == true)
$msgstrvalue = substr($msgstrvalue, 0, strlen($msgstrvalue) - 1);
$msgstr = $msgstrvalue;
}
else
$msgstr = "";
}
}
}
}
fclose($fp);
if($found == false)
$msgstr = $msgid;
return $msgstr;
}
}
}
}
//thanks to https://stackoverflow.com/questions/834303/startswith-and-endswith-functions-in-php
function startWith($str, $c, $sensitivity)
{
if(trim($str) == "")
return false;
elseif(strlen(trim($str)) <= 0)
return false;
else
{
if($sensitivity == true)
{
if(strlen(trim($str)) == strlen(trim($c)))
{
if(trim($str) == trim($c))
return true;
else
return false;
}
else
{
if(substr(trim($str), 0, strlen(trim($c))) == trim($c))
return true;
else
return false;
}
}
else
{
if(strlen(trim($str)) == strlen(trim($c)))
{
if(trim(strtolower($str)) == trim(strtolower($c)))
return true;
else
return false;
}
else
{
if(substr(trim(strtolower($str)), 0, strlen(trim($c))) == trim(strtolower($c)))
return true;
else
return false;
}
}
}
}
function endWith($str, $c, $sensitivity)
{
if(trim($str) == "")
return false;
elseif(strlen(trim($str)) <= 0)
return false;
else
{
if($sensitivity == true)
{
if(strlen(trim($str)) == strlen(trim($c)))
{
if(trim($str) == trim($c))
return true;
else
return false;
}
else
{
if(substr(trim($str), (strlen(trim($str)) - strlen(trim($c))), strlen(trim($c))) == trim($c))
return true;
else
return false;
}
}
else
{
if(strlen(trim($str)) == strlen(trim($c)))
{
if(trim(strtolower($str)) == trim(strtolower($c)))
return true;
else
return false;
}
else
{
if(substr(trim(strtolower($str)), (strlen(trim($str)) - strlen(trim($c))), strlen(trim($c))) == trim(strtolower($c)))
return true;
else
return false;
}
}
}
}
Como pueden ver la funcionalidad es muy simple:
Referencias:
1.- Wordpress
¿Te gustó este post?, entonces si lo deseas puedes apoyarnos para continuar con nuestra labor, gracias.
#: includes/api/class-wc-rest-system-status-controller.php:491
msgid "Terms in the product visibility taxonomy."
msgstr "Los términos en la taxonomía de visibilidad del producto."
Donde la primer línea (comienza con #) es un comentario sobre la funcionalidad de la sección en cuestión, la segunda línea es la llave y la tercera la traducción respectiva de esa llave.
Así de un modo simple podemos traducir temas, plugins y demás material para nuestra plantilla de Wordpress, una vez editado nuestro archivo hay que generar el archivo MO (Machine Object, podemos usar Poedit para agilizar el trabajo), luego dentro de Wordpress hay que copiar esos dos archivos a la carpeta wp-content/languages/plugins o wp-content/languages/themes respectivamente (dependiendo del tipo de componente), de lo contrario Wordpress no puede encontrarlos y no se puede efectuar la traducción.
Pero, el problema es que si queremos usar esos archivos (concretamente el archivo PO) desde un archivo PHP que no tenga ninguna relación, no podremos, ¿porqué no?, porque para leer los archivos PO necesitamos de las funciones _e o translate de Wordpress, esas funciones no existen de forma nativa en PHP. Así que podemos hacer dos cosas para remediar el problema:
- Integrar a nuestro sistema una librería que nos permita usar estas funciones de forma "nativa"
- Usar una función desarrollada por un servidor que hace lo mismo que la función "translate"
Con respecto a la segunda opción, presento a ustedes la función "getTranslatedStringFromPOFile", esta función retorna una cadena de texto que es el valor traducido (desde un archivo PO usando como referencia una llave) y acepta dos parámetros para funcionar: la ruta del archivo PO a leer y el ID o llave a leer.
El código fuente es el siguiente:
Actualización:
Gracias a Javier Gutierrez Chamorro (Guti) se ha hecho una mejora a esta función para reducir el tiempo de lectura de las cadenas traducidas, pueden ver el nuevo código fuente en este post.
|
//thanks to http://www.desarrolloweb.com/articulos/893.php
function getTranslatedStringFromPOFile($pofile, $msgid)
{
$found = false;
if(trim($pofile) == "")
return $msgid;
else
{
if(!file_exists(trim($pofile)))
return $msgid;
else
{
if(trim($msgid) == "")
return "";
else
{
$line = "";
$fp = fopen(trim($pofile), "r");
while(!feof($fp) || $found == false)
{
$line = trim(fgets($fp, 1024));
if(trim($line) != "")
{
if(startWith(strtolower(trim($line)), "msgid", false) == true)
{
$start = strpos(strtolower($line), "msgid");
$msgidvalue = substr($line, $start, strlen($line));
$start = strpos(strtolower($msgidvalue), " ");
$msgidvalue = substr($msgidvalue, $start + 1, strlen($line));
if(startWith(strtolower(trim($msgidvalue)), chr(34), false) == true)
$msgidvalue = substr($msgidvalue, 1, strlen($msgidvalue) - 1);
if(endWith(strtolower(trim($msgidvalue)), chr(34), false) == true)
$msgidvalue = substr($msgidvalue, 0, strlen($msgidvalue) - 1);
if(trim(strtolower($msgidvalue)) == trim(strtolower($msgid)))
{
$found = true;
$line = trim(fgets($fp, 1024));
if(trim($line) != "")
{
$start = strpos(strtolower($line), "msgstr");
$msgstrvalue = substr($line, $start, strlen($line));
$start = strpos(strtolower($msgstrvalue), " ");
$msgstrvalue = substr($msgstrvalue, $start + 1, strlen($line));
if(startWith(strtolower(trim($msgstrvalue)), chr(34), false) == true)
$msgstrvalue = substr($msgstrvalue, 1, strlen($msgstrvalue) - 1);
if(endWith(strtolower(trim($msgstrvalue)), chr(34), false) == true)
$msgstrvalue = substr($msgstrvalue, 0, strlen($msgstrvalue) - 1);
$msgstr = $msgstrvalue;
}
else
$msgstr = "";
}
}
}
}
fclose($fp);
if($found == false)
$msgstr = $msgid;
return $msgstr;
}
}
}
}
//thanks to https://stackoverflow.com/questions/834303/startswith-and-endswith-functions-in-php
function startWith($str, $c, $sensitivity)
{
if(trim($str) == "")
return false;
elseif(strlen(trim($str)) <= 0)
return false;
else
{
if($sensitivity == true)
{
if(strlen(trim($str)) == strlen(trim($c)))
{
if(trim($str) == trim($c))
return true;
else
return false;
}
else
{
if(substr(trim($str), 0, strlen(trim($c))) == trim($c))
return true;
else
return false;
}
}
else
{
if(strlen(trim($str)) == strlen(trim($c)))
{
if(trim(strtolower($str)) == trim(strtolower($c)))
return true;
else
return false;
}
else
{
if(substr(trim(strtolower($str)), 0, strlen(trim($c))) == trim(strtolower($c)))
return true;
else
return false;
}
}
}
}
function endWith($str, $c, $sensitivity)
{
if(trim($str) == "")
return false;
elseif(strlen(trim($str)) <= 0)
return false;
else
{
if($sensitivity == true)
{
if(strlen(trim($str)) == strlen(trim($c)))
{
if(trim($str) == trim($c))
return true;
else
return false;
}
else
{
if(substr(trim($str), (strlen(trim($str)) - strlen(trim($c))), strlen(trim($c))) == trim($c))
return true;
else
return false;
}
}
else
{
if(strlen(trim($str)) == strlen(trim($c)))
{
if(trim(strtolower($str)) == trim(strtolower($c)))
return true;
else
return false;
}
else
{
if(substr(trim(strtolower($str)), (strlen(trim($str)) - strlen(trim($c))), strlen(trim($c))) == trim(strtolower($c)))
return true;
else
return false;
}
}
}
}
Como pueden ver la funcionalidad es muy simple:
- Si el archivo existe, es abierto para lectura
- Se localiza la llave (leyendo línea por línea el archivo)
- Una vez localizada la llave, se lee la siguiente línea que es el valor a traducir
- Se cierra el archivo
- Se devuelve el valor traducido
Procedencia de las imágenes: |
File: Banderas de América URL: https://www.vecteezy.com/vector-art/117771-americas-flags Licencia: Creative Commons |
Referencias:
1.- Wordpress
¿Te gustó este post?, entonces si lo deseas puedes apoyarnos para continuar con nuestra labor, gracias.
Para editar archivos PO, yo uso poedit, así te ahorras editarlos a mano. En cuanto a la función, la verdad que no me gusta que tenga que abrir el archivo, buscar el string, y cerrar el archivo cada vez que se necesita una traducción. Es poco eficiente.
ResponderBorrarLo que yo haría sería leer el archivo completo en memoria, y entonces buscar las traducciones allí cada vez que se pidiera una, sin necesidad de volverlo a cargar.
También uso poedit y es muy bueno, tienes razón en lo de abrir y cerrar el archivo, la verdad no había pensado en eso y haré la corrección que me sugieres, gracias. :-bd
Borrar