Nous avons déjà vu qu'un navigateur web pouvait être configuré avec une langue par défaut, et que cette langue est transmise au serveur dans les flux HTTP de requête. Nous avons également vu que cette langue était exposée dans les méthodes de la requête. On peut donc facilement imaginer un mécanisme, dans lequel une application web prendrait cette langue en compte pour afficher ses pages dans la bonne langue, celle du navigateur, automatiquement.
Une application internationalisée est une application qui a la capacité
de d'afficher ses pages dans différentes langues, et de choisir celle du navigateur, quand elle
existe, automatiquement. Ce mécanisme repose entre autres, sur les ResourceBundle
définis dans le JDK.
Un ResourceBundle
est un jeu de fichiers texte, qui suit une convention de nommage
précise, et qui est rangé dans un même package. Le premier de ces fichiers texte porte le nom
du bundle, par exemple : org.paumard.bundles.ApplicationBundle
. Ce fichier
doit alors porter le nom ApplicationBundle.properties
, et être rangé dans le
package org.paumard.bundles
.
Ce fichier est un fichier texte, qui contient des paires clés / valeurs, ligne par ligne.
Exemple 5.22. Fichier bundle racine
bonjour.le.monde=Bonjour le monde ! fermeture.application=L'application va se fermer
On peut compléter ce bundle avec d'autres fichiers, dans des langues différentes. Ces autres fichiers
doivent suivre la convention de nommage suivante : on ajoute au nom le suffixe _fr
,
_en
, etc... où les caractères qui suivent _
désignent le code de la langue
de ce fichier. Dans notre exemple, le fichier ApplicationBundle_fr.properties
aura
même contenu que le fichier racine, et le contenu du fichier
ApplicationBundle_en.properties
sera en anglais.
Exemple 5.23. Fichier bundle en anglais
bonjour.le.monde=Hello world ! fermeture.application=The application will be shut down.
On peut ainsi créer des fichiers en espagnol (_es
), en allemand (_de
),
en italien (_it
), etc... À chaque fois, le fichier doit contenir les mêmes clés,
et des valeurs dans la langue désignée.
En Java, un bundle s'utilise de la façon suivante.
Exemple 5.24. Chargement d'un bundle
ResourceBundle bundle1 = ResourceBundle.getBundle("org.paumard.bundles.ApplicationBundle") ; ResourceBundle bundle2 = ResourceBundle.getBundle("org.paumard.bundles.ApplicationBundle", Locale.ENGLISH) ; System.out.println(bundle1.getString("bonjour.le.monde")) ; System.out.println(bundle2.getString("bonjour.le.monde")) ;
On peut charger un bundle en passant à la méthode getBundle()
la langue
(locale
) dans laquelle on veut charger ce bundle. Si cette langue n'est pas définie,
alors le bundle racine sera chargé. Notons que l'on peut lire la langue dans laquelle la JVM
s'exécute en invoquant la méthode Locale.getDefault()
.
On imagine donc assez bien, à partir de cet exemple simple, comment l'internationalisation d'une application web va pouvoir fonctionner.
L'internationalisation est gérée par les éléments de la librairie de tags standard fmt
.
Cette librairie est chargée de la façon suivante.
Exemple 5.25. Utilisation de la lirairie de tags fmt
<%@page contentType="text/html" pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <!-- suite de la page -->
Le premier tag de cette librairie est le tag setLocale
, qui permet de fixer la
langue dans laquelle une page doit s'afficher. Ce tag ne doit être utilisé que si l'en-tête
HTTP ne contient aucune indication de langue, ce qui ne devrait plus arriver sur les navigateurs
récents. Il reste que ce tag peut être très utile en phase de mise au point.
Dans notre exemple, on positionne la langue à la valeur fr_FR
(donc le français que
l'on utilise en France), pour toute la session. L'attribut scope
est l'attribut
classique que l'on a déjà rencontré, et qui peut prendre les valeurs page
,
request
, session
et context
.
Examinons l'exemple suivant.
Exemple 5.27. Formatage des messages localisés
<%@page contentType="text/html" pageEncoding="UTF-8" %> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <%@taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %> <fmt:setLocale value="en"/> <jsp:useBean id="marin" beanName="marin" scope="session" type="org.paumard.cours.model.Marin"/> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>JSP Page</title> </head> <body> <p>Locale = <%= request.getHeader("Accept-language") %></p> <fmt:bundle basename="org.paumard.cours.i18n.Messages"> <p><fmt:message key="last-name"/> = <c:out value="${marin.nom}"/></p> <p><fmt:message key="first-name"/> = <c:out value="${marin.prenom}"/></p> <fmt:message key="greetings-name-first-name"> <fmt:param value="${marin.nom}"/> <fmt:param value="${marin.prenom}"/> </fmt:message> <p></p> </fmt:bundle> </body> </html>
Voici le contenu du bundle associé.
Exemple 5.28. Bundle associé
last-name=nom first-name=prénom greetings-name-first-name=Bonjour {0} {1}
Tout d'abord, remarquons que la déclaration d'un bundle suit la même syntaxe que dans une application Java classique : un bundle est désigné par son nom en tant que ressource.
Remarquons ensuite que les éléments qui dépendent d'un bundle donné doivent être déclarés comme
sous-éléments de l'élément bundle
.
La librairie de tags fmt
nous donne un tag, message
, qui permet de désigner
une clé de ce bundle, et de l'afficher. Bien sûr, le message affiché est celui de la langue
choisie par le système, ou explicitement.
Les deux premiers messages de notre bundle sont des messages simples : first-name
et last-name
. En revanche, notre dernier message est en fait un format, qui déclare
deux paramètres {0}
et {1}
. Fixer les paramètres de ce message, se fait
ajoutant des sous-élément param
à l'élément message
.