自定义 Spring Boot 启动器:如何向 MessageSource 贡献 i18n 消息?

我正在编写一个自定义 Spring Boot 启动器,其他开发人员将放入他们的应用程序,这个启动器包含开箱即用的控制器和 UI 屏幕.

I'm writing a custom Spring Boot starter that other developers will drop into their applications, and this starter contains out-of-the-box controllers and UI screens.

这些 UI 屏幕是国际化的,并且 i18n 键/值位于一个包文件中:com/foo/wherever/i18n.properties.

These UI screens are internationalized and the i18n keys/values are in a package file: com/foo/wherever/i18n.properties.

我想确保当我的启动器在启动时加载时,这些 i18n.properties 在应用程序的 MessageSource 中自动可用,以便我的 UI 页面正常工作(通过普通 Spring Controller + ViewResolver +查看实现)应用开发者无需自己指定此文件.

I want to ensure that when my starter is loaded at startup, that these i18n.properties are available in the application's MessageSource automatically so that my UI pages work (rendered via normal Spring Controller + ViewResolver + View implementations) without the app developer having to specify this file themselves.

换句话说,他们应该能够将我的启动器添加到他们的运行时类路径中,并且一切都正常工作"而无需配置任何东西.

In other words, they should be able to add my starter to their runtime classpath and everything 'just works' without the need to configure anything.

现在,我发现app开发者可以自己创建src/main/resources/messages.properties文件手动配置application.properties:

Now, I have discovered that the app developer can create their own src/main/resources/messages.properties file and manually configure the additional messages file in application.properties:

spring.messages.basename = messages, com.foo.wherever.i18n

这会奏效.

但是,这需要以下两个条件:

However, this requires both of the following:

  1. 他们必须手动配置 spring.messages.basename 属性 - 这不是自动的.和
  2. 他们的应用程序类路径中必须有自己的 messages.properties 文件.如果 messages.properties 文件不存在,则 spring.messages.basename 甚至不起作用.即使他们不关心 i18n,这仍然是必需的 - 不可取.
  1. They must manually configure the spring.messages.basename property - it's not automatic. and
  2. They must have their own messages.properties file in their application classpath. If a messages.properties file does not exist, spring.messages.basename doesn't even work. Even if they don't care about i18n, this is still required - not desirable.

我想我可以将我的 i18n.properties 文件移动到 starter .jar 中的 classpath:/messages.properties 文件,但这似乎不是一个好的解决方案:如果应用程序开发有自己的 messages.properties 文件,只会读取其中一个,导致消息值丢失.

I suppose I could move my i18n.properties file to a classpath:/messages.properties file in the starter .jar, but that doesn't seem like a good solution: if the app dev has their own messages.properties file only one of them would be read, resulting in missing message values.

好像 Spring Boot MessageSourceAutoConfiguration 应该有一个 CompositeMessageSource 的概念,它迭代一个或多个 MessageSource 实例,这些实例是在 Spring ApplicationContext 中可用(和 Ordered)并且 that 由 DispatcherServlet 使用.这将允许任何初学者通过在其自动配置中声明一个 MessageSource 来为可用消息做出贡献

It seems as if Spring Boot MessageSourceAutoConfiguration should have a concept of a CompositeMessageSource that iterates over one or more MessageSource instances that are available (and Ordered) in the Spring ApplicationContext and that is used by the DispatcherServlet. This would allow any starter to contribute to the available messages just by declaring a MessageSource in their auto config

可以按照我的要求去做吗?对于应用开发者来说,最不干涉"的解决方案是什么?

Is it possible to do what I ask? What is the most 'hands off' solution for the app developer?

推荐答案

可能有点远,但你可以尝试使用 BeanFactoryPostProcessor.

Maybe it is long shot but you can try to use BeanFactoryPostProcessor.

思路如下:

  1. 将messageSource"bean 从应用程序上下文中取出.请注意,如果例如,它可能但不一定是弹簧靴的.开发者希望使用自己的实现,不要使用 spring boot 自动配置.

  1. Take "messageSource" bean out of the application context. Note that it might but does not have to be a spring boot's one if e.g. developer wants to use its own implementation and don't use spring boot autoconfiguration.

将其替换为您自己的实现,该实现尝试解析您的密钥"并将其余的委托给原始消息源.反之亦然,如果您希望开发人员能够覆盖您的翻译(如果原始消息源没有为未知键引发异常,则可能会出现问题).

Replace it with your own implementation that tries to resolve "your keys" and the rest delegate to original message source. Or vice versa if you want to make possible to override your translations by developer (there can be problems if original message source does not throw exception for unknown keys).

但可能有更好的方法来做到这一点.

But there might be a better way to do that.

相关文章