Standard implementation of
IMessageResolver.
This class will first try to perform message resolution based on the template context, then
on the origin, and finally on the specified default messages (if any).
Step 1: Template-based message resolution
For template-based resolution, not only the template being executed will be examined, but also
templates corresponding to fragments being inserted, so that if template A inserts a fragment from
B, and that fragment from B inserts a fragment from C, the requested message will be searched
in this order: A, B, C.
Note the order specified above allows container templates to override default message values specified
at children (inserted fragment) templates.
For each of these templates, several
.properties files will be examined. For example,
a message in template
/WEB-INF/templates/home.html for locale
gl_ES-gheada ("gl" = language, "ES" = country, "gheada" = variant) would be looked for
in
.properties files in the following sequence:
-
/WEB-INF/templates/home_gl_ES-gheada.properties
-
/WEB-INF/templates/home_gl_ES.properties
-
/WEB-INF/templates/home_gl.properties
-
/WEB-INF/templates/home.properties
Note the resolution mechanism used for accessing these template-based
.properties files will
be the same used for resolving the templates themselves. So for templates resolved from the ServletContext
its messages files will be searched at the ServletContext, for templates resolved from URL the corresponding
derived URLs will be called, etc.
Step 2: Origin-based message resolution
If no suitable message value is found during template-based resolution, origin-based resolution
is performed. This allows the resolution of messages from
.properties files living
in the classpath (and only in the classpath) in files corresponding with the names of the
classes being used as origin.
For example, a processor
my.company.processor.SomeDataProcessor using its own class
as origin will be able to resolve messages from a
my/company/processor/SomeDataProcessor_gl_ES.properties file in the classpath.
Also, if a message is not found there, resolution will be tried for each of the superclasses this
my.company.processor.SomeDataProcessor class extends, until a suitable message is found, or
no more superclasses (except
java.lang.Object exist).
Step 3: Defaults-based message resolution
If both template-based and origin-based message resolution fail, resolution will be tried using
the default messages specified via this class's
#setDefaultMessages(Properties) or
#addDefaultMessage(String,String) methods.
Defaults-based message resolution is not locale-dependent.
Absent message specification
Message resolution will return null if no message is found, in which case callers will have the possibility
to choose between asking the resolver to create an absent message representation or not.
This is precisely what the
useAbsentMessageRepresentation flag does in
ITemplateContext#getMessage(Class,String,Object[],boolean).
An absent message representation looks like
??mymessage_gl_ES?? and is useful to quickly determine
when a message is lacking from the application's configuration. Note
#{...}} message expressions will
always ask for an
absent message representation, whereas methods in the
#messagesexpression object will do it depending on the specific method being called.
Message caching
This implementation will cache template-based messages for those templates that are resolved (by their
corresponding
org.thymeleaf.templateresolver.ITemplateResolver) as cacheable. Non-cacheable
templates will not have their messages cached.
Origin-based messages will be always cached.
Extensibility
This implementation is designed for allowing the following extension points:
-
#resolveMessagesForTemplate(String,ITemplateResource,Locale): the mechanism for resolving
the messages for a specific uncached template. Might be called several times, one per nested template.
-
#resolveMessagesForOrigin(Class,Locale): the mechanism for resolving the messages for a specific
unchecked origin class. Might be called several times, one per class/superclass.
-
#formatMessage(Locale,String,Object[]): the way resolved messages are actually formated along
with their parameters (by default a
java.text.MessageFormat is used).
-
#createAbsentMessageRepresentation(ITemplateContext,Class,String,Object[]): the
mechanism for creating absent message representations, which can be customized if needed.