10 Internationalization - Reference Documentation
Authors: Andres Almiray
Version: 1.2.0
10 Internationalization
This chapter describes Internationalization (I18N
) features available to all applications.
10.1 The Messsage Source
Applications have the ability to resolve internationalizable messages by leveraging the behavior exposed bygriffon.core.i18n.MessageSource
which every single griffon.core.GriffonApplication
implements. This interface exposes the following methods:
- String getMessage(String key)
- String getMessage(String key, Locale locale)
- String getMessage(String key, Object[] args)
- String getMessage(String key, Object[] args, Locale locale)
- String getMessage(String key, List args)
- String getMessage(String key, List args, Locale locale)
- String getMessage(String key, Map args)
- String getMessage(String key, Map args, Locale locale)
NoSuchMessageException
if a message could not be resolved given the key sent as argument. The following methods take and additional defaultMessage
parameter that may be used if no configured message is found. If this optional parameter were to be null then the key
is used as the message; in other words, these methods never throw NoSuchMessageException
nor return null
unless the passed in key
is null.
- String getMessage(String key, String defaultMessage)
- String getMessage(String key, String defaultMessage, Locale locale)
- String getMessage(String key, Object[] args, String defaultMessage)
- String getMessage(String key, Object[] args, String defaultMessage, Locale locale)
- String getMessage(String key, List args, String defaultMessage)
- String getMessage(String key, List args, String defaultMessage, Locale locale)
- String getMessage(String key, Map args, String defaultMessage)
- String getMessage(String key, Map args, String defaultMessage, Locale locale)
app.getMessage('some.key')
List
as arguments are meant to be used from Groovy code whereas those that take an Object[]
are meant for Java code; this leads to better idiomatic code as the following examples revealapp.getMessage('groovy.message', ['apples', 'bananas']) app.getMessage("java.message", new Object[]{"unicorns", "rainbows"});
List
versions in Java, like thisimport static java.util.Arrays.asList; … app.getMessage("hybrid.message", asList("bells", "whistles"));
Message Formats
There are three types of message formats supported by default. Additional formats may be supported if the right plugins are installed. Resources may be configured using either properties files or Groovy scripts, please refer to the configuration section.Standard FormatThe first set of message formats are those supported by the JDK'sMessageFormat
facilities. These formats work with all versions of the getMessage()
method that take a List
or an Object[]
as arguments. Examples follow. First the messages stored in a properties filehealthy.proverb = An {0} a day keeps the {1} away yoda.says = {0} is the path to the dark side. {0} leads to {1}. {1} leads to {2}. {2} leads to suffering.
// Groovy String quote = app.getMessage('healthy.proverb', ['apple', 'doctor']) assert quote == 'An apple a day keeps the doctor away' // Java String quote = app.getMessage("yoday.says", new Object[]{"Fear", "Anger", "Hate"}); assertEquals(quote, "Fear is the path to the dark side. Fear leads to Anger. Anger leads to Hate. Hate leads to suffering");
MessageFormat
) and can only be resolved by Griffon. This format uses symbols instead of numbers as placeholders for arguments. Thus the previous messages can be rewritten as followshealthy.proverb = An {:fruit} a day keeps the {:occupation} away yoda.says = {:foo} is the path to the dark side. {:foo} leads to {:bar}. {:bar} leads to {:foobar}. {:foobar} leads to suffering.
// Groovy String quote = app.getMessage('healthy.proverb', [fruit: 'apple', occupation: 'doctor']) assert quote == 'An apple a day keeps the doctor away // Java import static griffon.util.CollectionUtils.map; String quote = app.getMessage("yoday.says", map().e("foo", "Fear").e("bar", "Anger").e("foobar","Hate")); assertEquals(quote, "Fear is the path to the dark side. Fear leads to Anger. Anger leads to Hate. Hate leads to suffering");
import griffon.util.Environmentwarning.label = { args -> if (Environment.current == Environment.PRODUCTION) { "The application has encountered an error: $args" } else { "Somebody setup us the bomb! $args" } }
10.2 Configuration
Messages may be configured in either properties files or Groovy scripts. Properties files have precedence over Groovy scripts should there be two files that match the same basename. The default configured basename is "messages
", thus the application will search for the following resources in the classpath
- messages.groovy
- messages.properties
Config.groovy
i18n.basenames = ['messages', 'menus', 'labels']
Both properties files and Groovy scripts are subject to the same locale aware loading mechanism described in Runtime Configuration, that is, the following resources will be searched for and loaded for a Locate set to de_CH_Basel
- messages.groovy
- messages.properties
- messages_de.groovy
- messages_de.properties
- messages_de_CH.groovy
- messages_de_CH.properties
- messages_de_CH_Basel.groovy
- messages_de_CH_Basel.properties
griffon-app/i18n
as these files are automatically processed with native2ascii when packaging is executed. The default messages.properties
file is placed in this directory upon creating an application with create-app.
10.3 Injecting Message Source Behavior
Any component may gain the ability to resolve messages through the application's MessageSource. You only need annotate the class withgriffon.transform.MessageSourceAware
and it will automatically gain all methods exposed by MessageSource
.This feature is just a shortcut to avoid reaching for the application instance from objects that do not hold a reference to it.Here's an example of a custom Java bean that's able to resolve messages@griffon.transform.MessageSourceAware
class Bean {
String name
}
class SampleService { String lookupValues(String arg) { Bean bean = new Bean(name: arg) bean.getMessage('some.message.key', [bean.name]) } }