Пакеты сообщений
Наиболее частой задачей локализации является обеспечение сообщений, соответствующих текущему языку пользователя. Для этого сообщения должны быть извлечены из кода и помещены в специальные файлы свойств, по одному файлу на каждый язык. Коллекция таких файлов называется пакетом сообщений.
Помимо сообщений, пакет сообщений также может содержать локализованные строки форматов.
Пакет сообщений проекта по умолчанию представляет собой набор файлов 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
И файлы будут иметь следующее содержимое:
localeDisplayName.en = English
localeDisplayName.ru = Русский
jmix.core.available-locales = en,ru
Создание сообщений
Группа и ключ
Обычно приложение содержит один пакет сообщений. Поскольку количество сообщений даже в простом приложении может быть довольно большим, рекомендуется создавать ключи свойств из двух частей: группы и ключа сообщения, разделенных косой чертой (/
). Это позволяет группировать связанные сообщения и избегать конфликтов имен. В следующем примере localization_demo.ex1.screen.main
- это группа, а application.caption
- это ключ сообщения:
localization_demo.ex1.screen.main/application.caption = Sample application
Также можно определить сообщение без группы, например:
messageWithoutGroup = Message without a group
Локализация модели данных
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
Имя перечисления локализуется в формате <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
Локализованные имена элементов модели данных можно легко создавать в визуальных дизайнерах Studio. Нажмите кнопку 🌐 (глобус) рядом с именем элемента и введите локализованные значения для доступных языков в диалоговом окне Localized Message. |
Дополнительные пакеты
Для того, чтобы придерживаться разумного размера файлов свойств в масштабном приложении с большим количеством сообщений, можно определить дополнительные пакеты:
-
Создайте набор файлов свойств с произвольным именем в любом каталоге раздела
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
-
Запишите локализованные сообщения в дополнительные файлы так же, как и в основном пакете.
-
Добавьте аннотацию
@MessageSourceBasenames
к классу приложения и укажите в ней путь и имя дополнительного пакета:@SpringBootApplication @MessageSourceBasenames({"localization_demo/ex1/additional_messages"}) public class LocalizationExampleApplication {
Сообщения из всех пакетов приложения загружаются в единый список, поэтому ключи свойств должны быть уникальными среди всех пакетов. |
Использование сообщений
В коде Java
Интерфейс Messages
Чтобы получать локализованные сообщения из пакета сообщений, используйте бин Messages
. Наиболее распространенным вариантом использования является вызов его метода getMessage()
и предоставление группы сообщений и ключа. Метод вернет сообщение для текущего пользовательского языка или заданного ключа, если сообщение не найдено.
В следующем примере определим сообщение в пакете сообщений и получим его, используя различные методы бина Messages
:
localization_demo.ex1/someNotification = Something has happened
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)
Все три метода возвращают одно и то же значение: Something has happened
.
1 | Ключ свойства задан целиком. |
2 | Группа и ключ сообщения заданы отдельно. |
3 | Если первым аргументом является Class , метод использует пакет класса как группу. |
Существует также перегруженный метод getMessage()
, принимающий Enum
. Используйте его для извлечения локализованного значения перечисления, например:
String message = messages.getMessage(Status.ACTIVE);
Интерфейс MessageBundle
Интерфейс MessageBundle
доступен в контроллерах экрана. Он предоставляет методы для получения локализованных сообщений одной группы, связанных с контроллером экрана. Он отличается от бина Messages тем, что может неявно получать группу сообщений от контроллера экрана, поэтому нет необходимости передавать ключ группы или имя класса.
Чтобы использовать MessageBundle
, инжектируйте его в контроллер:
@Autowired
private MessageBundle messageBundle;
@Autowired
private Notifications notifications;
Теперь его можно использовать, чтобы получить сообщение по ключу:
String someMessage = messageBundle.getMessage("someMessage");
Группа сообщения выводится из пакета контроллера экрана, как при использовании Messages.getMessage(getClass(), "someMessage")
.
Произвольную группу можно либо определить с помощью XML-атрибута messagesGroup
, описанного ниже, либо задать ее в контроллере с помощью метода setMessageGroup()
:
messageBundle.setMessageGroup("some.group");
Метод formatMessage()
интерфейса MessageBundle
извлекает локализованное сообщение по ключу, а затем использует его для форматирования входных параметров. Формат определяется в соответствии с правилами метода String.format()
. Например:
localization_demo.ex1.screen.user/userInfo=User name: %s
String formattedMessage = messageBundle.formatMessage("userInfo", user.getUsername());
В XML-дескрипторах экранов
Дескрипторы экрана и файлы конфигурации меню UI распознают префикс msg://
в сообщениях и загружают их из пакета сообщений.
Рассмотрим различные варианты использования msg://
с примерами.
-
Группа сообщения выводится из пакета экрана.
Например, если сообщение определено с группой
localization_demo.ex1.screen.user
:messages_en.propertieslocalization_demo.ex1.screen.user/someMessage = Some message
Его можно получить в дескрипторе экрана, расположенном в пакете
localization_demo.ex1.screen.user
, просто указав ключ сообщения без группы:localization_demo/ex1/screen/user/user-browse.xml<label value="msg://someMessage"/>
-
Получение сообщения с произвольной группой.
Сообщение из предыдущего примера можно получить на любом экране, указав группу и ключ после префикса
msg://
, например:localization_demo/ex1/screen/main/main-screen.xml<label value="msg://localization_demo.ex1.screen.user/someMessage"/>
Также можно установить произвольный пакет сообщений на уровне экрана с помощью атрибута
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">
-
Получение сообщения без группы.
Чтобы получить сообщение без группы, следует поставить тройную косую черту в префиксе
msg:///
, за которым следует ключ сообщения.Например, если сообщение определено так:
messageWithoutGroup = Message without a group
То его можно получить в любом дескрипторе экрана следующим образом:
<label value="msg:///messageWithoutGroup"/>