Concluyo esta sección de acceder a datos o hacer uso de otras funciones de Wordpress, pero usando PHP, esperando les halla sido de utilidad. También quiero agradecer a Javier Gutierrez Chamorro (Guti) por estar siempre al pendiente de lo que publico en este blog y hacerme observaciones, muchísimas gracias, si es para mejorar adelante, son bienvenidas las sugerencias. Pues bien, en esta última entrega de Wordpress voy a hacer una corrección a la función para leer un archivo PO desde php que se publicó algunas semanas atrás basada en las observaciones recibidas por Guti.
En el formato original esta función abre un archivo PO, lo lee línea por línea hasta que encuentra la llave a buscar, si la encuentra devuelve su valor, sinó habrá que esperar hasta que termine de leer todo el archivo y se retornará un valor vacío. Esto funciona sin problemas, el único detalle es ¿que pasa si varias veces se tiene que llamar esa función en el mismo archivo PHP?, pues que todas las veces que se requiera tendrá que abrir y cerrar el archivo, y buscar una y otra vez, lo cual es un procedimiento lento y además existe el riesgo de colapsar al servidor.
Publicidad
La corrección sugerida es vaciar el contenido de ese archivo a memoria, y luego ya buscar ahí lo que necesitemos, si tenemos la necesidad de buscar varias llaves traducidas, no habrá necesidad de abrir y cerrar el archivo una y otra vez, solo una; ahora solo hay que buscar en memoria las llaves traducidas.
Este es el nuevo código:
<?php
$translatedarray = array();
//thanks to http://www.desarrolloweb.com/articulos/893.php
//thanks to Javier Gutierrez Chamorro (Guti) http://www.javiergutierrezchamorro.com/
function getTranslatedStringFromPOFile($pofile, $msgid)
{
global $translatedarray;
if(trim($pofile) == "")
return $msgid;
else
{
if(!file_exists(trim($pofile)))
return $msgid;
else
{
if(trim($msgid) == "")
return "";
else
{
if(empty($translatedarray) == false)
return gettranslatedstring(trim($msgid));
else
{
$line = "";
$fp = fopen(trim($pofile), "r");
while(!feof($fp))
{
$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)
$msgkeyname = substr($msgidvalue, 1, strlen($msgidvalue) - 1);
if(endWith(strtolower(trim($msgkeyname)), chr(34), false) == true)
$msgkeyname = substr($msgkeyname, 0, strlen($msgkeyname) - 1);
$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);
array_push($translatedarray, array("ID" => trim($msgkeyname), "VALUE" => $msgstrvalue));
}
}
}
}
fclose($fp);
return getTranslatedString(trim($msgid));
}
}
}
}
}
//thanks to http://www.anerbarrena.com/php-foreach-4298/
function getTranslatedString($msgid)
{
global $translatedarray;
$GLOBALS["msgid"] = trim($msgid);
$filterarray = array_filter($translatedarray, "getrst");
foreach($filterarray as $key=>$value)
$thearray = $value;
if(empty($thearray) == true)
return "";
else
return $thearray["VALUE"];
}
function getrst($var)
{
if(empty($var) == false)
if(strtolower(trim($var["ID"])) == strtolower(trim($GLOBALS["msgid"])))
return $var;
}
//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;
}
}
}
}
$originalstr = "Shipping zones";
$translatedstr = getTranslatedStringFromPOFile("woocommerce-es_ES.po", trim($originalstr));
echo "valor original=".$originalstr.", valor traducido=".$translatedstr."<br><br>";
$originalstr = "Error: non-existing attribute ID.";
$translatedstr = getTranslatedStringFromPOFile("woocommerce-es_ES.po", trim($originalstr));
echo "valor original=".$originalstr.", valor traducido=".$translatedstr."<br><br>";
$originalstr = "Bouvet Island";
$translatedstr = getTranslatedStringFromPOFile("woocommerce-es_ES.po", trim($originalstr));
echo "valor original=".$originalstr.", valor traducido=".$translatedstr."<br><br>";
?>
El código sigue siendo básicamente el mismo, la única diferencia es que ahora, si el arreglo $translatedarray se encuentra vacio, se lee el archivo normalmente y se carga todo su contenido a esa variable, luego se manda a llamar a la función getTranslatedString que busca la llave y retorna el valor traducido.
En caso de que ya halla datos en $translatedarray entonces se llama directo a getTranslatedString pasandole como parámetro la llave a buscar, si todo sale bien esta función nos retornará el valor de la llave, que es la cadena traducida.
La corrección sugerida es vaciar el contenido de ese archivo a memoria, y luego ya buscar ahí lo que necesitemos, si tenemos la necesidad de buscar varias llaves traducidas, no habrá necesidad de abrir y cerrar el archivo una y otra vez, solo una; ahora solo hay que buscar en memoria las llaves traducidas.
Este es el nuevo código:
<?php
$translatedarray = array();
//thanks to http://www.desarrolloweb.com/articulos/893.php
//thanks to Javier Gutierrez Chamorro (Guti) http://www.javiergutierrezchamorro.com/
function getTranslatedStringFromPOFile($pofile, $msgid)
{
global $translatedarray;
if(trim($pofile) == "")
return $msgid;
else
{
if(!file_exists(trim($pofile)))
return $msgid;
else
{
if(trim($msgid) == "")
return "";
else
{
if(empty($translatedarray) == false)
return gettranslatedstring(trim($msgid));
else
{
$line = "";
$fp = fopen(trim($pofile), "r");
while(!feof($fp))
{
$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)
$msgkeyname = substr($msgidvalue, 1, strlen($msgidvalue) - 1);
if(endWith(strtolower(trim($msgkeyname)), chr(34), false) == true)
$msgkeyname = substr($msgkeyname, 0, strlen($msgkeyname) - 1);
$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);
array_push($translatedarray, array("ID" => trim($msgkeyname), "VALUE" => $msgstrvalue));
}
}
}
}
fclose($fp);
return getTranslatedString(trim($msgid));
}
}
}
}
}
//thanks to http://www.anerbarrena.com/php-foreach-4298/
function getTranslatedString($msgid)
{
global $translatedarray;
$GLOBALS["msgid"] = trim($msgid);
$filterarray = array_filter($translatedarray, "getrst");
foreach($filterarray as $key=>$value)
$thearray = $value;
if(empty($thearray) == true)
return "";
else
return $thearray["VALUE"];
}
function getrst($var)
{
if(empty($var) == false)
if(strtolower(trim($var["ID"])) == strtolower(trim($GLOBALS["msgid"])))
return $var;
}
//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;
}
}
}
}
$originalstr = "Shipping zones";
$translatedstr = getTranslatedStringFromPOFile("woocommerce-es_ES.po", trim($originalstr));
echo "valor original=".$originalstr.", valor traducido=".$translatedstr."<br><br>";
$originalstr = "Error: non-existing attribute ID.";
$translatedstr = getTranslatedStringFromPOFile("woocommerce-es_ES.po", trim($originalstr));
echo "valor original=".$originalstr.", valor traducido=".$translatedstr."<br><br>";
$originalstr = "Bouvet Island";
$translatedstr = getTranslatedStringFromPOFile("woocommerce-es_ES.po", trim($originalstr));
echo "valor original=".$originalstr.", valor traducido=".$translatedstr."<br><br>";
?>
El código sigue siendo básicamente el mismo, la única diferencia es que ahora, si el arreglo $translatedarray se encuentra vacio, se lee el archivo normalmente y se carga todo su contenido a esa variable, luego se manda a llamar a la función getTranslatedString que busca la llave y retorna el valor traducido.
En caso de que ya halla datos en $translatedarray entonces se llama directo a getTranslatedString pasandole como parámetro la llave a buscar, si todo sale bien esta función nos retornará el valor de la llave, que es la cadena traducida.
En el ejemplo hay tres traducciones a realizar, y hasta el momento de la prueba (archivo woocommerce-es_ES.po que contiene 21935 línea de texto) apenas si consume tiempo. Espero les sea de mucha utilidad.
¿Te gustó este post?, entonces si lo deseas puedes apoyarnos para continuar con nuestra labor, gracias.
Procedencia de las imágenes: |
File: Logo base de datos URL: http://images.all-free-download.com/images/graphiclarge/two_patch_icon_clip_art_9626.jpg Licencia: Creative Commons |
¿Te gustó este post?, entonces si lo deseas puedes apoyarnos para continuar con nuestra labor, gracias.
Muy buena mejora. Y gracias por el crédito.
ResponderBorrargracias a ti por tu apoyo.
BorrarAprovechando la sugerencia, lo he implementado yo también en C++ para FileOptimizer:
ResponderBorrarhttps://sourceforge.net/p/nikkhokkho/code/HEAD/tree/trunk/FileOptimizer/Source/clsLanguage.cpp.
que bien :) , osea que fileoptimizer usará ahora archivos PO para las traducciones?
BorrarEso espero. Estamos trabajando en ello :-)
ResponderBorrarYa hay una beta disponible:
ResponderBorrarhttps://sourceforge.net/p/nikkhokkho/discussion/fileoptimizer/thread/746b6fa6/
genial :-bd
Borrar