Я хочу представить веб-сайт пользователям на предпочитаемом ими языке, если веб-сайт поддерживает этот язык.
В Spring Boot я использую следующий bean-компонент для установки языка по умолчанию для клиента:
@Bean
public LocaleResolver localeResolver() {
SessionLocaleResolver localeResolver = new SessionLocaleResolver();
localeResolver.setLocaleAttributeName("user_locale"); // Not strictly needed
localeResolver.setDefaultLocale(Locale.ENGLISH);
return localeResolver;
}
Как я могу изменить его, чтобы взять язык клиента и проверить, есть ли он в списке поддерживаемых языков, например.
private List<Locale> LOCALES = Arrays.asList(new Locale("en"), new Locale("de"), new Locale("fr"), new Locale("sp"), new Locale("it"));
а затем установите локаль, используя что-то вроде
return locales.contains(locale) ? locale : Locale.ENGLISH;
Обратите внимание, что это должно происходить каждый раз при запуске сеанса.
Я имею в виду HTTP-заголовок, способ Spring Boot по умолчанию для обработки локали.
Вы можете получить текущую сохраненную локаль следующим образом:
Locale locale = LocaleContextHolder.getLocale();
localeResolver.setDefaultLocale(locale);
Хорошим способом, если файлы cookie разрешены, было бы реализовать это следующим образом:
@Bean
public LocaleResolver localeResolver() {
CookieLocaleResolver localeResolver = new CookieLocaleResolver("BALLROOM_LANGUAGE");
Locale locale = LocaleContextHolder.getLocale();
localeResolver.setDefaultLocale(locale);
return localeResolver;
}
Нет необходимости проверять, есть ли автоматически запрошенный язык клиента в вашем списке, так как он всегда будет возвращаться к вашей реализации сообщения по умолчанию (которая в вашем случае будет английской).
Один из способов позволить пользователю изменить локаль вручную (что всегда должно быть возможно) — это собственный LocaleController:
@Controller
@RequestMapping("/locale")
public class LocaleController {
@PostMapping(path = {"", "/"}, consumes = {MediaType.APPLICATION_FORM_URLENCODED_VALUE})
public String locale(@RequestParam("locale") String locale,
HttpServletRequest request,
HttpServletResponse response) {
if (locale != null && !locale.isBlank()) {
LocaleResolver localeResolver = RequestContextUtils.getLocaleResolver(request);
if (localeResolver == null)
throw new IllegalStateException("No LocaleResolver found");
try {
localeResolver.setLocale(request, response, StringUtils.parseLocale(locale));
} catch (IllegalArgumentException e) {
logger.debug("Ignoring invalid locale value [{}]: {}", locale, e.getMessage());
}
}
String referer = request.getHeader("referer");
return referer != null && !referer.isBlank() ? "redirect:" + referer : "redirect:/";
}
}
Вы просто отправляете почтовый запрос, содержащий желаемую локаль в виде строки, например, в виде en_US
.
Большое спасибо за ваш подробный ответ. Я не совсем понимаю, как в этом ответе достигается механизм по умолчанию, основанный на списке поддерживаемых языков. Если язык поддерживается (например, испанский), то он НЕ должен использоваться по умолчанию (английский). И это должно происходить каждый раз, когда кто-то открывает сеанс. Это была моя основная проблема с localeResolver.setDefaultLocale(locale);
в Bean. `.
Если, например, браузер отправляет es_ES
в качестве предпочтительного языкового стандарта, то Spring Boot устанавливает этот языковой стандарт в LocaleContextHolder. Что вам теперь нужно сделать, так это убедиться, что везде, где вы хотите установить свое приложение, у вас есть испанские опции. Spring Boot (соответственно Java) автоматически попытается получить испанские версии чего угодно. Это можно использовать для форматирования даты и времени или отображения текстового содержимого, которое вы сохранили внутри messages.properties
: тогда у вас есть база messages.properties
и поддерживаемые языки messages_en.properties
и messages_es.properties
.
Если вы устанавливаете локаль вручную с помощью localeResolver.setDefaultLocale(locale)
, то это локаль, которую Spring Boot использует при попытке разрешить локаль, например. сообщения проверки. Вы все еще должны обеспечить поддержку локали (языка), например. сообщения проверки на испанском языке, в противном случае Spring использует резервные варианты. Одной настройки локали недостаточно, вы также должны предоставить поддержку. Затем Spring знает, чего вы хотите, и автоматически попытается найти нужные сообщения.
Если вы хотите изменить локаль в зависимости от заголовка HTTP Accept-Language
, вам нужно использовать AcceptHeaderLocaleResolver
, например:
@Bean
public LocaleResolver localeResolver() {
var resolver = new AcceptHeaderLocaleResolver();
resolver.setDefaultLocale(Locale.ENGLISH);
resolver.setSupportedLocales(
List.of(Locale.ENGLISH,
Locale.FRENCH,
Locale.of("es"))
);
return resolver;
}
Его легко настроить, и я думаю, это именно то, что вам нужно.
Следующий шаг — получить точно локаль, определенную с помощью AcceptHeaderLocaleResolver
, и использовать ее, например, для получения сообщения из источников сообщений. Для этого вы можете использовать LocaleContextHolder
следующим образом:
@Autowired
private MessageSourceAccessor messageSourceAccessor;
@GetMapping(produces = MediaType.TEXT_PLAIN_VALUE)
public ResponseEntity<String> getGreeting() {
String msg = messageSourceAccessor.getMessage("msg", LocaleContextHolder.getLocale());
return ResponseEntity.ok(msg);
}
}
Вы можете посетить мой github , где я создал рабочий пример. Для проверки локали я использовал расширение Locale Switcher Chrome Extension.
Как вы передаете локаль в бэкэнд? Делает ли это fronted, или вы имеете в виду HTTP-заголовок
Accept-Language