Абстракция, которая, вероятно, здесь полезна, - MessageSource
. В Spring Framework он обычно используется для разрешения сообщений в пакете ресурсов (файл свойств), но вы можете легко реализовать вариант с резервной копией базы данных, возможно, вместо этого используйте JDB C, чтобы избежать накладных расходов и интенсивного кэширования значений.
Если у вас есть это, вы можете использовать MessageSourceAccessor
, например, в коде вашего контроллера, чтобы подготовить модель, которая будет отображаться для имеющегося объекта домена, который будет знать, какие значения i18nize, найти переведенное значение и поместить его в модель. Абстракция …Accessor
выбирает локаль из всех настроенных LocaleResolver
. IIR C, в Spring Boot это AcceptHeaderLocaleResolver
, т.е. значение, указанное в заголовке HTTP-запроса Accept-Language
, определяет, какой язык будет выбран.
Если вы хотите полностью автоматизировать это, вы можете захотеть подключите ваш механизм сериализации, чтобы сделать перевод прозрачным для вас. Джексон позволяет настроить сериализаторы так, чтобы они могли использовать MessageSourceAccessor
для автоматического перевода всех полей, снабженных определенной аннотацией.
@Retention(RetentionPolicy.RUNTIME)
@interface JsonInternationalized {}
@RequiredArgsConstructor
class I18nModule extends SimpleModule {
private final MessageSource messageSource;
@Override
public void setupModule(SetupContext context) {
MessageSourceAccessor accessor = new MessageSourceAccessor(messageSource);
InternationalizedSerializer serializer = new InternationalizedSerializer(accessor);
context.addBeanSerializerModifier(new InternationalizingBeanSerializerModifier(serializer));
}
@RequiredArgsConstructor
static class InternationalizingBeanSerializerModifier extends BeanSerializerModifier {
private final InternationalizedSerializer serializer;
@Override
public List<BeanPropertyWriter> changeProperties(SerializationConfig config, BeanDescription beanDesc,
List<BeanPropertyWriter> beanProperties) {
for (BeanPropertyWriter writer : beanProperties) {
if (writer.getAnnotation(JsonInternationalized.class) != null) {
writer.assignSerializer(serializer);
}
}
return beanProperties;
}
}
@RequiredArgsConstructor
static class InternationalizedSerializer extends ToStringSerializer {
private static final long serialVersionUID = -2391442803792997283L;
private final MessageSourceAccessor accessor;
@Override
public void serialize(Object value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(accessor.getMessage(value.toString()));
}
}
}
Вот важные аспекты:
- Мы определяем аннотацию для запуска i18n.
I18nModule
регистрирует BeanSerializerModifier
, который проверяет авторов на наличие свойств бина, аннотированных указанной аннотацией, и регистрирует пользовательский сериализатор для тех свойств, которые разрешают свойство через MessageSource
передано в модуль.
В приложении Spring Boot вы можете заставить этот модуль работать, просто зарегистрировав его как Spring bean в классе конфигурации:
@Bean
I18nModule i18nModule(MessageSource messageSource) {
return new I18nModule(messageSource);
}
Как видите, это требует некоторой церемонии. Я верну это команде, чтобы посмотреть, сможем ли мы немного улучшить нестандартный опыт.