Translate Extension
The translate extension adds internationalization capabilities to Jtwig. It heavily relies on the concept of MessageSource
, which will be detailed futher on. This extension is highly configurable and can be optimized for each specific use case.
Translation
The translation engine in Jtwig relies in two distinct concepts:
- Message Source
- Message Decoration
Message Source
Message source mechanism acts as a storage of translations, it allows one to get translations of text to another language, more specifically, to a Locale (check the official Java documentation java.util.Locale
). In Jtwig, if such message source engine is unable to find a requested translation, then it returns the given text.
Key and Free TextThere are two typical approaches used as input for translations. It is either a Key or Free Text. The difference between this two approaches is that keys aren't readable, while the provided free text can be. Because keys are not shown to the end-user (at least they shouldn't), they can incorporate contextual information, like the purpose of the text, for example,
registration.title
orregistration.subtitle
. Free text approaches tend to define the wording directly, for example,Register
orPlease, fill the form below and submit
. Jtwig allows for both approaches, where, for example, properties files can be used with the Key approach and Jtwig XLIFF can be used for the Free Text one.We believe translations should be context independent, that is, locating a given text or identifying the purpose of a given text should not be the purpose of a translation mechanism. However, given the size of some platforms, decouple this two concepts can cause more harm than good.
Message Decoration
Message decoration is the engine which allows one to modify the output of the message source. Jtwig translate extension makes use of a replacement strategy as decorator, allowing users to specify a map of replacements to modify the output, such will be detailed further on.
Configuration
TranslateConfiguration configuration = TranslateConfigurationBuilder
.translateConfiguration()
.withCurrentLocaleSupplier(currentLocaleSupplier)
.withStringLocaleResolver(localeResolver)
.withMessageSourceFactory(messageSourceFactory)
.build();
As mentioned this extension is highly configurable, it allows, as seen in the example above, to specify a LocaleResolver
, a locale supplier and a MessageSourceFactory
.
Locale Supplier
A locale supplier gives Jtwig the capability to retrieve a locale from the context when no locale is specified. By default Jtwig returns a static supplier which returns Locale.ENGLISH
as result.
LocaleResolver
The locale resolver is used to convert a raw String to a java.util.Locale
, by default Jtwig will use the Locale::forLanguageTag
method provided by the Java API.
MessageSourceFactory
The message source factory gets called when Jtwig is initializing the environment, it can be used to preload resources and provide and instance of the MessageSource
interface.
public interface MessageSourceFactory {
MessageSource create (Environment environment);
}
Jtwig provides several implementations of such factory. A singleton factory SingletonMessageSourceFactory
, which only returns the provided MessageSource
instance. A cached factory CachedMessageSourceFactory
allowing to, given a specific cache implementation, put it in front of the generated MessageSource
. Shipped within this extension it's also the PropertiesMessageSourceFactoryBuilder
which give the developer a nice API to create a MessageSourceFactory
to load messages from properties files.
Jtwig XLIFFJtwig XLIFF was developed as a way to support XLIFF defined translation files. It comes with a
XliffMessageSourceFactoryBuilder
quite similar to the properties message source factory.
Function translate
This function has two other alias, they are trans
and message
. It expects one argument at least, with the possibility of receiving two extra, optional, arguments. The first mandatory argument is the text to be translated.
{{ translate('Hello World') }}
If two arguments are provided it can either be a Locale, represented as a string or a map of replacements.
{{ translate('Hello World', 'pt') }}
{{ translate('Hello %name%', {'%name%': 'Jtwig'}) }}
If a map is provided Jtwig will use it as replacements applying to the message returned by the message source. Otherwise, if a string is provided, Jtwig will ask the message source mechanism for a given message with the locale provided.
{{ translate('Hello World', {'%name%': 'Jtwig'}, 'pt') }}
If three arguments are provided, then the map is expected as second argument and a string, representing a locale, the third.
The trans
tag
The trans
tag has the same capabilities as the translate
function allowing to specify the text to translate as body.
{% trans %}Hello world{% endtrans %}
{% trans into 'pt' %}Hello world{% endtrans %}
{% trans with {'%name%': 'Jtwig'} into 'pt' %}Hello %name%{% endtrans %}
{% trans with {'%name%': 'Jtwig'} %}Hello %name%{% endtrans %}
Note that, the text is trimmed before querying the message source for the translation.
Pluralization
Plural handling in Jtwig it's an easy to use and powerfull engine. Project jtwig-pluralization implements the underlying functionality.
The counter (single)
This whole functionality derives from a key piece of information, the counter. Such counter is used to derive the plural form to be used, as so, this pluralization engine only supports one subject. For example, 1 apple and 2 oranges
contains two subjects, therefore, outside of this engine capabilities, such can be address, for example, by splitting the sentence into two.
{0} No apples | {1} One apple | ]1, Inf[ Multiple apples
As per the previous example, the plural form contains three definitions (splitted by the |
character). Definitions start with a range selector, which can either be a single value {<value>}
or an interval of values, note that intervals can be inclusive or exclusive depending on the parentsis used. For example, [1, 2]
, ]0, 3[
, [1, 3[
, ]0, 2]
are all equivalent intervals.
The pluralization engine also trims the selected value. It uses the String:trim
method underneath.
Function translateChoice
This function allows for the same capabilities as the translate
plus choosing the plural form to use after processing the translation.
{{ '{0} No apples | {1} One apple | ]1, Inf[ Multiple apples'
| translateChoice(numberOfApples, "pt") }}
The previous example will look for a pt
translation of the sentence {0} No apples | {1} One apple | ]1, Inf[ Multiple apples
and, only after retrieving the translation, uses the pluralization engine to select, based on the counter (here defined as the variable numberOfApples
), the plural form.
Integration
Integrating Jtwig Translation Extension on your project is quite simple with the help of dependency managers. To check the most recent version, go to bintray.
Gradle
repositories {
jcenter()
}
dependencies {
compile 'org.jtwig:jtwig-translation-extension:1.X'
}
Maven
<repositories>
<repository>
<id>bintray</id>
<url>https://jcenter.bintray.com/</url>
</repository>
</repositories>
<dependencies>
<dependency>
<groupId>org.jtwig</groupId>
<artifactId>jtwig-translation-extension</artifactId>
<version>1.X</version>
</dependency>
</dependencies>
Examples
Check the jtwig-examples project on github for examples using this translation engine.