Supporting dynamic and translated titles in Apache Tiles
Asked Answered
G

3

6

I have a Spring MVC project that uses Apache Tiles. I have implemented so that titles can be read from a message source like this:

<tiles-definitions>    
    <definition name="some-definition" extends="public.base">
        <put-attribute name="title" value="some-definition.title" cascade="true" />
    </definition>
</tiles-definitions>

And in my template file (defined by public.base), I do the following:

<title><spring:message text="" code="${title}" /></title>

Now this works great for static translated titles, but I also want to support dynamic titles, e.g. for displaying a company name. I could do it like this:

<tiles-definitions>    
    <definition name="some-definition" extends="public.base">
        <put-attribute name="title" expression="${company.name}" />
    </definition>
</tiles-definitions>

And then simply output the title in my template like this: <c:out value="${title}" />. However, the problem then is that my code breaks because the value of the title attribute is no longer a message key. I want to be able to support the following scenarios:

  1. Static titles, e.g. "About Us"
  2. Purely dynamic titles, e.g. "${company.name}"
  3. Dynamic titles with translated content, e.g. "Welcome to ${company.name}"

Ideally, I could use expression language within my message source, but I could not get that to work. I have experimented quite a bit with various solutions, but I cannot seem to find a decent one. If I could use expression language within my message source, then this would be easy. For instance, would it be possible to do the following somehow?

some-definition.title = Hello there, ${company.name}

And in my template:

<spring:message text="" code="some-definition.title" var="test" />
<c:out value="${test}" />

The above does not work, as it outputs ${company.name} rather than the actual contents of the variable. Is there a way to make something like this work? Or are there any other ways in which I can support the scenarios that I listed above?

I thought about creating a custom JSTL tag where I would parse a string expression in plain Java code (the string that has been translated), but I realized that I would probably have to explicitly specify the root object for the "variable replacement" to work, as documented here. Then it does not seem like such a dynamic solution.

Is there any way in which I can accomplish this task? Any help is much appreciated!

Gloat answered 7/4, 2015 at 12:15 Comment(2)
Hello Andy, I have been using Thymeleaf (with Tiles) and your question reminds me of the first time I have to deal with messages: thymeleaf.org/doc/tutorials/2.1/usingthymeleaf.html#messagesDoralynne
Thank you for the link, @PatrickLC. You are right that this is how you typically do it, and I have done so in the past. However, I am still unsure how to do this in my particular use case without having to explicitly pass the parameters when translating the text. It may not even be possible to do what I want, I am not sure.Gloat
L
0

would localisation of the tiles definitions help at all? ref http://tiles.apache.org/framework/tutorial/advanced/l10n.html

otherwise i would look into a ViewPreparer that expands out the spring messages for you.

Lovemaking answered 12/4, 2015 at 17:59 Comment(1)
Localized tile definitions do help if my titles do not contain dynamic content. I was thinking about trying to implement a ViewPreparer before, and it might be the way to go. Thank you for your suggestions!Gloat
K
0

A tile definition can define an attribute called 'controllerClass'. This class should implement the org.apache.struts.tiles.Controller interface and its overridden execute() method is called before the tile definition is rendered.

The execute method has read/write access to the tiles attribute name-value pairs and also the HttpServletRequest object. You could look up your attribute and change values dynamically or else replace it with a semi static value from a property file.

<definition name="some-definition" extends="public.base" controllerClass="pkgName.CustomController">
        <put-attribute name="title" expression="${company.name}" />
    </definition>

And then in your CustomController class, you can change the attributes

public class CustomController implements Controller{
       public void execute(ComponentContext tileContext,
            HttpServletRequest request, HttpServletResponse response,
            ServletContext servletContext) throws ServletException, IOException {       
          String attrName = (String)tileContext.getAttribute("title");
          String attrVal = request.getAttribute("pageTitle"); //get a dynamic value or else retrieve from a resource bundle
          tileContext.putAttribute(attrName,attrVal);
    }

    public void perform(ComponentContext tileContext,
            HttpServletRequest request, HttpServletResponse response,
            ServletContext servletContext) throws ServletException, IOException {
        execute(tileContext, request, response, servletContext);
    }
}
Kujawa answered 16/4, 2015 at 8:9 Comment(0)
S
0

You may not use Tiles for this, juste your Spring-Model :

In controller:

@RequestMapping(value = { "/page1" }, method = RequestMethod.GET)
public String page1() {
    model.addAttribute("titre_page", messageSource.getMessage("home.hello", null,null)
}

In layout.jsp:

...
<title>${titre_page}</title>
...
<tiles:insertAttribute name="body" />
....
Specialistic answered 26/1, 2017 at 21:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.