Gestion du multi-langues

Eléments de base à considérer

A considérer:

  • Permettre une application multi-langues
  • S'adapter à la locale utilisée (format numérique)
  • Utilisation de standards
  • Pouvoir déléguer la partie de traduction à des traducteurs
  • Minimiser les impacts sur le développement
  • Prévoir des écrans avec des données de taille variable (label en français plus long qu'en anglais)
  • Permettre une traduction partielle
  • Tout ce qui est automatisable doit être automatisé

Approche générale

Cela conduit à l'application des règles suivantes:

  • Externaliser toute les chaines de caractères
  • Utiliser des layout dynamiques pour les écrans
  • Utiliser la Locale pour les formats numériques (saisie et visualisation)
  • Toujours utiliser le format numérique anglais pour les échanges (import, export)
  • Utiliser les date au format ISO (yyy-mm-dd) format internationnal pour éliminer tout doute

Externaliser les chaines de caractères

Afin de faciliter la vie des développeur et permettre une externalisation complète des chaines de caractères, on utilise une méthode très simple qui n'ajoute pas de surcharge au niveau du développement et qui permet de faire toutes les traductions et utiliser une application multi-langues par la suite.

On distingue 3 types de données à traduire:

  • Données liées aux objets métiers
  • Messages d'erreurs et log
  • Autre

Pour ce qui est des méta-données liées aux objets métiers, le fichier XML supporte déjà le multi-langue.

Les messages d'erreurs sont gérés par un format de fichier supportant le multi-langues.

Pour tout le reste, on externalise les chaines de caractères dans des classes AA.

Section technique - développement

Les classes AA

Chaque package a une classe AA qui ne contient que des variables de type String (static, non finale) qui est l'extraction des String du dit package. Chaque classe AA hérite de la classe AA du package parent. De cette manière cela permet de réutiliser les même chaines de caractère dans différents packages toujours en référent à la classe AA du package courant.

Pour chaque chaine de caractères utilisée, il faut:

  • Créer une variable "public static String" dans une classe AA
  • Utiliser cette variable dans le code

On ne se préocupe de rien de plus à ce stade. Ce n'est que pour le déployement que l'on va utiliser ces variables et faire un traitement pour permettre l'usage multi-langues.

Dans quelle classe AA créer la variable? Pour répondre à cette question, il faut s'interroger sur sa portée. Si la chaine de caractères est seulement utilisé par un package, la créer dans la classe AA du package, sinon la créer dans une classe AA dans un package parent.

Comme tous les packages contiennent une classe AA, il est inutile de faire l'import de classe AA.

// code d'une classe AA
package com.loribel.commons.swing;
public abstract class AA
    extends com.loribel.commons.AA // utiliser le nom complet de la classe parent
{
    public static String BUTTON_VALIDER = "Valider";
}
    // code dans la classe qui utilise la chaine de caractères
    ...
    JButton l_button = new JButton(AA.BUTTON_VALIDER);
    ...

Nomenclature dans les classes AA

On utilise une convention pour le noms des variables des classes AA.

  • BUTTON_xxx : Label d'un bouton.
  • CHECK_xxx : Label d'une case à cocher (checkBox) ou radio bouton (radioButton).
  • COL_xxx : Entête d'une colonne dans une table.
  • ERR_xxx : Message d'une exception, ou message d'erreur.
  • EXCEPTION_xxx : Message d'une exception, ou message d'erreur.
  • GROUP_xxx : Titre d'un groupe.
  • ICON_xxx : Nom de fichier pour une icone ou image.
  • IMG_xxx : Nom de fichier pour une image.
  • INFO_xxx : Info pour les boites d'attente ou écran de démarrage.
  • FILE_xxx : Nom de fichier.
  • LABEL_xxx : Label.
  • MNU_xxx : Item de menu.
  • MNU_xxx_c : Caractère d'accès rapide à un menu.
  • MNU_xxx_IMG : Nom du fichier image pour un menu.
  • MNU_xxx_DESC : Description de l'action d'un menu.
  • MSG_xxx : Message.
  • NODE_xxx : Label d'un noeud (TreeNode) dans un arbre.
  • QUESTION_xxx : Question qui est affiché dans une boite de dialogue.
  • STR_xxx : String utilisé à divers endroits.
  • TAB_xxx : Nom d'un onglet.
  • TITLE_xxx : Titre d'une fenêtre ou d'un panel.
  • TOOLTIP_xxx : Description d'un tool tip.
  • UNIT_xxx : Unité.
  • ZONE_xxx : Titre d'une zone.
Cette convention est disponible sur Loribel.com/java/normes

Comment traiter les classes AA lors du déploiement

Pour externaliser les String du projet contenu dans les classes AA, il suffit d'utiliser la tache ant generate-aa-bundle

ant generate-aa-bundle

Avant de lancer cette tache ant, il faut au préalable prendre en check-out si necessaire les fichiers bundle (xxx-bundle-aa.properties) et la classe AAInit.java. Lors de la génération, les valeurs dans les fichiers bundle ont priorité, si la valeur dans la classae AA est différente du contenu du fichier bundle, c'est le contenu du fichier qui sera gardé. Pour réinitialiser le fichier bundle avec ce qui se trouve dans le code (classe AA), simplement supprimer le fichier bundle et lancer la classe ant.

Comment modifier les traductions (class AA)

Pour modifier une traduction, il suffit de modifier les fichiers bundle. Si vous voulez être rigoureux, il est bon de changer la valeur de la constante associé dans la classe AA. Cela n'est pas nécessaire, mais cela permet de garder en phase le fichier bundle par défaut et la définition des constantes dans le code. De cette manière le fichier bundle par défaut pourra être regénéré à 100%. L'ordre dans les fichiers bundle n'a aucune importance. En cas de doublons, c'est la derniere valeur dans le fichier qui sera utilisée.

Comment ajouter des traductions (class AA)

S'il n'existe pas de fichier bundle associé à la langue à ajouter, il suffit de le créer. Le plus simple est de copier le fichier bundle par défaut et de le traduire. On peut aussi le créer vide et n'y ajouter que ce que l'on veut traduire.