【问题标题】:Read resource bundle properties in a managed bean读取托管 bean 中的资源包属性
【发布时间】:2012-11-19 06:47:42
【问题描述】:

使用<resource-bundle> 文件,我可以在我的JSF 页面中包含i18n 文本。

但是是否可以在我的托管 bean 中访问这些相同的属性,以便我可以使用 i18n 值设置面孔消息?

【问题讨论】:

    标签: jsf internationalization managed-bean


    【解决方案1】:

    假设您已将其配置如下:

    <resource-bundle>
        <base-name>com.example.i18n.text</base-name>
        <var>text</var>
    </resource-bundle>
    

    如果您的 bean 是请求范围内的,您可以通过 &lt;var&gt;&lt;resource-bundle&gt; 注入为 @ManagedProperty

    @ManagedProperty("#{text}")
    private ResourceBundle text;
    
    public void someAction() {
        String someKey = text.getString("some.key");
        // ... 
    }
    

    或者,如果您只需要一些特定的密钥:

    @ManagedProperty("#{text['some.key']}")
    private String someKey;
    
    public void someAction() {
        // ... 
    }
    

    但是,如果您的 bean 处于更广泛的范围内,则在方法本地范围内以编程方式评估 #{text}

    public void someAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        ResourceBundle text = context.getApplication().evaluateExpressionGet(context, "#{text}", ResourceBundle.class);
        String someKey = text.getString("some.key");
        // ... 
    }
    

    或者如果你只需要一些特定的键:

    public void someAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        String someKey = context.getApplication().evaluateExpressionGet(context, "#{text['some.key']}", String.class);
        // ... 
    }
    

    您甚至可以通过标准的ResourceBundle API 来获取它,就像 JSF 本身已经在幕后所做的那样,您只需要在代码中重复基本名称:

    public void someAction() {
        FacesContext context = FacesContext.getCurrentInstance();
        ResourceBundle text = ResourceBundle.getBundle("com.example.i18n.text", context.getViewRoot().getLocale());
        String someKey = text.getString("some.key");
        // ... 
    }
    

    或者,如果您通过 CDI 而不是 JSF 管理 bean,那么您可以为此创建一个 @Producer

    public class BundleProducer {
    
        @Produces
        public PropertyResourceBundle getBundle() {
            FacesContext context = FacesContext.getCurrentInstance();
            return context.getApplication().evaluateExpressionGet(context, "#{text}", PropertyResourceBundle.class);
        }
    
    }
    

    并注入如下:

    @Inject
    private PropertyResourceBundle text;
    

    或者,如果您使用 JSF 实用程序库 OmniFacesMessages 类,那么您只需设置其解析器一次,即可让所有 Message 方法使用该捆绑包。

    Messages.setResolver(new Messages.Resolver() {
        public String getMessage(String message, Object... params) {
            ResourceBundle bundle = ResourceBundle.getBundle("com.example.i18n.text", Faces.getLocale());
            if (bundle.containsKey(message)) {
                message = bundle.getString(message);
            }
            return MessageFormat.format(message, params);
        }
    });
    

    另请参阅javadocshowcase page 中的示例。

    【讨论】:

    • If your bean is request scoped 是唯一可以访问属性文件的范围吗?
    • @Kuriel:JSF @ManagedProperty 无法在更广的范围内注入更窄的范围。只有 CDI @Inject 是。如果您碰巧使用 CDI,请前往 stackoverflow.com/q/28045667
    • @BalusC 在资源包文件中写入带参数的文本时应使用哪种语法形式?
    • @séan35:只需将捆绑值(不是键!)传递给MessageFormat#format()
    • @ManagedProperty("#{text}") 也适用于 @ViewScoped@FlowScoped beans。
    【解决方案2】:

    另一种可能性:

    faces-config.xml

    <?xml version='1.0' encoding='UTF-8'?>
    <faces-config ...>
      <application>
        <locale-config>
          <default-locale>de</default-locale>
        </locale-config>
        <resource-bundle>
          <base-name>de.fhb.resources.text.backend</base-name>
          <var>backendText</var>
        </resource-bundle>
      </application>
    </faces-config>
    

    YourBean.java

    FacesContext context = FacesContext.getCurrentInstance();
    Application app = context.getApplication();
    ResourceBundle backendText = app.getResourceBundle(context, "backendText");
    backendText.getString("your.property.key");
    

    【讨论】:

      【解决方案3】:

      这是我正在使用的解决方案,不是那么简单,但至少可以工作:

      头等舱:

      package com.spectotechnologies.website.util;
      
      import java.util.Locale;
      import java.util.regex.Matcher;
      import java.util.regex.Pattern;
      import org.hibernate.validator.messageinterpolation.ResourceBundleMessageInterpolator;
      
      /**
       *
       * @author Alexandre Lavoie
       */
      public class MessageInterpolator extends ResourceBundleMessageInterpolator
      {
          public static final String LANGUAGE_TAG_PATTERN = "\\{[^}]*\\}";
      
          @Override
          public String interpolate(String p_sMessage, Context p_oContext)
          {
              return super.interpolate(replaceMessages(p_sMessage),p_oContext);
          }
      
          @Override
          public String interpolate(String p_sMessage, Context p_oContext, Locale p_oLocale)
          {
              StringManager.setLocale(p_oLocale);
      
              return super.interpolate(replaceMessages(p_sMessage),p_oContext,p_oLocale);
          }
      
          private String replaceMessages(String p_sMessage)
          {
              Matcher oMatcher;
              String sKey;
              String sReplacement;
              StringBuffer sbTemp = new StringBuffer();
      
              oMatcher = Pattern.compile(LANGUAGE_TAG_PATTERN).matcher(p_sMessage);
              while(oMatcher.find())
              {
                  sKey = oMatcher.group().substring(1,oMatcher.group().length() - 1);
      
                  sReplacement = StringManager.getString(sKey);
      
                  if(!sReplacement.startsWith("???"))
                  {
                      oMatcher.appendReplacement(sbTemp,sReplacement);
                  }
              }
      
              oMatcher.appendTail(sbTemp);
      
              return sbTemp.toString();
          }
      }
      

      二等:

      package com.spectotechnologies.website.util;
      
      import com.spectotechnologies.util.BundleManager;
      import com.spectotechnologies.util.FacesSessionManager;
      import java.util.Locale;
      
      /**
       * set-up and interface a BundleManager
       * save the bundleManager into the session
       * @author Charles Montigny
       */
      public final class StringManager
      {
          /** the session name of this class bundle manager */
          public static final String BUNDLE_MANAGER_SESSION_NAME = "StringManager_BundleManager";
      
          /**  List of ResourceBundle names to load.
           * Will be load in order.
           * The last ones values may overrite the first ones values. */
          private final static String[] BUNDLE_LIST = {
              "com.spectotechnologies.hibernate.validation.resources.ValidationMessages",
              "com.spectotechnologies.website.general.resources.ValidationMessages",
              "com.spectotechnologies.website.general.resources.General"};
      
          /** bundle manager */
          private static BundleManager m_oBundleManager = null;
      
          private static BundleManager getBundleManager()
          {
              if(m_oBundleManager == null)
              {
                  // get the bundle into the session
                  m_oBundleManager = (BundleManager)FacesSessionManager.getObject(BUNDLE_MANAGER_SESSION_NAME);
                  if(m_oBundleManager == null)
                  {
                      // session was empty, load a new one
                      m_oBundleManager = new BundleManager();
                      for(int iIndex = 0; iIndex < BUNDLE_LIST.length; iIndex++)
                      {
                          m_oBundleManager.addBundle(BUNDLE_LIST[iIndex]);
                      }
                      // add the bundle to the session
                      FacesSessionManager.setObject(BUNDLE_MANAGER_SESSION_NAME, m_oBundleManager);
                  }
              }
              return m_oBundleManager;
          }
      
          /**
           * get a string value in the bundle manager by a string key
           * @param p_sKey the string key
           * @return the value of the string key
           */
          public static String getString(String p_sKey)
          {
              return getBundleManager().getStringValue(p_sKey);
          }
      
          /**
           * set the locale
           * @param p_oLocale the locale to set
           */
          public static void setLocale(Locale p_oLocale)
          {
              getBundleManager().setLocale(p_oLocale);
      
              // update the session
              FacesSessionManager.setObject(BUNDLE_MANAGER_SESSION_NAME,
                      getBundleManager());
          }
      }
      

      在您需要使用属性文件覆盖 BUNDLE_LIST 之后。完成后,像这样使用它:

      sMessage = StringManager.getString("website.validation.modifySystem.modified");
      

      如果您有任何问题,请不要犹豫!

      编辑:

      你还需要声明MessageInterpolator

      META-INF/validation.xml

      <validation-config
          xmlns="http://jboss.org/xml/ns/javax/validation/configuration"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://jboss.org/xml/ns/javax/validation/configuration">
          <message-interpolator>com.spectotechnologies.website.util.MessageInterpolator</message-interpolator>
      </validation-config>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-03-15
        • 2011-09-10
        • 2011-07-13
        • 2023-04-07
        • 1970-01-01
        相关资源
        最近更新 更多