---
title: i18n - développement
---

# Developing a multilingual bot (i18n)

The [Multilingual bot](../user/guides/i18n) page in the user documentation covers the basics of internationalization
(_i18n_) for building bots with Tock: prerequisites, _Locale_, etc.

This page completes the documentation with elements specific to development.

## Prerequisites

To enable _Internationalization_ in Tock, programmatically or not, see [Multilingual bot](../user/guides/i18n).

## Principles

The code does not change once internationalization is activated. For example:

```kotlin
     send("Arrival at {0}", time)
```

is valid whether the module is enabled or not. 

At runtime, however, behavior differs significantly.

If internationalization is enabled, the following operations will be performed:

1. A key will be generated from the text passed in parameter, according to the namespace (the bot creator's organization)
   and the story in which the text is requested. In the case above, this should look like `app_arrivals_Arrival at {0}` where *app* is the namespace and
   *arrivals* is the story's main intent.

2. Tock then checks whether this key is already present in the database.
    * If so, it uses the wording present in the database for the requested language to find the most appropriate translation (the connector or interface type may also be taken into account).
    * If not, a key is created in base with the default label (`"Arrival at {0}"` in our example) used for the current language.
      * If the passed in text is an `I18nLabelValue` object which `defaultI18n` field holds a value for the current language, the latter is used instead

3. This label can then be viewed and modified in the administration interface:

![Internationalisation](../../img/i18n.png "Internationalisation")

## Message Format

The supported format is that of i18n support in java, specifically the one from [MessageFormat](https://docs.oracle.com/javase/10/docs/api/java/text/MessageFormat.html)
in java. This includes support for [ChoiceFormat](https://docs.oracle.com/javase/10/docs/api/java/text/ChoiceFormat.html) :

```kotlin
    send("There {0,choice,0#are no files|1#is one file|1<are {0,number,integer} files}.", 2)  
```

Tock also provides a *by* extension for dates, allowing you to specify a format in the parameters:

```kotlin
    send("Departure at {0}", departureDateTime by timeFormat) 
``` 

## User locale

See [Multilingual bot](../user/guides/i18n).

## Points of attention

Tock's internationalization module is efficient, but certain practices, however intuitive in Kotlin,
should be avoided, or you'll be in for a nasty surprise.

For example, this code works perfectly well with the i18n module deactivated.

```kotlin
send("There are $nb files") //DANGER!
```

but causes problems when activated. A new label will be created for each different value of the *nb* variable!
 
If you need to send "do not translate" responses, use the *BotBus.sendRaw*, *BotBus.endRaw* or *String.raw* methods.

```kotlin
    send("There are $nb files".raw) //CORRECT 
``` 

```kotlin
    send("There are {0} files", nb) //RECOMMENDED FORMAT
```  

* The collision risk between two labels is small as the story's main intent is made part of the key. 
If however you want to avoid any risk, you can use the *i18nKey* method:

```kotlin
    send(i18nKey("my_unique_key", "There are {0} files", nb)) 
```  

### Specifying localizations programmatically

Default values can be defined for several locales in a bot's code:

```kotlin
    send(i18nKey("departure", "Departure at {0}", setOf(I18nLocalizedLabel(Locale.FRENCH, textChat, "Départ à {0}")), nb))
```

By default, these default values will only be used when the key is used for the first time. To overwrite
existing values (including those defined via TOCK Studio) when the `defaultI18n` set is changed,
set the configuration value `tock_i18n_reset_value_on_default_change` to `true` (either as an environment variable,
or as a system property).

## Test internationalization

An example of a test device is available in the
[example bot source code](https://github.com/theopenconversationkit/tock-bot-open-data/blob/master/src/test/kotlin/rule)
It is necessary to extend the [test extension](https://github.com/theopenconversationkit/tock-bot-open-data/blob/master/src/test/kotlin/rule/OpenDataJUnitExtension.kt)
and then specify the [label match](https://github.com/theopenconversationkit/tock-bot-open-data/tree/master/src/test/kotlin/rule/TranslatorEngineMock.kt) to be tested.

All that remains is to indicate the desired locale:

```kotlin

    @Test
    fun `search story asks for departure date WHEN there is a destination and an origin but no departure date in context`() {
        ext.newRequest("Recherche", search, locale = Locale.FRENCH) {
            destination = lille
            origin = paris

            run()

            firstAnswer.assertText("Quand souhaitez-vous partir?")
        }
    }
```  
