Локализация JSF 2 (управляемый боб)
-
28-09-2019 - |
Вопрос
У меня есть файл свойств для локализации:
foo=Bar
title=Widget Application
Это связано как resource-bundle
На грани конфигурация:
<resource-bundle>
<base-name>com.example.messages.messages</base-name>
<var>msgs</var>
</resource-bundle>
Я могу получить доступ к этому просто отлично на просмотре Facelets с использованием EL:
<title>#{msgs.title}</title>
Однако, если есть такие вещи, как SQLExceptions, мне нужно иметь возможность писать сообщения из управляемого компонента. Это все работает также:
FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "There was an error saving this widget.", null);
FacesContext.getCurrentInstance().addMessage(null, message);
Вот проблема: я хочу иметь эти сообщения из файла свойств, чтобы они тоже могли быть изменены на основе локали. Есть ли простой способ получить доступ к файлу свойств, используя инъекцию?
Решение
Я задал довольно связанный вопрос на так:Как ввести несериализуемый класс (например, java.util.resourcebundle) с сварным швом
А внутри форума шва:http://seamframework.org/community/howtocreateAnnjectableresourcebundlewithweld.
Подводя итоги: я понял инъекционную ResourceBundle с 3 производителями. Сначала вам нужен FacescontextProducer. Я взял один из шва 3 альфа-источников.
public class FacesContextProducer {
@Produces @RequestScoped
public FacesContext getFacesContext() {
FacesContext ctx = FacesContext.getCurrentInstance();
if (ctx == null)
throw new ContextNotActiveException("FacesContext is not active");
return ctx;
}
}
Тогда вам нужен локальпродуктор, который использует FacescontextProducer. Я также взял его из шов 3 альфа.
public class FacesLocaleResolver {
@Inject
FacesContext facesContext;
public boolean isActive() {
return (facesContext != null) && (facesContext.getCurrentPhaseId() != null);
}
@Produces @Faces
public Locale getLocale() {
if (facesContext.getViewRoot() != null)
return facesContext.getViewRoot().getLocale();
else
return facesContext.getApplication().getViewHandler().calculateLocale(facesContext);
}
}
Теперь у вас есть все, чтобы создать ResourceBundleProducer, который может выглядеть так:
public class ResourceBundleProducer {
@Inject
public Locale locale;
@Inject
public FacesContext facesContext;
@Produces
public ResourceBundle getResourceBundle() {
return ResourceBundle.getBundle("/messages", facesContext.getViewRoot().getLocale() );
}
}
Теперь вы можете @inject ResourceBundle в ваши бобы. Обратите внимание, что он должен быть введен в преходящий атрибут, в противном случае вы получите исключение, жалующееся, что ResourceBundle не является сериализен.
@Named
public class MyBean {
@Inject
private transient ResourceBundle bundle;
public void testMethod() {
bundle.getString("SPECIFIC_BUNDLE_KEY");
}
}
Другие советы
Легче использовать, например, модуль сообщения о MyFaces Codi!
Вы можете сделать это с JSF в одиночку.
Начните с определения управляемого свойства на вашем бобовом бону. В конфигурации JSF вы можете установить значение управляемого свойства для экспрессии EL, которое ссылается на ваше ресурс.
Я сделал что-то вроде следующего, используя Tomcat 6. Единственное предостережение состоит в том, что вы не можете получить доступ к этому значению с конструктора вашего Backing Bean, поскольку JSF еще не будет инициализирован. Использовать @PostConstruct
По методу инициализации, если значение необходимо в начале жизненного цикла бобов.
<managed-bean>
...
<managed-property>
<property-name>messages</property-name>
<property-class>java.util.ResourceBundle</property-class>
<value>#{msgs}</value>
</managed-property>
...
</managed-bean>
<application>
...
<resource-bundle>
<base-name>com.example.messages.messages</base-name>
<var>msgs</var>
</resource-bundle>
...
</application>
Это имеет преимущество в том, чтобы сделать ваши методы поддержки бобов менее зависимы от технологии презентации, поэтому ее следует проще проверить. Это также контролирует ваш код из деталей, как имя, приведенное к расслоению.
Некоторые тестирования с использованием Mojarra 2.0.4-B09 показывают небольшое несоответствие при изменении пользователей MANALE MID-сеанса. In-Page EL Spriseions Используйте новый локаль, но в Beaning Bean не дан новой ссылке ResourceBundle. Чтобы сделать его согласованным, вы можете использовать значение свойства компонентов в EL Sepressions, например, использование #{backingBean.messages.greeting}
на месте #{msgs.greeting}
. Отказ Затем Page El и Beaning Bean всегда будут использовать локаль, которая была активна, когда началась сессия. Если пользователи имел Для переключения локалей середина сеанса и получите новые сообщения, вы можете попробовать сделать предварительную проверку бобовой фасоли и дать ей ссылки на оба сеансовой фасоли, так и для пакета ресурсов.
Вот пример о том, как это сделать:http://www.laliluna.de/articles/javaserver-faces-message-resource-bundle-tutorial.html.
Вы хотите взглянуть на ResourceBundle.getBundle()
часть.
Привет, Ларс
Это старый вопрос, но я добавляю еще один способ сделать это. Я искал что-то еще и побежал через это. Способы здесь все казались запутанными для чего-то, что не поражает меня как все это сложно. Играя с блеском, потому что это красиво, если вы спросите меня.
Учитывая файл:
/com/full/package/path/to/messages/errormessages.properties
Внутри файла:
SOME_ERROR_STRING=Your App Just Cratered
Я создаю метод «GetBundle ()», поскольку мне нравится ловить время выполнения и добавить значимое сообщение, поэтому я пойму, откуда он исходит. Не сложно и может помочь, если вы получите прихоти для поиска с файлами свойств по какой-то причине и не все правильно обновляете. Я иногда делаю этот частный, так как иногда есть метод помощника в классе (для меня). Это держит попытку ловить беспорядок из значимого кода.
Использование полного пути к файлу позволяет размещать его где-то, кроме диапазона / каталога по умолчанию, если у вас есть другие идеи на организации.
public/private ResourceBundle getMessageResourceBundle(){
String messageBundle = "com.full.package.path.to.messages.errormessages";
ResourceBundle bundle = null;
try{
bundle = ResourceBundle.getBundle(messageBundle);
}catch(MissingResourceException ex){
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE,
"Unable to find message bundle in XYZ Class", ex);
throw ex;
}
}
public void doSomethingWithBundle(){
ResourceBundle bundle = getMessageResourceBundle();
String someString = bundle.getString("SOME_ERROR_STRING");
...
}