Table of Contents
Asta4D affords basic i18n support by a built-in I18nMessageHelper. I18nMessageHelper requires a MessagePatternRetriever implementation to retrieve message by key. There is also a default implementation JDKResourceBundleMessagePatternRetriever which uses the JDK's built-in resource bundle mechanism.
I18nMessageHelper is an abstract classes which affords the basic interface for handling messages:
getMessage(String key)
getMessage(Locale locale, String key);
getMessageWithDefault(String key, Object defaultPattern)
return defaultPattern#toString() if message not found
getMessageWithDefault(Locale locale, String key, Object defaultPattern)
return defaultPattern#toString() if message not found
There are also two extended classes from I18nMessageHelper, which afford more flexible message functionalities especially about formatting message by given parameters. Configuration#setI18nMessageHelper can be used to customized which helper you want to use. The default is OrderedParamI18nMessageHelper. (I18nMessageHelperTypeAssistant#getConfiguredMappedHelper and I18nMessageHelperTypeAssistant#getConfiguredOrderedHelper can be used to retrieve a type safe configured helper.)
MappedParamI18nMessageHelper
Allow format message by a given parameter map, A MappedValueFormatter is required to supply concrete formatting style and the default is ApacheStrSubstitutorFormatter which uses StrSubstitutor from Apache Common lang3.
OrderedParamI18nMessageHelper(default)
Allow format message by a given parameter array. A OrderedValueFormatter is required to supply concrete formatting style and the default is JDKMessageFormatFormatter which uses JDK's MessageFormat to format message string.
There are several value formatter can be used by the above helpers. Notice that The MappedParamI18nMessageHelper requires implementation of MappedValueFormatter and the OrderedParamI18nMessageHelper requires implementation of OrderedValueFormatter.
Table 15.1. Built-in value formatters
formatter | interface | Description | Example |
---|---|---|---|
ApacheStrSubstitutorFormatter(default) | MappedValueFormatter | Use Apache Commons Lang's StrSubstitutor#replace to format messages. Use "{" and "}" to represent variables place holder. | "There are {count} items in the {item-name} list." |
JDKMessageFormatFormatter(default) | OrderedValueFormatter | Use JDK's MessageFormat#format to format messages. | "There are {1} items in the {2} list." |
SymbolPlaceholderFormatter | OrderedValueFormatter | Use JDK's String#format to format messages. | "There are %d items in the %s list." |
The I18nMessageHelper requires a MessagePatternRetriever implementation to retrieve message by key. There is a default implementation JDKResourceBundleMessagePatternRetriever which uses the JDK's built-in resource bundle mechanism. The base name of resource bundle files can be specified by JDKResourceBundleMessagePatternRetriever#setResourceNames which accepts a list of base name. The configured resource bundles will be passed to JDK's ResourceBundle#getBundle(String baseName, Locale locale, ClassLoader loader) to retrieve messages.
As the implementation of JDKResourceBundleMessagePatternRetriever, if the given locale is null, the default locale decision mechanism will be performed. See Section 15.1.3, “Default locale”.
Further, the JDKResourceBundleMessagePatternRetriever accepts ResourceBundleFactory to allow customize how to retrieve a resource bundle. The default is CharsetResourceBundleFactory which allows specify the encoding of message bundle files. Another built-in implementation is the LatinEscapingResourceBundleFactory, as the name suggests, the message files must be escaped by JDK's standard mechanism(via native2ascii).
The default locale will be decided by the following order and stop at the first non-null returned value.
Context.getCurrentThreadContext().getCurrentLocale()
Locale.getDefault()
Locale.ROOT
Since the Locale.getDefault() will return the local machine's locale by default, you may need to override the default locale to ROOT at the staring of your web application.
"afd:msg" tag can be used to declare an i18n aware message in a template file. The basic usage is as following:
<section> <article> <div class="panel panel-default"><div class="panel-body"> <!-- the inner html will be treated as default message if the key is not found in message bundle --> <afd:msg id="notexistingkey" key="sample.notexistingkey" p0="parameter works as well.">text here to be treated as default message.{0}</afd:msg><br/> </div></div> <div class="panel panel-default"><div class="panel-body"> <!-- simply specify parameters on tag --> <afd:msg id="peoplecount" key="sample.peoplecount" p0="4">dummy text</afd:msg><br/> <afd:msg id="peoplecount" key="sample.peoplecount" p0="7" locale="ja_JP">dummy text</afd:msg><br/> </div></div> <div class="panel panel-default"><div class="panel-body"> <!-- the parameter can be rendered by snippet too --> <afd:snippet render="ComplicatedSnippet:setMsgParam"> <afd:msg id="peoplecount" key="sample.peoplecount" p0="4">dummy text</afd:msg><br/> <afd:msg id="peoplecount" key="sample.peoplecount" p0="7" locale="ja_JP">dummy text</afd:msg><br/> </afd:snippet> </div></div> <div class="panel panel-default"><div class="panel-body"> <!-- attribute started with "@" will be treated as a key --> <afd:msg id="weatherreport" key="sample.weatherreport" @p0="sample.weatherreport.sunny">天気</afd:msg><br/> <afd:msg id="weatherreport" key="sample.weatherreport" @p0="sample.weatherreport.sunny" locale="ja_JP">天気</afd:msg><br/> </div></div> <div class="panel panel-default"><div class="panel-body"> <!-- attribute started with "#" will be treated as a sub key of current key, thus sample.weatherreport.sunny will be searched --> <afd:msg id="weatherreport" key="sample.weatherreport" #p0="rain">天気</afd:msg><br/> <afd:msg id="weatherreport" key="sample.weatherreport" #p0="rain" locale="ja_JP">天気</afd:msg><br/> </div></div> <div class="panel panel-default"><div class="panel-body"> <!-- treat message as text --> <afd:msg key="sample.textUrl"></afd:msg><br/> <!-- treat message as html --> <afd:msg key="sample.htmlUrl"></afd:msg><br/> <!-- treat message as text even it begins with html: --> <afd:msg key="sample.escapedUrl"></afd:msg><br/> </div></div> </article> </section>
public Renderer setMsgParam() { Renderer render = Renderer.create(); render.add("#peoplecount", "p0", 15); return render; }
There are something need to be explained:
default message
As commented in the source, the inner content of "afd:msg" will be treated as default message in case of the message of specified key cannot be found. Note that the default message will be formatted by specified parameters too.
This mechanism can also be used as a simple text replacing mechanism in the html template file in case of necessity.
parameter name
If the configured I18nMessageHelper is MappedParamI18nMessageHelper, the attribute names of current "afd:msg" element will be treated as parameter names directly. And if the configured I18nMessageHelper is OrderedParamI18nMessageHelper which is the default one, the attribute names started with single "p" and following with 0-started numbers will be treated as the values of parameter value array.
recursive parameter
The attributes which name started with "@" or "#" will be treated as recursive message's key. The different between "@" and "#" is that the "@" will be treated as a complete key but the "#" will be treated as a sub key of current message key.
parameter value
The value of attributes can be specified directly in the html template file, also can be rendered by a snippet as in the above example.
locale
Locale can be specified explicitly by ISO 639 locale string, if not, the default locale decision mechanism will be performed. See Section 15.1.3, “Default locale”.
The built-in template resolver and static resource handler can match the target file name with awareness of locale. The match locale will be decided by the default locale decision mechanism(See Section 15.1.3, “Default locale”). After the locale is decided, for example, for a locale as Locale("fr", "CA", "UNIX") to search a html template file "index.html", the target file will be searched by following order:
index_fr_CA_UNIX.html
index_fr_CA.html
index_fr.html
index.html
For the static resource files such as js, css, jpg, etc. will be searched by the same order as well.