diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java index 56d6c5c10ee5..8e803c3ed165 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfiguration.java @@ -16,7 +16,10 @@ package org.springframework.boot.autoconfigure.context; +import java.io.IOException; +import java.io.UncheckedIOException; import java.time.Duration; +import java.util.Properties; import org.springframework.aot.hint.RuntimeHints; import org.springframework.aot.hint.RuntimeHintsRegistrar; @@ -41,6 +44,7 @@ import org.springframework.core.Ordered; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; +import org.springframework.core.io.support.PropertiesLoaderUtils; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.util.CollectionUtils; import org.springframework.util.ConcurrentReferenceHashMap; @@ -81,6 +85,19 @@ public MessageSource messageSource(MessageSourceProperties properties) { } messageSource.setAlwaysUseMessageFormat(properties.isAlwaysUseMessageFormat()); messageSource.setUseCodeAsDefaultMessage(properties.isUseCodeAsDefaultMessage()); + + try { + if (properties.getCommonMessages() != null) { + Properties commonProperties = new Properties(); + for (Resource commonResource : properties.getCommonMessages()) { + PropertiesLoaderUtils.fillProperties(commonProperties, commonResource); + } + messageSource.setCommonMessages(commonProperties); + } + } + catch (IOException ex) { + throw new UncheckedIOException("Failed to load common messages", ex); + } return messageSource; } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java index 33bd1e446104..508be001a38c 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/context/MessageSourceProperties.java @@ -25,6 +25,7 @@ import org.springframework.boot.context.properties.ConfigurationProperties; import org.springframework.boot.convert.DurationUnit; +import org.springframework.core.io.Resource; /** * Configuration properties for Message Source. @@ -44,6 +45,11 @@ public class MessageSourceProperties { */ private List basename = new ArrayList<>(List.of("messages")); + /** + * Comma-separated list of locale-independent common messages. + */ + private List commonMessages; + /** * Message bundles encoding. */ @@ -123,4 +129,12 @@ public void setUseCodeAsDefaultMessage(boolean useCodeAsDefaultMessage) { this.useCodeAsDefaultMessage = useCodeAsDefaultMessage; } + public List getCommonMessages() { + return this.commonMessages; + } + + public void setCommonMessages(List commonMessages) { + this.commonMessages = commonMessages; + } + } diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfigurationTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfigurationTests.java index e30983164136..523a5109743f 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfigurationTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/context/MessageSourceAutoConfigurationTests.java @@ -116,6 +116,14 @@ void testMessageSourceFromPropertySourceAnnotation() { .run((context) -> assertThat(context.getMessage("foo", null, "Foo message", Locale.UK)).isEqualTo("bar")); } + @Test + void testCommonMessages() { + this.contextRunner + .withPropertyValues("spring.messages.basename:test/messages", + "spring.messages.common-messages:test/common-messages") + .run((context) -> assertThat(context.getMessage("hello", null, "Hello!", Locale.UK)).isEqualTo("world")); + } + @Test void testFallbackDefault() { this.contextRunner.withPropertyValues("spring.messages.basename:test/messages") diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/resources/test/common-messages.properties b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/test/common-messages.properties new file mode 100644 index 000000000000..432ea479457a --- /dev/null +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/resources/test/common-messages.properties @@ -0,0 +1 @@ +hello=world