Thymeleaf Spring JSF

1

I'm trying to internationalize templat, using

  • Thymeleaf 3.0
  • Spring 4.2.3
  • JSF 2.2

What is sent next to an email.

#{i18N.descriptionPortal}

When you print in the email html it looks like this

??i18N.descriptionPortal_pt_BR??

o Thymeleaf does not know about i18N that works on JSF pages, any tips on how to parameterize this?

Configuration for i18N and thymeleaf

@Configuration(value = "webapp")
@EnableWebMvc
@EnableTransactionManagement
@EnableScheduling
@ApplicationScoped
public class AppInitializer extends WebMvcConfigurerAdapter implements WebApplicationInitializer, ApplicationContextAware
{


    private ApplicationContext          applicationContext;

    @Override
    public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer)
    {
        configurer.enable();
    }

    @Override
    public void onStartup(final ServletContext servletContext) throws ServletException
    {
        final AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext();
        ctx.register(Config.class);
        //definido o listener do spring para o contexto
        servletContext.addListener(new RequestContextListener());
        servletContext.addListener(new ContextLoaderListener(ctx));
        ctx.setServletContext(servletContext);
    }


    @Bean
    @Autowired
    public ViewResolver viewResolver(@Qualifier("templateEngine") final TemplateEngine templateEngine)
    {
        final ThymeleafViewResolver resolver = new ThymeleafViewResolver();
        resolver.setTemplateEngine(templateEngine);
        resolver.setCharacterEncoding("UTF-8");
        return resolver;
    }


    @Bean(name = "templateEngine")
    public TemplateEngine templateEngine() throws Exception
    {
        final SpringTemplateEngine engine = new SpringTemplateEngine();
        engine.setEnableSpringELCompiler(true);
        engine.setTemplateResolver(templateResolver());
        engine.afterPropertiesSet();
        return engine;
    }

    private ITemplateResolver templateResolver()
    {
        final SpringResourceTemplateResolver resolver = new SpringResourceTemplateResolver();
        resolver.setApplicationContext(applicationContext);
        resolver.setPrefix("/WEB-INF/classes/mail/");
        resolver.setTemplateMode(TemplateMode.HTML);
        return resolver;
    }

    @Bean(name = "msg")
    public MessageSource messageSource()
    {
        final ResourceBundleMessageSource message = new ResourceBundleMessageSource();
        message.setBasenames("messages/messages", "messages/build");
        message.setDefaultEncoding("UTF-8");
        message.setUseCodeAsDefaultMessage(true);
        return message;
    }

    @Bean
    public LocaleResolver localeResolver()
    {
        final SessionLocaleResolver localeResolver = new SessionLocaleResolver();
        localeResolver.setDefaultLocale(new Locale("pt", "BR"));
        return localeResolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        final LocaleChangeInterceptor lci = new LocaleChangeInterceptor();
        lci.setParamName("msg");
        return lci;
    }   
}

These are the forms I tried to use in the template, I made several settings and nothing.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns:th="http://www.thymeleaf.org" th:with="lang=${#locale.language}" th:lang="${msg}">
<body>
    <table class="tableCenter">
        <tr>
            <th colspan="2">
                <h2>
                    <span th:utext="#{msg.descriptionPortal}" />
                    <span th:utext="#{descriptionPortal}" />
                </h2>
            </th>
        </tr>
        .
        .
        .

This is the result in the email received

  

?? msg.descriptionPortal_pt_BR ?? ?? descriptionPortal_pt_BR ??

This is the error when I try to use the i18N key in .xhtml

GRAVE: Error Rendering View[/mod/home.xhtml]
javax.el.ELException: /mod/home.xhtml: Property 'descriptionPortal' not found on type org.springframework.context.support.ResourceBundleMessageSource
    at com.sun.faces.facelets.compiler.TextInstruction.write(TextInstruction.java:88)
    at com.sun.faces.facelets.compiler.UIInstructions.encodeBegin(UIInstructions.java:82)
    at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:82)
    at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:72)
    at org.primefaces.component.outputpanel.OutputPanelRenderer.encodeMarkup(OutputPanelRenderer.java:65)
    at org.primefaces.component.outputpanel.OutputPanelRenderer.encodeEnd(OutputPanelRenderer.java:41)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
    at org.primefaces.renderkit.CoreRenderer.renderChild(CoreRenderer.java:89)
    at org.primefaces.renderkit.CoreRenderer.renderChildren(CoreRenderer.java:72)
    at org.primefaces.component.outputpanel.OutputPanelRenderer.encodeMarkup(OutputPanelRenderer.java:65)
    at org.primefaces.component.outputpanel.OutputPanelRenderer.encodeEnd(OutputPanelRenderer.java:41)
    at javax.faces.component.UIComponentBase.encodeEnd(UIComponentBase.java:919)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1903)
    at javax.faces.render.Renderer.encodeChildren(Renderer.java:176)
    at javax.faces.component.UIComponentBase.encodeChildren(UIComponentBase.java:889)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1896)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1899)
    at javax.faces.component.UIComponent.encodeAll(UIComponent.java:1899)
    at com.sun.faces.application.view.FaceletViewHandlingStrategy.renderView(FaceletViewHandlingStrategy.java:451)
    at com.sun.faces.application.view.MultiViewHandler.renderView(MultiViewHandler.java:131)
    at com.sun.faces.lifecycle.RenderResponsePhase.execute(RenderResponsePhase.java:120)
    at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
    at com.sun.faces.lifecycle.LifecycleImpl.render(LifecycleImpl.java:219)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:647)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:292)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.tomcat.websocket.server.WsFilter.doFilter(WsFilter.java:52)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.springframework.orm.hibernate5.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:151)
    at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:107)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at com.sys.filters.SysFilterLogin.executeRequest(SysFilterLogin.java:194)
    at com.sys.filters.SysFilterLogin.processSession(SysFilterLogin.java:142)
    at com.sys.filters.SysFilterLogin.doFilter(SysFilterLogin.java:46)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at com.sys.filters.SysFilterAllRequest.doFilter(SysFilterAllRequest.java:55)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at com.sys.filters.SysCharacterEncodingFilter.doFilter(SysCharacterEncodingFilter.java:39)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:240)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:207)
    at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:212)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:106)
    at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:502)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:141)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:79)
    at org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:616)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:88)
    at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:522)
    at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1095)
    at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:672)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.doRun(AprEndpoint.java:2500)
    at org.apache.tomcat.util.net.AprEndpoint$SocketProcessor.run(AprEndpoint.java:2489)
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1142)
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617)
    at org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
    at java.lang.Thread.run(Thread.java:745)

I have already done many other configurations but I practically always come up with the same result

    
asked by anonymous 05.01.2017 / 17:24

2 answers

1

This feedback from Themeleaf is that it did not find the text in pt_BR for the "descriptionPortal" variable.

Take a look at this response Using i18n

You basically need to create a messages_en.properties file inside resources / i18n / and have the variable there

descriptionPortal = Descrição do Portal em português

Add the parameter to the tag you are using, for example:

<p th:text="${descriptionPortal}"></p>
    
06.01.2017 / 07:54
1

The whole problem was generated as follows:

  • Themeleaf injects into your source somewhere, it just reads the MessageSource interface;
  • What should be the messageSource bean
  • How JSF needs java.util.ResourceBundle
  • Creates a singleton ResourceBundle object
  • In this case called i18N

    @Component("i18N")
    @Scope("singleton")
    public class SysResourceBundleRead extends ResourceBundle implements Serializable, MessageSource{
     ..
     ..
     ..
    }
  • See the object implementing MessageSource
  • Now in the configuration I get the object
  • @Qualifier ("i18N")
    
    @Bean(name = { "messageSource"})
    @Autowired
    public MessageSource messageSource(@Qualifier("i18N") final SysResourceBundleRead resourceBundleRead)
    {
        return resourceBundleRead;
    }
    
  • So who will use with this name uses the same object thinking that it is messageSource, default

The configuration in jsf integrating Spring goes like this

<application>
    <el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
    <el-resolver>com.sys.resolver.SysLocaleController</el-resolver>
    <resource-bundle>
        <base-name>messages.build</base-name>
        <var>build</var>
    </resource-bundle>
    <resource-bundle>
        <display-name>I18N</display-name>
        <base-name>messages.messages</base-name>
        <var>i18N</var>
    </resource-bundle>
    <locale-config>
        <default-locale>pt_BR</default-locale>
        <supported-locale>en_US</supported-locale>
        <supported-locale>pt_BR</supported-locale>
    </locale-config>
    <message-bundle>messages.messages</message-bundle>

</application>

To use in JSF, use this:

#{i18N.descriptionPortal}

To use in themeleaf use this:

#{descriptionPortal}

To use Spring, use this:

@Qualifier(name = { "messageSource"})
@Autowired
public MessageSource messageSource;

Or

@Qualifier(name = { "i18N"})
@Autowired
public SysResourceBundleRead i18N;

Both are the same object, but use different methods to read the keys, so you need to adjust your class for this to be synchronized.

    
10.01.2017 / 13:45