IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
logo

FAQ StrutsConsultez toutes les FAQ

Nombre d'auteurs : 25, nombre de questions : 96, dernière mise à jour : 23 février 2015  Ajouter une question

 

Cette FAQ a été réalisée à partir des questions fréquemment posées sur les forums de http://www.developpez.com et de l'expérience personnelle des auteurs.

Nous tenons à souligner que cette FAQ ne garantit en aucun cas que les informations qu'elle propose sont correctes. Les auteurs font leur maximum, mais l'erreur est humaine. Cette FAQ ne prétend pas non plus être complète. Si vous trouvez une erreur, ou que vous souhaitez nous aider en devenant rédacteur, lisez ceci.

SommaireI18N (6)
précédent sommaire suivant
 

Struts supporte nativement le mécanisme d'internationalisation et de localisation offert par la plateforme Java : le ResourceBundle et la Locale.

Pour obtenir un ResourceBundle foo.bar.MyResourceBundle, il suffit de créer un ou plusieurs fichiers dans le répertoire /foo/bar/ :

  • MyResourceBundle.properties : ce fichier contient les messages de la langue par défaut pour votre application ;
  • MyResourceBundle_XX.properties : ce fichier contient les mêmes messages dans la langue dont le code ISO est XX.


Exemple : si votre langue par défaut est l'anglais, vous aurez dans MyResourceBundle.properties une entrée du type :
Code : Sélectionner tout
default.welcome=hello
Si vous souhaitez supporter le français, vous aurez dans le fichier MyResourceBundle_fr.properties la même entrée :
Code : Sélectionner tout
default.welcome=bonjour
Il en sera de même pour toutes les langues et vous aurez autant de fichiers .properties que de langues que vous supporterez.

Il vous faudra ensuite déclarer ces ressources dans le descripteur de configuration de votre application (struts-config.xml) :
Code xml : Sélectionner tout
<message-resources parameter="foo.bar.MyResourceBundle" />

Attention : il ne faut pas préciser l'extension du fichier (.properties) et ne pas spécifier les codes ISO.
Il faut aussi absolument veiller à ce que le fichier soit accessible dans le CLASSPATH.

Dans les pages JSP, il faut déclarer l'internationalisation avec l'attribut locale du tag <html:html> :
Code JSP : Sélectionner tout
1
2
3
4
<%@ taglib uri="/WEB-INF/struts-html.tld" prefix="html"%> 
<html:html locale="true"> 
.. page content ... 
</html:html >

Mis à jour le 12 mai 2004 RanDomX

Pour changer la langue à la demande, il faut créer une action qui va mettre à jour la locale dans l'objet request. La locale fait partie des attributs d'une requête http et est donc conservée durant la navigation. De plus, la JVM charge tous les bundles au démarrage. Toutes les langues définies sont donc accessibles.

Imaginons trois liens :

Code JSP : Sélectionner tout
1
2
3
<html:link page='/switch.do?lang=fr&cty=FR'>FR</html:link> 
<html:link page='/switch.do?lang=en&cty=EN'>EN</html:link> 
<html:link page='/switch.do?lang=en&cty=US'>US</html:link>

Ces liens pointent sur une Action "SwitchAction" définie dans le mapping par l'alias "switch".
Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public class SwithLangAction extends Action  
{ 
   public ActionForward execute(ActionMapping mapping,  
                                                 ActionForm form,  
                                                 HttpServletRequest request,  
                                                 HttpServletResponse response) 
      throws IOException, ServletException  
   { 
      //récupération des paramètres passés et de l'URL du referer 
      String country = request.getParameter("cty"); 
      String language = request.getParameter("lang"); 
      String referer = request.getHeader("referer"); 
      HttpSession session = request.getSession(); 
      ActionForward forward = null; 
  
      // définition de la locale 
      setLocale( request, new Locale( language, country ) ); 
  
      // redirection vers une page définie par défaut 
      if( referer==null ) 
      { 
         forward = (mapping.findForward("success")); 
      } 
      // redirection vers l'URL du referrer. 
      else  
      { 
         forward = new RedirectingActionForward(); 
         forward.setPath( referer ); 
      } 
  
      return forward; 
   } 
}

Attention : certains serveurs ne transmettent pas le referer. Il faut donc explicitement le récupérer (dans un ActionForm par exemple).

Mis à jour le 13 mai 2004 hipchic RanDomX

Il faut utiliser l'attribut format du tag <bean:write>.

Code xml : Sélectionner tout
<bean:write name='mybean' property='number' format='#,##0.00' />

Ainsi, si la valeur numérique de la variable number de l'ActionForm référencée par « mybean » vaut 123456789, elle sera affichée 123,456,789.00, conformément au pattern #,##0.00 .

Vous pouvez aussi localiser les patterns de formatage, pour différencier ceux-ci en fonction de la langue. Pour ce faire, il faut les embarquer dans les bundles de ressources.

Exemple :
Code html : Sélectionner tout
number.format=#,##0.00

Il faut ensuite utiliser :
Code xml : Sélectionner tout
<bean:write name='mybean' property='number' formatkey='number.format'/>

Attention : le pattern utilisé doit être compatible avec la langue. Par exemple, '#,##0.00' ne fonctionnera pas avec la locale 'fr', puisque c'est un pattern anglais.

Mis à jour le 13 mai 2004 RanDomX

Le principe consiste à fusionner les resources-bundles au chargement.

Voici la classe qui se charge de le faire (l'API commons Logging est utilisée dans cet exemple pour la journalisation) :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package bla.bla.bla.struts; 
  
import java.io.InputStream; 
import java.util.Enumeration; 
import java.util.Properties; 
  
import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.apache.struts.util.MessageResourcesFactory; 
import org.apache.struts.util.PropertyMessageResources; 
  
public class MultiPropertyMessageResources extends PropertyMessageResources 
{ 
  
    protected static final Log log; 
  
    public MultiPropertyMessageResources(MessageResourcesFactory factory, String config) 
    { 
        super(factory, config); 
        log.info("Initializing, config='" + config + "'"); 
    } 
  
    public MultiPropertyMessageResources(MessageResourcesFactory factory, String config, boolean returnNull) 
    { 
        super(factory, config, returnNull); 
        log.info("Initializing, config='" + config + "', returnNull=" + returnNull); 
    } 
  
    protected void loadLocale(String localeKey) 
    { 
		label0: 
        { 
            if(log.isTraceEnabled()) 
                log.trace("loadLocale(" + localeKey + ")"); 
            synchronized(locales) 
            { 
                if(locales.get(localeKey) == null) 
                    break label0; 
            } 
            return; 
        } 
        locales.put(localeKey, localeKey); 
  
        String configFiles[] = config.split(","); 
        for(int i = 0; i < configFiles.length; i++) 
        { 
            String name = configFiles[i].trim().replace('.', '/'); 
            if(localeKey.length() > 0) 
                name = name + "_" + localeKey; 
            name = name + ".properties"; 
            InputStream is = null; 
            Properties props = new Properties(); 
            try 
            { 
                if(log.isTraceEnabled()) 
                    log.trace("  Loading resource '" + name + "'"); 
                ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); 
                if(classLoader == null) 
                    classLoader = getClass().getClassLoader(); 
                is = classLoader.getResourceAsStream(name); 
                if(is != null) 
                { 
                    props.load(is); 
                    is.close(); 
                } 
                if(log.isTraceEnabled()) 
                    log.trace("  Loading resource completed"); 
            } 
            catch(Throwable t) 
            { 
                log.error("loadLocale()", t); 
                if(is != null) 
                    try 
                    { 
                        is.close(); 
                    } 
                    catch(Throwable u) { } 
            } 
            if(props.size() < 1) 
                return; 
            synchronized(messages) 
            { 
                String key; 
                for(Enumeration names = props.keys(); names.hasMoreElements();  
					messages.put(messageKey(localeKey, key), props.getProperty(key))) 
                { 
                    key = (String)names.nextElement(); 
                    if(log.isTraceEnabled()) 
                        log.trace("  Saving message key '" + messageKey(localeKey, key)); 
                } 
  
            } 
        } 
  
        return; 
    } 
  
  
    static  
    { 
        log = LogFactory.getLog(MultiPropertyMessageResources.class); 
    } 
}

Il faut ensuite écrire un Factory pour Struts :

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package bla.bla.bla.struts; 
  
import org.apache.struts.util.MessageResources; 
import org.apache.struts.util.PropertyMessageResourcesFactory; 
  
  
public class MultiPropertyMessageResourcesFactory extends PropertyMessageResourcesFactory 
{ 
  
    public MultiPropertyMessageResourcesFactory() 
    { 
    } 
  
    public MessageResources createResources(String config) 
    { 
        return new MultiPropertyMessageResources(this, config, returnNull); 
    } 
}

Puis, il ne reste plus qu'à modifier le struts-config.xml :

Code xml : Sélectionner tout
1
2
3
4
<message-resources  
parameter="fichier1,fichier2,fichier3"  
factory="bla.bla.bla.struts.MultiPropertyMessageResourcesFactory"  
/>

Cette solution règle bien évidemment le problème pour toutes les ressources utilisées par Struts, en particulier le plugin Validator.

Mis à jour le 28 juin 2006 Alwin

Pour pouvoir utiliser un ResourceBundle défini en dehors du classpath, il faut déclarer un module de chargement de ressources comme suit.

Remarque : cette classe est une version améliorée de celle proposée pour la question sur le chargement de plusieurs ResourceBundle (cf. lien).

Ses fonctionnalités sont les suivantes :

  • support de fichier de ressources multiples recours aux clés de bundle ;
  • accepte les ressources dans le classpath ;
  • accepte les ressources de type URL.

Code java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package com.vvic.struts.utils; 
  
import java.io.InputStream; 
import java.net.URL; 
import java.util.Enumeration; 
import java.util.Properties; 
  
import org.apache.commons.logging.Log; 
import org.apache.commons.logging.LogFactory; 
import org.apache.struts.util.MessageResourcesFactory; 
import org.apache.struts.util.PropertyMessageResources; 
  
public class MultiPropertyMessageResources extends PropertyMessageResources { 
  
	protected static final Log log; 
  
	public MultiPropertyMessageResources(MessageResourcesFactory factory, 
			String config) { 
		super(factory, config); 
		log.info("Initializing, config='" + config + "'"); 
	} 
  
	public MultiPropertyMessageResources(MessageResourcesFactory factory, 
			String config, boolean returnNull) { 
		super(factory, config, returnNull); 
		log.info("Initializing, config='" + config + "', returnNull=" 
			+ returnNull); 
	} 
  
	protected void loadLocale(String localeKey) { 
		label0: { 
			if (log.isTraceEnabled()) 
				log.trace("loadLocale(" + localeKey + ")"); 
				synchronized (locales) { 
				if (locales.get(localeKey) == null) 
					break label0; 
				} 
			return; 
		} 
		locales.put(localeKey, localeKey); 
  
		String configFiles[] = config.split(","); 
		for (int i = 0; i < configFiles.length; i++) { 
			String name = configFiles[i].trim().replace('.', '/'); 
			if (localeKey.length() > 0) 
				name = name + "_" + localeKey; 
			name = name + ".properties"; 
			InputStream is = null; 
			Properties props = new Properties(); 
			try { 
				if (log.isTraceEnabled()) 
					log.trace("  Loading resource '" + name + "'"); 
				ClassLoader classLoader = Thread.currentThread() 
					.getContextClassLoader(); 
				if (classLoader == null) 
					classLoader = getClass().getClassLoader(); 
				is = classLoader.getResourceAsStream(name); 
				if (is != null) { 
					props.load(is); 
					is.close(); 
				} 
				if (log.isTraceEnabled()) 
					log.trace("  Loading resource completed"); 
			} catch (Throwable t) { 
				log.error("loadLocale()", t); 
				if (is != null) 
					try { 
						is.close(); 
					} catch (Throwable u) { 
				} 
			} 
  
			if (props.size() < 1) { 
				try { 
					is = new URL(name).openStream(); 
					props.load(is); 
					is.close(); 
				} catch (Throwable t) { 
					log.error("loadLocale()", t); 
				} 
			} 
			if (props.size() < 1) { 
				log.warn("Unable to load resource " + name); 
				return; 
			} 
			synchronized (messages) { 
				String key; 
				for (Enumeration names = props.keys(); names.hasMoreElements(); messages 
						.put(messageKey(localeKey, key), props.getProperty(key))) { 
					key = (String) names.nextElement(); 
					if (log.isTraceEnabled()) 
						log.trace("  Saving message key '" 
							+ messageKey(localeKey, key)); 
				} 
  
			} 
		} 
  
		return; 
	} 
  
	static { 
		log = LogFactory.getLog(MultiPropertyMessageResources.class); 
	} 
}

Exemple de configuration dans le fichier struts-config.xml :

Code xml : Sélectionner tout
1
2
3
4
<message-resources  
parameter="resources.application,file:///workspace/globalResources/erreurs"  
factory="com.vvic.struts.utils.MultiPropertyMessageResourcesFactory"  
/>

Mis à jour le 28 juin 2006 Alwin

Pour gérer l'encodage des caractères à afficher, il peut être nécessaire de passer par ceci en Struts1.

Créer une classe qui implémente l'interface Filter et dans la méthode doFilter faire l'encodage en UTF8 :

Code Java : Sélectionner tout
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
package chemin.filter 
import java.io.IOException; 
import javax.servlet.*; 
public class encodeUtf8 implements Filter{ 
	public void doFilter(ServletRequest request, 
	ServletResponse response, FilterChain chain) 
	throws IOException, ServletException 
	{ 
		request.setCharacterEncoding("UTF-8"); 
		chain.doFilter(request, response); 
		response.setCharacterEncoding("UTF-8"); 
	} 
	public void init(FilterConfig filterConfig) throws ServletException {} 
	public void destroy() {} 
}

Ajouter dans le fichier web.xml :
Code XML : Sélectionner tout
1
2
3
4
5
6
7
8
<filter> 
    <filter-name>encodeUtf8</filter-name> 
    <filter-class>chemin.filter.encodeUtf8</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>encodeUtf8</filter-name> 
    <url-pattern>/*</url-pattern> 
</filter-mapping>

Mis à jour le 2 décembre 2014 andry.aime Robin56

Proposer une nouvelle réponse sur la FAQ

Ce n'est pas l'endroit pour poser des questions, allez plutôt sur le forum de la rubrique pour ça


Réponse à la question

Liens sous la question
précédent sommaire suivant
 

Les sources présentées sur cette page sont libres de droits et vous pouvez les utiliser à votre convenance. Par contre, la page de présentation constitue une œuvre intellectuelle protégée par les droits d'auteur. Copyright © 2024 Developpez Developpez LLC. Tous droits réservés Developpez LLC. Aucune reproduction, même partielle, ne peut être faite de ce site et de l'ensemble de son contenu : textes, documents et images sans l'autorisation expresse de Developpez LLC. Sinon vous encourez selon la loi jusqu'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.