Qu'est ce qu'on se fait ch ... !

Aller au contenu | Aller au menu | Aller à la recherche

Internationalisation i18N avec GWT

  • vendredi, août 5 2011
  • Par littlewing
  • Category Java EE
  • Tags gwt, i18n, java, javaee, Planet-APRIL, Planet-Libre
  • aucun commentaire

spacer Me voila arrivé dans mon projet ou j'ai envie d'externaliser les chaînes de caractères pour pallier aux différents problèmes de locale qui peuvent être soit la locale utilisé dans les composants GWT, soit un quelconque problème d'enc@$ding dans les libellés.

Venant du monde JSF j'ai d'abord pensé qu'il fallait passer par des ressources bundle... que nenni !!!

Vous avez deux options ; faire tout à la main comme indiqué dans la documentation officielle utiliser l'outil de génération fourni en standard avec le compilateur GWT

J'exposerai dans ce billet deux types d'externalisation :

  1. l'externalisation des messages/constantes utilisés dans le code
  2. l'externalisation des messages contenus dans les fichiers ui.xml

Configuration préalable

Pour activer la prise en compte de l'internationalisation ou i18n pour les intimes, il faut d'abord ajouter la configuration dans le fichier module.gwt.xml

<inherits name="com.google.gwt.i18n.I18N" />
	<extend-property name="locale" values="fr" />
	<extend-property name="locale" values="en" />

On obtient donc le fichier suivant :

<?xml version="1.0" encoding="UTF-8"?>
<module rename-to="admin">
	<inherits name="com.google.gwt.user.User" />
	<inherits name="com.google.gwt.logging.Logging" />
	<inherits name="com.google.gwt.i18n.I18N" />
	<inherits name='com.google.gwt.user.theme.chrome.Chrome' />
	<inherits name="info.touret.winecellar.userinfo.UserInfo" />
	<inherits name="info.touret.winecellar.dao.persistencecommon" />
	<inherits name="com.googlecode.objectify.Objectify" />
	<inherits name='com.google.gwt.activity.Activity' />
	<inherits name="com.google.web.bindery.requestfactory.RequestFactory" />
	<source path="client" />
	<entry-point class="info.touret.winecellar.admin.client.Admin"></entry-point>
	<extend-property name="locale" values="fr" />
	<extend-property name="locale" values="en" />
</module>

l'externalisation des messages/constantes utilisés dans le code

Les messages et constantes

l'API i18n de GWT embarque de nombreuses classes avec des responsabilités bien déterminées :

  • Constants : des constantes externalisées
  • Messages : les messages et phrases externalisées ( des paramètres sont possibles )
  • ConstantsWithLookup : équivalent à Constants mais avec un comportement dynamique
  • Dictionary : Un dictionnaire embarqué dans la page hôte
  • Localizable : Spécialise le comportement d'une classe en fonction d'une ressource donnée
  • DateTimeFormat, NumberFormat : Formattage des des dates et nombres en fonction de la locale.

Il est également possible d'externaliser les messages contenus dans les page ***.ui.xml.

Création des messages

Voici ce que j'ai fait avec l'API Messages

J'ai crée une interface AdminMessages

import com.google.gwt.i18n.client.LocalizableResource.DefaultLocale;
import com.google.gwt.i18n.client.LocalizableResource.Generate;
import com.google.gwt.i18n.client.Messages;
 
 
@Generate(
format = { "com.google.gwt.i18n.rebind.format.PropertiesFormat" }, 
fileName = "AdminMessages", 
locales = {"fr","en","default"})
@DefaultLocale("en")
public interface AdminMessages extends Messages {
	@DefaultMessage("insert failed")
	@Key("insertko")
	public String insertko();
 
	@DefaultMessage("insert is ok")
	@Key("insertok")
	public String insertok();
 
	@DefaultMessage("The parameters are wrong")
	@Key("udpatefailwithparameters")
	public String udpatefailwithparameters();
 
	@DefaultMessage("Update failed")
	@Key("udpatefail")
	public String updatefail();
}

J'ai indiqué au niveau de la classe que je souhaitai que le compilateur génère les fichiers properties correspondants avec pour base le nom AdminMessages. J'ai aussi spécifié les locales disponibles et celle par défaut.

Ensuite, pour chaque méthode, j'ai spécifié le message par défaut ainsi que la clé utilisée lors de la génération.

Dans mon module, j'accède aux messages de la manière suivante :

AdminMessages constants ;
[...]
constants= GWT.create(AdminMessages.class);
 
[...]
 
Window.alert(constants.insertok());

Génération des resourcebundle

GWT permet la génération des fichiers properties avec les clés définies précédemment dans l'interface. Lors de la compilation, il faut ajouter le paramètre -extra pour la génération soit effective. Si vous utilisez maven, la configuration de votre plugin devrait ressembler à quelque chose comme ça :

<plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>gwt-maven-plugin</artifactId>
                <version>2.3.0-1</version>
                <dependencies>
                    <dependency>
                        <groupId>com.google.gwt</groupId>
                        <artifactId>gwt-user</artifactId>
                        <version>${gwt.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>com.google.gwt</groupId>
                        <artifactId>gwt-dev</artifactId>
                        <version>${gwt.version}</version>
                    </dependency>
                    <dependency>
                        <groupId>com.google.gwt</groupId>
                        <artifactId>gwt-servlet</artifactId>
                        <version>${gwt.version}</version>
                    </dependency>
                </dependencies>
                <configuration>
                    <appEngineVersion>${gae.version}</appEngineVersion>
                    <logLevel>INFO</logLevel>
                    <style>${gwt.style}</style>
                    <runTarget>/Winecellar.html</runTarget>
                    <extraJvmArgs>-Xmx512M -Xss1024k</extraJvmArgs>
                    __<extraParam>true</extraParam>__
                    <server>com.google.appengine.tools.development.gwt.AppEngineLauncher</server>
                    <copyWebapp>true</copyWebapp>
                    <modules>
                        <module>info.touret.winecellar.admin.Admin</module>
                        <module>info.touret.winecellar.winecellar</module>
                    </modules>
                    <i18nMessagesBundle>info.touret.winecellar.admin.client.AdminMessages</i18nMessagesBundle>
                </configuration>
                <executions>
                    <execution>
                        <id>gwtcompile</id>
                        <phase>prepare-package</phase>
                        <goals>
                            <goal>compile</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>

J'obtiens donc les fichiers suivants dans le répertoire target/extra/

  • AdminMessages_fr.properties
  • AdminMessages_default.properties
  • AdminMessages_en.properties

Avec un contenu ressemblant à ça :

# Generated from info.touret.winecellar.admin.client.AdminMessages
# for locale en

insertko=insert failed

insertok=insert is ok

udpatefail=Update failed

udpatefailwithparameters=The parameters are wrong

Il ne vous reste plus qu'à copier les fichiers dans le répertoire src/main/resources/mon package de l'interface

Petit bémol sur la version 2.3 du toolkit de google, si vous mettez des apostrophes, il y aura une exception bloquante à l'execution

 java.text.ParseException: Unterminated single quote
...

Le problème est connu coté google, à voir pour la suite ...

Internationalisation des fichiers ui.xml

Tout d'abord, je vous conseille de lire attentivement la documentation officielle , elle est bien faite spacer

Voila ce que j'ai fait dans mon code

Pour paramétrer la génération :

à la racine de mon fichier ui.xml

<!DOCTYPE ui:UiBinder SYSTEM "dl.google.com/gwt/DTD/xhtml.ent">
<ui:UiBinder xmlns:ui='urn:ui:com.google.gwt.uibinder'
    ui:generateFormat='com.google.gwt.i18n.rebind.format.PropertiesFormat'
    ui:generateKeys="com.google.gwt.i18n.rebind.keygen.MD5KeyGenerator"
    ui:generateLocales="default,en,fr"

Pour la description du message

On ajoute les libellés avec la balise ui:msg

<g:header><ui:msg description="users title">Users </ui:msg></g:header>

Ensuite, a l'instar des messages, on lance la compilation gwt avec le paramètre -extra . On obtient les fichiers présents avec pour nom le chemin absolu ( package inclus ) . Ex : info.touret.....AdminConsoleAdminConsoleUiBinderImplGenMessages_default.properties . Il nous reste plus qu'à le copier dans le répertoire src/main/resources/ mon package du fichier ui.xml

Forcer l'application d'une locale

Contrairement à JSF/JSP , l'application de la locale n'est pas automatique suivant la locale envoyée par le navigateur . On peut forcer la locale en appliquant le paramètre locale dans l'url (ex. &locale=fr ). A voir si je mets une combobox de sélection , un filtre (API Servlet ) pour appliquer la locale directement ou si je gère ça dans le point d'entrée GWT.

Encoding

Attention à l'encoding des fichiers! Il faut impérativement que les fichiers soient encodés au format UTF-8.

Exemple et code source

Le code est disponible sur le référentiel google à cette adresse : code.google.com/p/my-wine-cellar/source/browse/

Bye Dropbox, Hello Ubuntu One

  • mercredi, août 3 2011
  • Par littlewing
  • Category Ubuntu
  • Tags one, Planet-APRIL, Planet-Libre, PUF, ubuntu
  • 12 commentaires

spacer Depuis quelques temps ,j'hésitai à quitter le service dropbox et passer sur ubuntu one. Le changement des conditions d'utilisation de ce premier m'a fait sauter le pas.

Ubuntu One existe depuis quelques temps sur mon os préféré. Il permet entre autres

  • d'avoir un espace gratuit de stockage de 5Go ( au lieu de 2 sur dropbox )
  • de synchroniser sur différents médiums ( ubuntu, android, bientôt windows )
  • d'écouter de la musique stockée sur le cloud via une application android ( à l'instar de google music ou amazon )
  • de synchroniser les contacts

Personnellement, je ne recherche que la première partie qui est le stockage et la synchronisation de fichiers. Par rapport à Dropbox, j'ai même gagné l'upload automatique des photos prises par mon téléphone android spacer .

L'utilisation très simple et intégré par défaut dans l'interface utilisateur Ubuntu.

Ne souhaitant pas réinventer la roue, voici la procédure officielle d'installation sur Ubuntu Natty :

  • La documentation officielle décrit la procédure d'installation
  • et la procédure de gestion des fichiers

Pour ceux qui sont encore sous windows, canonical met à disposition la version beta du client windows ( à vos risques et périls ...)

Paramétrer votre blog dotclear pour une recherche opensearch

  • jeudi, juillet 28 2011
  • Par littlewing
  • Category Logiciels Libres
  • Tags dotclear, opensearch, Planet-APRIL, Planet-Libre
  • 2 commentaires

Qu'est-ce qu'opensearch ?

Pour faire simple et pour ne pas me substituer à une documentation déjà présente et bien fournie, c'est ce qui vous permet d'avoir un moteur recherche présent dans firefox, et consorts

Un exemple :

spacer

Pour ajouter votre blog, c est assez simple

Créer un fichier dc_opensearch.xml avec le contenu suivant :

<?xml version="1.0" encoding="UTF-8"?>

<OpenSearchDescription xmlns="a9.com/-/spec/opensearch/1.1/">
<ShortName>Qu'est-ce qu'on se fait ch...</ShortName>
<Description>Rechercher sur le blog Qu'est-ce qu'on se fait ch...</Description>
<Tags>alexandre touret</Tags>
<Url type="text/html"
     template="blog.touret.info/blog/index.php/?q={searchTerms}"/>
</OpenSearchDescription>

Modifiez les contenus des éléments selon les adresses de votre site.

Modifiez via l'éditeur de thème le fichier user_head.html de votre thème et ajouter le contenu suivant :

<!-- # This template is included at the end of _head.html template -->
<link rel="search" class="blog.touret.info/common-blog/dc_opensearch.xml" type="application/opensearchdescription+xml" title="blog.touret.info" />

Maintenant, le moteur de recherche apparaît dans votre navigateur, il ne vous reste plus qu'à l'ajouter!

Utilisation des services web exchange 2010 en java

  • lundi, juillet 25 2011
  • Par littlewing
  • Category Java EE
  • Tags exchange, jav
gipoco.com is neither affiliated with the authors of this page nor responsible for its contents. This is a safe-cache copy of the original web site.