消息包
本地化的最常见工作就是根据用户所在的语言环境提供本地化消息。因此,必须从代码中将消息抽取出来,并放置到特殊的属性文件内,一种语言建立一个文件。这样的一组文件被称为 消息包。
除了消息之外,消息包还可以包含 本地化数据格式字符串。
项目中默认的消息包由一组 messages_<language>.properties
文件组成,位于 src/main/resources
目录下的根包目录内。
消息包文件必须是 UTF-8 编码。 |
配置语言环境
当使用 Studio 创建新项目时,可以在项目创建向导中的 Locales 字段配置支持的语言环境。该字段支持选择语言及其编码。
Studio 将语言编码列表写入 jmix.core.available-locales 应用程序属性,将语言名称用 localeDisplayName.<language>
键值写入对应的 messages_<language>.properties
文件中。之后可以通过 Studio Project Properties 窗口的 Locales 标签页修改,或者手动修改。
例如,如果为应用程序定义了两种语言:English(en)
和 Deutsch (de)
,项目中则会有如下文件结构(假设根包是 com.company.demo
):
src/main/resources/
com/company/demo/
messages_en.properties
messages_de.properties
application.properties
文件有如下内容:
localeDisplayName.de=Deutsch
jmix.core.available-locales = en,de
创建消息
分组和键值
通常,应用程序只包含单一消息包。即使一个简单的应用程序也可能包含大量的消息,因此我们推荐属性键值由两部分组成:分组和消息键值,用 /
分隔。这样可以对相关的消息进行分组避免命名冲突。下面例子中,com.company.demo.view.main
是分组,applicationTitle.text
是消息键值:
com.company.demo.view.main/applicationTitle.text=Demo App
也可以定义无分组的消息,示例:
messageWithoutGroup = Message without a group
数据模型本地化
Jmix 引入了一些关于数据模型元素本地化的约定:实体、属性名称和枚举值。这些约定支持框架在 UI 组件中显示实体和枚举时方便查找本地化名称。
实体名称使用 <package>/<class>
格式本地化,属性名称使用 <package>/<class>.<attribute>
格式。示例:
# entity name
com.company.demo.entity/User=User
# attribute names
com.company.demo.entity/User.id=ID
com.company.demo.entity/User.username=Username
com.company.demo.entity/User.firstName=First name
com.company.demo.entity/User.lastName=Last name
com.company.demo.entity/User.password=Password
com.company.demo.entity/User.email=Email
枚举类使用 <package>/<class>
格式本地化,枚举值使用 <package>/<class>.<value>
格式。示例:
# enumeration name
com.company.demo.entity/Status=Status
# enumeration values
com.company.demo.entity/Status.ACTIVE=Active
com.company.demo.entity/Status.INACTIVE=Inactive
com.company.demo.entity/Status.SUSPENDED=Suspended
用 Studio 可视化设计器可以很容易创建数据模型元素的本地化名称。点击元素名称旁边的 🌐(地球)按钮,然后在 Localized Message 对话框中分别输入本地化值即可。 |
添加消息包
在带有很多消息的大应用程序中,你可以定义附加消息包以保持合理的属性文件大小:
-
在
src/main/resources
下面的任意文件夹创建一组任意命名的属性文件。下面例子中,我们在主消息包的同级目录中创建了一组additional_messages
文件:src/main/resources/com/company/demo/ additional_messages_en.properties additional_messages_de.properties messages_en.properties messages_de.properties
-
在附加消息包中按照主消息包一样的格式写入本地化消息。
-
为应用程序类添加
@MessageSourceBasenames
注解,并设置附加包的路径和名称:@SpringBootApplication @MessageSourceBasenames({"com/company/demo/additional_messages"}) public class DemoApplication implements AppShellConfigurator {
所有消息包中的键值加载至同一个列表中,因此需要保证所有包中键值的唯一性。 |
使用消息
在 Java 中使用
Messages 接口
使用 Messages
bean 从消息包获取本地化消息。最常见用法是调用 getMessage()
方法,为其提供消息分组和消息键值。方法返回当前用户语言环境的消息;如果无此消息,则返回传入的键值本身。
下面示例中,我们在消息包中定义了一条消息,并使用 Messages
bean 的不同方法获取:
com.company.demo/someNotification = Something has happened
String message1 = messages.getMessage("com.company.demo/someNotification"); (1)
String message2 = messages.getMessage("com.company.demo", "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
接口可以在 UI 视图控制器中使用。该接口提供获取与视图关联的单一消息组内本地化消息的方法。功能与 Messages bean 是有差别的,MessageBundle
直接获取与当前视图类相关的消息组,因此无需传递组键值或类名。
如需使用 MessageBundle
,将其注入控制器:
@ViewComponent
private MessageBundle messageBundle;
然后可以通过键值获取消息:
String someMessage = messageBundle.getMessage("someMessage");
消息的组名从视图类的包名推断,与使用 Messages.getMessage(getClass(), "someMessage")
类似。
可以使用下面描述的 messagesGroup
XML 属性定义任意消息组,也可以使用 setMessageGroup()
方法在控制器中设置:
messageBundle.setMessageGroup("some.group");
MessageBundle
的 formatMessage()
方法通过键键值检索本地化消息,然后使用消息来格式化输入参数。格式是根据 String.format()
方法规则定义的。例如:
com.company.demo.view.user/userInfo=User name: %s
String formattedMessage = messageBundle.formatMessage("userInfo", user.getUsername());
在 XML 描述中使用
Jmix UI 视图描述和菜单配置文件都能识别 msg://
前缀并从消息包加载消息。
我们通过示例看看使用 msg://
的不同情况。
-
消息分组通过视图的包名推断。
例如,如果定义了
com.company.demo.view.user
分组的消息:messages_en.propertiescom.company.demo.view.user/someMessage = Some message
在
com.company.demo.view.user
包内的视图描述文件中可以直接指定消息键值获取消息,而无需指定分组:com/company/demo/view/user/user-list-view.xml<span text="msg://someMessage"/>
-
获取任意分组内的消息。
通过在
msg://
后指定分组和键值,可以从其他视图获取上面示例中的消息,示例:com/company/demo/view/main/main-view.xml<span text="msg://com.company.demo.view.user/someMessage"/>
视图级别还可以使用
messagesGroup
属性设置任意消息包,这样的话,所有消息都默认从设置的包中获取:com/company/demo/view/sample/sample-view.xml<view xmlns="http://jmix.io/schema/flowui/view" messagesGroup="some.common.messages" title="msg://sampleView.title">
-
获取无分组的消息。
如需获取无分组的消息,可以在前缀中使用三个斜杠
msg:///
,然后直接跟消息键值。例如,定义消息:
messageWithoutGroup = Message without a group
视图控制器中可这样获取:
<span text="msg:///messageWithoutGroup"/>