可能远非完美,但这是我构建的......
我还需要说,由于 SEO 的需要,我稍微更改了默认语言选择机制,我决定不使用 get 参数,而是使用所选语言的 uri 路径的第一部分来更改语言。
例如:
http://myurl.com/en/test.html 而不是 http://myurl.com/test.html?lang=de
在我的基于注释的配置中:
@Bean
public LocaleResolver localeResolver() {
UriLocaleResolver uriLocaleResolver = new UriLocaleResolver();
return uriLocaleResolver;
}
语言环境解析器
public class UriLocaleResolver implements LocaleResolver {
private final Logger logger = LoggerFactory.getLogger(getClass());
private Locale locale = null;
@Autowired
private LocalizationService localizationService;
@Override
public Locale resolveLocale(final HttpServletRequest servletRequest) {
if (locale != null) {
return locale;
}
String languageIsoCode = null;
try {
languageIsoCode = ((String)servletRequest.getAttribute(RequestKey.LANGUAGE_ISO_CODE)).toLowerCase();
}
catch (Exception e) { }
if (StringUtils.isBlank(languageIsoCode) || !localizationService.getSupportedLocaleLanguageIsoCodes().contains(languageIsoCode)) {
logger.trace("Couldn't find valid language iso code. Using default locale '{}'", GlobalConstant.DEFAULT_LOCALE);
return GlobalConstant.DEFAULT_LOCALE;
}
logger.trace("Found language iso code '{}'", languageIsoCode);
return new Locale(languageIsoCode);
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
this.locale = locale;
}
}
检查 uri 中是否存在有效语言代码的过滤器...
@Component
public class UriLocalizationFilter extends OncePerRequestFilter {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private LocalizationService localizationService;
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
String uri = request.getRequestURI().substring(request.getContextPath().length());
String[] pathParts = uri.split("/");
if (!uri.startsWith(GlobalConstant.FRONTEND_RESOURCE_PATH_PREFIX) && pathParts.length >= 1 && pathParts[1].length() == 2) {
String originalLanguageIsoCode = pathParts[1];
String lowerCaseLanguageIsoCode = originalLanguageIsoCode.toLowerCase();
if (localizationService.getSupportedLocaleLanguageIsoCodes().contains(lowerCaseLanguageIsoCode)) {
logger.debug("Found valid language iso code {}", lowerCaseLanguageIsoCode);
}
else {
logger.debug("Found invalid language iso code {}. Using default language iso code {}.", lowerCaseLanguageIsoCode, GlobalConstant.DEFAULT_LOCALE.getLanguage());
lowerCaseLanguageIsoCode = GlobalConstant.DEFAULT_LOCALE.getLanguage();
}
String newUrl = StringUtils.removeStart(uri, '/' + originalLanguageIsoCode);
request.setAttribute(RequestKey.LANGUAGE_ISO_CODE, lowerCaseLanguageIsoCode);
logger.debug("Dispatching to new url '{}'", newUrl);
request.getRequestDispatcher(newUrl).forward(request, response);
}
else {
filterChain.doFilter(request, response);
}
}
public void setLocalizationService(LocalizationService localizationService) {
this.localizationService = localizationService;
}
}
}
在我的情况下,前端路径是“资源”,其中所有静态文件(如 js、css、字体等)都在放置。
localizationService.getSupportedLocaleLanguageIsoCodes() 是一个包含当前三种语言代码(en、ru、de)的 Set。
因此,如果出现错误的语言代码,例如 abc,我会使用我的默认语言“de”进行转发。对我来说,这是/是可以接受的解决方案,因为 uri 中有错误的语言代码意味着 uri 是由用户操纵的......
就像我说的那样,它可能不是“解决方案”;例如,我不确定它如何以及是否与 cookie 和/或“记住我”身份验证(使用 spring 安全性)一起工作......只是没有时间测试它......