Affichage des articles dont le libellé est okawix. Afficher tous les articles
Affichage des articles dont le libellé est okawix. Afficher tous les articles

mardi 9 mars 2010

À la recherche du XUL perdu

Comme expliqué dans un épisode précédent, après une dizaine d'années de fidélité aux autotools je suis récemment passé à CMake et l'essayer c'est l'adopter. Du coup, je me suis demandé si Okawix pourrait être construit avec ; et qui dit construire Okawix, dit compiler des composants XPCOM et la... pas de bol, CMake ne fournit pas de module pour faire du XPCOM. Enfin... pas encore :)

J'ai donc travaillé sur un module CMake permettant de détecter XUL ; en fait, sur plusieurs modules : un pour XUL lui même, un pour NSPR et un dernier module "utilitaire" qui fait une bonne partie du sale boulot. Ces modules sont maintenant à un stade ou ils permettent de compiler les composants d'Okawix sous Linux, Mac et Windows.

Sous Linux, la détection est faite grâce à pkg-config ; sous Mac et Windows aucune détection n'est tentée pour l'instant et l'utilisateur doit spécifier un chemin vers un SDK.

En plus de détecter les chemins des fichiers d'en-tête, des bibliothèques et des paramètres de compilation, le module XUL recherche l'emplacement des fichiers IDL, de l'exécutable xpidl et fournit même des macros pour faciliter la génération des fichiers .h et .xpt à partir des IDL.

Enfin, lorsque plusieurs SDK sont disponibles (ie les SDK "stable" et "unstable" proposés par pkg-config), le module permet de choisir un SDK suivant la disponibilité de certains composants. Par exemple, Okawix utilise nsIRunnable qui n'est pas dans le SDK "stable" ; il est alors possible de trouver le "bon" SDK en lui indiquant que l'on veut ce composant.

Le code est disponible sur un projet google et inclut un exemple de composant avec le CMakeLists.txt permettant de le compiler. Maintenant, je suis à la recherche de gens intéressés pour tester (voir utiliser) le truc et je suis preneur de tout retour : commentaire, suggestion, rapport de bug, etc.

vendredi 4 décembre 2009

Une seule traduction vous manque, et tout est cassé

Problème

Comme expliqué précédemment, je passe une bonne partie de mon temps de travail à développer Okawix, un navigateur en mode non connecté. Le logiciel est codé avec le Framework Mozilla, donc avec XUL/Javascript, et utilise aussi le système de traduction du Framework, enfin... les systèmes : des DTD pour la partie XUL et des fichiers properties pour Javascript.
Ces deux systèmes ont l'avantage d'être cohérents (genre, des DTD pour du XML, c'est la sauce, quoi), mais à l'usage présentent rapidement un inconvénient : toutes les chaînes doivent être traduites. Si une traduction manque dans un .properties, une exception sera levée à l'exécution ; bon là, c'est pas si grave, une exception ça peut encore se gérer. Si une traduction manque dans une DTD, les fichiers XUL utilisant cette traduction ne peuvent plus être affiché ; hu... là, ça peut faire mal.
J'ai donc pris rapidement l'habitude de traduire toutes les nouvelles chaînes en anglais et en français, les deux seules langues proposées par Okawix... avant. En effet, les traductions d'Okawix sont dorénavant gérées par le projet translatewiki.net (TWN), ce qui veut dire plein de traductions, dont certaines ne sont pas complètes ; ce qui veut aussi dire mise à jour de notre SVN automatiquement depuis TWN. De plus, Okawix créé automatiquement une liste des langues disponibles ; et pour finir, une fois une langue incomplète choisie il devient difficile de relancer le logiciel sans manipuler à la main la configuration du logiciel. Ouch...
Il fallait donc trouver une solution et après avoir demandé en vain à Google, j'en suis arrivé à la conclusion qu'il fallait que je trouve cette solution tout seul :)

Solution

L'idée est d'avoir une traduction "par défaut", qui est toujours complète et qu'on va utiliser pour combler les manques dans les autres traductions ; dans Okawix, la traduction par défaut est l'anglais.
On commence par déclarer un "content provider" pour la traduction par défaut dans le manifest de l'application, dans le cas d'Okawix, ça donne :
content defaultlocale locale/en-US/interfacewiki/
qui déclare donc un "content provider" nommé "defaultlocale" et qui pointe vers la traduction anglaise (au passage, promis, un de ces jours, je vire tous ces "interfacewiki" qui trainent un peu partout dans Okawix).
Pour la partie DTD, il faut alors charger la DTD de la traduction par défaut en dernier, dans Okawix ça ressemble à ça :
<!DOCTYPE window [
<!--ENTITY % wikiDTD SYSTEM "chrome://interfacewiki/locale/okawix.dtd"-->
<!--ENTITY % defaultDTD SYSTEM "chrome://defaultlocale/content/okawix.dtd"-->
%wikiDTD;
%defaultDTD;
]>
L'idée est que une entité ne peut déclarée qu'une seule fois, celles qui sont déclarées dans la traduction en cours sont chargées en premier et celles de la traduction par défaut ne font que "combler les trous".

On applique le même principe, ou presque, pour les fichiers properties :
<stringbundleset id="wk-strings-set">
<stringbundle src="chrome://interfacewiki/locale/okawix.properties"/>
<stringbundle src="chrome://defaultlocale/content/okawix.properties"/>
</stringbundleset>
On charge d'abord la traduction en cours, puis on "comble les trous", tout pareil, quoi... sauf que dans le cas du javascript, tout n'est pas terminé : il nous faut une fonction pour récupérer la traduction dans le stringbundleset. Ce qui donne a peu près ça :
my_translate_function = function( aBundleset, aString ) {
for( var i = 0 ; i < aBundleset.childNodes.length ; i++ ) {
var bundle = aBundleset.childNodes[ i ];
try {
return bundle.getString( aString );
}
catch( someerror ) {
}
}
return aString;
}
La fonction parcourt l'ensemble des stringbundle et appelle leur fonction getString, si la traduction existe elle est renvoyée, sinon une exception est levée, on l'attrape et on continue. Si la traduction n'existe nul part, on renvoie la chaîne d'origine.

Voila... je ne sais pas exactement ce que les puristes penseront de ce genre de méthode, mais au moins avec ça Okawix est capable de survivre à des traductions partielles :)

lundi 21 septembre 2009

Trad' en trois actes

ACTE I : innocence

Il y a quelques temps, suite à une idée de Romanito, je m'étais lancé dans l'écriture d'une extension MediaWiki pour gérer des traductions. Le principe était simple, les chaînes à traduire et les traductions étaient stockées dans des pages wiki, l'extension ne fournissant qu'une manière simplifiée d'éditer les pages. Les traductions pouvaient ensuite être récupérée par un script Python pour être incluse dans le logiciel à traduire. Le système était simpl(ist)e, fonctionnel et je l'ai d'ailleurs mis en production et testé sur le wiki de Yabause.

Cette partie de l'histoire s'achève là, ou presque... je me suis ensuite rendu compte que pour pouvoir traduire le port Windows de Yabause, il me faudrait des outils qui n'existaient pas encore et je me suis alors lancé dans leur développement. Et je n'ai pas fini.

ACTE II : révélation

Une bonne partie de mon temps de travail est consacrée au développement d'Okawix, un navigateur hors-ligne pour les contenus de Wikipédia. Un des points fort du logiciel est qu'il permet de récupérer facilement le contenu de tous les wikis géré par la fondation (oui, même Wikipédia en normand, dé diou). Pour faire bonne mesure, il fallait pouvoir proposer aux utilisateurs une traduction de l'interface dans un maximum de langues.

Tout ceci nous a amené à découvrir un projet absolument fabuleux: translatewiki.net (TWN). En gros, l'idée est la même : amener des gens à traduire en passant par une extension de MediaWiki ; par contre, le projet est beaucoup plus avancé : l'extension est stable, gère plusieurs projets, plusieurs formats de fichier et les contributeurs sont nombreux.

Après avoir fourni un patch pour le support des DTD, Okawix est venu s'ajouter à la liste des projets gérés par TWN. Et la, je dois dire que j'ai été impressioné par la vitesse à laquelle le logiciel a été traduit dans des langues plus ou moins exotiques. De plus, TWN est configuré pour accéder directement à notre dépôt : en lecture, pour récupérer les nouvelles chaînes à traduire, et en écriture, pour nous envoyer les traductions. Un vrai bonheur.

ACTE III : tentation

Avec d'un coté un mini-projet que je suis seul à (ne pas) maintenir et de l'autre un projet maintenu, actif, en évolution et qui a réuni autour de lui une communauté de traducteurs, je pense que le choix va être rapidement fait :)

Bien sur, tout n'est pas encore prêt à fonctionner et le ne le sera pas demain : il faut déja postuler sur TWN et être accepté ; mais même avant cela, il faut terminer la bibliothèque Respire pour que le port Windows soit complétement traductible, écrire un patch pour TWN pour gérer le fichiers de traduction de mini18n et surement d'autres détails à régler.

Bref... encore pas mal de choses à faire en perspective, mais l'idée d'avoir un système de traduction fonctionnant de manière autonome est séduisante, très séduisante et mérite surement le détour.