Пакеты сообщений

Наиболее частой задачей локализации является обеспечение сообщений, соответствующих текущему языку пользователя. Для этого сообщения должны быть извлечены из кода и помещены в специальные файлы свойств, по одному файлу на каждый язык. Коллекция таких файлов называется пакетом сообщений.

Помимо сообщений, пакет сообщений также может содержать локализованные строки форматов.

Пакет сообщений проекта по умолчанию представляет собой набор файлов messages_<language>.properties, расположенных в базовом пакете в папке src/main/resources.

Файлы пакетов сообщений должны иметь кодировку UTF-8.

Настройка локалей

При создании нового проекта в Studio вы можете настроить список поддерживаемых языков в поле Locales мастера проекта. Это поле позволяет выбрать код языка и задать его название.

Studio записывает список кодов языков в свойство приложения jmix.core.available-locales, а названия языков - в соответствующие файлы messages_<language>.properties с ключом localeDisplayName.<language>. Позже вы можете отредактировать эти свойства вручную или использовать вкладку Locales окна Project Properties в Studio.

Например, если для приложения определено два языка: en - English и ru - Русский, в проекте будет следующая структура файлов (при условии, что базовым пакетом является localization_demo.ex1):

 src/
    main/
        resources/
            localization_demo/
                ex1/
                    messages_en.properties
                    messages_ru.properties
            application.properties
text

И файлы будут иметь следующее содержимое:

messages_en.properties
localeDisplayName.en = English
properties
messages_ru.properties
localeDisplayName.ru = Русский
properties
application.properties
jmix.core.available-locales = en,ru
properties

Создание сообщений

Группа и ключ

Обычно приложение содержит один пакет сообщений. Поскольку количество сообщений даже в простом приложении может быть довольно большим, рекомендуется создавать ключи свойств из двух частей: группы и ключа сообщения, разделенных косой чертой (/). Это позволяет группировать связанные сообщения и избегать конфликтов имен. В следующем примере localization_demo.ex1.screen.main - это группа, а application.caption - это ключ сообщения:

localization_demo.ex1.screen.main/application.caption = Sample application
properties

Также можно определить сообщение без группы, например:

messageWithoutGroup = Message without a group
properties

Локализация модели данных

Jmix вводит некоторые правила локализации элементов модели данных, таких как имена сущностей и атрибутов, значения перечисления. Это позволяет фреймворку находить локализованные имена при отображении сущностей и перечислений в компонентах UI.

Имя сущности локализуется в формате <package>/<class>, имя атрибута - в формате <package>/<class>.<attribute>. Например:

# entity name
localization_demo.ex1.entity/Customer = Customer
# attribute names
localization_demo.ex1.entity/Customer.id = Id
localization_demo.ex1.entity/Customer.version = Version
localization_demo.ex1.entity/Customer.name = Name
properties

Имя перечисления локализуется в формате <package>/<class>, значение перечисления - в формате <package>/<class>.<value>. Например:

# enumeration name
localization_demo.ex1.entity/Status = Status
# enumeration values
localization_demo.ex1.entity/Status.ACTIVE = Active
localization_demo.ex1.entity/Status.SUSPENDED = Suspended
localization_demo.ex1.entity/Status.INACTIVE = Inactive
properties
Локализованные имена элементов модели данных можно легко создавать в визуальных дизайнерах Studio. Нажмите кнопку 🌐 (глобус) рядом с именем элемента и введите локализованные значения для доступных языков в диалоговом окне Localized Message.

Дополнительные пакеты

Для того, чтобы придерживаться разумного размера файлов свойств в масштабном приложении с большим количеством сообщений, можно определить дополнительные пакеты:

  1. Создайте набор файлов свойств с произвольным именем в любом каталоге раздела src/main/resources. В приведенном ниже примере файлы additional_messages созданы в том же базовом пакете приложения, что и основной пакет сообщений:

     src/
        main/
            resources/
                localization_demo/
                    ex1/
                        additional_messages_en.properties
                        additional_messages_ru.properties
                        messages_en.properties
                        messages_ru.properties
  2. Запишите локализованные сообщения в дополнительные файлы так же, как и в основном пакете.

  3. Добавьте аннотацию @MessageSourceBasenames к классу приложения и укажите в ней путь и имя дополнительного пакета:

    @SpringBootApplication
    @MessageSourceBasenames({"localization_demo/ex1/additional_messages"})
    public class LocalizationExampleApplication {
    java
Сообщения из всех пакетов приложения загружаются в единый список, поэтому ключи свойств должны быть уникальными среди всех пакетов.

Использование сообщений

В коде Java

Интерфейс Messages

Чтобы получать локализованные сообщения из пакета сообщений, используйте бин Messages. Наиболее распространенным вариантом использования является вызов его метода getMessage() и предоставление группы сообщений и ключа. Метод вернет сообщение для текущего пользовательского языка или заданного ключа, если сообщение не найдено.

В следующем примере определим сообщение в пакете сообщений и получим его, используя различные методы бина Messages:

messages_en.properties
localization_demo.ex1/someNotification = Something has happened
properties
String message1 = messages.getMessage("localization_demo.ex1/someNotification"); (1)

String message2 = messages.getMessage("localization_demo.ex1", "someNotification"); (2)

String message3 = messages.getMessage(getClass(), "someNotification"); (3)
java

Все три метода возвращают одно и то же значение: Something has happened.

1 Ключ свойства задан целиком.
2 Группа и ключ сообщения заданы отдельно.
3 Если первым аргументом является Class, метод использует пакет класса как группу.

Существует также перегруженный метод getMessage(), принимающий Enum. Используйте его для извлечения локализованного значения перечисления, например:

String message = messages.getMessage(Status.ACTIVE);
java

Интерфейс MessageBundle

Интерфейс MessageBundle доступен в контроллерах экрана. Он предоставляет методы для получения локализованных сообщений одной группы, связанных с контроллером экрана. Он отличается от бина Messages тем, что может неявно получать группу сообщений от контроллера экрана, поэтому нет необходимости передавать ключ группы или имя класса.

Чтобы использовать MessageBundle, инжектируйте его в контроллер:

@Autowired
private MessageBundle messageBundle;
@Autowired
private Notifications notifications;
java

Теперь его можно использовать, чтобы получить сообщение по ключу:

String someMessage = messageBundle.getMessage("someMessage");
java

Группа сообщения выводится из пакета контроллера экрана, как при использовании Messages.getMessage(getClass(), "someMessage").

Произвольную группу можно либо определить с помощью XML-атрибута messagesGroup, описанного ниже, либо задать ее в контроллере с помощью метода setMessageGroup():

messageBundle.setMessageGroup("some.group");
java

Метод formatMessage() интерфейса MessageBundle извлекает локализованное сообщение по ключу, а затем использует его для форматирования входных параметров. Формат определяется в соответствии с правилами метода String.format(). Например:

messages_en.properties
localization_demo.ex1.screen.user/userInfo=User name: %s
properties
String formattedMessage = messageBundle.formatMessage("userInfo", user.getUsername());
java

В XML-дескрипторах экранов

Дескрипторы экрана и файлы конфигурации меню UI распознают префикс msg:// в сообщениях и загружают их из пакета сообщений.

Рассмотрим различные варианты использования msg:// с примерами.

  1. Группа сообщения выводится из пакета экрана.

    Например, если сообщение определено с группой localization_demo.ex1.screen.user:

    messages_en.properties
    localization_demo.ex1.screen.user/someMessage = Some message
    properties

    Его можно получить в дескрипторе экрана, расположенном в пакете localization_demo.ex1.screen.user, просто указав ключ сообщения без группы:

    localization_demo/ex1/screen/user/user-browse.xml
    <label value="msg://someMessage"/>
    xml
  2. Получение сообщения с произвольной группой.

    Сообщение из предыдущего примера можно получить на любом экране, указав группу и ключ после префикса msg://, например:

    localization_demo/ex1/screen/main/main-screen.xml
    <label value="msg://localization_demo.ex1.screen.user/someMessage"/>
    xml

    Также можно установить произвольный пакет сообщений на уровне экрана с помощью атрибута messagesGroup, чтобы все сообщения извлекались по умолчанию из него:

    localization_demo/ex1/screen/user/user-browse.xml
    <window xmlns="http://jmix.io/schema/ui/window"
            caption="msg://UserBrowse.caption"
            messagesGroup="additional_messages"
            focusComponent="usersTable">
    xml
  3. Получение сообщения без группы.

    Чтобы получить сообщение без группы, следует поставить тройную косую черту в префиксе msg:///, за которым следует ключ сообщения.

    Например, если сообщение определено так:

    messageWithoutGroup = Message without a group
    properties

    То его можно получить в любом дескрипторе экрана следующим образом:

    <label value="msg:///messageWithoutGroup"/>
    xml