[[i18n]]
= i18n

:Notice: Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements. See the NOTICE file distributed with this work for additional information regarding copyright ownership. The ASF licenses this file to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at. http://www.apache.org/licenses/LICENSE-2.0 . Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR  CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
:page-partial:


Apache Isis' support for internationlization (i18n) allows every element of the domain model (the class names, property names, action names, parameter names and so forth) to be translated.

It also supports translations of messages raised imperatively, by which we mean as the result of a call to `title()` to obtain an object's title, or messages resulting from any business rule violations (eg xref:refguide:applib-methods:prefixes.adoc#disable[disable...()] or xref:refguide:applib-methods:prefixes.adoc#validate[validate...()], and so on.

The xref:vw:ROOT:about.adoc[Web UI (Wicket viewer)] (that is, its labels and messages) is also internationalized using the same mechanism.
If no translations are available, then the Wicket viewer falls back to using Wicket resource bundles.

Isis does not translate the values of your domain objects, though.
So, if you have a domain concept such as `Country` whose name is intended to be localized according to the current user, you will need to model this yourself.

== Implementation Approach

Most Java frameworks tackle i18n by using Java's own `ResourceBundle` API.
However, there are some serious drawbacks in this approach, including:

* if a string appears more than once (eg "name" or "description") then it must be translated everywhere it appears in every resource bundle file
* there is no support for plural forms (see this link:http://stackoverflow.com/questions/14326653/java-internationalization-i18n-with-proper-plurals/14327683#14327683[SO answer])
* there is no tooling support for translators

Apache Isis therefore takes a different approach, drawing inspiration from GNU's https://www.gnu.org/software/gettext/manual/index.html[gettext] API and specifically its `.pot` and `.po` files.
These are intended to be used as follows:

* the `.pot` (portable object template) file holds the message text to be translated
* this file is translated into multiple `.po` (portable object) files, one per supported locale
* these `.po` files are renamed according to their locale, and placed into the 'appropriate' location to be picked up by the runtime.
The name of each `.po` resolved in a very similar way to resource bundles.

The format of the `.pot` and `.po` files is identical; the only difference is that the `.po` file has translations for each of the message strings.
These message strings can also have singular and plural forms.

[IMPORTANT]
====
Although Apache Isis' implementation is modelled after GNU's API, it does _not_ use any GNU software.
This is for two reasons: (a) to simplify the toolchain/developer experience, and (b) because GNU software is usually GPL, which would be incompatible with the Apache license.
====

This design tackles all the issues of ``ResourceBundle``s:

* the `.po` message format is such that any given message text to translate need only be translated once, even if it appears in multiple places in the application (eg "Name")
* the `.po` message format includes translations for (optional) plural form as well as singular form
* there are lots of freely available editors https://www.google.co.uk/search?q=.po+file+editor[to be found], many summarized on this https://www.drupal.org/node/11131[Drupal.org] webpage. +
+
In fact, there are also online communities/platforms of translators to assist with translating files.
One such is https://crowdin.com/[crowdin] (nb: this link does not imply endorsement).

In Apache Isis' implementation, if the translation is missing from the `.po` file then the original message text from the `.pot` file will be returned.
In fact, it isn't even necessary for there to be any `.po` files; `.po` translations can be added piecemeal as the need arises.

== API

The main API is the `TranslationService`:

* xref:refguide:applib:index/services/i18n/TranslationService.adoc[leveloffset=+2]

The `translate(...)` methods are closely modelled on GNU's gettext API.
The first version is used when no translation is required, the second is when both a singular and plural form will be required, with the `num` parameter being used to select which is returned.
In both cases the `context` parameter provides some contextual information for the translator; this generally corresponds to the class member.

The mode meanwhile determines the behaviour of the service.
More on this below.

