我想在我的 Spring Boot 应用程序上实现本地化。基于消息束的本地化工作正常。但我需要根据我的主表数据从数据库读取区域设置消息来实现相同的功能。实现这一点的最佳实践是什么。我想通过对现有实体类进行最小的更改来实现此解决方案。
要从数据库读取消息,您必须实现自定义MessageSource。为此,必须实现 MessageSourceInterface。
有了数据库,它应该看起来像这样。
我的数据库消息源
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.lang.Nullable;
import java.text.MessageFormat;
import java.util.Locale;
public class MyDatabaseMessageSource implements MessageSource {
MyRepository myRepository;
public MyDatabaseMessageSource(MyRepository myRepository) {
this.myRepository = myRepository;
}
@Override
@Nullable
public String getMessage(String code, Object[] args, String defaultMessage, Locale locale) {
String message = this.myRepository.findTranslation(code, locale);
if (message != null) {
if (args != null && args.length > 0) {
message = new MessageFormat(message).format(args);
}
return message;
}
return defaultMessage;
}
@Override
public String getMessage(String code, Object[] args, Locale locale) throws NoSuchMessageException {
String message = this.myRepository.findTranslation(code, locale);
if (message != null) {
if (args != null && args.length > 0) {
message = new MessageFormat(message).format(args);
}
return message;
}
throw new NoSuchMessageException(code, locale);
}
@Override
public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
String message = this.myRepository.findTranslation(code, locale);
if (message != null) {
return message;
}
throw new NoSuchMessageException(code, locale);
}
}
消息源配置
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
@Configuration
public class MessageSourceConfig implements WebMvcConfigurer {
@Autowired MyRepository myRepository;
@Bean("messageSource")
public MessageSource messageSource() {
return new MyDatabaseMessageSource(this.myRepository);
}
}
更好的方法是使用
AbstractMessageSource
并实施 resolveCode()
。重要提示:如果使用 AbstractMessageSource,还必须注意缓存,否则每次调用 resolveCode()
时都会访问数据库。
我的数据库消息源
import org.springframework.context.support.AbstractMessageSource;
import java.text.MessageFormat;
import java.util.Locale;
public class MyDatabaseMessageSource extends AbstractMessageSource {
MyRepository myRepository;
public MyDatabaseMessageSource(MyRepository myRepository) {
this.myRepository = myRepository;
}
@Override
protected MessageFormat resolveCode(String code, Locale locale) {
String value = this.myRepository.findTranslation(code, locale);
if (value != null) {
return new MessageFormat(value, locale);
}
return null;
}
}
在我看来,MessageSource 对于按区域设置获取员工列表没有用。
了解 MessageSource 是一个 API (MessageSourceInterface),可以使用代码和区域设置选择文本(例如翻译),这一点很重要。是否使用 MessageSource 实现中的代码和/或区域设置来选择字符串取决于您。如果您查看 MessageSource 接口,您会发现 getMessage() 返回一个 String,而不是对象列表。
Validation 和 Thymeleaf 等组件使用 MessageSource 来选择文本。您定义代码和可选参数或/和 DefaultMessage。
如果不支持区域设置,您可能还需要在 MessageSource 实现中实现回退。
组件设置区域设置。
[组件] <->[消息源]<->[数据源]
百里香叶
<h1 th:text="#{home_headline}"/>
您也可以直接使用MessageSource。
@Autowired MessageSource messageSource;
String methodeName() {
return this.messageSource.getMessage("home_headline", null, null, Locale.forLanguageTag("en"));
}