2008-09-17 16 views
5

Est-ce que Facelets a des caractéristiques pour des étiquettes de texte d'interface utilisateur internationalisées plus lisibles ou plus lisibles que ce que vous pouvez faire autrement en utilisant JSF? Par exemple, avec JSF simple, l'utilisation de h: outputFormat est une manière très verbeuse d'interpoler des variables dans les messages.Etiquettes internationalisées dans JSF/Facelets

Précision: Je sais que je peux ajouter une entrée de fichier de message qui ressemble à:

label.widget.count = You have a total of {0} widgets. 

et afficher cette (si j'utilise Seam) avec:

<h:outputFormat value="#{messages['label.widget.count']}"> 
    <f:param value="#{widgetCount}"/> 
</h:outputFormat> 

mais C'est beaucoup de fouillis pour sortir une phrase - juste le genre de chose qui donne un mauvais nom JSF.

Répondre

3

Vous pouvez créer votre propre bibliothèque de balises de visages pour le rendre moins bavard, quelque chose comme:

<ph:i18n key="label.widget.count" p0="#{widgetCount}"/> 

Ensuite, créez le taglib dans votre vue dir: /components/ph.taglib.xml

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "https://facelets.dev.java.net/source/browse/*checkout*/facelets/src/etc/facelet-taglib_1_0.dtd"> 

<facelet-taglib xmlns="http://java.sun.com/JSF/Facelet"> 
    <namespace>http://peterhilton.com/core</namespace> 

    <tag> 
     <tag-name>i18n</tag-name> 
     <source>i18n.xhtml</source> 
    </tag> 

</facelet-taglib> 

create/components/i18n.xhtml

<?xml version="1.0" encoding="UTF-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<ui:composition xmlns="http://www.w3.org/1999/xhtml" 
    xmlns:ui="http://java.sun.com/jsf/facelets" 
     xmlns:h="http://java.sun.com/jsf/html"   
    xmlns:f="http://java.sun.com/jsf/core"> 

    <h:outputFormat value="#{messages[key]}"> 
      <!-- crude but it works --> 
     <f:param value="#{p0}" /> 
     <f:param value="#{p1}" /> 
     <f:param value="#{p2}" /> 
     <f:param value="#{p3}" /> 
    </h:outputFormat> 

</ui:composition> 

Vous pouvez probablement trouver une manière élégante de passer les arguments avec un peu de recherche.

Enregistrez-vous maintenant votre nouvelle taglib dans web.xml

<context-param> 
<param-name>facelets.LIBRARIES</param-name> 
<param-value> 
     /components/ph.taglib.xml 
    </param-value> 
</context-param> 

ajouter juste xmlns:ph="http://peterhilton.com/core" à votre point de vue et vous êtes tous ensemble!

+0

Bonne réponse, et proche de ce que nous avons fait jusqu'ici. Le problème principal est que vous ne pouvez pas l'utiliser dans les valeurs d'attribut. –

-1

Utilisez ResourceBundle et les fichiers de propriétés.

+0

Pourriez-vous expliquer un peu plus? Je ne sais pas ce que vous voulez dire, puisque OP a déjà dit qu'il l'utilise. – Sietse

3

Je n'ai jamais rencontré une autre façon de le faire autre que outputFormat. C'est malheureusement assez verbeux.

La seule autre chose que je peux suggérer est de créer le message dans un bean de support, puis de le sortir plutôt que messageFormat.

Dans mon cas, j'ai SpringSourceSource intégré avec JSF (en utilisant MessageSourcePropertyResolver). Ensuite, il est assez facile d'obtenir des messages paramétrés dans vos beans backing. Il vous suffit de connaître le Locale dans lequel se trouve votre utilisateur (encore une fois, le Locale est lié à une propriété bean backing via JSF ou Java).

Je pense que les paramètres - en particulier dans les messages - sont une chose que JSF pourrait vraiment faire mieux!

3

J'ai pensé à ce plus, et il me semble que je pourrais probablement écrire ma propre fonction JSTL qui prend une clé de message et un nombre variable de paramètres:

<h:outputText value="#{my:message('label.widget.count', widgetCount)}"/> 

et si ma fonction de message HTML code le résultat avant la sortie, je même pas besoin d'utiliser le h: outputText

#{my:message('label.widget.count', widgetCount)} 
+0

Si vous faites ceci et le faites fonctionner, écrivez-moi s'il vous plaît le codez;) Sérieusement cependant, ce serait une grande ressource si vous étiez en mesure de le libérer quelque part. –

5

Puisque vous utilisez Seam, you can use EL dans le fichier de messages.

Propriété:

label.widget.count = You have a total of #{widgetCount} widgets. 

XHTML:

<h:outputFormat value="#{messages['label.widget.count']}" /> 

Il utilise encore outputFormat, mais il est moins bavard.

+0

La seule limite de cette approche est que vous êtes lié à l'utilisation de cette étiquette aveC# {widgetCount} ou que vous devez utiliser explicitement "widgetCount" pour l'utiliser. – Damo

3

Vous pouvez utiliser la Seam interpolator:

<h:outputText value="#{interpolator.interpolate(messages['label.widget.count'], widgetCount)}"/> 

Il a @BypassInterceptors sur si la performance devrait être ok.

1

Vous pouvez utiliser le Bean directement si vous interpolez les messages.

label.widget.count = You have a total of #{widgetCount} widgets. 
label.welcome.message = Welcome to #{request.contextPath}! 
label.welcome.url = Your path is ${pageContext.servletContext}. 

${messages['label.widget.count']} est peuvent acceuillir.

Celui-ci fonctionne très bien avec Spring:

package foo; 

import javax.el.ELContext; 
import javax.el.ELException; 
import javax.el.ExpressionFactory; 
import javax.el.ResourceBundleELResolver; 
import javax.faces.context.FacesContext; 

import org.springframework.web.jsf.el.SpringBeanFacesELResolver; 

public class ELResolver extends SpringBeanFacesELResolver { 
    private static final ExpressionFactory FACTORY = FacesContext 
      .getCurrentInstance().getApplication().getExpressionFactory(); 
    private static final ResourceBundleELResolver RESOLVER = new ResourceBundleELResolver(); 

    @Override 
    public Object getValue(ELContext elContext, Object base, Object property) 
      throws ELException { 
     Object result = super.getValue(elContext, base, property); 
     if (result == null) { 
      result = RESOLVER.getValue(elContext, base, property); 
      if (result instanceof String) { 
       String el = (String) result; 
       if (el.contains("${") | el.contains("#{")) { 
        result = FACTORY.createValueExpression(elContext, el, 
          String.class).getValue(elContext); 
       } 
      } 
     } 
     return result; 
    } 
} 

Et ...

Vous devez changer l'EL-Resolver dans faces-config.xml de org.springframework.web.jsf.el.SpringBeanFacesELResolver à

Cordialement

<el-resolver>foo.ELResolver</el-resolver> 
+0

Attention: peut provoquer une boucle sans fin, sachez ce que vous faites. –