Internacionalizar una web en php

main_icoDespués de muchos meses trabajando en una aplicación que, por azares del destino, alguien decidió que se realizase en php utilizando como frontend Drupal (del que solo se utiliza el sistema de registro y poco más) y después de infinitos test de usuarios (que nunca son suficientes) y después de generar un proyecto con 31.000 líneas de código propias (el total sin contar drupal suma más de 203.000) llega el momento de venderlo.

El primer cliente siempre es el peor, pero es que el segundo ¡es holandés! y, claro, lo quiere en inglés… Y algún lumbrera le asegura que tendrán la versión en inglés ¡¡en una semana!!. Lo bonito del tema es que cuando aseguró eso no preguntó a nadie del equipo de desarrollo. ¿Para qué? Las fechas las ponen ellos, qué más da que sea algo imposible.

Total, que, de casualidad, nos enteramos de que hay que hacer este «pequeño» cambio, las traducciones no serán un problema, porque tenemos gente que puede hacerlo bien y rápido, pero, ¿cómo internacionalizamos el php? La parte que cubre Drupal (y que podría traducirse desde el mismo sistema) es mínima, en total tenemos 425 archivos php donde hay textos en castellano en cualquiera de ellos, además, parte en html, parte en php y parte en javascript… Cualquier otro programador hubiese presentado su carta de renuncia o hubiese pedido una baja laboral. Además, ya nos han dicho que no piensan pagarnos las horas extras y que si cometemos errores tendremos que arreglarlos en nuestro tiempo libre.. ¡Eso si que son condiciones laborales y no las de los mineros de asturias!

Sin embargo mi responsabilidad como profesional me obliga a atender las peticiones por absurdas que sean e intentar dar soluciones… Así que os pongo un resumen de lo que hicimos:

Problema número 1: qué sistema de internacionalización usar.

Al contrario que Java, que dispone de un sistema i18n con properties desde el principio, php adolece de este mecanismo estandar. Después de valorar varias opciones (muchas usadas en programas populares como prestashop, etc.) descubrimos que lo mejor es utilizar gettext.

Gettext es un proyecto GNU que, afortunadamente, es utilizado muy ampliamente en Linux para proporcionar internacionalización a sus programas. Es por ello que está presente en la mayoría de las distribuciones (incluyendo las que usamos para desarrollo y pruebas) y, además, tiene un módulo para php que también está normalmente incluida en las instalaciones normales de php (incluso en XAMPP está).

¿Cómo funciona gettext? Básicamente se basa en localizar todas las cadenas de texto ya escritas y sustituirlas por una función que la traduce. En el caso de php esta suele ser la función gettext(‘cadena’) o, abreviada _(‘cadena’). De esta forma, el texto en html:

<p>Esto es un texto</p>

Lo modificaremos en:

<p><?php _("Esto es un texto")?></p>

Luego el sistema localizará, según los parámetros de idioma, su traducción y la escribirá. Si no encuentra ninguna escribirá esa misma cadena.

Así que el primer, y más tedioso, problema es sustituir todas las cadenas de texto en nuestro programa por estas sustituciones. No hay una forma única y automatizada de hacerlo, porque podemos encontrarnos texto dentro del código php, dentro de etiquetas html o incluso dentro de código javascript y dependiendo de dónde se encuentre esa cadena deberá traducirse (o no).

Problema número 2: traducir las cadenas

Una vez que tenemos «marcadas» todas nuestras cadenas, deberemos generar un archivo con las traducciones… Esto ya es más sencillo de automatizar porque podemos utilizar herramientas que ya existen. La más adecuada es poedit. Esta herramienta nos permite escanear directorios de fuentes y almacena las cadenas que no están traducidas en un catálogo para después permitir que un traductor las vaya traduciendo sin tener que saber nada de php.

Antes de utilizar poedit es muy recomendable que establezcamos las rutas de los directorios donde vamos a guardar los catálogos traducidos. Generalmente esto se hace en el directorio raiz de la aplicación creando estos directorios:

locale/xx_XX/LC_MESSAGES

donde xx_XX es el código del idioma y país (en_GB en nuestro caso). Dentro de cada uno de esos directorios almacenaremos los .po (y .mo que compilamos) que generaremos con poedit.

Una vez creados los directorios, arrancamos el poedit y lo configuramos indicando que el directorio principal será «.» y los directorios a escanear serán ../../../ (suponiendo que hemos respetado la estructura que os he comentado). También es importante el tema de los plurales que, en caso del español sería:

nplurals=2; plural=n != 1;\n

Una vez todo en su lugar solo tendremos que actualizar para que poedit busque en todos los archivos y nos encuentre todas las cadenas que se pueden internacionalizar. Utilizando el mismo programa podemos hacer que los traductores nos traduzcan las cadenas y nos devuelvan el mismo .po ya traducido.

Problema número 3: hacer que el sistema use el idioma del usuario

Para que funcione gettext para php hay que incluir las siguientes líneas al principio del script:

putenv("LC_ALL=$locale");
setlocale(LC_ALL, $locale, 'english');
bindtextdomain("messages", __DIR__."/Locale");
bind_textdomain_codeset("messages", 'UTF-8');
textdomain("messages");

Lo relevante ahí es que $locale ha de contener el idioma (en_GB) messages es el nombre que tiene el catálogo poedit (así tendremos un messages.po en el directorio correspondiente) y que a bindtextdomain hay que pasarle el directorio donde hemos colocado nuestros locales.

Para el caso de drupal vamos a utilizar el idioma que el usuario ha puesto en su perfil, por lo que el código adicional a utilizar es:

global $language;
$locale = $language->language;
if ($locale=='en')
    $locale="en_GB.utf8";
else
    $locale = 'es_ES.utf8';

Esto es así porque los locales han de ser tal como están en el sistema operativo y, sin embargo, los idiomas en drupal solo indican el idioma y no el locale.

Seguimos en ello (hay muchos archivos) y además, nos queda pendiente la internacionalización de los correos y de los informes que generamos… Seguiremos informando.

Construir una pantalla para AMSTRAD en cartón

Bueno, no completamente en cartón, es cierto, los componentes electrónicos no pueden, de momento hacerse con cartón… No obstante, el resto si.

2016-04-23

El caso es que, merced a mi nostalgia ochentera me compré un viejo CPC 128 para recordar los tiempos en que yo tenía una CPC464 (que, por desgracia, alguien en casa de mis padres decidió que merecía el triste destino de los desechos). Una ved adquirido uno de segunda mano venía el segundo problema, ¿cómo poder verlo? Si lo recordáis los AMSTRAD venían con una pantalla que tenía la fuente de alimentación incorporada.

Mirando a mi alrededor vi que tenía un montón de cosas que ya no usaba, sin embargo, la mayoría era de la era PC, posterior a la de los CPC, pero, ¡quien dijo miedo! me propuse utilizar todo lo posible de lo que tenía alrededor y no comprar nada nuevo… Si, eso se suele llamar reciclar… Excepto la parte electrónica imprescindible.

Lo primero que «reciclé» es una pantalla de un portatil que ya tenía más de 10 años de antiguedad pero que era muy bueno en su época. ¿El problema? Que solo se trataba de un panel LCS y, como tal, necesitaba un controlador para poder decodificar las señales de entrada a algo visible… Buscando, buscando encontré en ebay un controlador adecuado que es este:

(HDMI+DVI+VGA) LCD screen Controller Board Kit for 15″ 1400X1050 ITSX95C que luce muy parecido a esta foto:

s-l1600

Hay que ser muy cuidadoso de que el modelo de panel que teneis coincide exactamente con el del controlador o no pasará nada de nada… De hecho, el primero que pedí tuvieron que cambiármelo por otro.El montaje quedaba de esta manera, más o menos:

IMG_20150420_163557

Con este artefacto ya disponía de entradas DVI, VGA y HDMI para mi panel, y tras comprobar que funcionaba adecuadamente el siguiente paso era.. Convertir la salida del CPC en VGA… Otra cosa que no es sencilla, porque la salida de video es un RGB ciertamente especial… Pero no hay problema que no tenga solución en china, en este caso venía con esta forma:

516709548_502

Y se puede encontrar en aliexpress con este sugerente nombre:

Arcade game RGB/CGA/EGA/YUV to VGA HD video converter board 1 VGA output

El caso es que esta placa dispone de una entrada RGBS (es la que usé yo) y una salida VGA (entre otras muchas cosas que hacen esta placa muy interesante). Solo me faltaba montar los cables con la entrada RGB hacia estos pines y ya tendría la conversión RGBS->VGA->Panel.

Solo nos quedaba el problema de la alimentación… El CPC necesitaba dos entradas, una de 5V y otra de 12V, las dos placas que hemos visto necesitaban (curiosamente) 5V esta última y 12V el controlador del panel… Así pues solo necesitábamos alguna fuente de alimentación que nos diese suficiente «chicha» para alimentar estas tres cosas… Y, ¡cómo no! estaba rodeado de esqueletos de PCs con sus viejas fuentes de alimentación ATX que, curiosamente, dan salidas de 12V y de 5V en cantidad abundante.

Un poquito de paciencia y soldador y ya tenía montados todos los cables, desde la fuente a las placas y al CPC y desde el CPC a la placa de conversión… Probamos y…. ¡Funciona! Eso si, el maremagnum de cables y la colocación del panel sobre la mesa no era lo que más prometía… Esta vez, no obstante, no quería hacer nada demasiado definitivo, por lo que, simplemente, encontré suficiente cajas de cartón como para montar esto:

2016-04-23-2
2016-04-23

Y con esto y un bizcocho… Listos para jugar a todo color…

2016-04-23-3

Si te interesó esto, igual te interesa alguno de estos:

Lecciones informáticas II: La sobregestión

Hace tiempo que se viene contando este chiste, y nos viene al pelo:

secreto_exito2

Cuentan las crónicas, que en el año 96, se celebró una competición de remo entre dos equipos: uno compuesto por trabajadores de una conocida gran empresa española y otros por sus colegas de una empresa japonesa del mismo sector. Apenas se da la salida, los japoneses salen zumbando, banzai, banzai, dale que te pego al remo, y cruzan la meta una hora antes que el equipo español.

De vuelta a casa, la Dirección se reúne en comité para analizar las causas de tan bochornosa actuación, llegando a la siguiente conclusión que difunde el secretario -una vez levantada acta- a todo el personal de la empresa a través del correo electrónico: “Se ha podido establecer que la victoria de los japoneses se debe a una simple argucia táctica: mientras que en su dotación había un jefe de equipo y diez remeros, en la nuestra había un remero y diez jefes de servicio. Para el próximo año se tomarán las medidas oportunas que reviertan este resultado”.

En el año 97 se repite la carrera y nuevamente el equipo japonés comienza a distanciarse desde la primera remada. Los españoles, pese a sus camisetas Lotto, zapatillas Nike y remos de carbono hidratado (que han costado a la empresa un ojo de la cara), llegan esta vez con dos horas y media de retraso.

La Dirección convoca nueva reunión después de un sonado rapapolvo de Gerencia. Para estudiar lo acaecido encargan a un departamento ‘ad hoc’ la investigación y al cabo de dos meses de pesquisas se establece que: “El equipo japonés, con táctica obviamente conservadora, mantuvo su estructura tradicional de un jefe de equipo y diez remeros. Por el contrario, el equipo español, con las medidas renovadoras adoptadas después del fracaso del año pasado, optó por una estructura abierta, más dinámica y se compuso de un jefe de servicio, dos asesores de gerencia, cinco jefes de sección, tres representantes sindicales (que exigieron hallarse a bordo) y un remero. Por lo que el Comité de Dirección, tras minucioso análisis llega a la siguiente conclusión: EL REMERO ES UN INCOMPETENTE”, su informe de dedicación no está completo y el número de brazadas imputado no corresponde con el informe trimestral de planificación.

A la luz de tan crucial informe, la empresa crea un departamento especialmente dedicado a preparar la siguiente regata. En el año 98, como el lector puede suponer, el equipo japonés se escapa nada más producirse la salida. La trainera hispana, cuya composición había sido encargada ese año al departamento de Nuevas Tecnologías, llega con cuatro horas de retraso. A fin de evaluar los resultados, vuelve a reunirse el Comité de Dirección con los representantes de la alta gerencia en la cuarta planta, o planta noble, del edificio de Dirección. Se llegó a la siguiente conclusión, según consta en acta: “Este año, el equipo nipón, optó una vez más por una tripulación tradicional formada por un jefe de equipo y diez remeros.

El español, tras una auditoría externa y el asesoramiento de los departamentos de Organización y de Informática y el informe de un grupo de consultores de Arthur Andersen, optó por una formación mucho mas vanguardista y operativa y se compuso de: un jefe de servicio, tres jefes de sección con plus de productividad, dos auditores de Arthur Andersen y cuatro vigilantes jurados de Prosegur con instrucciones concretas de no quitar ojo al único remero, al cual la empresa había amonestado y castigado quitándole todos los pluses e incentivos por el fracaso del año anterior, además tendrá una reunión de briefing cada 100 brazadas y se le exigirá rellenar por triplicado un informe final por cada entrenamiento.”

Tras varias jornadas maratonianas de reuniones al más alto nivel de Dirección con los diversos responsables de departamento y con el apoyo de un estudio de consultoría externo, se ha acordado que para la regata del próximo año el remero será expulsado de la plantilla de la empresa y sustituido por una contrata externa, ya que a partir de la vigesimoquinta milla marina se ha observado cierta dejadez en el remero de plantilla, una dejadez preocupante que se manifiesta en comentarios dichos entre dientes, entre remada y remada, del tipo: “Anda y que os den” o “El año que viene va a venir a remar vuestra puta madre” y una actitud que incluso roza el pasotismo en la línea de meta.

Al margen de lo gracioso que pueda ser el chiste, explica muy bien un concepto que está muy arraigado en nuestras empresas: la sobregestión. Alguien, en vista de la descripción de lo que sucede en el chiste quizá todavía se está preguntando, ¿porqué los Japoneses nos ganaron? Bueno, si se hacen la pregunta es que son del estilo sobregestionador.

Este tipo de persona, que es sobregestionadora en el trabajo, simplemente no se fía de que sus subordinados tengan la dedicación que dicen tener, porque, y esto es lo fundamental, ellos no están gestionando personas en pos de conseguir un objetivo, sino que están procurando que las personas a su cargo hagan cuantas más horas mejor y que sepan en todo momento, que esas horas son propiedad exclusiva de la empresa. Para este tipo de persona los objetivos de la empresa o la calidad del resultado obtenido son secundarios y serán siempre proporcionales al tiempo que los empleados se queden con el culo pegado a la silla. La calidad o la brillantez de los resultados tendrán que ser sacados a base de broncas o «avisos» a los empleados después de asegurarse que tras las horas dedicadas lo obtenido no es suficiente. Son los jefes de «execel», los peores gestores que puede tener ningún negocio y, desde luego, incapaces de sacar nada bueno de ninguno de sus trabajadores.

Porque, no nos engañemos, las personas trabajan en base a sus motivaciones y si la motivación es evitar una bronca o figurar más horas que otro en los informes de actividad, poco o nada puede aportar a un proyecto más allá de su presencia y su docilidad. ¿Queremos trabajadores así? ¿no sería mejor motivar en base a los resultados obtenidos y premiar en forma de tiempo y realización personal? ¿es tan importante saber a qué dedica un empleado cada milisegundo que está ocupando espacio en la silla? Como decía yoriento, «estar motivado no es tener ganas, es tener motivos»… Desmotivar a alguien con una sobregestión es algo inevitable y encadena a jefe y empleado a un círculo vicioso de más gestión-> menos eficiencia->más gestión-> menos eficiencia…. Romper ese círculo es bastante sencillo, pero nunca debe ser el empleado el que de el primer paso. Todo lo más que puede conseguir nuestro jefe sobregestionador es que el remero se vaya a otra empresa (si es bueno) o se limite a mover los brazos sin ilusión para cubrir el parte de horas.

En mi actividad actual nos han sometido a un sistema que exige registrar en un documento a qué dedicamos cada hora del día y comparar la actividad realizada efectivamente con esa previsión ¡¡cada mañana!! eso junto con una planificación semanal que asigna cada hora disponible a una supuesta actividad aprobada y la necesidad de redactar un documento semanal de seguimiento justificando cada minuto del día… ¿El resultado? la productividad ha caído en picado y la iniciativa de cada empleado se ha reducido a cero, ya que cada cosa que se propone y que requiere la colaboración de alguien termina muriendo con un «no tengo horas asignadas para hacer eso». Si combinamos eso con la inexperiencia y la falta de exactitud inherente a las estimaciones semanales nos encontramos con una receta perfecta para el fracaso.

Otras entradas de la serie «lecciones informáticas»:

Experimentando con cordova

Llevo tiempo desarrollando aplicaciones para móviles, las más conocidas para BiblioEteca, otras propias que no he llegado a sacar al market y otras encargadas por terceros. He vivido todas las épocas, desde el más terrible de los SDK para Android hasta la penosa situación de tener que aprender objective c y limpiar la memoria cada vez que hacía cualquier cosa en ios… Como he comenzado desde los avernos (incluso programé en J2ME, tenéis que creerme), el uso de tecnologías que permiten la multiplataforma en móviles es algo que me atrajo desde el primer momento. Dicho y hecho, había que probar alguna estas «nuevas» tecnologías en algún proyecto… Y como no tenía ninguno a mano, pues me inventé un jueguecito para perder el tiempo. Hoy os presento el resultado y en próximas entradas os explicaré un poco los puntos principales de trabajar con «una capa más» encima de nuestros desarrollos…

imagen-promocionalPega al Rubius… Un juego para desahogarse dando de leches a mi youtuber de cabecera (mis hijos están suscritos a su canal).

Como veréis se puede jugar incluso en el navegador .. Y debería poderse jugar también en los teléfonos de Microsoft, pero no he conseguido hacer funcionar los simuladores en máquinas virtuales (ni reales), y no he conseguido que me lo prueben en un teléfono real, por lo que no he intentado siquiera subirlo a su tienda… Cualquier comentario es bienvenido.

Lecciones informáticas: La resistencia al cambio

Hoy en día están apareciendo un montón de noticias sobre la posibilidad de reemplazar obreros por robots y los cambios económicos que esa situación desencadenaría. En efecto el temor a ser reemplazado por máquinas no es algo nuevo y viene provocado, en mayor o menor medida por una resistencia al cambio que es, en el caso de la tecnología, un freno importante a la adopción de nuevas maneras de trabajo.

301111_1462_1No pienso soltar aquí una lección sobre la resistencia al cambio, pero si que quiero dejar algunas notas sobre las resistencias más obvias que he encontrado en mi carrera y algunas recetas comunes para lidiar con ella. Como siempre, lo veremos con ejemplos reales.

Cada vez que se diseña un nuevo sistema empresarial hay que tener en cuenta no solo al cliente (que es quien paga), sino al usuario final y a aquel que va a trabajar con el sistema de alguna manera (que no tienen porqué coincidir). Las actitudes y motivaciones de cada uno de estos actores suele ser diferente e, incluso, en muchos de los casos divergente. Cuando me han encargado un sistema siempre he intentado tener en cuenta a todos los usuarios, pero hay veces que los conflictos han de solucionarse en la organización y no tiene nada que ver con el sistema. Los problemas más habituales suelen ser:

  • Falta de involucración de la dirección. A pesar de ser quien financie el sistema nuevo, hay veces que los mismos directivos encargan los sistemas para «modernizarse» sin haber pensado en serio que el sistema cambiaría la forma de trabajar de sus empleados. Si se construye el sistema siguiendo las directrices de la dirección lo más probable es que los usuarios terminen renegando del sistema y eviten por todos los medios que este pase a producción.
  • Falta de motivación entre los usuarios. Si algo funciona no lo cambies… dice la máxima de los ingenieros, y eso es así siempre que los cambios no aporten valor de verdad. Los usuarios suelen estar acostumbrados a hacer las cosas de una manera y si no somos capaces de explicarles las ventajas que traerá a su trabajo el nuevo sistema (o si estas no existen), los usuarios estarán más motivados a ignorar el nuevo sistema que a usarlo de verdad. Si el sistema no se prueba y consensúa con los usuarios es muy dificil que su uso sea voluntario.
  • Falta de comunicación entre los distintos actores. Por mucho que seamos unos desarrolladores impresionantes y seamos capaces de realizar proezas técnicas, si no hacen lo que deben o en la manera en la que puede ayudar a los usuarios a realizar su trabajo estaremos construyendo en el vacío. Solo se puede construir algo útil si nos comunicamos con todos los afectados y ellos entre sí. Consecuencia de esta falta de comunicación puede ser la falta de entendimiento sobre los objetivos del proyecto. Lo que a unos les puede parecer un sistema fundamental para el funcionamiento futuro de la empresa para otros puede verse como un gasto inutil de dinero que no va a ser utilizado.
  • Exceso de «mano izquierda». Si alguien os dice alguna vez que es capaz de contentar a todo el mundo, simplemente te está mintiendo. Con los acuerdos (si son buenos) todo el mundo queda insatisfecho en algún aspecto, pero ha conseguido que los aspectos importantes sean tenidos en cuenta. Si algún gestor intenta tener a todo el mundo contento a base de mano izquierda, sin ceder ni exigir lo suficiente, la negociación y la implantación del sistema estarán abocados al fracaso.

¿Cómo se debería realizar una implantación exitosa de un sistema en una organización?

En primer lugar habría que recopilar todas las opiniones de todos los afectados para ver si la idea es compartida, si es una simple imposición o si nos encontramos con oposiciones frontales. En caso de que la idea no sea compartida hay que conseguir, ya desde el momento de los requisitos, involucrar a cuantos más usuarios mejor para intentar averiguar en que puntos el nuevo sistema les va a hacer la vida más sencilla… Si no conseguimos esto, bueno, estaremos ante un sistema impuesto y, probablemente, mal orientado desde la dirección… Si, podemos hacerlo, pero ya sabemos que no será adoptado sin más.

Antes de terminar el sistema se necesita que los usuarios finales (o los principales) vean resultados y hagan comentarios de mejoras que poder introducir. La mayor parte de las veces serán mejoras interesantes y, si la resistencia es fuerte, al menos mostraremos que se les tiene en cuenta. Llegados a este punto puede pasar que la cooperación no exista. Pueden pensar que no es su trabajo andar con pruebas de sistemas sin terminar o que no quieran en absoluto oir hablar del sistema. Este es un caso de manual en el que se requiere que la dirección se involucre y vuelva a explicar qué se espera del sistema y porqué se les está teniendo en cuenta en su construcción. Fallar en esta comunicación nos da muchos puntos para que lo que se termine produciendo sea tirado a la basura.

Finalmente, cuando el producto está terminado, antes de pasar a producción definitivamente habría que mantener un «paralelo» entre las formas de trabajar antiguas y nuevas de manera que se hagan patentes las ventajas. Si no hay ventajas es que algo hemos hecho mal.

Si el sistema se impone por parte de la dirección veremos que los problemas que nos surgen serán algunos de estos:

  • Quejas constantes, intentando demostrar que el sistema está mal construido y atacando de cualquier manera la posibilidad de su paso definitivo a producción.
  • Lentitud de aprendizaje. Aunque el sistema sea sencillo e intuitivo, si se da la impresión de que es difícil de utilizar se están poniendo piedras al despliegue definitivo y puede que se consiga retrasar el mismo exigiendo más formación.
  • Ignorar el sistema. Aún más doloroso que las quejas constantes es la actitud de los usuarios que cuando les salta un error deciden, por su cuenta y riesgo, volver a la forma antigua de trabajar diciendo «esto no funciona» y tirando por la borda cualquier posibilidad de arreglar el problema, informar del uso correcto o corregir el defecto.

Todavía recuerdo el día en el que entregamos un gran sistema web para muchos miles de usuarios y el empleado encargado de mantenerlo a partir de ese día (que era el responsable del sistema anterior) decidió negarse a responsabilizarse del nuevo sistema porque nadie le había preguntado. Como el proyecto era para una administración pública no había manera humana de convencer a este funcionario ni de hacerle entrar en razón, así que se tuvo que contratar a otra persona para que hiciese su trabajo, con el coste añadido que esto suponía.

También me escuece aún el recuerdo del paso a producción de un sistema que tardamos seis meses en recopilar los requisitos manteniendo reuniones semanales con todos los afectados y, tras pasar a producción el sistema, nos llamaron para decirnos… Muy bien, ya vemos que tipo de cosas hace el sistema, ahora os vamos a contar qué es lo que queremos que haga…… ¡¡¿¿??!!