[[i18n]]
=== Internationalization

The internationalization architecture of the Holon platform relies upon the <<LocalizationContext>> interface, which is the main entry point for the localization of messages, numbers and date/time elements.

==== Localizable messages

A _localizable_ message is represented using the following attributes:

* A *default* message: The default message to use if the localized message is not available or a localization provider is not available.
* A localization *message code*: The symbolic message code to use as identifier to provide message localizations.
* Optional message *arguments*: A set of arguments to be used to replace conventional placeholders in the message String with the actual values at message localization time.

The link:{apidir}/com/holonplatform/core/i18n/Localizable.html[Localizable^] interface is available to represent a localizable message.

[source, java]
.Building a Localizable
----
include::{examplesdir}/com/holonplatform/core/examples/ExampleI18n.java[tag=localizable,indent=0]
----
<1> Build a `Localizable` with a _defaultMessage_ and a message localization code
<2> Build a `Localizable` using a localization argument too

[[i18n.caption]]
==== `@Caption` annotation

The link:{apidir}/com/holonplatform/core/i18n/Caption.html[Caption^] annotation can be used to provide the localizable message to use as the _caption_ (i.e. the short description or explanatory label of an element) of an element.

The annotation attributes are:

* `value`: The _default_ message to use as a caption
* `messageCode`: The symbolic message code to use to provide message translations

The `@Caption` annotation support must be declared and documented by the classes/elements which actually support it.

TIP: For example, the default <<StringValuePresenter>> supports the `@Caption` annotation for `enum` values presentation.

[[i18n.MessageProvider]]
==== Message providers

To perform actual messages localization the link:{apidir}/com/holonplatform/core/i18n/MessageProvider.html[MessageProvider^] API interface is used. A `MessageProvider` provides a message translation for a specified message localization identifier and a `Locale` representing the language/country for which the translation is required.

The Holon platform makes available a default `MessageProvider`, which uses _properties_ files as message localization containers. It can be created using the `fromProperties(String... basenames)` static method:

[source, java]
----
include::{examplesdir}/com/holonplatform/core/examples/ExampleI18n.java[tag=pmp,indent=0]
----
<1> Build a `MessageProvider` which uses _properties_ files with `messages` as base name
<2> Build a `MessageProvider` which uses _properties_ files with `messages` as base name in the `i18n` folder and set `UTF-8` as encoding

Properties file names are resolved using the configured _basenames_ as prefix. This prefix can be followed by the  `Locale` language, country and variant codes, separated by an underscore (`_`) character. The files must have the `.properties` extension.

The _basenames_ follow the `java.util.ResourceBundle` conventions: essentially, a fully-qualified classpath location. If the base name doesn't contain a package qualifier, it will be resolved from the classpath root. Note that the JDK's standard `ResourceBundle` treats dots as package separators: this means that `test.messages` is equivalent to `test/messages` as folder structure.

The `Locale` attributes are used to build a fallback message localization resolution chain, starting from the most qualified `Locale` definition and matched against the `Locale` for which the message localization is requested.

As an example, suppose to have a `messages` folder under the classpath root containing the following files:

* *messages_en_US_var.properties*: This file will be used for a `Locale` with `en` as language, `US` as country and `var` as variant
* *messages_en_US.properties*: This file will be used for a `Locale` with `en` as language, `US` as country and no variant
* *messages_en.properties*: This file will be used for a `Locale` with `en` as language and a country different from `US`
* *messages_it.properties*: This file will be used for a `Locale` with `it` as language, ignoring country or variant
* *messages.properties*: This is the default file to use as fallback if no other match is found for a `Locale`

A message localization properties file simply contains the list of the available localizations (translations), 
organized by message localization code. For example the `test.msg=translation` line declares `translation` as the localization of the `test.msg` message code.

[[LocalizationContext]]
==== LocalizationContext

The link:{apidir}/com/holonplatform/core/i18n/LocalizationContext.html[LocalizationContext^] interface is the main entry point for localization of messages, numbers and date/time elements.

==== Building a LocalizationContext

The `LocalizationContext` interface provides a fluent builder to create `LocalizationContext` instances:

[source, java]
----
include::{examplesdir}/com/holonplatform/core/examples/ExampleI18n.java[tag=ctxbuild,indent=0]
----
<1> Add a `MessageProvider` using _properties_ files located under the `messages` folder (see <<i18n.MessageProvider>>)
<2> Add a `MessageProvider` using _properties_ files located under the `messages2` folder (see <<i18n.MessageProvider>>)
<3> Use the `$` character as message localization arguments placeholder (replacing the default `&` character)
<4> Use the _medium_ format as default date format style
<5> Use the _full_ format as default time format style
<6> Use the `boolean.true` message code to localize the `true` boolean values
<7> Use the `boolean.false` message code to localize the `false` boolean values
<8> Initially Localize the LocalizationContext using the default system `Locale`
<9> Initially Localize the LocalizationContext using the `US` `Locale`

==== Obtaining a LocalizationContext

If the `LocalizationContext` is registered as a <<Context>> resource using the default context resource key ( i.e. the fully qualified `LocalizationContext` class name), it can be obtained by using the convenience `getCurrent()` static method.

The `require()` static method can be used to obtain the current `LocalizationContext` or throwing an exception if it's not available as context resource.

Furthermore, the `requireLocalized()` static method acts the same as the `require()` method, but additionally requires that the current `LocalizationContext` is localized.

==== Localizing a LocalizationContext

Before using a `LocalizationContext`, you must ensure that it is _localized_, i.e. bound to a specific `Locale`. This will be the `Locale` used for the localization of messages, numbers and date/time elements. To _localize_ a `LocalizationContext`, the `localize(...)` method con be used, providing the `Locale` instance.

To fine tune the context localization, a link:{apidir}/com/holonplatform/core/i18n/Localization.html[Localization^] object can be used instead of a simple `Locale`.

A `Localization` is bound to a `Locale` and allows to setup:

* A _parent_ `Localization`, i.e. the Localization to use as fallback when a localization operation cannot be successfully performed using the current localization, for example because a message translation is not available. This allows the creation of a `Localization` hierarchy;
* The default decimal positions to use to format a localized numeric decimal value, if decimal positions are not explicitly given;
* The default date format style
* The default time format style

[source, java]
.LocalizationContext localization
----
include::{examplesdir}/com/holonplatform/core/examples/ExampleI18n.java[tag=localize,indent=0]
----
<1> Require a `LocalizationContext` to be available as context resource 
<2> Localize the `LocalizationContext` using the `US` `Locale`
<3> Check the `LocalizationContext` is localized
<4> Localize the `LocalizationContext` using a `Localization`

[[LocalizationChangeListener]]
==== Listening to localization changes

The link:{apidir}/com/holonplatform/core/i18n/LocalizationContext.LocalizationChangeListener.html[LocalizationChangeListener^] interface can be used to listen to context localization changes.

The `LocalizationContext` localization, and therefore the current context `Locale`, changes when the `localize(...)` method is invoked.

The `addLocalizationChangeListener(LocalizationChangeListener listener)` method, or the corresponding `withLocalizationChangeListener(LocalizationChangeListener listener)` builder method, can be used to be notified of localization changes.

The `LocalizationChangeEvent` provides information about the `LocalizationContext` from which the localization change was triggered and the new `Locale` of the context, if available.

==== Using the LocalizationContext

The `LocalizationContext` API provides several methods to perform localizations of messages, temporal values and numbers.

* For numbers formatting, the `NumberFormatFeature` enumeration can be used to tune the format style
* For date and times formatting, the `TemporalFormat` enumeration can be used to specify the format style 

The Java 8 `java.time.*` API is fully supported by the `LocalizationContext` API.

[source, java]
----
include::{examplesdir}/com/holonplatform/core/examples/ExampleI18n.java[tag=localization,indent=0]
----
<1> Print the current LocalizationContext `Locale`
<2> Localize a message providing the message localization code and the default message to use if no translation is available for the current LocalizationContext `Locale`
<3> Localize a message using a `Localizable`
<4> Format a number using default styles and localization settings
<5> Format a number using the _percent_ style
<6> Format the given number using 2 decimal places
<7> Get the LocalizationContext `NumberFormat` for `Integer` numbers localization
<8> Format a `Date` considering the date value of `DATE` type (without time)
<9> Format a `Date` considering the date value of `DATE_TIME` type (including time) and using the `LONG` style for both date and time parts
<10> Format a `LocalDate` with default style
<11> Format a `LocalDateTime` using `FULL` style for the date part and `SHORT` style for the time part
<12> Get the `DateFormat` to use to format `Date`s without time
<13> Get the `DateTimeFormatter` to use to format temporals with date and time

==== MissingMessageLocalizationListener

One or more link:{apidir}/com/holonplatform/core/i18n/LocalizationContext.MissingMessageLocalizationListener.html[MissingMessageLocalizationListener^] can be registered to a `LocalizationContext` to be notified when a message localization is missing from any of the available `MessageProvider`.

The `MissingMessageLocalizationListener` provides the localization message code for which the localization was requested, in addition to the `Locale` and the optionally provided default message.

The `withMissingMessageLocalizationListener(...)` method of the `LocalizationContext` builder can be used to register a `MissingMessageLocalizationListener`.

[source, java]
----
include::{examplesdir}/com/holonplatform/core/examples/ExampleI18n.java[tag=missing,indent=0]
----
<1> Add a `MissingMessageLocalizationListener` to the `LocalizationContext` which logs missing message localizations
