Localization

Every label the components show comes from the add-on’s message bundle: the message input’s placeholder, the accessible names of its buttons, the error banner and its Retry, the copy and wrap actions of a code block, the Show more toggle of a long message. There are two ways to change them, and they compose.

Changing Every Chat

The add-on’s keys are grouped by component:

Key family Covers

aiChat.i18n.*

The chat’s own announcements of the generation lifecycle, read to screen readers.

aiMessageInput.i18n.*

The message input: placeholder, send, stop, attach, and the messages shown on a rejected file.

aiMessageList.i18n.*

The message list: error banner, retry, scroll-to-bottom, copy, and the collapse toggle.

aiCodeBlock.i18n.*

A code block: copy, copied, and the two wrap labels.

Redefine any of them in the application’s own message bundle, and every component in the application follows:

aiChat.i18n.generating=Generating the answer
aiMessageInput.i18n.send=Send the message

This is also how the components are translated: define the keys in the message bundle for each locale, as for any other Jmix message.

Changing One Chat

A nested i18n element re-words a single instance. On aiChat it mirrors the component tree: attributes on the element itself reach the chat, and nested messageInput, messageList, and codeBlock elements reach the parts it composes:

XML
<aichat:aiChat id="chat" width="100%" height="100%">
    <aichat:i18n generating="msg://chat.generating"
                 failed="msg://chat.failed">
        <aichat:messageInput placeholder="msg://chat.placeholder"
                             send="msg://chat.send"/>
        <aichat:messageList retry="msg://chat.retry"
                            showMore="msg://chat.showMore">
            <aichat:codeBlock copy="msg://chat.codeCopy"
                              wrapOn="msg://chat.codeWrapOn"/>
        </aichat:messageList>
    </aichat:i18n>
</aichat:aiChat>
Message bundle
com.company.demo.view.localization/chat.generating=Working on it
com.company.demo.view.localization/chat.failed=That did not work
com.company.demo.view.localization/chat.placeholder=Ask about this ticket
com.company.demo.view.localization/chat.send=Send the question
com.company.demo.view.localization/chat.retry=Try again
com.company.demo.view.localization/chat.showMore=Read the whole question
com.company.demo.view.localization/chat.codeCopy=Copy this snippet
com.company.demo.view.localization/chat.codeWrapOn=Wrap the lines

The same elements are available on the components themselves when they are used standalone. See aiMessageInput, aiMessageList, and aiCodeBlock.

Precedence

The two mechanisms layer, with the more specific winning:

  1. The add-on’s own message bundle supplies every label.

  2. A key redefined in the application’s message bundle replaces it everywhere.

  3. An attribute on a nested i18n element replaces it for that one instance.

An element overrides rather than replaces: a label you do not declare keeps the value from the level below, and an empty i18n element changes nothing. So a chat that declares no i18n at all still shows an application-wide override, and a chat that declares one still shows the application’s wording for every label it does not mention.