mercredi 27 mars 2013

[Devoxx France] C'est parti !


Je ne l'avais pas annoncé mais j'assiste à la deuxième édition de Devoxx France. Petite soeur de Devoxx, elle se déroule à Paris sur trois jours (du 27 au 29 mars). C'est grâce à developpez.com que je me suis vu offrir une entrée gratuite afin de couvrir cet évènement. Je vais essayer de faire quelques billets pendant la conférence (en fonction du temps que j'aurai de disponible) mais ferai dans tout les cas un compte rendu sous forme d'article une fois la conférence terminée.

Me voilà donc parachuté au centre de conférence du Marriott Hotel Paris rive gauche. Je me suis présenté assez tôt (vers 7h50) pour retirer mon badge et j'ai bien fait. Il n'y avait presque personne mais 20 minutes plus tard c'était la cohue. J'ai profité du temps que j'avais pour faire un peu le tour et repérer les diverses salles de la conférence. Avec la stratégie du premier arrivé premier assis, il vaut mieux ne pas arriver trop en retard, en particulier pour les hands-on-lab.

Pour cette première journée j'ai prévu les sessions suivantes :


  • 6 Minute Apps! Build Your First Modern Web App
  • Stratégie de testing de code legacy
  • Spock, le testing nouvelle génération
  • NFC, l'interaction facilitée des mobiles avec leur environnement
  • Good Bad and Ugly Maven - a puzzler session


Les journée vont être denses et intenses, c'est parti !


jeudi 3 janvier 2013

[Java] Resources et internationalisation simple avec ResourceBundle


Un moyen simple d'internationaliser son code Java est d'utiliser la class ResourceBundle avec des fichiers properties.

Voici une IHM simple suivi de son code :


public final class SimpleFrame extends JFrame {
    
    private JLabel label;
    private JButton closeButton;

    public SimpleFrame() {
        super("Simple Frame");
        initComponents();
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setPreferredSize(new Dimension(280, 70));
        pack();
        setLocationRelativeTo(null);
    }
    
    private void initComponents() {
        label = new JLabel("Hello world!");
        closeButton = new JButton("Close");
        closeButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        setLayout(new FlowLayout(FlowLayout.CENTER));
        add(label);
        add(closeButton);
    }
}


Vous noterez les trois chaînes de caractères écrites en dur dans le code.

La classe ResourceBundle permet d'externaliser ces ressources dans un fichier properties, le tout pouvant être internationalisé de surcroît.

Voici le code d'une IHM similaire à la précédente :
public final class I18nFrame extends JFrame {
    
    private static final ResourceBundle RESOURCES = 
                               ResourceBundle.getBundle(I18nFrame.class.getName());
    private JLabel label;
    private JButton closeButton;

    public I18nFrame() {
        super(RESOURCES.getString("title"));
        initComponents();
        setDefaultCloseOperation(DISPOSE_ON_CLOSE);
        setPreferredSize(new Dimension(280, 70));
        pack();
        setLocationRelativeTo(null);
    }
    
    private void initComponents() {
        label = new JLabel(RESOURCES.getString("label.text"));
        closeButton = new JButton(RESOURCES.getString("closeButton.text"));
        closeButton.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                dispose();
            }
        });
        setLayout(new FlowLayout(FlowLayout.CENTER));
        add(label);
        add(closeButton);
    }
}

Les chaînes de caractères sont stockées dans un fichier properties portant le même nom que la classe (ici I18nFrame.properties) et situé dans le même package.
label.text = Hello world!
closeButton.text = Close
title=Internationalized Frame

On obtient le résultat suivant


Pour ajouter une nouvelle langue il suffit de créer un fichier properties pareil au premier en y ajoutant un suffixe à son nom. Le suffixe indique la locale concernée, ainsi un fichier I18nFrame_fr.properties spécifie les ressources pour la langue française (cf la javadoc de  ResourceBundle pour plus de détails).
label.text = Bonjour tout le monde !
closeButton.text = Fermer
title=Fenêtre internationalisée

Ce qui donne :




Ce mécanisme est assez simple et très facile à mettre en oeuvre, très utile pour internationaliser son code. Un dernier exemple pour la représentation textuelle d'une enum.
public enum Country {
    FRANCE,
    GERMANY,
    USA;
    
    private static final ResourceBundle RESOURCES = 
                               ResourceBundle.getBundle(Country.class.getName());

    @Override
    public String toString() {
        return RESOURCES.getString(name());
    }
}

avec le fichier Country.properties
FRANCE = France
GERMANY = Germany
USA = United State of America
et Country_fr.properties
FRANCE = France
GERMANY = Allemagne
USA = Etats Unis d'Amérique


Vous n'avez plus d'excuse pour hardcoder vos chaînes de caractère ;-)

@++