Sistema de traducción de extensiones para NAVE

Este documento tiene como principal objetivo fomentar la traducción de extensiones mediante un sistema escalable que, aunque inicialmente puede ser complicado de entender, al final, cuando se comprende la funcionalidad y se tiene correctamente configurado, se minimiza el tiempo total empleado en generar un paquete de idioma con la traducción. Como detalle, se tardará mucho más tiempo en traducir las extensiones que en generar los paquetes xpi para instalarlos.

  • Versión de este documento: 1.3.0.1
  • Autor: Oscar Manuel Gómez Senovilla
  1. Introducción
  2. Fases del proceso de traducción
  3. Casos prácticos
  4. Tratamiento de las extensiones desde NAVE
  5. Contacto, correcciones y sugerencias

Introducción

El sistema empleado está basado en crear unos scripts para el shell bash que contienen unos valores de configuración adecuados que, procesados mediante otro script central encargado de realizar todas las operaciones, y en conjunción con unos "ficheros de plantilla" adecuados, se encargará de realizar los reemplazos necesarios en estas plantillas para generar los ficheros de instalación necesarios para conseguir un paquete xpi traducido de la extensión. Los llamados ficheros de plantillas tendrán, como convención, el mismo nombre del original más la extensión extra .sed, porque se usa la utilidad GNU sed con dichos ficheros para realizar las sustituciones y generar los ficheros finales.

El objetivo final ideal de este documento es crear una propuesta de sistema estándar para traducción de extensiones. Como veremos, el sistema es totalmente multiidioma (aunque nos centramos en la obtención de ficheros xpi para es-ES), ya que es fácilmente adaptable a cualquier otro idioma. De momento, al menos se adopta en el ámbito de NAVE, en donde tendríamos cuando menos unas especificaciones homogéneas de trabajo bien definidas, sobre todo para que se pueda mantener una traducción de una extensión por otra persona en el caso de cambio de traductor por cualquier circunstancia.

Fases del proceso de traducción

En el proceso de la traducción de una extensión se pueden distinguir tres fases esenciales: preparación inicial del entorno, traducción de las cadenas y empaquetamiento de la traducción.

Requisitos

El software necesario es el siguiente:

  • Shell. El shell o intérprete de comandos que usaremos durante todo el proceso será bash. Para ello, necesitas que tu sistema operativo lo tenga (quizás valga algún shell compatible). En los sistemas linux/unix, viene con el sistema base. En MacOSX también lo tienes, pero no está en windows. Para este último, existe el paquete cygwin, que implementa versiones para windows de muchas herramientas nativas GNU. Otras herramientas o comandos que hacen falta son tar, sed, zip, unzip y grep. Asegúrate de que tienes todos instalados. Para facilitar la navegación por ficheros y directorios, se recomienda la instalación de mc (midnight commander). Hemos redactado unas instrucciones de instalación de cygwin para ayudarte en esta tarea.
  • Traducción de la extensión. Para esta parte, se indican varias posiblidades más abajo.

Estructura de directorios

Introducción

El primer paso para empezar a realizar traducciones es tener creada la estructura de directorios, que crearemos a partir de un directorio concreto cuyo nombre convendremos que será ~/MT. Lo creamos, si no existe, con mkdir -p ~/MT, donde "~" es el directorio raíz personal del usuario en unix. ATENCION: el shell diferencia mayúsculas y minúsculas, así que pongamos especial cuidado en este aspecto. Si por cualquier motivo deseas crearlo en otro sitio, después de crearlo, pon un enlace simbólico a ese sitio, de tal manera que ~/MT apunte a este directorio y asegurándote de tener los permisos adecuados si lo haces fuera de tu directorio personal.

Preparación de la estructura de directorios

La estructura de directorios se crea a partir de la descarga del fichero tar con la estructura base. Para ello, descarga este fichero en el directorio ~/MT y, desde ese directorio, descomprímelo con la instrucción tar zxvf extensiones.tar.gz, obteniendo la estructura siguiente (que se puede ver con el comando tree, si está instalado) para la traducción de extensiones:

~/MT
|-- MT.sh
|-- OmegaT.sh
|-- compare-locales.pl
|-- extensiones
|   |-- MT.sh -> ../MT.sh
|   |-- OmegaT.sh -> ../OmegaT.sh
|   |-- XPI.sh
|   |-- XPI_lang.sh -> <?=$XPI_lang?> 
|   |-- <?=$XPI_lang?> 
|   |-- _TEMPLATE
|   |   |-- 0.0.0
|   |   |   |-- MT.sh -> ../../MT.sh
|   |   |   |-- OmegaT.sh -> ../../OmegaT.sh
|   |   |   |-- XPI.sh -> ../../XPI.sh
|   |   |   |-- generic -> ../generic
|   |   |   |-- moz2po.sh -> ../../moz2po.sh
|   |   |   |-- mt.jar -> ../../mt.jar
|   |   |   |-- po2moz.sh -> ../../po2moz.sh
|   |   |   |-- po2tmx.sh -> ../../po2tmx.sh
|   |   |   |-- unzipxpi.sh -> ../../unzipxpi.sh
|   |   |   `-- version.cfg
|   |   |-- _sed
|   |   |   |-- chrome.manifest.sed
|   |   |   |-- contents.rdf.sed
|   |   |   |-- install.js.sed
|   |   |   `-- install.rdf.sed
|   |   |-- extension.cfg
|   |   |-- extension.kbabel
|   |   |-- extension.omt
|   |   |   |-- omegat
|   |   |   `-- omegat.project
|   |   |-- generic
|   |   |   |-- chrome
|   |   |   |   `-- contents.rdf -> ../../_sed/contents.rdf.sed
|   |   |   |-- chrome.manifest -> ../_sed/chrome.manifest.sed
|   |   |   |-- install.js -> ../_sed/install.js.sed
|   |   |   `-- install.rdf -> ../_sed/install.rdf.sed
|   |   `-- l10n
|   |       |-- ab-CD.cfg
|   |       `-- es-ES.cfg
|   |-- moz2po.sh
|   |-- mt.jar -> ../mt.jar
|   |-- po2moz.sh
|   |-- po2tmx.sh
|   `-- unzipxpi.sh
|-- mt.jar -> mt5xx.jar
 -- mt5xx.jar

Falta el fichero mt5xx.jar (donde "xx" depende del número de versión), que se obtiene al descomprimir MozillaTranslator. En esta estructura se dan cobertura a varios programas, así que habrá ficheros que serán necesarios o no según el programa o programas elegidos. En cada caso, la función de cada fichero sólo se explica en su apartado correspondiente.

La filosofía sobre la que se asienta la estructura de directorios consiste en tener diferenciados los elementos comunes y no comunes en cada parte del proceso, alojando los ficheros adecuados en los directorios adecuados para cada tarea parcial, para no repetir elementos o definiciones de forma innecesaria.

Puedes usar el método rápido e ir directamente a casos prácticos si no quieres ver todos los detalles del propósito de cada fichero. Puedes volver a este punto después para aclarar cualquier posible duda.

Directorio raíz global para las traducciones

Nos vamos al directorio raíz con cd ~/MT Podemos comprobar en cualquier momento el directorio en el que estamos con la instrucción pwd.

Ficheros

Comprobamos que en este directorio tendremos los ficheros comunes a todos los elementos que luego irán por debajo en la estructura de directorios. Estos ficheros son:

  • Para MT:
    • El fichero de la versión correspondiente de MT (mt5xx.jar).
    • Un enlace simbólico a este fichero llamado mt.jar, con el objetivo de tener un nombre de fichero que valga para todas las versiones de MT. Esto lo conseguimos con la orden ln -sf mt5xx.jar mt.jar.
    • Un fichero llamado MT.sh, que será el script que lance MT para realizar la traducción.
  • Para programas que usan formato po:
    • En mi caso, el directorio translate, donde he instalado el translate-toolkit.
  • Otros:
    • OmegaT: el fichero zip en la forma OmegaT_*.zip, que descomprimo usando unzip -d omegat <OmegaT_XX.zip>, siendo XX una serie de números indicando la versión, y con lo que se crea el directorio omegat, conteniendo los ficheros de ejecución de OmegaT.
  • Si se tiene instalado perl (en linux estará instalado, en win32, no, y en MacOSX lo desconozco), disfrutaremos de la utilidad del script compare-locales.pl, que se encargará de verificar la consistencia de las cadenas. Como este fichero no es de uso exclusivo de las extensiones (en realidad se usa sólo para los productos, pero es funcional tanto para productos como para extensiones), está en este directorio y no debajo.
  • Finalmente, tenemos un directorio llamado extensiones, que se ha creado con la instrucción mkdir extensiones.

Podemos comprobar que tenemos todos los elementos con la orden ls -l:

-rw-r--r--  1 oscar oscar    6083 2004-09-26 10:15 compare-locales.pl
drwxr-xr-x  3 oscar oscar    1024 2006-02-05 03:22 extensiones
-rwxr-xr-x  1 oscar oscar 1762482 2004-09-19 21:37 mt522.jar
lrwxrwxrwx  1 oscar oscar       9 2006-02-05 03:22 mt.jar -> mt522.jar
-rwxr-xr-x  1 oscar oscar     105 2005-08-11 02:29 MT.sh

Las columnas donde pone "oscar" son exclusivas de mi sistema, por lo que en el tuyo, saldrá otro usuario y grupo distintos. Las fechas, ignóralas. Lo importante es que salga mt.jar -> mt5xx.jar (donde el símbolo del guión seguido por el de mayor indica que se trata de un enlace simbólico) apunte a la última versión de MT.


Directorio raíz global para las extensiones

Definición

Nos vamos al directorio de las extensiones con la instrucción cd extensiones (la ruta completa es ~/MT/extensiones/). Este directorio contiene los scripts que generan los xpi y enlaces simbólicos hacia los scripts del directorio de MT. También contiene un subdirectorio _TEMPLATE (que usaremos para crear la estructura para una nueva extensión), y un directorio para cada extensión que se traduzca.

Ficheros

En este directorio, aparte de los subdirectorios mencionados, sólo hay estos ficheros:

  • Un enlace simbólico al fichero MT.sh del directorio raíz de la estructura. El objetivo es simplemente tenerlo disponible de manera fácil sin tener que estar jugando con muchos directorios padre. Lo creamos con ln -s ../MT.sh. Verás que se puede omitir el nombre de destino al usar ln en caso de coincidir con el de origen.
  • El script XPI_langXXX.sh, siendo XXX un número de script que irá aumentando según se añadan funcionalidades o se corrijan defectos. Para saber la versión exacta, mira los comentarios al principio del fichero. Este script se anuncia y proporciona desde la lista de correo de NAVE, por lo que si hay versiones nuevas, habrá que descargarlas en este directorio. Siempre puedes descargar la última versión renombrada, pero no debe ser necesario, al ir incluida en el fichero con la estructura de directorios. Para saber la versión exacta de este fichero, mira los comentarios al principio del mismo, para renombrarlo con su nombre correspondiente.
  • Un enlace simbólico llamado XPI_lang.sh y que apunta al script XPI_langXXX.sh citado anteriormente, que también habrá que actualizar con cada nueva versión del script. Esto se hace con ln -sf XPI_langXXX.sh XPI_lang.sh.
  • El script XPI.sh, cuya función es llamar a XPI_lang.sh de una forma más cómoda, con el parámetro del idioma o idiomas deseados y generar el xpi. Será el script que realmente ejecutemos.
  • Los scripts moz2po.sh, po2moz.sh y po2tmx.sh, que se usan para trabajar con herramientas que reconozcan el formato po.
  • El script unzipxpi.sh, cuyo uso se explica más adelante.
  • El directorio _TEMPLATE, con la estructura para las extensiones y las versiones de las mismas.

Comprobamos el contenido del directorio en una estructura recién creada con los pasos indicados:

-rwxr-xr-x  1 oscar oscar  1617 2006-03-04 03:22 moz2po.sh
lrwxrwxrwx  1 oscar oscar     8 2006-03-20 13:32 MT.sh -> ../MT.sh
lrwxrwxrwx  1 oscar oscar    12 2006-03-20 13:32 OmegaT.sh -> ../OmegaT.sh
-rwxr-xr-x  1 oscar oscar   677 2006-03-20 10:02 po2moz.sh
-rwxr-xr-x  1 oscar oscar   141 2006-03-04 03:26 po2tmx.sh
drwxr-xr-x  7 oscar oscar  1024 2006-03-20 13:32 _TEMPLATE
-rwxr-xr-x  1 oscar oscar   948 2006-03-20 13:27 unzipxpi.sh
-rwxr-xr-x  1 oscar oscar 19202 2006-03-19 21:16 <?=$XPI_lang?> 
lrwxrwxrwx  1 oscar oscar    14 2006-03-20 13:32 XPI_lang.sh -> <?=$XPI_lang?> 
-rwxr-xr-x  1 oscar oscar    92 2006-02-05 14:54 XPI.sh

En este instante, el último fichero es el <?=$XPI_lang?>, al cual apunta el fichero XPI_lang.sh.


Directorio raíz global para una extensión determinada

Definición

Este directorio contendrá los ficheros que sean de uso específico de la extensión y que no dependan de una versión específica. Necesitaremos crearlo cuando vayamos a comenzar la traducción de una extensión. Se creará un directorio dentro del directorio raíz de las extensiones (~/MT/extensiones/) para traducir una extensión concreta. El nombre del directorio puede ser cualquiera, pero se recomienda que sea lo más parecido al nombre de la extensión, en minúsculas y sin espacios, para poder identificarlo fácilmente, sobre todo cuando se tienen unas cuantas extensiones acumuladas. Este directorio lo creamos con la instrucción cp -a _TEMPLATE directorio (siendo directorio el nombre de directorio elegido para alojar la extensión), y actuará de contenedor para todas las versiones que se vayan a traducir de esta extensión. Nos cambiamos a él con cd directorio. El directorio absoluto es ~/MT/extensiones/directorio/.


Ficheros

Los ficheros que habrá en este directorio y cuya función y contenido se explicará más adelante, son:

  • Un fichero llamado extension.cfg. Este fichero contiene asignaciones de variables que son específicas de la extensión, pero no tiene información de ningún idioma concreto.
  • Un directorio llamado l10n, que contiene una plantilla llamada ab-CD.cfg (válida para cualquier idioma), y el fichero es-ES.cfg, con definiciones específicas para NAVE. En versiones del script anteriores a la 013, estos ficheros estaban fuera de l10n, que no existía, pero en caso de tenerlos fuera de l10n, el script se encarga de crear el directorio y moverlos a su nueva ubicación.
  • Para hacerlo más legible, se han movido los ficheros de plantilla a un nuevo directorio llamado _sed:
    • Si la extensión funciona con Firefox y/o Thunderbird, un fichero de plantilla llamado install.rdf.sed.
    • El fichero contents.rdf.sed. Este fichero tiende a desaparecer, siendo susituido por chrome.manifest, del cual también hay su plantilla, chrome.manifest.sed.
    • Si la extensión funciona con Mozilla Suite o SeaMonkey, un fichero de plantilla llamado install.js.sed. Este fichero también tiende a desaparecer.
  • También está el directorio generic, que contiene enlaces a los ficheros de plantilla anteriores. Se explica más adelante.
  • El directorio extension.omt, cuyo uso es exclusivo de OmegaT.

El directorio _TEMPLATE (cuyo contenido hemos copiado para crear la nueva estructura) tiene el siguiente contenido:

_TEMPLATE
|-- 0.0.0
|   |-- MT.sh -> ../../MT.sh
|   |-- OmegaT.sh -> ../../OmegaT.sh
|   |-- XPI.sh -> ../../XPI.sh
|   |-- generic -> ../generic
|   |-- moz2po.sh -> ../../moz2po.sh
|   |-- po2moz.sh -> ../../po2moz.sh
|   |-- po2tmx.sh -> ../../po2tmx.sh
|   |-- unzipxpi.sh -> ../../unzipxpi.sh
|   `-- version.cfg
|-- _sed
|   |-- chrome.manifest.sed
|   |-- contents.rdf.sed
|   |-- install.js.sed
|   `-- install.rdf.sed
|-- extension.cfg
|-- extension.kbabel
|-- extension.omt
|   |-- omegat
|   `-- omegat.project
|-- generic
|   |-- chrome
|   |   `-- contents.rdf -> ../../_sed/contents.rdf.sed
|   |-- chrome.manifest -> ../_sed/chrome.manifest.sed
|   |-- install.js -> ../_sed/install.js.sed
|   `-- install.rdf -> ../_sed/install.rdf.sed
`-- l10n
    |-- ab-CD.cfg
    `-- es-ES.cfg


Directorio raíz para la versión de la extensión

Definición

Este directorio contiene los ficheros con la información de la versión de la extensión. Necesitaremos crearlo cuando vayamos a traducir una versión nueva de una extensión. También es el directorio de trabajo de MT a la hora de traducir la versión específica de una extensión. Aunque puede tener cualquier nombre, le asignamos el número de la versión de la extensión. Lo creamos haciendo un duplicado del directorio 0.0.0 (que nos sirve de plantilla) con cp -a 0.0.0 1.0 (suponiendo que sea la versión 1.0 de la extensión), y nos cambiamos a él con cd 1.0. El directorio absoluto es ~/MT/extensiones/<nombre_extension>/1.0/.


Ficheros

Los ficheros necesarios inicialmente en este directorio son:

  • Enlace simbólico al script de generación del xpi, XPI.sh. Creamos el enlace simbólico con ln -s ../../XPI.sh.
  • Un enlace al directorio generic, cuya función es contener enlaces que usará el script a los ficheros sed necesarios que están en el directorio raíz de la extensión, y que estarán con su estructura final. Creamos el enlace con ln -s ../generic.
  • Un fichero version.cfg. Este fichero contiene información específica de la versión de la extensión.

El resto de enlaces son opcionales, dependiendo del programa a usar para traducir la extensión, cosa de la cual nos ocuparemos en su momento.

Con las instrucciones anteriores, la orden tree debe dar este resultado:

|-- MT.sh -> ../../MT.sh
|-- OmegaT.sh -> ../../OmegaT.sh
|-- XPI.sh -> ../../XPI.sh
|-- generic -> ../generic
|-- moz2po.sh -> ../../moz2po.sh
|-- po2moz.sh -> ../../po2moz.sh
|-- po2tmx.sh -> ../../po2tmx.sh
|-- unzipxpi.sh -> ../../unzipxpi.sh
`-- version.cfg


Descripción del funcionamiento de los scripts


Funcionamiento básico

IMPORTANTE: Todos los scripts mencionados en este tutorial que acaben son la extensión .sh, deberán tener el atributo de ejecución, necesario para poder ejecutarse en un shell. Para ello, se puede ejecutar desde el directorio en donde haya algún script la instrucción chmod a+x *.sh. Esto sólo ocurre en ~/MT/ y en ~/MT/extensiones/.

El script XPI_lang.sh es el motor de todo el sistema. Como hemos dicho, este nombre de fichero será un enlace simbólico al último script XPI_langXXX.sh situado en el directorio raíz de las extensiones, con el objetivo de que no haya que retocar los enlaces de los directorios para cada nueva versión, por ello lo llamaremos de forma genérica XPI_lang.sh. Para actualizarlo, partiendo de la base de que estamos en el directorio de las extensiones y que el último script es el <?=$XPI_lang_version?>, lo haríamos con la instrucción ln -f -s <?=$XPI_lang?> XPI_lang.sh.

En los shells de unix, la primera línea del script indica el intérprete que se usará para procesar el script, de ahí que todos estos scripts tengan como primera línea #!/bin/bash. Tampoco está de más comentar que los caracteres a partir del símbolo "#" en una misma línea se consideran comentarios.

El script XPI_lang.sh está pensado para soportar cualquier idioma, y para ello, necesita un parámetro que le indique qué idioma va a procesar. Por ello, e incluso para mayor comodidad, el script que nosotros ejecutaremos manualmente es uno llamado XPI.sh, que a su vez llama al XPI_lang.sh con el idioma que vaya a procesar como parámetro. Para tener la posibilidad de procesar más de un idioma en la misma ejecución (aunque en nuestro caso no va a ser así), este script contiene la variable $IDIOMAS, en donde iría la lista de códigos de idioma separados por espacios. El contenido del script XPI.sh para procesar únicamente traducciones "es-ES", es el siguiente:

#!/bin/bash
IDIOMAS="es-ES"
for I in $IDIOMAS; do
    . ../../XPI_lang.sh $I 2> $I.log
done

Al ejecutarlo, siempre desde el directorio de trabajo, nos crea en el mismo un fichero es-ES.log, conteniendo el detalle de todas las instrucciones ejecutadas, con el objetivo de depurar posibles errores. Este fichero, al estar indicado con el redireccionador ">", se sobreescribe cada vez que se ejecuta el script XPI.sh.

En primer lugar, el script espera encontrar en el directorio de la extensión un fichero llamado extension.cfg, y otro en el directorio l10n llamado es-ES.cfg, donde "es-ES" cambiará para cada valor indicado en la variable $IDIOMAS. Si cualquiera de estos dos ficheros no existe, el script terminará con un mensaje de error.


Scripts con variables de configuración

Vamos a ver el contenido de los scripts y las variables que usan según su ejecución, para entender mejor qué hacen y por qué.


Script extension.cfg

Como hemos dicho, el script XPI_lang.sh procesa en primer lugar el fichero extension.cfg. Este fichero tiene como objetivo tener la información que sea genérica para la extensión, y que sea independiente tanto del idioma a traducir (si acaso podemos exceptuar el en-US) como de la versión de la extensión que se esté traduciendo, como pueden ser el autor, el EID o los productos para los que está diseñada la extensión. Podemos ver el fichero extension.cfg para linky como ejemplo:

#!/bin/bash
# Nombre del fichero xpi sin la versión ni la extensión .xpi
EXT_NAME="linky"
# Acerca de (<em:aboutURL>)
EXT_ABOUTURL=""
# Nombre largo de la extensión (<em:name>)
EXT_BRAND_NAME="Linky"
# Descripción de la extensión (<em:description>)
EXT_DESCRIPTION=""
# EID original de la extensión (<em:id>)
EXT_EID="{24898804-7da3-4355-9e8d-065f3ee79ccc}"
# Autor de la extensión (<em:creator>)
EXT_CREATOR="Henrik Gemal"
# URL para el icono (<em:iconURL>)
EXT_ICONURL=""
# Página del proyecto de la extensión (<em:homepageURL>)
EXT_HOMEPAGEURL="http://gemal.dk/mozilla/linky.html?ver=2.4.0"
# URL interna de opciones (<em:optionsURL>)
EXT_OPTIONS_URL="chrome://linky/content/pref-panel-extension.xul"
# URL de actualización de la extensión (<em:updateURL>)
EXT_UPDATEURL="http://gemal.dk/mozilla/update.rdf?id=%ITEM_ID%&idversion=%ITEM_VERSION%&app=%APP_ID%&appversion=%APP_VERSION%"


# Set to 1 if the extension works in the application. Else, set to 0
set_value $MOZ $VALUE 1 # Mozilla Suite
set_value $TB $VALUE  1 # Thunderbird
set_value $FF $VALUE  1 # Firefox
set_value $NVU $VALUE 1 # NVU
set_value $SM $VALUE  1 # Seamonkey
set_value $SB $VALUE  0 # Sunbird
set_value $NS $VALUE  0 # Netscape
set_value $FLO $VALUE 0 # Flock

. ${VERSION_DIR}/version.cfg

NOTA: Independientemente del script del que se hable, todos los contenidos de las variables cuyo destino sea el fichero install.rdf (Firefox y Thunderbird) o contents.rdf, irán en formato utf-8. Si el destino fuera el install.js (específicamente para Mozilla Suite), entonces el juego de caracteres será ISO-8859-1).

Los valores de los parámetros se obtienen del fichero install.rdf del xpi en inglés, y se les quita las etiquetas de apertura y cierre (>em:PARAMETRO< y </em:PARAMETRO>). Si alguno no se usara o no existiera, no es necesario definirlo. Como el objetivo del script no es exclusivo para NAVE, habrá casos de valores de variables que para es-ES no se usen, pero como básicamente es copiar y pegar y en teoría este fichero no se modifica nunca, pues lo configuramos adecuadamente y lo dejamos correctamente. Hay que prestar atención a $EXT_NAME, que va a ser el nombre del fichero final. La función set_value toma como parámetros $MOZ, $TB, $FF, $NVU, etc, que tendrán 0 ó 1 dependiendo de si la extensión es válida para el producto correspondiente. Por defecto, está todo a 0.


Script version.cfg

Si te fijas, la última línea del script (. ${VERSION_DIR}/version.cfg) procesa a continuación el fichero version.cfg que se encuentra en el directorio de trabajo (por lo que obviamente, depende de la versión, como además su propio nombre indica). Como podrás imaginar, este fichero contiene parámetros que son exclusivos de la versión, y tomaremos el fichero version.cfg para la versión 2.6.0 de linky:

# Sufijo producto
#PROD_SUFIJO="moz17 moz18 tb"
# Poner los sufijos de la plataforma para esta version
#PLAT_SUFIJO="linux win mac"

EXT_VERSION="2.6.0"

# Descomentar sólo si $EXT_VERSION no va en el nombre del xpi
#EXT_VERSION_NAME="20050111"

if [[ "$(get_value $MOZ $VALUE)" = "1" ]]; then
        # Set these to appropiate value for Mozilla Suite.
        set_value $MOZ $MIN_VERSION "1.7"
        set_value $MOZ $MAX_VERSION "1.8"
        # Other changeable
fi

if [[ "$(get_value $FF $VALUE)" = "1" ]]; then
        # Set these to appropiate value for Firefox.
        set_value $FF $MIN_VERSION "1.0"
        set_value $FF $MAX_VERSION "1.5+"
fi

if [[ "$(get_value $TB $VALUE)" = "1" ]]; then
        # Set these to appropiate value fo Thunderbird.
        set_value $TB $MIN_VERSION "1.0"
        set_value $TB $MAX_VERSION "1.5"
fi

if [[ "$(get_value $NVU $VALUE)" = "1" ]]; then
        # Set these to appropiate value for NVU.
        set_value $NVU $MIN_VERSION "1.0"
        set_value $NVU $MAX_VERSION "1.0"
fi

if [[ "$(get_value $SM $VALUE)" = "1" ]]; then
        # Set these to appropiate value for Seamonkey.
        set_value $SM $MIN_VERSION "0.1"
        set_value $SM $MAX_VERSION "1.0"
fi

if [[ "$(get_value $SB $VALUE)" = "1" ]]; then
        # Set these to appropiate value for Sunbird.
        set_value $SB $MIN_VERSION "0.1"
        set_value $SB $MAX_VERSION "0.3"
fi

if [[ "$(get_value $NS $VALUE)" = "1" ]]; then
        # Set these to appropiate value for Netscape.
        set_value $NS $MIN_VERSION "7.0"
        set_value $NS $MAX_VERSION "8.0"
fi

# Other optional parameters for locales, etc
MOZILLA_LOCALE_VERSION="1.7"
MOZILLA_REGION_VERSION="1.7"

Al igual que el extension.cfg, hay algunas variables sacadas de parámetros del install.rdf. Vamos a ver cada una de ellas:

  • PROD_SUFIJO: Variable opcional que en el caso de linky está comentada. Contiene una lista de sufijos separados por espacios, y su objetivo es proporcionar un sufijo al xpi en caso de que la extensión necesite generar xpi distintos dependiendo del producto. Un ejemplo es enigmail, que tiene como valores "moz17 tb" para la versión 0.92.0. En otras versiones tenía "moz17 moz18 tb". Precisamente porque en el caso de enigmail la dependencia del producto cambiaba con la versión, por eso las variables se definen en este fichero, pero si en una extensión se ve que la dependencia es independiente de la versión, podría definirse la variable en el fichero extension.cfg. De todos modos, si se define la variable en ambos sitios, el valor definido en el version.cfg sobreescribirá a cualquiera definido anteriormente.
  • PLAT_SUFIJO: Igual que la anterior, pero el objetivo es para extensiones que necesitan un xpi distinto para cada plataforma, como el caso de calendar, que se explica más adelante. En el caso comentado anteriormente de enigmail, se da la circunstancia de que genera xpi dependientes del producto y de la plataforma, por lo que en ese caso se definen ambas variables, generando como resultado un producto cartesiano de todas las combinaciones de todos los productos con todas las plataformas como sufijo adicional a cada fichero generado.
  • EXT_VERSION: Es el número de versión interno de la traducción, y que normalmente figura tanto en el nombre de fichero como identificador de versión en el install.rdf.
  • EXT_VERSION_NAME: Esta variable sólo se usa en el caso de que en el nombre del xpi, la versión no sea $EXT_VERSION, sino otro texto cualquiera, por lo que el texto indicado sustituirá al número de la versión a la hora de formar el nombre del fichero xpi.
  • $MAX_VERSION/$MIN_VERSION: Indica la versión mínima y máxima para las que está diseñada la extensión, dependiendo del producto. Esto se obtiene mirando el fichero los parámetros "minversion" y "maxversion" correspondientes al producto adecuado dentro de la sección "targetApplication" del fichero install.rdf. En el caso de linky, el contenido de la sección es el siguiente:

      <em:targetApplication>
        <Description>
          <!-- Mozilla Firefox -->
          <em:id>{ec8030f7-c20a-464f-9b0e-13a3a9e97384}</em:id>
          <em:minVersion>0.8</em:minVersion>
          <em:maxVersion>1.0</em:maxVersion>
        </Description>
      </em:targetApplication>
      <em:targetApplication>
        <Description>
          <!-- Mozilla Thunderbird -->
          <em:id>{3550f703-e582-4d05-9a08-453d09bdfdc6}</em:id>
          <em:minVersion>0.5</em:minVersion>
          <em:maxVersion>1.0</em:maxVersion>
        </Description>
      </em:targetApplication>
      <em:targetApplication>
        <Description>
          <!-- Mozilla 1.x -->
          <em:id>{86c18b42-e466-45a9-ae7a-9b95ba6f5640}</em:id>
          <em:minVersion>1.0</em:minVersion>
          <em:maxVersion>1.8</em:maxVersion>
        </Description>
      </em:targetApplication>
     
    
  • MOZILLA_LOCALE_VERSION, MOZILLA_REGION_VERSION: Variables que se usan para el fichero contents.rdf, pero que aparentemente están en desuso. Podemos despreocuparnos de su valor.


Script ab-CD.cfg

Después de procesarse el fichero version.cfg, se procesa el fichero es-ES.cfg, cuyo objetivo es contener variables específicas del idioma e independientes de la versión de la extensión. Este es el último de los scripts que llama XPI_lang.sh para tomar datos, y cualquier variable definida anteriormente en alguno de los scripts quedará machacada con este script en caso de llamarse igual, por lo que podemos aprovechar esta circunstancia para redefinir variables, si nos interesara. En el caso de linky, el contenido del fichero es el siguiente:

# Fichero para crear xpi de Linky
#
# Cadenas de la traducci³n (utf-8)

# Principio de bloque modificable
# Traducción del valor en inglés
EXT_DESCRIPTION="Abre, descarga y valida enlaces e imágenes en pestañas o ventanas"

# Valor del uuid de la traducción de la extensión
EXT_LANGPACK_EID="{60130e5a-274a-4c73-88cf-3ef31ffa10de}"

# Nombre del directorio de la extension en NAVE
EXT_DIRNAME=$EXT_NAME

# Valores cogidos del ingles
EXT_ICONURL="chrome://linky/content/icon.png"
EXT_OPTIONSURL="chrome://linky/content/pref-panel-extension.xul"

# Fin de bloque modificable
# Bloque de variables para actualizar la extensión
EXT_URLBASE="http://nave.escomposlinux.org/productos/extensiones/"
EXT_HOMEPAGEURL="${EXT_URLBASE}${EXT_DIRNAME}/"
EXT_UPDATE_BASE="${EXT_URLBASE}actualizar.php?actualizar=s"
EXT_UPDATE_ADD="\&amp;extension=${EXT_DIRNAME}"
if [ "$PROD_SUFIJO$PLAT_SUFIJO" ]; then
  EXT_UPDATE_ADD=${EXT_UPDATE_ADD}"\&amp;plataforma=@PT@"
fi
EXT_UPDATEURL="${EXT_UPDATE_BASE}${EXT_UPDATE_ADD}"

#(Those 3 are UTF-8 encoded)
EXT_LANGPACK_CREATOR="Proyecto NAVE"
EXT_LANGPACK_CONTRIBUTORS="Proyecto NAVE"
EXT_LANGPACK_TITLE="Español (España)"

Para el funcionamiento de las extensiones en NAVE, el fichero para es-ES está dividido en dos bloques: una parte inicial donde hay que ajustar los valores, y otra donde los valores son comunes a todas las extensiones para NAVE y, por tanto, no deben ser modificados. Las variables usadas en el bloque modificable son:

  • EXT_DESCRIPTION: Traducción del parámetro "description" en el install.rdf. Si no existiera, habrá que crearlo, ya que esta cadena saldrá como descripción en el gestor de extensiones. Seguramente si en vez de una cadena fuera una url del tipo chrome:, se podría poner la traducción en un fichero properties y no haría falta en el fichero de idioma.
  • EXT_LANGPACK_EID: EID único para la traducción. MUY IMPORTANTE: el EID debe ser distinto de cualquier otro existente para cualquier traducción. Por ello, el procedimiento es ejecutar el comando uuidgen, que te generarú un número distinto cada vez que lo ejecutes. Cuando te guste uno, lo coges y ya se queda asignado para siempre.
  • EXT_DIRNAME: Directorio donde se alojará la extensión en la web de NAVE. Por defecto, que sea igual al valor de $EXT_NAME en minúsculas, aunque el valor ideal sería "echo $EXT_NAME|tr [A-Z] [a-z]", para forzar la conversión a minúsculas en caso de que hubiera alguna mayúscula en $EXT_NAME.


Ficheros de plantilla

A continuación, vamos a ver los ficheros de plantilla, que acaban con la extensión .sed y se colocan en el directorio _sed en la raíz de cada extensión. Su función es generar un fichero con su mismo nombre pero sin la extensión .sed adecuado, por lo que su contenido está basado en dicho fichero original.


Fichero install.js.sed para Mozilla Suite

Si siguiendo los pasos anteriores tenemos el fichero xpi/install.js, tendremos que crear el "fichero de plantilla". Para ello, deberíamos retocar el fichero install.js para convertirlo en algo que nos sirva para todas las versiones, y así tener ya un fichero .sed para esta extensión.

Este fichero está en el lenguaje de programación javascript y usa codificación iso-8859-1. Normalmente no es necesario tener conocimientos de este lenguaje para al menos echar un vistazo. Lo que sí es importante es que el contenido final debe tener una sintaxis correcta para el intérprete de javascript de mozilla. Lo más normal es buscar la cadena "en-US" y sustituirla por "es-ES", y la cadena ".jar" por "es-ES.jar". Esta labor puede ser complicada, pero ya me he tomado la molestia de hacerlo y ya puedes descargar el install.js.sed para linky. Es posible que este fichero de plantilla valga para otras extensiones, pero tendrás que comprobarlo manualmente en cada caso, y para ello no te fijes en si se parece o no (porque no se parece), pero he simplificado y generalizado en lo posible el proceso de instalación para intentar que valga para todas las extensiones, cosa que de momento así está siendo.

Verifica en el fichero extension.cfg que set_value $MOZILLA $VALUE tiene "1".


Fichero install.rdf para Firefox y/o Thunderbird

Se sabe si una extensión es para Firefox y/o Thunderbird (en el futuro se podría aplicar también a Seamonkey) si existe el fichero xpi/install.rdf. Luego, este fichero (que está en formato xml y usa el juego de caracteres utf-8) contiene una sección indicando las versiones soportadas de los productos soportados. A partir de la versión 008 del script, esta labor está simplificada al máximo. En la gran mayoría de las ocasiones, el fichero install.rdf.sed tendrá sólo estas tres líneas:

@SED_DESCRIPTION@
@SED_FILE@
@SED_PRODUCTOS@

Hay excepciones que no se ajustan a esta forma, siendo dos de ellas las que veremos después, chatzilla y calendar, en donde sólo hay que sustituir @SED_FILE@ por unos valores adecuados, extraídos del fichero install.rdf original. La única forma de comprobar si hay que modificar algo sobre este modelo, es probando el funcionamiento en real después de generar el xpi, y si se produce algún fallo que se vea que es por existir contenidos diferentes e incompatibles en el fichero generado.


Fichero chrome.manifest

Este fichero es nuevo a partir del nuevo toolkit que se usa a partir de Firefox y Thunderbird 1.5. En mis pruebas, he visto que si existe, tiene preferencia ante cualquier otra declaración, pero si no existe, se sigue usando el método antiguo. La filosofía es muy parecida a la del install.rdf.sed, pero no he sido capaz de generar el contenido completo automáticamente en todos los casos, pero sí el contenido de las líneas relativas al contenido del fichero jar. El fichero chrome.manifest.sed de plantilla tiene este contenido:

@MANIFEST_CONTENT@
@MANIFEST_LOCALE@
@MANIFEST_SKIN@

Esto genera un fichero chrome.manifest de esta forma:

content @CHROME_NAME@ jar:chrome/@JAR_FILE@!/content/
locale @CHROME_NAME@ @AB_CD@ jar:chrome/@JAR_FILE@!/locale/@AB_CD@/@CHROME_NAME@/
skin @CHROME_NAME@ [nombre_skin|default] jar:chrome/@JAR_FILE@!/skin/

donde:

  • @CHROME_NAME@ se susitituye con el nombre interno de la extensión
  • @JAR_FILE@ se sustituye con el nombre del fichero jar con el idioma
  • @AB_CD@, se sustituye por el idioma, que suele ser todas las apariciones de "en-US".
  • la cadena correspondiente a [nombre_skin] se obtiene del fichero contents.rdf en el interior del directorio jar/skin/. En caso de que no exista ningún fichero contents.rdf se usa la cadena "default".

Con estos últimos valores, ya podremos generar un chrome.manifest.sed que sustituya los valores adecuados. Lo ideal sería hacer una copia del chrome.manifest original, y sustituir las líneas que empiezan por "content", "locale" y "skin" por "@MANIFEST_CONTENT@", "@MANIFEST_LOCALE@" y "@MANIFEST_SKIN@", respectivamente. Algunas veces esto no será posible, por lo que hay que recurrir al uso de las otras variables de sustitución mencionadas.


Fichero contents.rdf

Este fichero es especial y contiene información necesaria para el paquete. Es sencillo de tratar, pero si este fichero no está correctamente, puede dar muchos quebraderos de cabeza.

Este fichero usa la variable $MOZILLA_LOCALE_VERSION, cuyo valor no parece ser crítico para el funcionamiento, y usado únicamente por los paquetes de idioma de Mozilla.


Traducción de la extensión


Preparativos

A la hora de iniciar la traducción de una extensión, haremos los siguientes preparativos:

  • Si es una extensión nueva, preparar la estructura para la extensión con sus ficheros, siguiendo las instrucciones para los scripts extension.cfg y es-ES.cfg.
  • Crear el directorio de la versión, junto con sus ficheros de versión. Las operaciones siguientes se harán desde el directorio de la versión.
  • Si ya tenemos una versión anterior, podemos copiar el version.cfg para realizar menos modificaciones manuales.
  • Descargar el xpi en inglés de la versión a traducir en este directorio, y descomprimirlo usando el nuevo script unzipxpi.sh [fichero.xpi] [directorio]. Este script tiene dos parámetros opcionales: el nombre de un fichero xpi a descomprimir y el directorio en el que se va a descomprimir (por defecto, xpi). Si no se indica ningún parámetro (no es aconsejable), el script busca los ficheros *-en-US.xpi del directorio para saber el fichero que tiene que descomprmir, creando una lista (sólo debería haber uno). El script automatiza las siguientes acciones, que debemos comprobar (y corregir manualmente en caso de error):
    • Borra el directorio jar existente
    • Descomprime el fichero xpi en el directorio de destino
    • Mueve el fichero jar del directorio chrome obtenido al directorio de la versión
    • Descomprime el fichero jar con su contenido
    • Verifica que la estructura de los directorios a traducir sea jar/locale/ab-CD/<NOMBRE>/, modificándola adecuadamente si no fuera así.
  • Modificar el fichero version.cfg según los valores que tengan los ficheros install.rdf e install.js (en su caso) del directorio xpi (creado al descomprimir el xpi) sobre las versiones soportadas para cada producto y la versión de la extensión según se explica en este apartado.
  • Opcionalmente, y si la extensión no es multiplataforma o tiene algún fichero o directorio especial dentro del directorio chrome, podemos usar el directorio generic (o el enlace al mismo) para incluirlo en su lugar correspondiente, ya que el script copia el contenido del directorio generic al directorio resultante.


Programas de traducción de extensiones

En realidad la tarea de traducir una extensión no es una tarea muy complicada, por lo que queremos simplificar el proceso, brindando la mayor variedad de posibilidades en vez de ceñirnos a un único programa. Actualmente, las posibilidades, dependiendo del formato de origen soportado, son:

Elegiremos una o varias herramientas (dependiendo de nuestro sistema, gustos, etc) para realizar el proceso de traducción de las cadenas del fichero jar con la herramienta o herramientas elegidas. Una vez terminado, exportamos la traducción de estas cadenas al directorio jar/locale/es-ES/, con la misma estructura que jar/locale/en-US/, y volveremos a este punto para continuar con el proceso de traducción de la extensión. NOTA: el contenido del fichero contents.rdf, si existe, no será utilizado por el script, ya que se genera uno propio desde la plantilla.


Generar el xpi


Ejecutar el script que genera el xpi

Si ya hemos hecho todo lo anterior, estamos a escasos segundos de tener el xpi. Para ello, desde el directorio de trabajo, ejecutamos ./XPI.sh, y en pocos segundos, obtendremos en el mismo directorio el xpi resultante, con el nombre extension-version-es-ES.xpi.

Durante la ejecución del script, saldrá algún mensaje informativo, pero son pocos. En el fichero es-ES.log se crea en cada ejecución un fichero de log con todos los detalles de la ejecución del script, que se corresponde por estar activada la depuración en bash con set -x.


Comprobar de la consistencia de las cadenas

A partir de la versión 009 del script, se efectúa una comprobación adicional de la consistencia de las cadenas mediante una llamada al script en perl compare-locales.pl, que se encarga de comparar las cadenas existentes en los ficheros de dos directorios dados como argumentos, y si no existe exactamente el número de cadenas en ambos directorios, muestra un mensaje indicando las cadenas y los ficheros en que se encuentran esas cadenas que faltan o sobran. Para que esto tenga lugar, es necesario tener instalado perl en el sistema, pero si no se tuviera, pues no es una circunstancia grave, ya que simplemente el script no se ejcutará y no se llevará a cabo esta comprobación adicional. Como dijimos antes, si se han seguido los pasos anteriores a la hora de traducir con MT, no deberíamos preocuparnos.

Para ver como funciona, vamos a ver su ejecución de forma normal:

$ ./XPI.sh
Comparando la consistencia de la traducción en-US es-ES... Las cadenas son correctas
Realizando sustituciones...
Hay que volver

A continuación, si no se tiene perl instalado:

$ ./XPI.sh
Perl no está instalado en el sistema. No se puede comprobar la consistencia.
Realizando sustituciones...
Hay que volver

Cuando el script detecta algún error, muestra un mensaje y vuelca la salida completa del script perl. Vamos a provocar un error modificando una entidad:

$ ./XPI.sh
Comparando la consistencia de la traducción es-ES... ¡¡CUIDADO, NO COINCIDEN LAS CADENAS!!
no comparison for ./linky/contents.rdf
Entities in ./linky/linky.dtd don't match:
  In en-US:
    linky.label
  In es-ES:
    Xlinky.label
Realizando sustituciones...
Hay que volver

En este caso, dice que en el fichero linky.dtd en el subdirectorio linky (las rutas son relativas al directorio jar/locales/AB-CD/ correspondiente), hay una entidad que es distinta. A la vista de los posibles errores, deberemos saber interpretarlos para corregirlos. En ningún caso está previsto que se interrumpa la ejecución del script y, por tanto, se deje de generar el xpi dependiendo del resultado de esta comprobación, ya que es opcional. Si obtenemos un aviso solamente porque no existe el fichero contents.rdf, no hay que preocuparse, ya que este fichero está en vía de reemplazo por el chrome.manifest, presente en los productos más modernos.

<?

// SEPARADOR PHP

?>


Casos prácticos

Vamos a poner algunos casos prácticos sobre lo descrito en el documento, donde hay algunas variantes que puede ser interesante considerar. Para ello, se han elegido tres extensiones: linky, chatzilla y calendar.


Caso práctico 1: Traducción de Linky

Introducción

Linky reúne unos requisitos que permiten explicar cómo afrontar una extensión de traducción simple que genera un único xpi que sirve para todas las plataformas, todos los productos y que se adapta a la gran mayoría de los casos.

<?

/*

Lo que voy a explicar son los pasos que he tenido que seguir para actualizar de la versión 2.4.0 a la 2.6.0, intentando detallar solamente aspectos muy concretos que pudieran no quedar cubiertos en la explicación global. Para seguir los pasos, en tu caso supondremos que es la primera vez que afrontas la traducción de esta extensión, por lo que puedes ir creando toda la estructura de directorios y ficheros para linky. Al ser la primera vez, tenemos que crear el directorio que va a albergarla (~/MT/extensiones/linky). Dentro de este directorio ponemos los ficheros linky.cfg y linky-es-ES.cfg, creando enlaces hacia ellos con los nombres específicos, es decir, con ln -s linky.cfg extension.cfg y ln -s linky-es-ES.cfg es-ES.cfg. Los ficheros .sed para linky se ajustan a la norma genérica, por lo que los ejemplos de la sección donde se explican estos ficheros te valdrán.

A continuación, vamos a hacerlo un poco difícil (sólo en este caso), partiendo de la base de que no tenemos el Glossary.zip de la 2.4.0 y tenemos que regenerarlo. Para ello, crea los directorios para ambas versiones, descarga la versión 2.4.0 en inglés y sigue los pasos para crear los ficheros necesarios para la versión 2.4.0. Recuerda comprobar la estructura del directorio locale/en-US/una vez descomprimido. Por otro lado, descarga la versión 2.4.0 en español, descomprímelo en un directorio temporal y copia el fichero .jar que se encuentra dentro del directorio chrome al directorio de trabajo de su versión. De vuelta al directorio de trabajo, descomprímelo igual que el en-US, pero no borres el directorio jar creado previamente por éste, sino haz que se mezclen ambos, de tal forma que en jar/locales/ tengamos las cadenas de ambos idiomas.

A continuación, ejecuta MT, importa las cadenas a traducir, luego la traducción, guarda el Glossary.zip y sal de MT. Como última paso antes de abandonar este directorio, copia el Glossary.zip al directorio de la nueva versión con cp Glossary.zip ../2.6.0/. Ahora ya vamos a realizar todas las operaciones desde el directorio de trabajo de la nueva versión, la 2.6.0.

Ejecuta MT e importa las cadenas de la 2.6.0. Si te sale una ventana con cambios, traduce lo que te salga. Puedes ver desde el menú Edit-> Chrome view si las cadenas, al menos aparentemente, han sido importadas y están traducidas. Ahora, exporta las cadenas y guarda el nuevo Glossary.zip. Si quieres, realiza la operación para asegurarte de la consistencia de la traducción.

*/
?>

Primero, se crea el directorio linky desde el directorio de extensiones, ejecutando cp -a _TEMPLATE linky. A continuación, y como se trata de la versión 2.7.1, desde el interior del directorio linky, creo este directorio con cp -a 0.0.0 2.7.1. Dentro del directori de la versión, descargo el xpi en inglés, lo renombro a linky-2.7.1-en-US.xpi y lo descomprimo con ./unzipxpi.sh linky-2.7.1-en-US.xpi, con lo que se crea el directorio xpi con el contenido, y el directorio jar con el contenido de las cadenas. Además, si observamos el contenido del fichero jar con unzip -t linky.jar, veremos que en locale/en-US/ le falta el directorio con el nombre:

$ unzip -t linky.jar
Archive:  linky-en-US.jar
    testing: content/                 OK
    testing: locale/                  OK
    testing: locale/en-US/            OK
    testing: content/contents.rdf     OK
    testing: content/context.xul      OK
    testing: content/icon.png         OK
    testing: content/main.js          OK
    testing: content/main.xul         OK
    testing: content/pref-overlay.xul   OK
    testing: content/pref-panel-advanced.xul   OK
    testing: content/pref-panel-extension.xul   OK
    testing: content/pref-panel.xul   OK
    testing: content/pref.js          OK
    testing: content/select-links.js   OK
    testing: content/select-links.xul   OK
    testing: content/shared.js        OK
    testing: locale/en-US/contents.rdf   OK
    testing: locale/en-US/main.dtd    OK
    testing: locale/en-US/main.properties   OK

Afortunadamente, el script unzipxpi.sh se ha encargado de solventar esta situación, y lo ha creado dentro del directorio jar:

|-- content
|   |-- contents.rdf
|   |-- context.xul
|   |-- icon.png
|   |-- main.js
|   |-- main.xul
|   |-- pref-overlay.xul
|   |-- pref-panel-advanced.xul
|   |-- pref-panel-extension.xul
|   |-- pref-panel.xul
|   |-- pref.js
|   |-- select-links.js
|   |-- select-links.xul
|   `-- shared.js
`-- locale
    |-- en-US
        `-- linky
            |-- contents.rdf
            |-- main.dtd
            `-- main.properties

A continuación, elijo una de las herramientas para traducir, y la traducción queda en jar/locale/es-ES/. Por último, ejecuto el script para generar el xpi, ./XPI.sh, y no obtengo advertencias ni errores, con lo que obtengo el fichero linky-2.7.1-es-ES.xpi, y lo pruebo. Si viera algún fallo, volvería al punto necesario para arreglar el problema, y ejecutarí los pasos posteriores necesarios para volver a generar el xpi.

<?
// Separador PHP

// Chatzilla
?>


Caso práctico 2: Traducción de Chatzilla

Introducción

Se ha elegido Chatzilla como ejemplo para este documento porque presenta una variante mínima respecto a linky, pero suficiente como para ser tenida en cuenta y que puede surgir en alguna extensión.

Los pasos a realizar son exactamente iguales, pero teniendo en cuenta que la estructura "estándar" del install.rdf.sed no funciona con chatzilla. El fichero install.rdf.sed resultante (para la versión 0.9.68) es el siguiente:

@SED_DESCRIPTION@
    <em:file>
      <Description about="urn:mozilla:extension:file:@JAR_FILE@">
        <em:package>content/@EXT_NAME@/</em:package>
        <em:package>content/@EXT_NAME@/ff/</em:package>
        <em:locale>locale/@AB_CD@/@EXT_NAME@/</em:locale>
        <em:skin>skin/modern/@EXT_NAME@/</em:skin>
      </Description>
    </em:file>
@SED_PRODUCTOS@

Simplemente la sección @SED_FILE@ se ha sustituido por un valor manual de los contenidos teóricos, producidos por dependencia de varios productos.

El script busca los ficheros contents.rdf y añade automáticamente las rutas correspondientes. La circunstancia por la que no vale es porque el script genera una línea extra (bajo mi punto de vista, correcta), pero que produce resultados extraños. Si ponemos un install.rdf.sed como el de linky, se generan las siguientes líneas en la parte correspondiente a @SED_FILE@:

    <em:file>
      <Description about="urn:mozilla:extension:file:@JAR_FILE@">
        <em:package>content/@EXT_NAME@/</em:package>
        <em:package>content/@EXT_NAME@/sm/</em:package>
        <em:package>content/@EXT_NAME@/ff/</em:package>
        <em:locale>locale/@AB_CD@/@EXT_NAME@/</em:locale>
        <em:skin>skin/modern/@EXT_NAME@/</em:skin>
      </Description>
    </em:file>

<?

// Separador PHP

// Calendar
?>


Caso práctico 3: Traducción de Calendar

La traducción de calendar presenta otra variante importante respecto de linky, ya que necesita un fichero xpi distinto para cada plataforma. También tiene la variante de que, por ejemplo, los nombres de fichero no se corresponden con la versión interna, sino que usa una especie de "doble nomenclatura". Vamos a ver cómo tratar estas variantes, aunque básicamente el procedimiento es muy similar al de linky.

Preparar el directorio de la extensión

Creamos el directorio para la extensión dentro del directorio raíz de las extensiones (en nuestro caso, calendar) con los ficheros y enlaces descritos en la estructura de árbol. Puedes ver los ficheros extension.cfg y es-ES.cfg de calendar específicos que uso yo mismo. El resto de pasos de este apartado es igual que con linky. Hay que tener en cuenta que calendar funciona tanto en Mozilla, Firefox y Thunderbird.

Preparar el directorio de la versión

En este caso, y debido a que en el caso específico de calendar las versiones se rigen por fecha, la última versión disponible en el momento de escribir este texto es la "20060116", por lo que el directorio para esta versión tendrá este nombre. Lo creamos desde el directorio de la extensión con cp -a 0.0.0 20060116 y vamos al interior del mismo.

Primero, descargamos los xpi originales en inglés de cada plataforma. Elegimos uno como referencia inicial (mejor siempre el de linux) para tomar los datos que vayan en el version.cfg, pero NO vamos a usar el script unzipxpi.sh, ya que (al menos actualmente) no produce el efecto deseado, por lo que realizamos el proceso manualmente. Descomprimimos el xpi con unzip -d linux mozilla_calendar-0.2.0.20060116-fx+tb-linux.xpi. Repetimos esto con los xpi de win32 y mac, especificando "win" y "mac" como directorios donde descomprimir cada uno. A continuación, necesitamos el fichero install.rdf en el directorio xpi, así que tecleamos mkdir -p xpi/chrome; cp linux/install.rdf xpi para tenerlo. Después, mv linux/chrome/calendar.jar xpi/chrome (tenemos que preservar este fichero), y hacemos lo habitual con el fichero con las cadenas en inglés con mv linux/chrome/calendar-en-US.jar .;unzip -d jar calendar-en-US.jar. Ahora podemos borrar todos los duplicados e innecesarios con rm -rf linux/chrome win/chrome mac/chrome.

Después, rellenamos los ficheros extension.cfg y es-ES.cfg con los valores del fichero xpi/install.rdf. Editamos el fichero version.cfg con los valores de la versión para cada producto, pero tenemos que hacer más cosas en este fichero. Por tener un fichero xpi distinto para cada plataforma, editamos el fichero version.cfg y ponemos la variable $PLAT_SUFIJO con el valor "linux win mac", siendo éstos los nombres de los directorios en donde hemos descomprimido antes cada uno de los xpi, que además servirán como sufijo de cada xpi resultante. Ponemos el valor de la versión ("20060116") en la variable $EXT_VERSION_NAME, ya que el xpi resultante contiene esta cadena en el nombre del fichero, además de la versión, y descomentamos la variable.

En el caso de calendar, en gran parte por adaptarla de forma coherente al sistema que estamos viendo, se han hecho algunos cambios. El primero es que calendar está enfocada a ser multiidioma, pero sigue pecando del problema de no separar el en-US en el código. Para ello, se separa un calendar.jar genérico (no incluye el directorio locale) y luego se genera un calendar-es-ES.jar incluyendo sólo las cadenas de traducción, y que es compatible con el formato del proyecto original.

El fichero install.rdf.sed es el siguiente:

@SED_DESCRIPTION@

    <!-- Generic jar file -->
    <em:file>
      <Description about="urn:mozilla:extension:file:@EXT_NAME@.jar">
        <em:package>content/@EXT_NAME@/</em:package>
        <em:skin>skin/classic/@EXT_NAME@/</em:skin>
        <em:skin>skin/modern/@EXT_NAME@/</em:skin>
      </Description>
    </em:file>
    <!-- Lang file -->
    <em:file>
      <Description about="urn:mozilla:extension:file:@EXT_NAME@-@AB_CD@.jar">
        <em:id>@EXT_LANGPACK_EID@</em:id>
        <em:locale>locale/@AB_CD@/@EXT_NAME@/</em:locale>
        <em:contributor>@EXT_LANGPACK_CONTRIBUTORS@</em:contributor>
      </Description>
    </em:file>
@SED_PRODUCTOS@

En esta estructura, vamos a tener algunos cambios en los directorios que hay dentro del directorio de trabajo:

  1. Creamos el directorio generic con los ficheros de información de la instalación de la extensión.
  2. El directorio jar se crea igual, así que cualquier jar te valdrá para generarlo, ya que son todos iguales. Para generar el fichero genérico, vamos al directorio jar y hacemos zip -r ../generic/chrome/calendar.jar $(ls -d */|grep -v locale). Después, borramos los directorios implicados con rm -rf $(ls -d */|grep -v locale), para dejar sólo el directorio locale, y volvemos al directorio de trabajo.
  3. Esto es lo más complicado. Necesitamos tener un directorio con el nombre de la plataforma y/o producto (en el caso de calendar sólo hay plataformas), siendo cada nombre cada valor indicado en $PLAT_SUFIJO, es decir, linux, win y mac en cada caso. Estos directorios se crearán al descomprimir el xpi correspondiente y el parámetro -d (el de linux ya lo hicimos antes). Contendrán cada uno la estructura de directorios que sea específica de la plataforma, eliminando los ficheros que ya están en el directorio generic. En este caso, borramos el directorio chrome y los ficheros install.*, y dejamos el resto de directorios (components y other stuff). Esto sustituye al directorio xpi de extensiones de un fichero multiplataforma.

Una vez preparado el directorio de la versión, los pasos de la traducción con MT y generar el xpi son exactamente igual, ya que el script se encarga de ver si están definidas las variables adecuadas y generar los ficheros necesarios en cada caso. Después de ejecutar el script, obtendremos un xpi por cada plataforma en el directorio de trabajo.


Tratamiento de las extensiones desde NAVE

La página principal para las extensiones publicadas es http://nave.escomposlinux.org/productos/extensiones/, donde se podrán ver las extensiones existentes y sus últimas versiones, además de estar clasificadas según los productos para los que han sido diseñadas. Actualmente, no todas han sido diseñadas con este sistema, pero si intentará ir actualizando todas las extensiones con el tiempo. Al seleccionar una extensión concreta, se irá a la página de la traducción de dicha extensión, en donde hay más detalles sobre la misma.

Las extensiones que se producen con este sistema son de un único idioma, circunstancia que, junto a la indefinición sobre una base para traducción de extensiones desde mozilla.org, ha conllevado a que desde NAVE se traten las extensiones como "propias y únicas". Esto quiere decir que cuando se instala una extensión desde NAVE que ha sido creada con este sistema, no tendrá conexión con la extensión original ni su sistema de actualizaciones.


Colaborar con NAVE

Independientemente de lo anterior, lo que debe primar es la coordinación y colaboración entre NAVE y los proyectos de extensiones. El traductor de la extensión mantendrá contacto con el proyecto original de la extensión, proporcionando el material necesario que le sea solicitado, independientemente de que se realice el instalador para NAVE. No es deseable una situación en donde exista una traducción en NAVE y no haya constancia en el proyecto original, de la misma forma que sería deseable que cualquier traducción es-ES existente de una extensión en un proyecto, no tuviera su propio instalador en NAVE, en cuyo caso sería deseable ponerse en contacto con el traductor para lograr este objetivo. Juntando lo anterior, tampoco es deseable que los traductores en ambos casos sean distintos, sino la misma persona.

Si tienes una extensión traducida y quieres que se publique en NAVE, es requisito previo a día de hoy que esté adaptada a este sistema. Si tienes algún problema para adaptarla, podemos ayudarte a hacerlo. El medio de contacto, mientras no se diga lo contrario, es la lista de correo de NAVE, a la que debes estar suscrito. Después, también tendremos los .cfg y .sed empleados, para el caso futuro en que haya alguna falta de continuidad en el mantenimiento y alguien quiera tomar el relevo. Por último, te haríamos llegar un fichero que tendrías que rellenar, conteniendo datos para la página de la extensión en NAVE, y donde podrías adjuntar capturas de pantalla y otros datos que consideres apropiados.


Babelzilla

Adicionalmente, es aconsejable estar en estrecha colaboración con el foro español de Babelzilla, que aunque es un proyecto que sólo tiene unos meses de vida (septiembre de 2005), es donde se vienen concentrando, desde su creación, tanto los autores de extensiones (buscando traducciones para sus extensiones) como los traductores de extensiones (para traducir y estar al tanto de las novedades), y está en auge constante. También es deseable intentar ir sincronizando poco a poco las extensiones existentes allí, y que los traductores de las ya existentes en español colaboren en ambos proyectos (NAVE y Babelzilla).


Contacto, correcciones y sugerencias

Si tienes información sobre extensiones traducidas que no tenemos, o cualquier otra cosa relacionada con lo expuesto en este documento, escribe a la lista o usa el formulario de contacto (preferiblemente usa la lista) para informar sobre ello.

<!--

Consideraciones adicionales

Hay un detalle que es importante tener en cuenta, sobre todo si en un futuro (quizás cercano) sufre modificación en el sentido esperado.

Las extensiones vienen genéricamente con el idioma en-US de forma "única e inseparable".
Esta circunstancia, bajo mi punto de vista, introduce un problema grave que mozilla.org todavía no ha afrontado (al menos con garantías).
En una extensión, los ficheros con las cadenas de traducción ocupan un espacio realmente ínfimo, pero esto no justifica desde el punto de vista organizativo que no haya una separación modular entre código y cadenas de traducción (incluyendo al inglés, por supuesto).
Esto viene porque cada extensión tiene un identificador único de extensión (EID), que por defecto se asigna al conjunto del código de la extensión + el paquete en-US.
Cuando se realiza una traducción de una extensión a otro idioma, o bien se añade al paquete original junto al en-US (con lo que el paquete puede engordar de tal manera que haya que descargar no sé cuantos megas inútiles innecesariamente, por no hablar de la heterogeneidad de mantener coordinadas las traducciones, como la página de calendar) o se hace un paquete con un único idioma. Esto lleva a la situación de asignar un nuevo EID a cada traducción, pero resulta un poco ridículo o incoherente cuando un producto es una copia de otro con la excepción del idioma que se ve en pantalla. Esto es muy importante a la hora de las actualizaciones, que es una de las razones de ser de las extensiones. Para que una extensión pueda actualizarse automáticamente, necesita acceder al sitio de actualización con su propio (y único) EID. Si la traducción alojada en NAVE de una extensión mantiene el mismo EID que el del sitio en inglés, o bien se "usurpa" dicho EID, provocando que existan dos productos "distintos" con el mismo EID, que se actualizarían (en el mejor de los casos) de dos sitios distintos, o bien se crea un EID nuevo, lo que obliga a tener una estructura independiente de una extensión, pudiendo darse la circunstancia de que existan versiones nuevas de la extensión que no permitan la actualización.

La decisión tomada ha sido tener un EID único y distinto para las traducciones de extensiones, que son instaladores completos y contienen únicamente la traducción es-ES.


Correcciones y sugerencias

Si se observa alguna incorrección en este documento (por
pequeña que sea), quiere mejorar alguna parte o añadir
más información, propóngalo en la
lista de correo de
NAVE
para que se realicen dichos cambios lo más pronto posible.

 

-->