DLL’s, BPL’s, Carga dinámica/Estática y «Packages en Runtime»

lunes, 19 de julio de 2010 9 comentarios
Share Button

Cuando uno empieza a conocer Delphi (al menos a mi me pasó) y dependiendo de si «viene» de otros lenguajes, se hace un lío con las diferentes formas en que podemos generar un programa; Con la forma de trabajar con packages o sin packages, con los ficheros a distribuir,… Y le empiezan a surgir diferentes preguntas:

¿Porqué mi ejecutabe ocupa tanto si sólo he puesto un botón?
¿Qué son los packages de liberías? ¿Los debo copiar con mi aplicación?
¿Porque si marco «Build with runtime packages» mi programa ocupa tampoco?
¿Porque si marco «Build with runtime packages» mi programa no funciona en otras máquinas?
¿Como trabajar con DLL’s? ¿Y con BPL’s? ¿Cual es mejor? ¿Es lo mismo?

Y muchas otras relacionadas con los elementos que aparecen en el título de esta entrada.

Mi idea en este caso es, intentar aclarar algunos de estos términos y las diferentes formas de generar un programa desde Delphi (utilizando DLL’s y BPL’s -packages-). Otra cosa, es que lo consiga…  ;-D

Antes de comenzar, debemos aclarar algunos términos o elementos que debemos tener claros antes de continuar.

——————————————————————————————————————————————-

BWRP = «Build with runtime packages»

Esta opción se encuentra en las «Opciones de proyecto/Packages» y con ella conseguimos:

  • ACTIVADA: El programa no incluye las librerías (normalmente la VCL y componentes de terceros) en el EXE; El ejecutable es más pequeño, pero necesita de los packages (BPL’s) de la VCL; Al distribuir la aplicación se deben copiar también esos ficheros (los necesarios -NOTA1-) y los packages que hayamos creado nosotros.
  • DESACTIVADA: El programa incluye en el EXE los packages de librerías y componentes de terceros. En un único fichero va todo incluído. El EXE tiene mayor tamaño (lógico porque todo va incluído).

NOTA1: Se puede saber qué librerías (DLL’s o BPL’s) necesita un ejecutable utilizando herramientas como «Dependency Walker», GExperts o CnWizards.

DLL = «Dinamic Link Libray / Librería de enlace dinámico»

Son ficheros con código ejecutable, que se utilizan en sistemas Windows, y que forma parte de otras aplicaciones o del propieo sistema operativo. Permiten hacer que los programas sean más pequeños y que el código que contienen pueda ser usado por diferentes aplicaciones.

BPL = «Borland Package Library»

En pocas palabras podemos decir que una BPL es una DLL sólo para Delphi. Las BPL’s son más potentes que las DLL’s. Permiten almacenar más información fFunciones, procedimientos, Units, pero también Clases, Objetos y Componentes). La mayor potencia de estos ficheros se «paga» con la exclusividad de poderlos utilizar únicamente en Delphi.

Carga estática de librerías

Tanto para DLL’s como para BPL’s, cuando hablamos de carga estática, nos referimos a que al ejecutarse el programa, se carga automáticamente esa librería. Aunque en ese momento no se vaya a utilizar el código que hay dentro de la librerías, esta se carga al iniciar. Si la librerías no existe en disco el programa falla durante la carga y no es posible ejecutarlo.

Carga dinámica de librerías

La carga dinámica de packages, tiene como contrapartida que es más compleja (programáticamente) que la carga estática. La carga se debe hacer de forma expresa por el programador cuando se dese. Esto significa que sólo se cargará esa librería cuando se necesite. El programa puede funcionar aunque no esté (el programador deberá comprobarlo antes de cargarla). Este sistema hace que este tipo de carga sea ideal para sistemas con plugins/Addins.

——————————————————————————————————————————————-

Una vez revisado esto, voy a intentar explicar las diferencias al crear un proyecto, segun si utilizamos DLL’s o BPL’s y carga estática/dinámica.

EXE + DLL con Carga estática(El EXE puede ser con o sin BWRP)

Tal y como hemos dicho, la DLL debe existir en disco cuando se ejecuta la aplicación, de otra forma esta no funcionaría y fallaría al arrancar.
Hay que definir dónde se encuentra la DLL (en el que la carga -el EXE-)

function Sumar(x,y:integer):Integer; stdcall; external 'sumas.dll';

Y con eso ya se puede hacer la llamada:

Res := Sumar(4,5);

EXE + DLL con Carga dinámica(El EXE puede ser con o sin BWRP)

En este caso el programa puede funcionar aunque la DLL no exista; En el momento de intentar cargarla se debe comprobar si está o no en disco. Se puede cargar cuando se necesita y descargarla cuando ya no es útil. La carga es un poco más compleja que el caso anterior.

Se utiliza LoadLibrary para cargar la DLL en el momento en que se necesita:

H := LoadLibrary('SUMAS.DLL');

Para acceder a las funciones de la DLL se usa GetProcAddress:

@sum := GetProcAddress(H, 'Sumar2');

En el programa que hace la llamada (el EXE) debe estar predefinido el tipo de la función a la que vamos a realizar la llamada:

Sum: function(x,y:Integer):integer; stdcall;

EXE + BPL con Carga estática(El EXE puede ser con o sin BWRP)

En este caso no hace falta definir nada referente a la función que se encuentra en el package, simplemente hacer referencia a ella en diseño (añadiendo la unit al USES).

Si el programa principal (EXE) se compila con «BRWP Desactivado» todo va dentro del EXE (componentes de terceros y código de la VCL); Si se compila con «BWRP activado» la VCL y los packages de terceros van aparte; Estos packages se deberán distribuir junto al EXE.

Utilizando carga estática es obligatorio que exista el package en disco y que esté accesible al arrancar la aplicación; Si la BPL no existe el programa no puede funcionar.

EXE + BPL con Carga dinámica + RTTI(El EXE debe ser con BWRP)

Es el caso más potente que tenemos. Cargar el package (hemos dicho que las BPL’s son más potentes que las DLL’s) de forma dinámica. Para ello hacemos uso de RTTI (Runtime Type Information) que es lo que le da la potencia extra a las BPL’s. Es obligatorio en este caso que «BWRP esté activado»; Es decir, obligatoriamente debemos distribuir nuestra aplicación con packages.

Los packages se cargan de forma dinámica con LoadPackage (de forma similar a cómo se hace con LoadLibrary):

H := LoadPackage('RESTAS.BPL');

Podemos acceder a las funciones de la misma forma que lo hacemos con las DLL’s, utilizando GetProcAddress:

@resta := GetProcAddress(H, 'Resta');

Podemos utilizar RTTI para acceder a classes que previamente se han registrado (con RegisterClass) utilizando funciones de RTTI como GetClass:

AClass := GetClass('TFormMain');

Y podemos acceder a métodos de las clases utilizando también RTTI, utilizando MethodAddress:

// Acceder al método
Routine.Data := Pointer((F as FormClass));
// Ejecutar al código
Routine.Code := (F as FormClass).MethodAddress('ExecForm');

No es necesario definir nada en el programa principal, puesto que podemos obtener todo la información de las clases definidas en el package utilizando RTTI.

Quedaría una última combinación, posible, pero un poco extraña, que sería EXE sin «runtime packages» y con carga dinámica. Y digo que es un poco rara, porque es un poco contracorriente. Utilizar BPL’s tiene la ventaja que le confiere utilizar RTTI, sin ella los BPL’s pasan a ser DLL’s normales. Esta opción haría justo eso, utilizar BPL’s, pero sin RTTI.

EXE + BPL con Carga dinámica sin RTTI(El EXE sin BWRP)

Esta opción (un poco rara) sería la de utilizar una aplicación con «BRWP Desactivado» (es decir TODO en un único EXE) y cargar en él package de forma dinámica. Esto es posible, pero en este caso perdemos la opción de utilizar RTTI; El EXE (fichero único) podría funcionar sin que exista la BPL que vamos a cargar. Al no poder utilizar RTTI, las «mejoras» que tienen las BPL’s se pierden y pasan a usarse como DLL’s.

Se pueden cargar las BPL’s de forma dinámica con LoadPackage:

H := LoadPackage('RESTAS.BPL');

Y para acceder a las funciones usamos GetProcAddress (como en las DLL’s):

@resta := GetProcAddress(H, 'Resta');

Por supuesto si intentamos acceder a información de clases (GetClass) el programa falla.
Más o menos hasta aquí las diferentes opciones de compilar el proyecto y algunas referencias a cómo hacer las llamadas y las definiciones.

Todo ello está implementado en los ejemplos que ajunto al final de esta entrada. Hay un grupo de proyectos (compilado con Delphi 6) que incluye los siguientes ficheros:

  • sumas.dpr: Proyecto que genera un DLL con una función de suma
  • Call_suma_estat.dpr: Proyecto para llamar a una DLL con carga estática.
  • Call_suma_dinam.dpr: Proyecto para llamar a una DLL con carga dinámica.
  • restas.dpk: Proyecto para generar una BPL con una función de resta y un formulario.
  • Call_resta_estat.dpr: Proyecto para llamar a la BPL con carga estática.
  • Call_suma_dinam.dpr: Proyecto para llamar a la BPL con carga dinámica (uso de RTTI y proyecto compilado con Runtime Packages).
  • Call_resta_dinam_sin_pack.dpr: Proyecto para llamar a la BPL con carga dinámica, pero sin compilación con packages (sin uso de RTTI).

El Grupo de proyectos completo se puede descargar desde aquí.

[Link descarga código fuente]

AÑADIDO: El otro día me dejé sin poner algunas referencias que tengo sobre el tama y que me parecen interesante, así que ahí van:

Categories: OOP Tags: , ,

Promesas incumplidas…

jueves, 15 de julio de 2010 Sin comentarios
Share Button

Personalmente no estoy afectado, pero sí muuuuuchos otros usuarios que han comprado productos antes del Mundial FIFA 2010 (Sudáfrica).

En España (y en otros países) muchas empresas se apuntaron al (SE APROVECHARON DEL) tirón publicitario del Mundiál para aumentar sus ventas afreciendo variadas ofertas, si España ganaba el mundiál.
La mayoría de empresas con sedes internacionales lo hicieron también en otros países, así que supongo que en cierta forma las pérdidas en unos, paliarán las ganancias en otros (además de por supuesto, los seguros contratados en caso de ganar determinada selección).

¡Hasta aquí todo perfecto! ¡España ha ganado el mundiál y ahora toca cumplir! ¿O no?

Pues parece que hay empresas que ahora no están por la labor; «Donde dije digo, digo Diego».

Este es el caso de Toshiba, que anunciaba a bombo y platillo que «Si gana la roja, tú ganas», de forma que si comprabas un portátil/televisor de la marca, y España ganaba el mundiál, te retornaban TODO TU DINERO (y lo pongo en mayúsculas, porque así estaba en la oferta);

<VER LA IMAGEN EN GRANDE>

¿Cual es la excusa?

Pues que parece que habia que registrarse en la web de toshiba para poder acceder a la oferta.  Por supuesto, este «PEQUEÑÍSSSSIMO» detalle «sin importancia» estaba en la letra pequeña pequeñísima, de las condiciones de la oferta.

Tal vez legalmente sea correcto (cosa que está por ver), pero «éticamente» es un ¡ROBO A MANO ARMADA!

Visto lo visto, alguna otra empresa importante como TomTom se está «intentando» escabullir de sus promesas, con similares excusas.

BIEN

por las empresas que están cumpliendo sus compromisos, Media Markt, Carrefour, PC City, Banesto, Seguros Pelayo, Panda, y tantas otras más pequeñas que están asumiendo sus compromisos con los consumidores.

MAL

por Toshiba y TomTom, las primeras (veremos si son las últimas) que se apuntan al carro  cuando las cosas van bien y son las primeras en «echar a correr» cuando las cosas se han puesto feas (para ellos).

Para los usuarios que se encuentran en este caso, la OCU (Organización de Consumidores y Usuarios) recomienda seguir estos pasos, para presentar demanda y llegar a Juicio si es necesario.

Links:

Grupo en Facebook

Blog relacionado con información sobre el tema (timo-toshiba.2010)

Noticia en BBC mundo

Noticia en ElMundo.es

Noticia en CadenaSer.Com

Noticia en ADN.es

Noticia en ABC.es

Noticia en La Vanguardia

Noticia en FACUA (Consumidores en Acción)

Página de OCU (Organización de consumidores y Usuarios); ¿Qué hacer?

Categories: Offtopic, Otros Tags: , ,

Primeros pasos con ExtJS

miércoles, 9 de junio de 2010 6 comentarios
Share Button

Estos días estoy revisando soluciones para realizar algunas aplicaciones web; O más concretamente «portar» aplicaciones a un entorno Web. Para ello estoy revisando ExtJS. Segun su página web dice textualmente:

«Ext JS is a cross-browser JavaScript library for building rich internet applications.»

Espero pronto descubrir que si es verdad…  ;-)

Antes de nada debemos preparar el equipo con lo necesario para poder empezar.

Instalar un Web Server

Si es que no tenemos ninguno instalado, deberemos instalar uno; E en los equipos con

Windows XP se puede añadir el IIS de Microsoft, en mi caso he optado por instalar Apache 2.2.8. Podéis descargarlo desde la web de Apache, o como en mi caso seleccionar alguno de los paquetes de instalación que lo incluyen, como es el caso de AppServ (Apache 2.2.8, PHP 5.2.6, MySQL 5.0.51b, phpMyAdmin-2.10.3) disponible en la web de AppServNetwork.

Una vez instalado en vuestro equipo (o en otro) podéis comprobar que el Webserver  funcioma abriendo el explorador en la dirección   http://127.0.0.1 o  http://localhost

En el caso de apache veréis una página similar a esta:

Prepara el directorio para test

En mi caso dentro del directorio donde se publican la páginas (www en  c:\AppServ\www) he creado un directorio

llamado Ejemplos. Dentro de la carpeta ejemplos y para jerarquizer los proyectos he creado una estructura como la que se ve a la derecha. Además debemos crear un directorio ext donde copiaremos el contenido de las librerás ExtJS descargadas desde su página web (versión 2.x).

Dentro del directorio Ejemplos, crearemos las carpetas css, ext, img y js donde almacenaremos los diferentes ficheros de los proyectos.

La prueba definitiva

Finalmente haremos la última comprobación para asegurarnos de que todo funciona correctamente y se ejecutan las ExtJs correctamente. Pare ello crearemos una página HTML en el directorio ejemplos con el siguiente código (que nos servirá de inicio para nuestros ejemplos).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
<!-- Do NOT put any DOCTYPE here unless you want problems in IEs. -->
<html>
 
<!-- Each valid html page must have a head; let's create one. -->
<head>
  <!-- The following line defines content type and utf-8 as character set. -->
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 
  <!-- Ext relies on its default css so include it here. -->
  <!-- This must come BEFORE javascript includes! -->
  <link rel="stylesheet" type="text/css" href="ext/resources/css/ext-all.css">
 
  <!-- Include here your own css files if you have them. -->
 
  <!-- First of javascript includes must be an adapter... -->
  <script type="text/javascript" src="ext/adapter/ext/ext-base.js"></script>
 
  <!-- ...then you need the Ext itself, either debug or production version. -->
  <script type="text/javascript" src="ext/ext-all-debug.js"></script>
 
  <!-- Include here your extended classes if you have some. -->
 
  <!-- Include here you application javascript file if you have it. -->
  <script type="text/javascript" src="./js/application.js"></script>
 
  <!-- Set a title for the page (id is not necessary). -->
  <title id="page-title">Test</title>
 
  <!-- You can have onReady function here or in your application file. -->
  <!-- If you have it in your application file delete the whole -->
  <!-- following script tag as we must have only one onReady. -->
  <script type="text/javascript">
 
  // Path to the blank image must point to a valid location on your server
  Ext.BLANK_IMAGE_URL = 'ext/resources/images/default/s.gif';
 
  // Main application entry point
  Ext.onReady(function() {
 
	// alert("Congratulations!  You  have Ext configured correctly!");
    // console.info('Ejemplo1');
 	Ext.MessageBox.show({
	    title: 'Prueba de mensaje',
	    msg: 'Hola a todos',
	    width: 400, 
	    buttons: Ext.MessageBox.OK
	});
  });
  </script>
 
<!-- Close the head -->  
</head>
 
<!-- You can leave the body empty, or write your content. -->
<body>
<span style="color: rgb(102, 0, 0);">Testeando página de inicio...</span>
</body>
 
<!-- Close html tag at last -->
</html>

Puedes descargar este archivo aquí (comprimido como ZIP).

Si todo ha ido bien y en nuestro navegador escribimos: http://localhost/ejemplos/ deberíamos ver la siguiente pantalla:

En este punto tenemos la instalación correcta y ya podemos comenzar a practicar. Pero eso será otro día…

Categories: ExtJS, Programación Tags: ,

ENCUESTA: Sistema de control de versiones

lunes, 7 de junio de 2010 4 comentarios
Share Button

Después de un breve tiempo de innacividad, espero en breve volver a publicar de forma más asídua.

Vuelvo a publicar con una escuesta sobre los sistema de Control de Versiones.

Una de las cosas que creo básicas para un programador, cuando uno ya lleva un tiempo en esto y el volumen de código generado empieza a ser grande, es un  buen control de versiones, que además se puede utilizar como backup y repositorio de fuentes. Y ya no sólo cuando se trabaja en grupo, sino a nivel personal.

Para mi, es una de quellas cosas, que una vez que las pruebas, a no puedes «vivir» sin ellas.   ;-)

Os animo a que votéis y déis vuestra opinión.

Un saludo.

¡¡Duros a 3 pesetas!! Pues no…

jueves, 25 de marzo de 2010 4 comentarios
Share Button

Pues eso siempre me ha dicho mi madre:

– «Mira hijo, que nadie da duros a 3 pesetas!!».

¿Y qué razón tenía!  Me explico…

Por si no os habéis dado cuenta, la web ya no está en los servidores de 000webhost. ¿Porqué? Pues eso me gustaría saber a mi…

000Webhost ofrece dominios gratuítos. Yo mismo lo he recomendado alguna vez en aquí en mi web y en otros foros.

Resulta que el pasado Sábado TODO el contenido de mi web fue borrado/eliminado de los servidores de 000webhost. Ningun aviso, ninguna advertencia, ningun correo,…  NADA.  No sólo la web estaba innaccesible, sino que el acceso a los posibles datos estaba cancelado.

Los que visitáis asíduamente esta web, sabéis qué contenidos ofrezco, todos de creación propia, nada de enlaces a contenido ilegal, nada que imcumpla sus Términos del Servicio.

Me he dirijido a ellos y por varios medios he intentado que me dieran razones del porqué del cierre. Lo único que he obtenido (y lo he tenido que hacer desde una cuenta externa) es esto:

Mierda de explicación Respuesta a la consulta (link)

Viene a decir algo así como:

«Cierro tu web porque incuple los Términos del servicio».
Cuando preguntas qué terminos del servicio has inclumplido te dicen:
«No te lo puedo decir por razones de seguridad»
Lo que para mi significa:
«Te lo borramos porque nos da la gana y no te damos ninguna explicación»

Se te queda cara de tonto y muy mala leche.

Estoy convencido de que mi web no incumplía ninguno de los términos. ¿Porqué cancelarla entonces?

Mi opinión es, que símplemente no soy un cliente rentable. Mientras estás como cliente gratuíto obtienes un buen servicio, supongo para que te plantees hacer un Upgrade. Una vez que se demuestra que no eres un cliente potencial que va a dejar dinero ya no sirves como cliente. No interesas.

Como ya he dicho, desde aquí mismo y desde otros foros he recomendado esta servicio gratuíto de hosting; En este momento retiro esa recomendación. Sólo espero que cuiden mejor a los clientes que pagan de lo que lo han hecho conmigo.

Hubiera bastado con un simple correo, un simple aviso, para retirar cualquier contenido ilegal de la web (si es que lo hubiera habido -que no es así-), un simple correo avisando del cierre, como mínimo para poder realizar copias de seguridad. NADA.
He perdido algunas horas en poder restaurar el contenido de la web. No sólo están los artículos (de los que tenía copia) sino que aparte hay muchos ejemplos, ficheros, imágenes,… que he tenido que buscar en varios lugares, sin poder llegar a restaurarlas todas.  ;-(

Por supuesto cualquier comentario será bienvenido.

Un saludo y lo dicho: «Nadie da duros a 3 pesetas… si ya lo decía mi madre».

AÑADO: Los que seguíais la web vía Feed o la teníais en los marcadores, tal vez deberías actualizar los links.

http://www.000webhost.com/includes/tos.php

Aplicación multiidioma con GNU Gettext

viernes, 5 de marzo de 2010 26 comentarios
Share Button

He probado algunos sistema de traducción para programas Delphi, entre ellos multiidioma2he de destacar los componentes de TsiLang Component Suite , que me parecen muy buenos y completos.

Estos días necesitaba un paquete gratuíto y revisando páginas y foros he llegado a GNU Gettext for Delphi and C++ Builder. Me parece un paquete muy sencillo de utilizar y por lo que he probado hasta ahora, cómodo y eficaz.

En esta entrada voy a explicar desde cero los pasos que he seguido para conseguir una aplicación multiidioma.

PREPARATIVOS

(1) GNU Gettext

Descargar desde la página «GNU Gettext for Delphi and C++ Builder» el programa de instalación. También se puede encontrar la última versión en SourceForge.

Una vez descargado el ficchero e instalado tendremos lo necesario para generar nuestros ficheros de traducción e integrarlos en el programa.

NOTA: Hay una versión especial compatible con Delphi 2009 que podemos descargar desde aquí, si estamos utilizando esta versión de Delphi..

Si se ha instalado correctamente, nos pedirá reiniciar el sistema.
Una vez instalado, si desde el explorador de Windows pulsamos Click derecho con el ratón sobre una carpeta, nos debería aparecer una nueva opción «Extract Translations to Template«.
generar_traducciones

(2) Poedit for Windows

Necesitaremos una herramienta para poder traducir (ya seamos nosotros o una tercera persona) los ficheros de traducción a los diferentes idiomas. Esto está pensado para que esa posible tercera persona (que puede no tener Dephi instalado)  pueda traducir un fichero sólo con esta herramienta (y el fichero .po como veremos después).

Descargamos el programa desde la página (http://www.poedit.net/) y lo nstalaremos.

Una vez realizados estos dos pasos previos, crearemos un pequeño proyecto de ejemplo donde realizar las pruebas.

Para ello, desde Delphi comenzamos una nueva aplicación y en el formulario generaremos algo similar a esto:

TRADUCCIÓN

(a) Preparar el  proyecto.

Una vez tenemos nuestra aplicación funcionando debemos preparnos para comentar lo necesario para traducción.
(1) Lo primero es añadir la unit gnugettext.pas a nuestro proyecto. Las units que usesn traducciones deberán tenerla en el uses.

NOTA: Si habéis realizado la instalación estandard debería estar en:
«c:\Archivos de programa\dxgettext\gnugettext.pas»

(2) Añadir al OnCreate de nuestros formularios el siguiente código:

// Traducir el formulario
TranslateComponent(Self);

(3) Preparar la estructura de directorios para organizar las traducciones. Dentro del directorio de la aplicación crearemos una carpeta llamada locale y dentro de ella un árbol de directorios similar al que se ve en la imagen.

directorios1

En este ejemplos, yo voy a utilizar 4 idiomas (es, en, fr, ca); Contando que el original va a ser el Español(es) debemos crear la estructura para los otros 3 (inglés, francés y catalán). Nos quedará un arbol de directorios como este:

directorios2

(b) Generar fichero de traducciones (.po)

(1) Para generar el fichero de traducciones del proyecto se debe extraer todas las cadena «traducibles» y almacenarlas en un fichero; Para ello basta con que, desde el explorador de Windows, pulsemos Click derecho sobre la carpeta del proyecto y seleccionemos la opción «Extract Translations to template».
Esto generará un fichero default.po en el directorio de la aplicación.

generar_traducciones

(2) Copiaremos este fichero dentro de los directorios LC_MESSAGES; Tantas copias como directorios tengamos. Después de eso tendremos varios ficheros .po; Uno en el directorio de la aplicación y uno dentro de cada carpeta de traducción:

appdir/appTest.exe
appdir/default.po
appdir/locale/en/LC_MESSAGES/default.po (Traducciones al inglés)
appdir/locale/fr/LC_MESSAGES/default.po (Traducciones al francés)
appdir/locale/ca/LC_MESSAGES/default.po (Traducciones al catalán)

(c) Traducir los ficheros.

En este punto ya se pueden abrir cada uno de los ficheros .po y traducirlo utilizando poedit. Una vez abierto el fichero con poedit, veremos una pantalla como esta:


Una vez finalizada la traducción de palabras y cerrado el programa veremos que en cada directorio aparecen 2 ficheros; El  default.po (original) y el de traducción llamado default.mo.
Repetimos esto con todos los ficheros de traducción.

(d) Cómo utilizar las traducciones en nuestro programa

Una vez los ficheros de traducción estén generados, para utilizarlos desde la aplicación añadirenmos el siguiente código a los botones de activación de los idiomas.

botones_idiomas

// para el catalán
UseLanguage('ca');
RetranslateComponent(Self);
 
// para el inglés
UseLanguage('en');
RetranslateComponent(Self);
...

Si ejecutamos la aplicación veremos que al pulsar los botones cambia es aspecto del formulario.

Para finalizar, aun nos queda un detalle, que es, que la cadena que aparece al pulsar el botón «Hola Mundo!»  no aparece traducida.

Para ello utilizaremos la función de traducción  _().
La llamada que actualmente está así:

MessageDlg('Hola', mtInformation, [mbOK], 0);

Pasará a colocarse así:

MessageDlg(_('Hola'), mtInformation, [mbOK], 0);

PASOS FINALES

Con eso nuestro programa debería quedar traducido completamente. Si movemos el EXE y la carpeta locale a cualquier otro sitio veremos que el programa funciona correctamente. Si sólo movemos el EXE, el efecto es que no aparace nada traducido.

Queda un último detalle, que es integrar las traducciones en el EXE, para que todo quede en el ejecutable y no debamos preocuparnos del directorio locale.

integrar_traducciones

Basta con pulsar click derecho sobre el EXE de nuestra aplicación desde el explorador de Windows, Seleccionar la opción «Embeb Translations» y seleccionar los ficheros de traducción que queremos integrar.

integrar_traducciones2

Con esto debería ser todo.

UPDATE: (20/04/2011)

Pues haciendo pruebas he llegado a obtener el mismo proble que comenta Sil en sus comentarios (en mi caso utilizando Delphi XE). Se trata de que al intentar añadir las traducciones al exe se obtiene un error con la referencia: «6637DB2E-62E1-4A60-AC19-C23867046A89».

Revisando por Internet, parece que se solventa sustituyendo unas constantes que hay en gnugettext.pas.

(1) Buscar esta sección en la unit gnugettext.pas:

  // DetectionSignature: used solely to detect gnugettext usage by assemble
  DetectionSignature: array[0..35] of AnsiChar='2E23E563-31FA-4C24-B7B3-90BE720C6B1A';
  // Embedded Header Begin Signature (without dynamic prefix written by assemble)
  BeginHeaderSignature: array[0..35] of AnsiChar='BD7F1BE4-9FCF-4E3A-ABA7-3443D11AB362';
  // Embedded Header End Signature (without dynamic prefix written by assemble)
  EndHeaderSignature: array[0..35] of AnsiChar='1C58841C-D8A0-4457-BF54-D8315D4CF49D';
  // Assemble Prefix (do not put before the Header Signatures!)
  SignaturePrefix: array[0..2] of AnsiChar='DXG'; // written from assemble

(2) Y sustituirlas por estas:

  // DetectionSignature: used solely to detect gnugettext usage by assemble
  DetectionSignature: array[0..35] of AnsiChar='6637DB2E-62E1-4A60-AC19-C23867046A89';
  // Embedded Header Begin Signature (without dynamic prefix written by assemble)
  BeginHeaderSignature: array[0..35] of AnsiChar='';
  // Embedded Header End Signature (without dynamic prefix written by assemble)
  EndHeaderSignature: array[0..35] of AnsiChar='';
  // Assemble Prefix (do not put before the Header Signatures!)
  SignaturePrefix: array[0..16] of AnsiChar='#0#0#0#0#0#0#0#0';//'DXG'; // written from assemble

Con este ambio ha desaparecido el error y se integran perfectamente las traducciones.

Espero que haya sido útil.

Espero comentarios, sugerencias, errores,… y demás.

CÓMO MONTAR UN NEGOCIO Y GANAR PASTA DESDE CERO

martes, 2 de marzo de 2010 3 comentarios
Share Button

Otros posibles títulos que he barajado para esta reflexión han sido:

  • «Cómo convertir lo gratuito en negocio y forrarte con ello»
  • «Cómo ganar una pasta con el trabajo de otros»
  • «Cómo ser un buitre profesional»
  • «¡A tomar pol culo!» (este era para desfogarme…)
  • «Así es como se hace negocio en España»

Antes de empezar, he de decir que no soy ningún fan de Google, tienen sus cosas buenas y sus cosas malas (como todos), pero hay que reconocerles que durante los últimos años han trabajado duro. Han innovado y han apostado por un modelo de negocio muy particular (diferente al de otras empresas) y por lo que se ve no les está iendo mal.cc

Desde el punto de vista del usuario «de a pie» Google ofrece una serie de servicios «gratuitos» entre ellos su buscador (al igual que otras empresas); Me centro en este, porque seguramente es el más utilizado. Y cuando hablo de gratuito me refiero a nivel estrictamente «monetario». Si yo quiero buscar la página de «Coca-Cola», la del «Museo del Prado» o la de «Delphi Prism» puedo hacerlo usando Google, Yahoo, Bing,… y me sale gratis(1).

(1) He aquí donde empieza todo. Google a día de hoy gana mucho dinero, esto lo sabe todo el mundo, y a los usuarios estos servicios no nos cuestan dinero (hablo del buscador, pero podemos generalizar esto con muchos otros servicios y con otras empresas similares).

A alguien se le ha ocurrido que esto no puede ser, unos no pagan y otros ganan mucho. Nooooooorrrr.

¡¡Estos son los buitres y ahí está el negocio!!

No puede ser que unos estén obteniendo cosas GRATIS y otros se estén FORRANDO, hay que conseguir sacar «tajada».

Pasos a seguir a partir de este momento:

(ACTO-1)
________________________________________

Como resulta que Google ha montado un buen negocio y ganan mucha pasta, los buitres-chupópteros(2) están buscando la forma de conseguir dinero fácil beneficiándose, no de su trajabo, sino del que han realizado otros.

(2): Los buitres-chupópteros-carroñeros son esas compañías que aquí, dan un servicio pésimo, cobran mucho por sus ADSL, dan un nivel inferior al de otros países europeos y tienen unas compañías de móvil donde lo único que les preocupa es adquirir clientes de cualquier forma (publicidad engañosa, dudosos contratos por teléfono, horrorosos servicios de atención al cliente,…). Sí, esas, las compañías de teléfonía.

Estos «elementos» (según ha dicho el «presi» de Telefónica) lo que quieren hacer es cobrar a los buscadores por utilizar sus líneas ?¿?¿?¿:

Telefónica abre fuego contra los buscadores

Eso, eso, que los de Google vayan «currando» y nosotros a ver si, sin «pegar ni chapa» pillamos algo (¿no os recuerda al modelo de negocio de las SGAE?).

(ACTO-2)
________________________________________

Al ministro de Industria (un tal Sebastián), que debe salir del mismo sitio que la ministra de cultura (la «Sinde»), si esa que va dando coba a los de las SGAE, no se le ha ocurrido otra cosa que decir que es viable:

Sebastián afirma que es «una opción posible» que las operadoras cobren a Google

(ACTO-3)
________________________________________

¡Ya está! ¡Se abrió la veda!

Visto lo visto (y si el ministro «Sebas» lo dice), pues los demás «buitres» allá que han ido de cabeza (y los que se apuntarán…).

Vodafone se abona a la propuesta de cobrar a Google por usar la red

(ACTO-4)
________________________________________

El ministro «Sebas», «erre que erre», a lo suyo; Yo creo que como ha visto que su propuesta ha tenido éxito (sobre todo entre los «buitres») pues se ha «envalentonao» e insiste:

El ministro Sebastián defiende cobrar una tasa a los buscadores

(ACTO-FINAL)
________________________________________

Por último, como no, en una reunión de «buitres» no podían faltar ellos. Los innombrables. Yo creo que ya pronto cobrarán por su modelo de negocio (que debería estar patentado aquí en España -con la venia y aprobación de la «Sinde»-):

  • El de cobrar por no hacer nada.
  • El de cobrar por todo.
  • El de «cobrar por si…»    Por si copias, por si bajas, por si compartes…
  • El de cobrar por ver, oír y escuchar.

Lo lógico es que Telefónica cobre de Google y nos pague a nosotros

¡Pues ya estamos todos!

.
.
.

¡¡Así es como se monta un negocio en España!!

No se dónde acabará todo eso; Yo creo que como Google «LOS VA A MANDAR A TOMAR POL CULO A TODOS» «les va a decir que no», lo que más me temo de esto, es que lo mismo nos dicen (con «Sebas» y la «Sinde» a la cabeza):

-Bueno, pues vamos a cobrarles a los usuarios, que al final son los que usan Google, que es quien usa nuestras redes de telefonía, que nosotros «somos quienes lo hacemos todo»… (3)

(3) Palabras del director de telefónica (César Alierta)

«Las redes las ponemos nosotros, el peering lo hacemos nosotros, los sistemas los hacemos nosotros, el customer care lo hacemos nosotros, el servicio post-venta lo hacemos nosotros, el servicio de instalación lo hacemos nosotros… lo hacemos todo. Quiero decir, ellos tienen algoritmos y contenidos…»

Pobrecitos, mira que son malos esos «aprovechados» de Google…

¡¡Así es como se monta un negocio en España!!
AÑADIDO(02/03/2010): Os coloco el link del video con la conferencia. Los comentarios no tienen desperdicio.

Telefónica quiere cobrar a los buscadores


Categories: Humor, Offtopic Tags: , , ,

GlibWMI 1.8beta liberada (Sourceforge)

miércoles, 24 de febrero de 2010 6 comentarios
Share Button

Acabo de cerrar la versión 1.8b de la librería GLibWMI.

Nuevos componentes y algunas correciones a errores referentes a propiedades y «leaks» de memoria (los más importantes).

La librería está accesible completa en SourceForge (GLibWMI).

SourceForge

Podéis descargar los fuentes vía SVN desde:

http://glibwmi.svn.sourceforge.net/svnroot/glibwmi/

O también podéis descargar los ficheros desde aquí.

Guardar configuración de Base de Datos

miércoles, 27 de enero de 2010 6 comentarios
Share Button

Es una cosa que en multitud de ocasiones hemos necesitado hacer; Ya sea con la configuración del acceso a Base de Datos, con la configuración de propiedades, guardar estado del programa, posición,…

En este caso en concreto (a raiz de este hilo en Clubdelphi) se trata de guardar la configuración de Base de Datos. El contenido importante de la propiedad ConnectionString.

Podemos almacenada TODO el contenido de la propiedad en un sólo elemento o guardar los elemtos relevantes de la conexión (Servidor, usuario, Base de Datos y password); En mi caso he preferido el segundo.

Para ello lo más sencillo es utilizar la clase TIniFile que provee Delphi.

Para guardar los valores utilizamos WriteString:

// Grabar
ini.WriteString(CONFIG_SECTION, 'User', edtUser.Text);
ini.WriteString(CONFIG_SECTION, 'password', edtPassword.Text);
ini.WriteString(CONFIG_SECTION, 'Server', edtServer.Text);
ini.WriteString(CONFIG_SECTION, 'BaseDatos', cbBD.Text);

Y para recuperarlos el equivalente ReadString:

// Cargar datos
edtUSer.Text := ini.ReadString(CONFIG_SECTION, 'User', STR_EMPTY);
edtPassword.Text := ini.ReadString(CONFIG_SECTION, 'password', STR_EMPTY);
edtServer.Text := ini.ReadString(CONFIG_SECTION, 'Server', STR_EMPTY);
cbBD.Text := ini.ReadString(CONFIG_SECTION, 'BaseDatos', STR_EMPTY);

Una vez tenemos los datos podemos montar la conexión y activarla.

const
STR_CONN = 'Provider=SQLOLEDB.1;Password=%s;Persist Security Info=True;' +
'User ID=%s;Initial Catalog=%s;Data Source=%s';
 
...
 
// Intentar conectar
ADOConnection1.ConnectionObject.ConnectionString :=
Format(STR_CONN, [edtPassword.Text, edtUser.Text, cbBD.Text, edtServer.Text]);

En este ejemplo además se utiliza otra conexión con casi los mismos parámetros introducidos, pero accediendo a la tabla master, para preguntar al servidor SQL por las Bases de Datos disponibles y así mostrarlas al usuario:

SELECT * FROM SysDataBases

Adjunto el ejemplo coon el código.

<DESCARGAR EJEMPLO>

En este caso, la conexión es con SQL Server mediante OLEDB. En general, para esta y otras conexiones os recomiendo una web creada específicamente al respecto:

ConnectionString.com

Resultados de la encuesta sobre SGBD’s

lunes, 25 de enero de 2010 Sin comentarios
Share Button

Hoy se ha cerrado la encuesta que había en el Blog referente al SGBD que la gente usa en sus programas.

Me ha servido un poco, para probar el plugin de encuestas, pero también (aunque los votantes no han sido muchos en esta «prueba piloto») me ha sorprendido un poco el resultado.

Sinceramente no pensé que SQL Server apareciera tan arriba. Personalmente trabajo con ella y me gusta mucho, pero la gente suele ser reacia en los foros a utilizarla (o eso me parecía a mi desprender de los comentarios que leía).

También creo que es una solución más a nivel profesional, mientras que me da la impresión que Firebird, puede ser más una elección personal. Eso explicaría que la gente la use, aunque no les acabe de gustar (por obligación) ;-D

Un saludo.

Categories: Bases de Datos, Encuesta Tags: , ,