# eXist i18n XQuery Module Documentation

## Introduction

The eXist i18n module provides an easy to use mechanism to internationalize (i18n) any kind of XML document.

## Brief description

Following features are supported by the eXist i18n module

- Text translation
- Parameter substitution within text translations
- Usage of internationalized parameters
- Attribute translation

See the reference and configuration sections to utilize the i18n extension within your application.

## Reference

All i18n tags or attributes use a key to retrieve localized text from the i18n catalogue. If no catalogue is available for a chosen language and there is no default catalogue configured then the 'defaultValue' is used. See the description of the i18n tags / attributes to see where to place the 'defaultValue'.

### Language catalogues

Catalogues are holding the language data and have the following (flat) structure:

    <catalogue xml:lang="de">
    <mys key="Welcome">Willkommen</msg>
    <msg key="Cancel">Abbrechen</msg>
    </catalogue>

The xml:lang attribute on the catalogue tag defines the language for the catalogue. The attribute value should correspond to ISO 639. The catalogue itself is made up of an flat list of msg tags. Each has an attribute 'key' with a unique value to identify the translated text. The translated text itself is placed as node value of the msg node.

### Text translation

    <i18n:text key="uniqueID">Text in default language</i18n:text>

The <i18n:text> tag is used to mark text to be translated. The attribute @key is used to find the respective translation from a specific catalogue. The text value of the <i18n:text> node can be used as default translation and is further displayed if no catalogue for a selected language exists (and no default language is configured).

### Parameter substitution for text

<i18n:translate> provides parameter substitution for internationalized text. The substitution can either be archived by the numerical order of the i18n:param tags or by character keys. Be aware that numerical and character parameter substitution must not be mixed within one i18n:translate tag.

#### Numerical i18n:param substitution

Parameters are referenced with numbers in angle brackets. Be aware that the i18n:param count starts with 1.

    <i18n:translate>
    <i18n:text key="textWithParam">{2} is prerequisite for {1}.(E.W. Dijkstra)</i18n:text>
    <i18n:param>reliability</i18n:param>
    <i18n:param>Simplicity</i18n:param>
    </i18n:translate>

The above example resolves to: 'Simplicity is prerequisite for reliability.(E.W. Dijkstra)

#### Character i18n:param substitution

Using character parameter substitution uses keys instead of the numerical order to substitute parameters. The order of the parameters in the i18n:text tag does not matter.

    <i18n:translate>
    <i18n:text key="textWithParam">{key1} is prerequisite for {key2}.(E.W. Dijkstra)</i18n:text>
    <i18n:param key="key1">Simplicity</i18n:param>
    <i18n:param key="key2">reliability</i18n:param>
    </i18n:translate>

The above example resolves to: 'Simplicity is prerequisite for reliability.(E.W. Dijkstra)

### Translation of parameters

i18n:params can be translated just like i18n:text tags.

    <i18n:translate>
    <i18n:text key="textWithParam">{key1} is prerequisite for reliability.(E.W. Dijkstra)</i18n:text>
    <i18n:param key="key1">
    <i18n:text key="simplicity">Simplicity</i18n:text>
    </i18n:param>
    </i18n:translate>

### Attribute translation

Use i18n(key,defaultValue) to translate attributes where the parameter 'defaultValue' is optional.

    <div attr1="i18n(key1)" attr2="i18n(key2,defaultValue1)"/>

## Configuration

### Automatically process XML

The i18n xquery module is configured via the controller.xql in your application. A typical configuration to process any .html file in an application would look like this:

    xquery version "1.0";

    import module namespace request="http://exist-db.org/xquery/request";
    import module namespace xdb = "http://exist-db.org/xquery/xmldb";

    declare variable $exist:path external;
    declare variable $exist:resource external;

    if (ends-with($exist:resource, ".html")) then
    <dispatch xmlns="http://exist.sourceforge.net/NS/exist">
    <view>
    <forward url="/db/i18n/modules/view.xql"/>
    </view>
    </dispatch>
    else
    <ignore xmlns="http://exist.sourceforge.net/NS/exist">
    <cache-control cache="yes"/>
    </ignore>

### Usage of i18n via XQuery calls

Another variant is to directly call the i18n:process function within the i18n module:

    (:~ i18n.xql:
    : i18n processing on the given set of nodes. Call this function from
    : within other functions to enable recursive processing of i18n tags.
    :
    : @param $nodes - the nodes to process
    : @param $selectedLang - chosen language, controls which i18n catalogue to load
    : @param $pathToCatalogues - path that points to the available i18n catalogues within the eXist database
    : @param $defaultLang - language that is used if no i18n catalogue can be found for the chosen language
    :)
    declare function i18n:process($nodes as node()*,
          $selectedLang as xs:string, $pathToCatalogues as xs:string,
          $defaultLang as xs:string)

The following sample shows how this could be done:

    xquery version "1.0";xquery version "1.0";

    import module namespace i18n = "http://exist-db.org/xquery/i18n" at "/db/i18n/modules/i18n.xql";

    declare option exist:serialize "method=xhtml media-type=text/html";
    (: get some html containing i18n tags :)
    let $content := doc('index.html')/*

    return
    i18n:process($content,'de','/db/i18n/data','es')

## Usage

### Select language

The language to use for internationalization can be chosen in various ways

- via http parameter 'lang', e.q http://exist/index.html?lang=de
- as xquery parameter $selectedLang if the i18n module is called directly
- xml:lang attribute on the root node of the markup to process

### Path to i18n catalogues

The path to the catalogue files can be given as follows:

- via http parameter 'cataloguesPath'
- as xquery parameter $cataloguesPath if the i18n module is called directly
- using the attribute i18n:catalogues on the root node of the processed markup

### Default Language

Chosing a default language (without placing it as inline markup within i18n tags) can be done with:

- via http parameter 'defaultLang'
- as parameter $defaultLang if the i18n module is called directly
- using the attribute i18n:default-lang on the root node of the processed markup