Enviornment: JSF 2.1.7 SEAM 2.3.0 JBOSS 5.1.2
My application has a string that needs to be localized
"I agree to WorldSite's Privacy Policy and Cookie Notice"
Where the italicized Privacy Policy and Cookie Notice are hyperlinks to other pages.
Originally our facelet was set up like this:
<h:outputText value="#{messages['iAgreeTo']}" />
<h:outputLink target="_blank" value="#{bean.privacyPolicy}">#{messages['privacyPolicy']}</h:outputLink>
<h:outputText value="#{messages['and']}"/>
<h:outputLink target="_blank" value="/jsf/Notice.xhtml">
<h:outputText value="#{messages['cookieNotice']}"/>
<f:param name="content" value="Cookie-Notice"/>
<f:param name="application" value="#{bean.application}"/>
</h:outputLink>
Note: We have URL rewriting in place that takes /jsf/Notice.xhtml and rewrites to
rewrite pattern: /#{application}/Notice/#{content}
result:http://contextRoot/contextPath/myApp/Notice/Cookie-Notice
This allowed for piecemeal translations of the individual keys
iAgreeTo=I agree to WorldSite's 
privacyPolicy=Privacy Policy
and= and 
cookieNotice=Cookie Notice
But this required a workaround for some languages (in "iAgreeTo" and "and" keys)
iAgreeTo=J'accepte la 
privacyPolicy=Politique de la vie privée
and= de WorldSite et les 
cookieNotice=Note D'information sur les Cookies
Ideally I would like to be able to have the links be movable within the key. Something like this:
iAgreePhrase=I agree to WorldSite's #{messages['privacyPolicyLink']} and the #{messages['cookieNoticeLink']}
privacyPolicy=Privacy Policy
cookieNotice=Cookie Notice
//The following non-translatable keys held in a separate file
privacyPolicyLink=<h:outputLink target="_blank" value="#{bean.privacyPolicy}">#{messages['privacyPolicy']}</h:outputLink>
cookieNoticeLink=<h:outputLink target="_blank" id="cookieNoticeLink" value="/jsf/Notice.xhtml">\
#{messages['cookieNotice']}\
<f:param name="content" value="Cookie-Notice"/>\
<f:param name="application" value="#{bean.application}"/>\
</h:outputLink>
But the facelet returns the JSF tags (h:outputLink) as strings instead of expanding them to their HTML tags. I can use <a>
tags, but then I'm putting rewrite logic in the properties file which is difficult to maintain
iAgreePhrase=I agree to WorldSite's #{messages['privacyPolicyLink']} and the #{messages['cookieNoticeLink']}
privacyPolicy=Privacy Policy
cookieNotice=Cookie Notice
//The following non-translatable keys held in a separate file
privacyPolicyLink=<a target="_blank" href="#{bean.privacyPolicy}">#{messages['privacyPolicy']}</a>
cookieNoticeLink=<a target="_blank" href="#{contextPath}/#{bean.application}/Notice/Terms-and-Conditions">\
#{messages['cookieNotice']}</a>
Is there a way I can achieve my desired effect without having to put rewrite logic in the resource bundle? Some thoughts I have are forcing the application container to process the facelet twice/reorder it, so it inserts the resource bundles first, and then expands the JSF tags.
Alternatively I may be able to construct the rewritten URL in a bean then call that from my resource bundle?
While Oversteer's answer is certainly applicable, this could also prove helpful. You can create URLs from EL expressions like this:
#{facesContext.externalContext.encodeActionURL('/myapp/Notice/Privacy-Policy')}
To include HTML markup in a message, you need to use escape="false"
in <h:outputText/>
, for example:
<h:outputText escape="false" value="#{messages['iAgreePhrase']}" />
And, in your messages.properties (or localized version):
iAgreePhrase=I agree to WorldSite's <a href="#{facesContext.externalContext.encodeActionURL('/myapp/Notice/Privacy-Policy')}">Privacy Policy</a> and ...
This has the problem that the URL is calculable only from within an HTTP request, if you for example use the message key from within an asynchronous thread, the URL will not be calculated (there's no facesContext available).