<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>/dev/GON.cl &#187; php</title>
	<atom:link href="http://blog.gon.cl/cat/development/php/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.gon.cl</link>
	<description>blog respaldo anti-amnesia</description>
	<lastBuildDate>Wed, 28 Jul 2010 20:44:48 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>es</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Respetarte tu mismo debes, (Cr&#237;tica a Joomla #1)</title>
		<link>http://blog.gon.cl/post/676</link>
		<comments>http://blog.gon.cl/post/676#comments</comments>
		<pubDate>Wed, 11 Mar 2009 06:29:27 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[joomla]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[crÃ­tica]]></category>
		<category><![CDATA[xml]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=676</guid>
		<description><![CDATA[Mientras trabaja por volver a levantar un sitio que antiguamente usaba joomla 1.0, tuve un peque&#241;a molestia en el panel de control del nuevo 1.5, debido a que me sal&#237;a un mensaje de error.
Afortunadamente no era fatal, ya que igualmente pod&#237;a modificar los par&#225;metros del sitio sin mayor inconveniente. Pero es molesto ver que algo [...]]]></description>
			<content:encoded><![CDATA[<p>Mientras trabaja por volver a levantar un sitio que antiguamente usaba joomla 1.0, tuve un peque&ntilde;a molestia en el panel de control del nuevo 1.5, debido a que me sal&iacute;a un mensaje de error.</p>
<p>Afortunadamente no era fatal, ya que igualmente pod&iacute;a modificar los par&aacute;metros del sitio sin mayor inconveniente. Pero es molesto ver que algo no est&aacute; bien, menos en un sistema grande como lo es Joomla.</p>
<p>El error me indicaba que hab&iacute;a un archivo XML que no se estaba &#8220;parseando&#8221; adecuadamente, pero no me dec&iacute;a cual archivo ni cual error ten&iacute;a.</p>
<p>Entonces decid&iacute; bajar una copia de seguridad del sitio completo, y replicarlo en mi m&aacute;quina local para averiguar el error. Record&eacute; que en linux existen miles de aplicaciones por consola, lo suficientemente poderosas para <strong>parsear</strong> y <strong>validar</strong> los XML&#8217;s de mi sitio.</p>
<p>Ya tuve <a href="http://blog.gon.cl/post/12">una experiencia grata con el comando <strong>find</strong></a>. Pero me faltaba el comando para validar un archivo xml. Buscando encontr&eacute; que posiblemente el comando <strong>xmllint</strong> me podr&iacute;a servir. Aunque finalmente no me ayud&oacute;, revel&eacute; un peque&ntilde;o detalle que no me esperaba.</p>
<p><strong>xmllint</strong> tiene una opci&oacute;n para validar, pero para realizar ese trabajo, requiere que 1) el archivo XML defina un DTD o 2) se le pase por par&aacute;metro. Probando sin usar un DTD por par&aacute;metro: prob&eacute; lo siguiente:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">find</span> . <span style="color: #660033;">-name</span> <span style="color: #ff0000;">&quot;*.xml&quot;</span> <span style="color: #660033;">-exec</span> xmllint <span style="color: #660033;">--noout</span> <span style="color: #660033;">--valid</span> <span style="color: #ff0000;">&quot;{}&quot;</span> \;</pre></div></div>

<p>Lamentablemente, el resultado no fue lo que esperaba. TODOS los XML salvo uno, eran inv&aacute;lidos, debido a que NO TEN&Iacute;AN definido el DTD. Gracias a ese archivo que s&iacute; lo ten&iacute;a, descubr&iacute; que joomla TIENE en su sitio un archivo DTD para que los desarrolladores lo incluyan en sus XML de configuraci&oacute;n. De esta forma, el desarrollador obliga a que sus archivos XML tengan la estructura que el sistema requiere.</p>
<p>Lo peor&#8230; ese &uacute;nico archivo v&aacute;lido, era de un plugin de terceros y no de los desarrolladores oficiales. Es decir, los desarrolladores oficiales de joomla NO RESPETAN sus propias reglas al escribir el c&oacute;digo.</p>
<p>Finalmente, xmllint no era lo que estaba buscando, ya que solo deb&iacute;a comprobar cual era el o los archivos mal formados (etiquetas mal cerradas, mal anidadas, &#8230;). Como no sab&iacute;a, consulte en una lista de correo (una de las que tengo en la lista de comunidades), donde me dieron la soluci&oacute;n: <strong>xmlwf</strong>.</p>
<p>Simplemente cambi&eacute; el comando anterior por el siguiente y asunto arreglado:</p>

<div class="wp_syntax"><div class="code"><pre class="bash" style="font-family:monospace;"><span style="color: #c20cb9; font-weight: bold;">find</span> . <span style="color: #660033;">-name</span> <span style="color: #ff0000;">&quot;*.xml&quot;</span> <span style="color: #660033;">-exec</span> xmlwf <span style="color: #ff0000;">&quot;{}&quot;</span> \;</pre></div></div>

<p>Encontr&eacute; los culpables (eran 2), los correg&iacute; y di por terminado el asunto.<br />
Pero me qued&eacute; con el sabor amargo de la despreocupaci&oacute;n que los desarrolladores de Joomla han tenido en un detalle tan simple. &iquest;Que confianza me dan para cuando aparezca una nueva actualizaci&oacute;n del sistema?</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/676/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Problemas de migraci&#243;n (y cr&#237;tica a wordpress #1)</title>
		<link>http://blog.gon.cl/post/464</link>
		<comments>http://blog.gon.cl/post/464#comments</comments>
		<pubDate>Thu, 08 Jan 2009 23:21:59 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[wordpress]]></category>
		<category><![CDATA[crÃ­tica]]></category>
		<category><![CDATA[openid]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=464</guid>
		<description><![CDATA[Disculpa, pero esta entrada estÃ¡ disponible sÃ³lo en English.
]]></description>
			<content:encoded><![CDATA[<p>Disculpa, pero esta entrada estÃ¡ disponible sÃ³lo en <a href="http://blog.gon.cl/en/cat/development/php/feed">English</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/464/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gonium tiene nuevo blog</title>
		<link>http://blog.gon.cl/post/402</link>
		<comments>http://blog.gon.cl/post/402#comments</comments>
		<pubDate>Mon, 29 Dec 2008 09:52:23 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[wordpress]]></category>
		<category><![CDATA[blog]]></category>
		<category><![CDATA[gonium]]></category>
		<category><![CDATA[temas wordpress]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=402</guid>
		<description><![CDATA[Ya que tengo espacio, hay que aprovecharlo.
Un lugar donde explicar las cosas
Mientras no tengo un m&#243;dulo de para blogear funcional en Gonium, no me queda otra que usar al enemigo (Wordpress). Lo cual no es del todo malo, sino justamente lo contrario.

La idea de tener un blog exclusivamente para el desarrollo de Gonium, me permitir&#225; [...]]]></description>
			<content:encoded><![CDATA[<p>Ya que tengo espacio, hay que aprovecharlo.</p>
<h2>Un lugar donde explicar las cosas</h2>
<p>Mientras no tengo un m&oacute;dulo de para blogear funcional en Gonium, no me queda otra que usar al enemigo (Wordpress). Lo cual no es del todo malo, sino justamente lo contrario.</p>
<p><a href="http://gon.boaboa.org/wblog/"><img class="aligncenter size-full wp-image-400" title="gonium_blog_120x60" src="http://blog.gon.cl/wp-content/uploads/2008/12/gonium_blog_120x60.png" alt="gonium_blog_120x60" width="120" height="60" /></a></p>
<p>La idea de tener un blog exclusivamente para el desarrollo de Gonium, me permitir&aacute; poder dejar en claro cuales son las ideas que se est&aacute;n implementando o se desarrollaran a futuro, all&aacute; en su propio lugar. Hay mucho por hacer, por lo tanto, mantener una bit&aacute;cora de desarrollo (m&aacute;s que un precario Roadmap), espero me sirva mucho m&aacute;s.</p>
<p>Un detalle importante: el blog,  el proyecto en Google en Code, los mensajes en Twitter, los commits de svn e incluso la documentaci&oacute;n autogenerada del API, se mantendr&aacute;n todos en idioma ingl&eacute;s principalmente.</p>
<p>La raz&oacute;n de esto es muy sencilla: <strong>universalidad</strong>. Aunque no me gusta la idea, lamentablemente en comunicaciones, el ingl&eacute;s es lo m&aacute;s universal. No por ser de origen chileno quisiera que solo alg&uacute;n amigo m&iacute;o de ac&aacute; lo ocupe. Espero que a todo a quien le sirva tenga la posibilidad de ocuparlo. &iquest;Quien me dice que alguien por ah&iacute; no estar&aacute; ya husmeando el c&oacute;digo? &iquest;Y si este alguien hablara en italiano? &iquest;O franc&eacute;s? &iquest;o alem&aacute;n? &iquest;o chino?</p>
<p>Adem&aacute;s, habiendo tenido experiencia en el proyecto <a href="http://gdt.sourceforge.net">GDT</a>, not&eacute; como muchos usuarios, aun cuando en su mayor&iacute;a se trataba de hispano-parlantes, simplemente no les gust&oacute; la idea de usar objetos y m&eacute;todos nombrados en espa&ntilde;ol. No entiendo estas ma&ntilde;as, pero se que son frecuentes y extendidas. De hecho, <a href="http://edsiper.linuxchile.cl/blog/">Eduardo Silva</a>, en su charla de <a href="http://monkeyd.sourceforge.net/blog/">Monkey HTTP Daemon</a> en el <a href="http://2008.encuentrolinux.cl/">Encuentro Linux</a>, mencion&oacute; haber tenido ese problema con los hispano-parlantes, as&iacute; que decidi&oacute; simplemente dejar todo, lista de correo, blog, documentaci&oacute;n, etc, en ingl&eacute;s. Esta vez, adoptar&eacute; la misma idea y ver&eacute; que sucede.</p>
<p>Por el momento, no espero una explosi&oacute;n de usuarios, ni mucho menos mientras la versi&oacute;n funcional brilla por su ausencia, pero s&iacute; espero ideas, comentarios y en general <strong>feedback.</strong> Ya me han estado preguntando cosas como &#8220;&iquest;est&aacute;s reclutando gente?&#8221;, lo cual es un alivio para esos minutos en que me cuestiono el &#8220;&iquest;para que diablos estoy haciendo algo que solo me importa a m&iacute;?&#8221;. Por si acaso, s&iacute; estoy reclutando gente :B . &iquest;Desarrolladores en Zend Framework? Bienvenidos! Cualquier tipo de aporte ser&aacute; igualmente bien recibido, ya sea de parte de un <strong>PHP</strong>ero, <strong>jQuery</strong>sta, <strong>CSS</strong>ero, Traductor, Dise&ntilde;ador o Art&iacute;sta son plenamente bienvenidos.</p>
<p><span id="more-402"></span></p>
<h2>Confirmando lo que pensaba</h2>
<p>Gracias a todo esto, tuve una ocurrencia del tipo &#8220;oh, &iquest;y si hago que el template de wordpress sea el mismo que el de Gonium?&#8221;. Con eso basto para ponerme a meter un poco de mano en la creaci&oacute;n de un tema. Nuevamente confirmo lo que pens&eacute; hace mucho tiempo atr&aacute;s acerca de wordpress, es espagetti.</p>
<p>Realmente es una de las APIs (si es que puede siquiera llamarse as&iacute; a su &#8220;codex&#8221;) m&aacute;s espantosas que he visto. Gracias a que participo en tecnosquad.org y a que dedicamos un d&iacute;a para &#8220;la &eacute;pica b&uacute;squeda de un tema nuevo&#8221;, fue como aquella tarde recolecte bastantes temas atractivos y los guarde &#8220;por si acaso&#8221;. Finalmente no encontramos nada que nos hiciera sentir ese &#8220;wow, es tema est&aacute; pintado para tecnosquad&#8221;, pero igualmente la b&uacute;squeda me trajo un buen producto.</p>
<p>Ocupe uno de esos temas para codear el mio. Entonces fue cuando note la importancia de ciertos detalles.</p>
<p>El primero es sobre el tama&ntilde;o de un tema. Por ejemplo los temas m&aacute;s &#8220;profesionales&#8221; suelen tener m&aacute;s archivos e incluso permiten agregar paneles de opciones al backend de wordpress. En esos archivos extra, los temas definen sus propias funciones, las cuales no tienen ninguna interfaz com&uacute;n, cada tema implementa sus cosas a su pinta. Algunos usaban clases/objetos, pero la mayor&iacute;a solo funciones sueltas.</p>
<p>Otro detalle importante, es que aun cuando las funciones &#8220;del n&uacute;cleo&#8221; para plantillas est&aacute;n documentadas, el solo hecho de leer un archivo fuente resulta ca&oacute;tico. Casi nada de pulcritud, incluso me atrevo a aventurar que ning&uacute;n tema de los que termine bajando (y fueron muchos), ni si quiera ten&iacute;an el c&oacute;digo propiamente indentado.</p>
<p>Una de las primeras cosas que aprend&iacute; con el Zend Framework, fue el patr&oacute;n de dise&ntilde;o &#8220;Two Steps&#8221; para plantillas, es decir, una plantilla &#8220;layout&#8221; que crea el esqueleto de la p&aacute;gina, y luego se agregan los contenidos sobre este layout, que pueden provenir de otros scripts de vista. En wordpress, simplemente no existe tal cosa. No quise mirar m&aacute;s hacia adentro del c&oacute;digo, pero lo que vi por fuera (las plantillas), me dan m&aacute;s ganas de &#8220;terminar&#8221; de una vez una versi&oacute;n usable de Gonium. Estoy seguro que ser&iacute;a una delicia para los dise&ntilde;adores.</p>
<p>M&aacute;s tarde, cuando ya pueda blogear tranquilo en Gonium, migrar&eacute; el contenido y me deshar&eacute; del wordpress. La idea principal est&aacute; m&aacute;s viva que nunca: el objetivo es crear un administrador de contenido de prop&oacute;sito general, pero BIEN HECHO.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/402/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Gonium, nuevo demo y nuevos componentes</title>
		<link>http://blog.gon.cl/post/357</link>
		<comments>http://blog.gon.cl/post/357#comments</comments>
		<pubDate>Thu, 11 Dec 2008 04:17:46 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[datagrid]]></category>
		<category><![CDATA[docbook]]></category>
		<category><![CDATA[gonium]]></category>
		<category><![CDATA[jquery]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[phpdocumentor]]></category>
		<category><![CDATA[xml]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=357</guid>
		<description><![CDATA[Gracias a la wena onda de Tecnoman, que se auspicio con hosting y me dejo hincharle las pelotas para que instalara PDO en un servidor en producci&#243;n, tengo el demo de Gonium en un hosting nuevo. Ahora intentar&#233; de alg&#250;n modo recompensar aquello, posteando m&#225;s seguido en tecnosquad.org.
Aprovechando eso, sub&#237; una copia m&#225;s reciente.
Hace unos [...]]]></description>
			<content:encoded><![CDATA[<p>Gracias a la <em>wena onda</em> de Tecnoman, que se auspicio con hosting <span style="text-decoration:line-through;">y me dejo hincharle las pelotas para que instalara PDO en un servidor en producci&oacute;n</span>, tengo el demo de Gonium en un <a href="http://gon.boaboa.org">hosting nuevo</a>. Ahora intentar&eacute; de alg&uacute;n modo recompensar aquello, posteando m&aacute;s seguido en <a href="http://tecnosquad.org">tecnosquad.org</a>.</p>
<p>Aprovechando eso, sub&iacute; una copia m&aacute;s reciente.</p>
<p>Hace unos d&iacute;as agregu&eacute; al trunk del repositorio, una copia propia del proyecto <cite><a href="code.google.com/p/zend-framework-datagrid/"><strong>zend-framework-datagrid</strong></a></cite>, con la diferencia de que mi copia permite traducirlo con Zend_Translate y los comentarios est&aacute;n corregidos. Tambi&eacute;n correg&iacute; unos <em>warnings</em> menores. Adem&aacute;s le cambi&eacute; el prefijo a las clases de &#8220;Core_&#8221; (originalmente en zf-datagrid) a &#8220;Rox_&#8221;, para darle concordancia a mi estructura de directorios. Podr&iacute;a decir entonces que es un peque&ntilde;o fork :B</p>
<p>Tambi&eacute;n agregu&eacute; todo jQuery UI al directorio p&uacute;blico. Una ejemplo de esto es la peque&ntilde;a demostraci&oacute;n con el efecto acorde&oacute;n que le agregu&eacute; al widget de Login.</p>
<p>Y por &uacute;ltimo, agregu&eacute; un directorio con XML&#8217;s en formato docbook, para poder usarlos en conjunto con la documentaci&oacute;n creada con phpDocumentor.</p>
<p>Espero tener una documentaci&oacute;n un poco m&aacute;s completa m&aacute;s adelante.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/357/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Gonium: Rompiendo el RoadMap</title>
		<link>http://blog.gon.cl/post/352</link>
		<comments>http://blog.gon.cl/post/352#comments</comments>
		<pubDate>Tue, 25 Nov 2008 23:16:10 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[gonium]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=352</guid>
		<description><![CDATA[A veces no es bueno quedarse pegado con un objetivo, pudiendo romper otro m&#225;s r&#225;pidamente.
Entre ayer y hoy, logr&#233; romper el segundo objetivo del Roadmap inicial de Gonium, consistente en crear la arquitectura modular para el Backend administrativo.
Ahora, la aplicaci&#243;n cuenta con 2 sistemas modulares independientes, uno para el Frontend (el sitio visible para todo [...]]]></description>
			<content:encoded><![CDATA[<p>A veces no es bueno quedarse pegado con un objetivo, pudiendo romper otro m&aacute;s r&aacute;pidamente.</p>
<p>Entre ayer y hoy, logr&eacute; romper el segundo objetivo del Roadmap inicial de Gonium, consistente en crear la arquitectura modular para el Backend administrativo.</p>
<p>Ahora, la aplicaci&oacute;n cuenta con 2 sistemas modulares independientes, uno para el Frontend (el sitio visible para todo usuario) y otro para el Backend (donde solo usuarios con privilegios pueden modificar cosas).</p>
<p>Esto significa, por ejemplo, que el m&oacute;dulo &#8220;user&#8221; que puede ver un usuario corriente (donde podr&aacute; modificar su perfil y esas cosas), ser&aacute; distinto del m&oacute;dulo &#8220;user&#8221; del administrador (donde se podr&aacute; crear/borrar/modificar cuantas usuarios).</p>
<p>Para dejarlo plenamente funcional, a&uacute;n falta crear los m&oacute;dulos administrativos (as&iacute; como los de usuario corriente), pero al menos, la arquitectura de directorios y bootstraping ya est&aacute;n adaptados para trabajar de esta manera.</p>
<p><span id="more-352"></span></p>
<h2>Implementaci&oacute;n</h2>
<p>La t&eacute;cnica utilizada, consisti&oacute; de los siguientes pasos:</p>
<h3>Separar el bootstrap de Frontend del boostrap del Backend</h3>
<p>Se creo un admin.php en el public_html, al mismo nivel de index.php, el cual carga el Core/boostrap.php pero cambiando el Environment a &#8216;Admin&#8217;.</p>
<p>Esto signific&oacute; modificar las reglas de .htaccess para redirigir las peticiones que pasaran por la url <strong>admin/</strong> a admin.php</p>
<h3>Crear clases &#8220;inicializadoras&#8221; para cada Environment distinto</h3>
<p>Esto debido a que ciertos plugins b&aacute;sicos y configuraciones especificas del Frontend no tienen sentido en el Backend (y los futuros de Backend no tienen sentido en el Frontend).</p>
<h3>Cambiar la estructura de directorios</h3>
<p>Casi vuelvo a dejar la embarr&aacute; con la copia de trabajo, pero finalmente lo salv&eacute;. Se tuvo que armar una nueva arquitectura de directorios para alojar los m&oacute;dulos administrativos. Aprovechando eso, tambi&eacute;n se movieron los m&oacute;dulos b&aacute;sico del Frontend y el controlador de errores, los 3 ahora son subcarpetas de /application/Core/Module. Esto fue pensado debido a que las clases controladoras son las &uacute;nica que no respetan el codding-standar de usar prefijos por cada carpeta, para separarlas como si fueran distintos namespaces. No lo necesitan tampoco, porque estas clases jam&aacute;s se deber&iacute;an cargar como librer&iacute;as (al estilo de Zend_Loader).</p>
<h3>Separar el controlador de errores del Frontend</h3>
<p>Ya ten&iacute;a implementado un controlador de errors, que despliega por pantalla cualquier Exception disparada durante el proceso del dispatcher. El problema es que este controlador estaba sujeto al m&oacute;dulo &#8220;default&#8221; del frontend, por lo tanto, no se pod&iacute;a usar desde el backend directamente. Se resolvi&oacute; separar este controlador de ambos directorios, dejandolo independiente, y siendo este agragado al &#8220;Front Controller&#8221;. como una carpeta independiente. Este controlador DEBE estar disponible en todos los &#8216;Environments&#8217;.</p>
<h3>Agregar un enrutador especial para el Backend</h3>
<p>Hab&iacute;a estado trabajando con un enrutador corriente como lo es el Zend_Controller_Router_Route con una regla sencilla. Pero no me percat&eacute; que el enrutador predeterminado, usaba internamente (y por defecto) un enrutador llamado <code class="code">Zend_Controller_Router_Route_Module. Cambiandolo a ese, logr&eacute; crear un enrutador 'admin' que funciona bien en la estructura modular separada del backend.</code></p>
<p>Pens&eacute; que ser&iacute;a m&aacute;s sencillo&#8230; D:</p>
<p>No me quedo otra que hacerlo por esta v&iacute;a, ya que las rutas se resuelven en tiempo de &#8220;dispatching&#8221;, por ende no puedo configurarlas despues que la aplicaci&oacute;n ya empieza a correr.</p>
<p>Si alguien conoce alguna soluci&oacute;n m&aacute;s limpia, favor de comunicarse conmigo, sino pruebenlo, ya hice el respectivo commit al repositorio del proyecto.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/352/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>phpDocumentor: como doxygen pero para PHP</title>
		<link>http://blog.gon.cl/post/296</link>
		<comments>http://blog.gon.cl/post/296#comments</comments>
		<pubDate>Tue, 23 Sep 2008 20:11:51 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[documentaciÃ³n]]></category>
		<category><![CDATA[phpdocumentor]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=296</guid>
		<description><![CDATA[Documentar el c&#243;digo es m&#225;s que dejarlo bonito. Es hacerlo entendible.
&#8220;Comentar el c&#243;digo es como limpiar el cuarto de ba&#241;o; nadie quiere hacerlo, pero el resultado es siempre una experiencia m&#225;s agradable para uno mismo y sus invitados&#8221;
 &#8211; Ryan Campbell
Uno de los prop&#243;sitos iniciales de este blog, era combatir mi inquietante amnesia. No se [...]]]></description>
			<content:encoded><![CDATA[<p>Documentar el c&oacute;digo es m&aacute;s que dejarlo bonito. Es hacerlo entendible.</p>
<blockquote><p>&#8220;Comentar el c&oacute;digo es como limpiar el cuarto de ba&ntilde;o; nadie quiere hacerlo, pero el resultado es siempre una experiencia m&aacute;s agradable para uno mismo y sus invitados&#8221;<br />
<em> </em><em>&#8211; Ryan Campbell</em></p></blockquote>
<p>Uno de los prop&oacute;sitos iniciales de este blog, era combatir mi inquietante amnesia. No se ustedes, pero me es muy frecuente, que despu&eacute;s de muchos d&iacute;as, semanas o meses sin ver el c&oacute;digo que estaba trabajando, termino olvidando que hac&iacute;a o como funcionaba.</p>
<blockquote><p>&#8220;Ley de Alzheimer de la programaci&oacute;n: si lees un c&oacute;digo que escribiste hace m&aacute;s de dos semanas es como si lo vieras por primera vez&#8221;<br />
<em> &#8212; Via Dan Hurvitz</em></p></blockquote>
<p>Hay solo una forma de combatirlo: documentando.</p>
<p>Ser&aacute; una lata, pero creo (seriamente) que los lenguajes de programaci&oacute;n debieran mandar <strong>advertencias</strong> cuando no documentamos el c&oacute;digo fuente.</p>
<p>Cuando estuve en inserto en el proyecto GDT, me top&eacute; de cerca con Doxygen, una excelente herramienta para documentar el c&oacute;digo en funci&oacute;n de etiquetas especiales insertas en los comentarios. Muchos a&ntilde;os antes, me toc&oacute; conocer otra grandiosa herramienta, que ayer re-descubr&iacute;: <a href="http://www.phpdoc.org/"><strong>phpdocumentor</strong></a>.</p>
<h2>&iquest;Que tiene de fant&aacute;stico?</h2>
<p>Tiene varios detalles que lo hacen un amor:</p>
<ul>
<li>Esta escrito en PHP.</li>
<li>En su documentaci&oacute;n incluye los tags especiales, con ejemplos, para escribir correctamente los comentarios.</li>
<li>Funciona por interfaz web y por consola. Posibilitando automatizar el proceso de documentaci&oacute;n</li>
<li>Se puede configurar, guardando un archivo personalizado <strong>.ini</strong> con las opciones. Esto permite automatizar m&aacute;s a&uacute;n el proceso.</li>
<li>Exporta a varios formatos, incluyendo HTML, PDF y CHM. Incluso tiene diversas plantillas para producir distintos estilos de HTML. Tambi&eacute;n se pueden personalizar estas plantillas.</li>
</ul>
<p>Sin duda debe tener m&aacute;s gracias, pero con eso es suficiente por ahora.</p>
<h2>Ejemplos</h2>
<p>Para probar, document&eacute; TODAS las clases de Gonium y <a href="http://boaboa.org/docs/">dej&eacute; copia ac&aacute;</a>. Sin ir m&aacute;s lejos, la <a href="http://framework.zend.com/apidoc/core/">documentaci&oacute;n del API de Zend Framework</a> est&aacute; producida con phpDocumentor.</p>
<h2>Sugerencia</h2>
<p>Ser buen programador, no solo significa adoptar las mejores convenciones para escribir el c&oacute;digo, usar el mejor IDE (esto es una estupidez, pero lo he escuchado), presumir el uso de patrones de dise&ntilde;o novedosos o presumir de c&oacute;digo limpio y &oacute;ptimo. Documentar es una tarea b&aacute;sica que DEBIERA SER OBLIGATORIA. No solo si sufres alg&uacute;n problema de memoria (con la de tu cabeza, no con la del PC) como yo.</p>
<p>Adem&aacute;s es mucho m&aacute;s tedioso documentar un mont&oacute;n de clases ya escritas, que no sabes exactamente que hace, que comenzar documentando desde le principio. Si estas comenzando un proyecto, HAZLO YA, sino TAMBIÉN.</p>
<h2>Caso personal</h2>
<p>En Gonium hay algunas cuantas clases, que en su momento me pareci&oacute; bueno crear mientras se me ocurr&iacute;a como implementarlas (por ah&iacute; por febrero de este a&ntilde;o). Ahora no recuerdo que diablos quer&iacute;a hacer con ellas :B</p>
<p>Fuente de las citas: <a title="Otras 101 citas c&eacute;lebres del mundo de la inform&aacute;tica" href="http://www.variablenotfound.com/2008/04/otras-101-citas-clebres-del-mundo-de-la.html">Variable not found: Otras 101 citas c&eacute;lebres del mundo de la inform&aacute;tica</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/296/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Roxydemo!</title>
		<link>http://blog.gon.cl/post/285</link>
		<comments>http://blog.gon.cl/post/285#comments</comments>
		<pubDate>Mon, 22 Sep 2008 03:02:38 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[cms]]></category>
		<category><![CDATA[demo]]></category>
		<category><![CDATA[gonium]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[poo]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=285</guid>
		<description><![CDATA[Ayer no se porque me di&#243; ganas de probar mi c&#243;digo in&#250;til proyecto personal en un hosting gratuito.
Mientras lo hac&#237;a, coment&#233; aquello en mi canal de irc favorito. Fue entonces cuando @janitux me comenta que tenia un hosting y un dominio en desuso.
Igualmente planeaba contratar un dominio y hosting m&#225;s adelante para levantar un demo. [...]]]></description>
			<content:encoded><![CDATA[<p>Ayer no se porque me di&oacute; ganas de probar mi <span style="text-decoration:line-through;">c&oacute;digo in&uacute;til</span> <a href="http://code.google.com/p/gonium">proyecto personal</a> en un hosting gratuito.</p>
<p>Mientras lo hac&iacute;a, coment&eacute; aquello en <a href="http://embed.mibbit.com/?server=irc.powers.cl&amp;channel=%2C%23linux&amp;forcePrompt=true&amp;promptPass=true">mi canal de irc favorito</a>. Fue entonces cuando <a href="https://twitter.com/janitux">@janitux</a> me comenta que tenia un hosting y un dominio en desuso.</p>
<p>Igualmente planeaba contratar un dominio y hosting m&aacute;s adelante para levantar un demo. Pero gracias a esto puedo adelantarlo.</p>
<p style="text-align:center;">Para mirarlo (por ahora nada m&aacute;s que un simple home), pueden acceder ac&aacute;:</p>
<p style="text-align:center;"><a href="http://gon.boaboa.org/"><img class="size-full wp-image-287" title="Gonium Demo" src="http://blog.gon.cl/wp-content/uploads/2008/09/gonium_demo_120x60.png" alt="Demostraci&oacute;n" width="120" height="60" /></a></p>
<p style="text-align:center;">Y para mirar las fuentes, pueden acceder al repositorio ac&aacute;:</p>
<p style="text-align:center;"><a href="http://code.google.com/p/gonium"><img class="size-full wp-image-286" title="Gonium Project" src="http://blog.gon.cl/wp-content/uploads/2008/09/gonium_project_120x60.png" alt="" width="120" height="60" /></a></p>
<p>No esperen mucho, pues muchas caracter&iacute;sticas b&aacute;sicas de uso a&uacute;n no est&aacute;n implementadas. Lo importante es probar como funciona el <a href="http://es.wikipedia.org/wiki/Back_end#En_dise.C3.B1o_web_.28o_desarrollo_web.29">backend</a> en un &#8220;ambiente de producci&oacute;n&#8221; . Es muy distinto probar las aplicaciones as&iacute; que en el &#8220;&aacute;mbiente de desarrollo&#8221;, donde todas las condiciones necesarias son modificables por el desarrollador.</p>
<p>Por el momento, el &uacute;nico m&oacute;dulo o sub-aplicaci&oacute;n interesante que puedo mostrar es <a href="http://gon.boaboa.org/twitter">http://gon.boaboa.org/twitter</a> Espero que les guste. :B</p>
<p>Por el momento va bien. Gracias a ello logr&eacute; encontrar algunos detalles que no hab&iacute;a visto en mi ambiente de desarrollo.</p>
<p>Gracias <a href="https://twitter.com/janitux">@janitux</a>, espero poder sacarle provecho <img src='http://blog.gon.cl/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  .</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/285/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>ZendFramework: problemas de codificaci&#243;n de caract&#233;res con la Base de datos.</title>
		<link>http://blog.gon.cl/post/275</link>
		<comments>http://blog.gon.cl/post/275#comments</comments>
		<pubDate>Tue, 16 Sep 2008 05:14:55 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[juego de caractÃ©res]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[zend db]]></category>
		<category><![CDATA[zend form]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=275</guid>
		<description><![CDATA[Este es otro caso en que me pena el tema de las codificaciones de caracteres.
SIEMPRE que uno trabaje con Bases de datos, sobre todo en paises de habla no-inglesa, se esta expuesto al tremendo cacho (problema) de manipular datos con caracteres no-ascii, como por ejemplo las &#241;-Ñ y diversas vocales acentuadas, tildes, apostrofes, cremillas, tongos [...]]]></description>
			<content:encoded><![CDATA[<p>Este es otro caso en que me pena el tema de las codificaciones de caracteres.</p>
<p>SIEMPRE que uno trabaje con Bases de datos, sobre todo en paises de habla no-inglesa, se esta expuesto al tremendo cacho (problema) de manipular datos con caracteres no-ascii, como por ejemplo las &ntilde;-Ñ y diversas vocales acentuadas, tildes, apostrofes, cremillas, tongos y cuanta modificacion rara se le pueda hacer a una letra.</p>
<p>Hasta ahora, he trabajado TODO con codificaci&oacute;n utf8 por ser m&aacute;s amplia en este sentido que las otras codificaciones corrientes (iso-8859-1*, latin1, &#8230;).</p>
<h2>Motivo</h2>
<p>Trabajando con Zend Form, note un extra&ntilde;o comportamiento. Cuando establec&iacute;a manualmente un dato en un campo, si este ven&iacute;a acentuado, entonces al dibujar por la vista, <strong>aparec&iacute;a en blanco</strong>.</p>
<p>Haciendo un <code>var_dump( $dato );</code> descubr&iacute; que la cadena de texto ven&iacute;a con caracteres mal formados. Preguntando en <a href="http://www.forosdelweb.com/f68/zend-form-zend-db-no-llevan-bien-624967/">Foros del Web</a> y navegando, d&iacute; con una pista.</p>
<p>El m&eacute;todo escape() de Zend_View provocaba que la cadena mal formada retornara en blanco. Seguramente si me pongo a mirar el c&oacute;digo fuente de Zend_Form* llegar&eacute; a encontrar una llamada a ese m&eacute;todo (no lo he hecho, pero por el efecto lo deduzco).</p>
<p>Adem&aacute;s, buscando por este problema, tanto en listas de correo sobre ZF, como en la documentaci&oacute;n de Mysql y adem&aacute;s en otra respuesta a mi pregunta en el mismo foro, encontr&eacute; que existen 2 consultas SQL (para MySQL) que arreglan el problema:</p>
<blockquote>
<pre>SET NAMES 'UTF8'
SET CHARACTER SET UTF8</pre>
</blockquote>
<p>Pero eso es espec&iacute;fico a Mysql. La otra soluci&oacute;n es manipular la configuraci&oacute;n del servidor, cosa que no se puede hacer en un hosting.</p>
<h2>Soluci&oacute;n</h2>
<p>La soluci&oacute;n b&aacute;sica es ejecutar esa par de consultas SQL. Pero hay que ver globalmente el problema para saber donde, como y cuando hacerlo.</p>
<p>De partida, mi aplicaci&oacute;n pretender ser no-dependiente del motor de base de datos.</p>
<p>Lo otro, es que intento mantener &#8220;limpio&#8221; el dise&ntilde;o del c&oacute;digo, en el sentido de que cada cosa valla en el lugar que corresponde, dependiendo del patr&oacute;n y/o paradigma adoptado.</p>
<p>Entonces, no es cosa de llegar y ponerlo en el index.php</p>
<p>Una soluci&oacute;n podr&iacute;a ser extender la clase Zend_Db_Adaptar_PdoMysql y a&ntilde;adir la consulta. Pero esto a&ntilde;ade un prop&oacute;sito espec&iacute;fico a algo que pretende ser general.</p>
<p>Bajo el mismo sentido de llegar a una soluci&oacute;n generalizada, se me ocurri&oacute; externalizar el charset de la consulta. As&iacute; que simplemente, a&ntilde;ad&iacute; un dato m&aacute;s al config.ini</p>
<blockquote>
<pre>database.adapter          = pdo_mysql   ; php extension, or Object adapter (1)
<strong>database.charset          = utf8        ; (optional) Character Set </strong>
database.params.host      = localhost   ; database host
database.params.username  = username    ; username to conect database
database.params.password  = password    ; password to conect database
database.params.dbname    = goniumdb   ; name of database
database.params.prefix    = rox_        ; table prefix
database.params.profiler  = "1"         ; Enable/disable profiler</pre>
</blockquote>
<p>Los Controller Plugins b&aacute;sicos de Gonium los dise&ntilde;&eacute; con el prop&oacute;sito de configurar cosas espec&iacute;ficas, asi que decid&iacute; por el momento, hacer ah&iacute; las consultas, PERO solo cuando el adapter ocupado sea alguno basado en mysql. As&iacute; que finalmente mi c&oacute;digo quedo as&iacute;:</p>
<blockquote>
<pre>$config = Zend_Registry::get('core_config');
$db = Zend_Registry::get('core_db');
$db-&gt;getConnection();

// Set charset
if( isset($config-&gt;database-&gt;charset) &amp;&amp; $config-&gt;database-&gt;charset !== null )
{
    switch( $config-&gt;database-&gt;adapter )
    {
        case 'mysql':
        case 'mysqli':
        case 'pdo_mysql':
            $db-&gt;query('SET NAMES \''.strtoupper($config-&gt;database-&gt;charset).'\'');
            $db-&gt;query('SET CHARACTER SET '.strtoupper($config-&gt;database-&gt;charset));
        break;
    }
}</pre>
</blockquote>
<p>Todo eso en el plugin Database. Es cosa de gustos en donde ponerlo, yo lo hice en un plugin, tambi&eacute;n se puede poner directo en el bootstrap, o extendiendo Zend_Db*, o que se yo&#8230;</p>
<h2>&iquest;Y luego que?</h2>
<p>Creo que me ver&eacute; obligado a probar YA en otros motores de base de datos, haber como se comportan&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/275/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>ZendFramework: Manejar errores de los Controller Plugins</title>
		<link>http://blog.gon.cl/post/269</link>
		<comments>http://blog.gon.cl/post/269#comments</comments>
		<pubDate>Sun, 14 Sep 2008 23:58:54 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[Desarrollo]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[error]]></category>
		<category><![CDATA[excepciÃ³n]]></category>
		<category><![CDATA[excepciones]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[plugin]]></category>
		<category><![CDATA[poo]]></category>
		<category><![CDATA[zend framework]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=269</guid>
		<description><![CDATA[Si han trabajado con Zend Framework usando el patr&#243;n MVC, sabr&#225;n lo que es el Front Controller y sus &#8220;Action Plugins&#8221;.
A principios de este a&#241;o me top&#233; con un problema que dej&#233; pasar, hasta ahora.
Al configurar el FrontController, uno de los par&#225;metros usuales a fijar, es registrar y configurar el plugin ErrorHandler. Este plugin permite [...]]]></description>
			<content:encoded><![CDATA[<p>Si han trabajado con Zend Framework usando el patr&oacute;n MVC, sabr&aacute;n lo que es el Front Controller y sus &#8220;Action Plugins&#8221;.</p>
<p>A principios de este a&ntilde;o me top&eacute; con un problema que dej&eacute; pasar, hasta ahora.</p>
<p>Al configurar el FrontController, uno de los par&aacute;metros usuales a fijar, es registrar y configurar el plugin <strong>ErrorHandler</strong>. Este plugin permite redirigir a un <em>m&oacute;dulo-&gt;controlador-&gt;acci&oacute;n</em> cuando se dispara una excepci&oacute;n durante el Dispatch Loop. Esto en conjunto con establecer que el FrontController no dispare excepciones, permite presentar un bonito error manualmente, con los detalles que el desarrollador quiera mostrar.</p>
<p>Sin embargo, hasta hoy, no fui capaz de entender porque cuando otro Plugin disparaba una excepci&oacute;n, esta pasaba de largo, sin hacer caso a mi ErrorHandler.</p>
<p>Afortunadamente, hoy me despert&eacute; con el pie izquierdo, por lo cual me di la ma&ntilde;a de examinar el c&oacute;digo del Framework (bendito sean los kits de desarrollo libres). Y afortunadamente conozco Xdebug, que me facilit&oacute; la tarea de encontrarlo.</p>
<p>Es un problema de dise&ntilde;o del ZendFramework, pero lamentablemente, seg&uacute;n lo que pude leer, no se me ocurre uno mejor que proponer. En cambio, mi soluci&oacute;n es OLVIDAR el plugin ErrorHandler que trae el framework, y hacer uno manualmente, con una ma&ntilde;a m&aacute;s ma&ntilde;osa que el original.</p>
<p><span id="more-269"></span></p>
<h2>El problema de dise&ntilde;o</h2>
<p>El dispatch loop, es un proceso en el cual se ejecutan, secuencialmente, los m&eacute;todos de los Plugins y el controlador de acci&oacute;n que corresponda.</p>
<p>El Zend Framework, usando todas las capacidades de Programaci&oacute;n Orientada a Objetos que PHP permite, dispara excepciones cada vez que ocurre algun error en alg&uacute;n procedimiento.</p>
<p>Si se dispara una, entonces el dispatch loop la captura. Si configuramos correctamente el FrontController, el resultado esperado es que nos redirija al controlador de errores que hayamos creado.</p>
<p>Para lograr eso, el Plugin ErrorHandler enga&ntilde;a al dispatch, dici&eacute;ndole que el ciclo NO HA FINALIZADO, reemplaza el <strong>controlador de acci&oacute;n</strong> que se estaba ejecutando por el <strong>controlador de acci&oacute;n de error</strong> y finalmente, continua el ciclo del Dispatch.</p>
<p>Eventualmente, podr&iacute;a ocurrir que el <strong>controlador de acci&oacute;n de error</strong> tambi&eacute;n dispare una excepci&oacute;n. Si esto ocurre y se mantiene la misma condici&oacute;n, se crear&iacute;a un ciclo infinito. Para prevenir esto, el plugin ErrorHandler comprueba &#8220;<em>si es que ya se encuentra en un controlador de acci&oacute;n de error</em> &#8220;, en tal caso simplemente arroja la excepci&oacute;n, pues no se puede manejar si el manejador est&aacute; malo.</p>
<p>Pero, en Zend Framework, cuando se redirije de una acci&oacute;n a otra, el dispatch VUELVE a ejecutar los plugins. Por lo tanto, si es un plugin el que dispara la excepci&oacute;n, entonces caer&aacute; en el caso anteriormente descrito. Es decir, &#8220;ya me encuentro en un controlador de error, por ende, si no se puede manejar la excepci&oacute;n, simplemente hay que lanzarla (throw)&#8221;.</p>
<p>&iexcl;Esto es lo que ocurre!, si es un plugin el err&oacute;neo, entonces se volver&aacute; a ejecutar cuando se redirija al controlador de errores.</p>
<h2>Soluci&oacute;n propuesta, sin modificar las clases del Framework.</h2>
<p>Consiste en crear un plugin ErrorHandler propio, que haga lo mismo que el del framework, pero adem&aacute;s des-registre los plugins. De este modo, al entrar en el loop, no volver&aacute; a producirse un error, en cambio se capturar&aacute; la excepci&oacute;n como era esperado, para finalmente desplegarla por pantalla a trav&eacute;s de una vista.</p>
<p>Antes de continuar, es necesario tener la precauci&oacute;n de que nuestro Error Controller tenga <strong>la menor cantidad posible</strong> de c&oacute;digo, que pueda producir excepciones y adem&aacute;s no dependa de algunos de los plugins que posiblemente tambi&eacute;n disparen excepciones. OJal&aacute;, capture el error y lo mande por pantalla en una plantilla HTML y nada m&aacute;s.</p>
<p>El &Uacute;NICO plugin que no deber&iacute;a ser des-registrado, es el que maneja la vista (o mejor a&uacute;n, el <strong>Layout</strong> de la vista).</p>
<p>&iquest;Como? As&iacute;:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #009933; font-style: italic;">/** Zend_Controller_Plugin_ErrorHandler */</span>
<span style="color: #b1b100;">require_once</span> <span style="color: #0000ff;">'Zend/Controller/Plugin/ErrorHandler.php'</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #009933; font-style: italic;">/**
 * Replace of classic Zend Framework ErrorHandler controller plugin
 */</span>
<span style="color: #000000; font-weight: bold;">class</span> Rox_Controller_Plugin_ErrorHandler <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Plugin_ErrorHandler
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> postDispatch<span style="color: #009900;">&#40;</span>Zend_Controller_Request_Abstract <span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$frontController</span> <span style="color: #339933;">=</span> Zend_Controller_Front<span style="color: #339933;">::</span><span style="color: #004000;">getInstance</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        parent<span style="color: #339933;">::</span><span style="color: #004000;">postDispatch</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$request</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$response</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getResponse</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #b1b100;">if</span> <span style="color: #009900;">&#40;</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$response</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">isException</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #339933;">&amp;&amp;</span> <span style="color: #009900;">&#40;</span><span style="color: #339933;">!</span><span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span>_isInsideErrorHandlerLoop<span style="color: #009900;">&#41;</span><span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#123;</span>
            <span style="color: #b1b100;">foreach</span><span style="color: #009900;">&#40;</span> <span style="color: #000088;">$frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">getPlugins</span><span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span> <span style="color: #b1b100;">as</span> <span style="color: #000088;">$plugin</span> <span style="color: #009900;">&#41;</span>
            <span style="color: #009900;">&#123;</span>
                <span style="color: #666666; font-style: italic;">// Don't unregister Layout Plugin, to show Error Layout</span>
                <span style="color: #b1b100;">if</span><span style="color: #009900;">&#40;</span> <span style="color: #339933;">!</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$plugin</span> instanceof Rox_Controller_Plugin_Layout<span style="color: #009900;">&#41;</span> <span style="color: #009900;">&#41;</span>
                    <span style="color: #000088;">$frontController</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">unregisterPlugin</span><span style="color: #009900;">&#40;</span><span style="color: #000088;">$plugin</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
            <span style="color: #009900;">&#125;</span>
        <span style="color: #009900;">&#125;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p><a href="http://code.google.com/p/gonium/source/browse/trunk/application/library/Rox/Controller/Plugin/ErrorHandler.php">Ac&aacute; est&aacute; el ejemplo implementado en Gonium</a>, funcion&aacute; impecable hasta ahora.</p>
<h2>&iquest;TO DO?</h2>
<p>Se me ocurre que puede ser buena idea extender, adem&aacute;s, el Plugin Broker del FrontController, de tal modo que se pueda establecer si un plugin es &#8220;sticky&#8221; (permanente) o no, de tal modo que el nuevo ErrorHandler des-registre solo aquellos plugins prescindibles.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/269/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Traducci&#243;n de Zend Validate con gettext y poedit</title>
		<link>http://blog.gon.cl/post/210</link>
		<comments>http://blog.gon.cl/post/210#comments</comments>
		<pubDate>Sat, 06 Sep 2008 07:54:37 +0000</pubDate>
		<dc:creator>gon</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[php]]></category>
		<category><![CDATA[i18n]]></category>
		<category><![CDATA[internationalization]]></category>
		<category><![CDATA[l10n]]></category>
		<category><![CDATA[localizaciÃ³n]]></category>
		<category><![CDATA[mvc]]></category>
		<category><![CDATA[php5]]></category>
		<category><![CDATA[poo]]></category>
		<category><![CDATA[traducciÃ³n]]></category>
		<category><![CDATA[zend form]]></category>
		<category><![CDATA[zend framework]]></category>
		<category><![CDATA[zend validate]]></category>

		<guid isPermaLink="false">http://blog.gon.cl/?p=210</guid>
		<description><![CDATA[Zend Framework cuenta con una l&#243;gica de Formularios bastante &#8220;chori&#8221;.
Consta de una clase Zend_Form, algunas cuantas Zend_Form_Element_* y algunos Zend_Form_Decorator_*.
Lo &#8220;chori&#8221; es como funciona. Integra en un solo objeto la l&#243;gica de los datos de un formulario, la vista html, el procesamiento de las entradas por cada campo (elemento) y la validaci&#243;n de los valores [...]]]></description>
			<content:encoded><![CDATA[<p>Zend Framework cuenta con una l&oacute;gica de Formularios bastante &#8220;chori&#8221;.</p>
<p>Consta de una clase Zend_Form, algunas cuantas Zend_Form_Element_* y algunos Zend_Form_Decorator_*.</p>
<p>Lo &#8220;chori&#8221; es como funciona. Integra en un solo objeto la l&oacute;gica de los datos de un formulario, la vista html, el procesamiento de las entradas por cada campo (elemento) y la validaci&oacute;n de los valores ingresados.</p>
<p>As&iacute; nos ahorramos la lata de escribir varios scripts por separado. Antes era necesario coordinar los nombres de los elementos con las claves que llegaban por $_GET o $_POST. Al hacer cualquier cambio al formulario html, pod&iacute;a provocarle hipo al script validador.</p>
<p>Ahora solo es necesario declarar el formulario, agregarle los validadores a cada elemento (que sea necesario), los decoradores del formulario y/o de los elementos y ya esta todo cocinado. Se pasa el objeto $form al script de vista y autom&aacute;ticamente es dibujado como HTML, y nuestro script Controller puede perfectamente procesar los mismos inputs declarados en el Form.</p>
<p><a href="http://bolsadeideas.cl/zsamer/2008/05/sistema-de-login/">Tutoriales</a> y <a href="http://framework.zend.com/manual/en/zend.form.quickstart.html">documentaci&oacute;n</a> para trabajar con Zend Form abundan, as&iacute; que no voy a profundizar en ello.</p>
<h1>El Problema</h1>
<p>Los validadores arrojan mensajes de error cuando el valor recibido no coincide con su criterio de validaci&oacute;n. Pero estos mensajes estan en idioma ingl&eacute;s, definidos en constantes de clase en cada clase Zend_Validate_*.</p>
<h1>La soluci&oacute;n</h1>
<p>Zend_Translate permite introducir texto traducible en nuestro c&oacute;digo.</p>
<h2>Escoger un adaptador de traducci&oacute;n</h2>
<p>Entre sus adaptadores, mi favorito por el momento es el basado en Gettext. Las ventajas de gettext son m&uacute;ltiples:</p>
<ul>
<li>Las traducciones est&aacute;n en un formato binario y no texto plano, lo que facilita evitar problemas como la codificaci&oacute;n de caracteres en distintos sistemas operativos. De hecho, la codificaci&oacute;n es un par&aacute;metro que se guarda en el mismo binario, ahorrando el &#8220;parseo&#8221; para detectarlo.</li>
<li>PHP es compatible con gettext, por lo tanto, la integraci&oacute;n es directa. Cuanta con funciones nativas para cargar las traducciones y adem&aacute;s soporta la macro <strong>_(&#8216;texto&#8217;)</strong> para convertir cualquier <strong>string</strong> en su traducci&oacute;n.</li>
<li>El rendimiento de carga uso es alt&iacute;simo comparado con cualquier otro adaptador basado en texto.</li>
</ul>
<p>Por su puesto que, dada las circunstancias, se puede escoger cualquier otro adaptador. Solo que gettext es mi favorito <img src='http://blog.gon.cl/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' />  .</p>
<p><a href="http://framework.zend.com/manual/en/zend.translate.html">Ac&aacute; hay m&aacute;s detalles</a> sobre Zend_Translate y sus adaptadores.</p>
<p>Zend_Form permite usar autom&aacute;ticamente los mensajes que ya est&eacute;n traducidos cuando ocupamos validadores con &eacute;l. &iquest;Pero como se hace la magia?</p>
<p><span id="more-210"></span></p>
<h2>Directorios de traducci&oacute;n</h2>
<p>Debemos escoger tambien donde y como guardar las traducciones.</p>
<p>En mi caso hice esta estructura de directorios:</p>
<pre>/language/*/LC_MESSAGES</pre>
<p>Donde * es el c&oacute;digo del idioma (es, en, fr, &#8230;, es_CL). Es la forma corriente para las traducciones usando gettext. Para el ejemplo, usese &#8220;es&#8221;.</p>
<h2>Iniciar Zend_Translate</h2>
<p>Es cosa de poner el siguiente c&oacute;digo en alg&uacute;n lugar previo a la carga de los controladores de acci&oacute;n:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">Zend_Loader<span style="color: #339933;">::</span><span style="color: #004000;">loadClass</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend_Translate'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$translate</span> <span style="color: #339933;">=</span> <span style="color: #000000; font-weight: bold;">new</span> Zend_Translate<span style="color: #009900;">&#40;</span>
        <span style="color: #0000ff;">'gettext'</span><span style="color: #339933;">,</span>
        APP_ROOT<span style="color: #339933;">.</span><span style="color: #0000ff;">'/language/'</span><span style="color: #339933;">,</span>
        <span style="color: #000000; font-weight: bold;">null</span><span style="color: #339933;">,</span>
        <span style="color: #990000;">array</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'scan'</span> <span style="color: #339933;">=&gt;</span> Zend_Translate<span style="color: #339933;">::</span><span style="color: #004000;">LOCALE_DIRECTORY</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
<span style="color: #000088;">$translate</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">setLocale</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'es'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
Zend_Registry<span style="color: #339933;">::</span><span style="color: #004000;">set</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend_Translate'</span><span style="color: #339933;">,</span> <span style="color: #000088;">$translate</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span></pre></div></div>

<p>En mi caso, lo hice en un Controller Plugin, pero tambi&eacute;n es posible dejarlo en el Bootstrap. Es importante usar el Zend_Registry para guardar nuestro objeto de traducci&oacute;n. Tambi&eacute;n es importante guardarlo con la clave<strong>&#8216;Zend_Translate&#8217;</strong>, pues Zend_Form busca ese nombre autom&aacute;ticamente en el registry para traducir los mensajes de error que retornan los validadores. Si no le ponemos <strong><strong>&#8216;Zend_Translate&#8217;</strong></strong>, la documentaci&oacute;n del api de Zend_Form tiene unos m&eacute;todos para establecer el objeto de traducci&oacute;n.</p>
<h2>&iquest;C&oacute;mo hacer el texto &#8220;traducible&#8221;?</h2>
<p>Primero, debe haber texto traducible. De ac&aacute; en adelante se asume que estamos trabajando con el patr&oacute;n MVC.</p>
<p>Podemos hacer 3 cosas, separadas o mezcladas:</p>
<h3>1) Helper de Vista</h3>
<p>Usar el m&eacute;todo helper de vista <strong>translate</strong> para traducir en los scripts de vista (si tenemos todo autom&aacute;tico, deber&iacute;a funcionar de inmediato).</p>
<p>Ejemplo:</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;h1&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">translate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Hello World'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/h1&gt;
&lt;p&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">translate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'This is an example'</span><span style="color: #009900;">&#41;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/p&gt;</pre></div></div>

<h3>2) Usar la macro _()</h3>
<p>La macro _() puede usarse para mandar el texto traducible a las vistas desde los controladores.</p>
<p>Vease esta m&aacute;cro como si fuera una funci&oacute;n cualquiera, que realiza lo siguiente: <em>Si existe texto traducido para la cadena de entrada, entonces retorna una cadena con el texto traducido, sino retorna la misma cadena de entrada.</em></p>
<p>Ejemplo:</p>
<p>MyController.php</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> MyModule_IndexController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> indexAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span> <span style="color: #339933;">=</span> <span style="color: #990000;">_</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Hello world'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">message</span> <span style="color: #339933;">=</span> <span style="color: #990000;">_</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'This is an example'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>index.phtml</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;h1&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">message</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/h1&gt;
&lt;p&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/p&gt;</pre></div></div>

<h3>3) Usar directamente el objeto Zend_Translate</h3>
<p>Esta es la forma que &#8220;deber&iacute;a usarse&#8221; siempre, mientras no sea el script de vista donde podemos usar el helper.</p>
<p>Variando un poco el ejemplo anterior, quedar&iacute;a as&iacute;:</p>
<p>MyController.php</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;"><span style="color: #000000; font-weight: bold;">&lt;?php</span>
<span style="color: #000000; font-weight: bold;">class</span> MyModule_IndexController <span style="color: #000000; font-weight: bold;">extends</span> Zend_Controller_Action
<span style="color: #009900;">&#123;</span>
    <span style="color: #000000; font-weight: bold;">public</span> <span style="color: #000000; font-weight: bold;">function</span> indexAction<span style="color: #009900;">&#40;</span><span style="color: #009900;">&#41;</span>
    <span style="color: #009900;">&#123;</span>
        <span style="color: #000088;">$lang</span> <span style="color: #339933;">=</span> Zend_Registry<span style="color: #339933;">::</span><span style="color: #004000;">get</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Zend_Translate'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
&nbsp;
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$lang</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">translate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'Hello world'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
        <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">view</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">message</span> <span style="color: #339933;">=</span> <span style="color: #000088;">$lang</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">translate</span><span style="color: #009900;">&#40;</span><span style="color: #0000ff;">'This is an example'</span><span style="color: #009900;">&#41;</span><span style="color: #339933;">;</span>
    <span style="color: #009900;">&#125;</span>
<span style="color: #009900;">&#125;</span></pre></div></div>

<p>index.phtml</p>

<div class="wp_syntax"><div class="code"><pre class="php" style="font-family:monospace;">&lt;h1&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">title</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/h1&gt;
&lt;p&gt;<span style="color: #000000; font-weight: bold;">&lt;?php</span> <span style="color: #990000;">echo</span> <span style="color: #000088;">$this</span><span style="color: #339933;">-&gt;</span><span style="color: #004000;">message</span> <span style="color: #000000; font-weight: bold;">?&gt;</span>&lt;/p&gt;</pre></div></div>

<p>Hasta ahora, solo se ha preparado el terreno. Al probar el controlador y al vista, deber&iacute;a</p>
<h2>&iquest;C&oacute;mo Traducir?</h2>
<p>Ac&aacute; est&aacute; la gracia. Entra en juego la herramienta <a href="www.poedit.net/ ">Poedit</a>.</p>
<p>Instalarla en windows es cosa de bajar el instalador y click, click, &#8230;</p>
<p>Instalarla en linux, es cosa de buscar en los repositorios, en debian/ubuntu ser&iacute;a as&iacute;:</p>
<pre>
<blockquote>
sudo apt-get install poedit</blockquote>
</pre>
<p>Luego, es necesario hacerle un peque&ntilde;o arregl&iacute;n.</p>
<p>Una caracter&iacute;stica de trabajar con poedit, es que puede encontrar el texto traducible en la aplicaci&oacute;n, examinando los archivos fuente. Autom&aacute;ticamente, cualquier cadena de texto encerrada en la macro _() ser&aacute; considerada &#8220;una cadena traducible&#8221;. Nos interesa que tambien tome las cadenas que aparecen dentro del m&eacute;todo translate().</p>
<p>Otra cosa importante. No se puede agregar otras cadenas manualmente en poedit. Aparentemente eso es malo en felixibilidad, pues no se puede agregar cualquier texto que uno quiera a la traducci&oacute;n. Sin embargo, esto es bueno por eficiencia, as&iacute; no habr&aacute;n cadenas basura en el binario de traducci&oacute;n, solo estar&aacute;n presentes aquellas que realmente est&eacute;n en el c&oacute;digo fuente de la aplicaci&oacute;n.</p>
<p>El arregl&iacute;n consiste en:</p>
<ul>
<li>Ir al men&uacute; Archivo -&gt; Preferencias &#8230;</li>
<li>Pesta&ntilde;a &#8220;Procesadores&#8221;, escoger PHP y presionar Editar</li>
<li>En la lista de extensiones, dejar la caja as&iacute;: *.php;*.phtml</li>
<li>En la caja &#8220;Linea de comandos para procesar&#8221; agregar al final: -L php</li>
</ul>
<p>Luego, al crear un cat&aacute;logo (as&iacute; se llama el archivo *.mo que contendr&aacute; la traducci&oacute;n), debemos configurarlo con lo siguiente:</p>
<ul>
<li>Ir al men&uacute; Cat&aacute;logo -&gt; Opciones &#8230;</li>
<li>Pesta&ntilde;a &#8220;Palabras clave&#8221;, agregar una nueva y poner: translate</li>
<li>En la pesta&ntilde;a &#8220;Carpetas&#8221;, se debe poner la ruta al c&oacute;digo fuente que se va a traducir. Recomiendo poner una ruta relativa. Relativa a la posici&oacute;n donde guardar&eacute;mos el cat&aacute;logo (*.po y *.mo)</li>
</ul>
<p>Listo. Esto har&aacute; que el procesador de gettext lea los archivos .php y .phtml dentro de la carpeta de inter&eacute;s. Adem&aacute;s tomar&aacute; traducciones desde el m&eacute;todo translate().</p>
<h1>&iquest;C&oacute;mo traduje los mensajes de los validadores de Zend Framework?</h1>
<p>Una opci&oacute;n abr&iacute;a sido pasar poedit por la carpeta Zend/Validate del framework, pero lamentablemente, los mensajes de error no est&aacute;n en una forma que se pueda escanear con gettext. Cada mensaje de error es un c&oacute;digo (string) guardado en una constante de clase, adem&aacute;s de un array donde la clave es la constante de clase correspondiente, y su valor contiene un string con el mensaje en s&iacute;.</p>
<p>As&iacute; que opte por hacer algo un poco m&aacute;s sucio, pero v&aacute;lido.</p>
<p>Cree un archivo template.php, el cual contiene un array, pero de la siguiente forma:</p>
<pre><?php
$translate[_('isEmpty')] = 'Value is empty, but a non-empty value is required';
$translate[_('stringEmpty')] = "'%value%' is an empty string";

//... Y as&iacute; con todos los mensajes de error que aparecen en Zend/Validate/*
</pre>
<p>Si se fijan, cada clave de array est&aacute; encerrada por la macro de traducci&oacute;n _().</p>
<p>&iquest;Cual es la magia?, configurar el cat&aacute;logo en Poedit, para que pase por este archivo, actualizar el catalogo desde el c&oacute;digo fuente, y listo.</p>
<p>El archivo finalmente <a href="http://code.google.com/p/gonium/source/browse/trunk/app/language/templates/form/zend_validate.php">qued&oacute; as&iacute;</a>.</p>
<p>Ahora, la otra alternativa, es actualizar el cat&aacute;logo desde una plantilla *.pot. En el fondo, es igual a un .po, que podemos editar afuera y Poedit no va a alegar, pero si lo har&aacute; si volvemos a actualizar desde el c&oacute;digo fuente.</p>
<p>El .po qued&oacute; <a href="http://code.google.com/p/gonium/source/browse/trunk/app/language/es/LC_MESSAGES/zend_validate.po">as&iacute; finalmente</a>.</p>
<p>As&iacute; que si alguien necesita traducir los mensajes de los validadores de Zend Framework, ac&aacute; hay 2 formas ya listas para bajar y "compilar".</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.gon.cl/post/210/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic page generated in 1.218 seconds. -->
<!-- Cached page generated by WP-Super-Cache on 2010-07-31 13:15:37 -->
