Я теперь ищу платформу для многоязычных веб-приложений. В данный момент мне кажется, что лучшим выбором является Spring MVC. Но я считался с фактом, что все инструкции для разработчиков предлагают переключить использование языков LocaleChangeInterceptor таким способом:
http://www.somesite.com/action/?locale=en
К сожалению, существует много причин, почему я хотел бы, избегают этого. Как я мог сделать код языка, чтобы быть основной частью URL? Например:
http://www.somesite.com/en/action
Спасибо.
UPD: я нашел следующее решение. Это еще не завершено, но работы. Решение состоит в двух частях - фильтр сервлета и боб сопоставителя локали. Это - взгляды немного hackish, но я не вижу другой способ решить эту проблему.
public class LocaleFilter implements Filter
{
...
private static final String DEFAULT_LOCALE = "en";
private static final String[] AVAILABLE_LOCALES = new String[] {"en", "ru"};
public LocaleFilter() {}
private List getSevletRequestParts(ServletRequest request)
{
String[] splitedParts = ((HttpServletRequest) request).getServletPath().split("/");
List result = new ArrayList();
for (String sp : splitedParts)
{
if (sp.trim().length() > 0)
result.add(sp);
}
return result;
}
private Locale getLocaleFromRequestParts(List parts)
{
if (parts.size() > 0)
{
for (String lang : AVAILABLE_LOCALES)
{
if (lang.equals(parts.get(0)))
{
return new Locale(lang);
}
}
}
return null;
}
@Override
public void doFilter(ServletRequest request, ServletResponse response,
FilterChain chain) throws IOException, ServletException
{
List requestParts = this.getSevletRequestParts(request);
Locale locale = this.getLocaleFromRequestParts(requestParts);
if (locale != null)
{
request.setAttribute(LocaleFilter.class.getName() + ".LOCALE", locale);
StringBuilder sb = new StringBuilder();
for (int i = 1; i < requestParts.size(); i++)
{
sb.append('/');
sb.append((String) requestParts.get(i));
}
RequestDispatcher dispatcher = request.getRequestDispatcher(sb.toString());
dispatcher.forward(request, response);
}
else
{
request.setAttribute(LocaleFilter.class.getName() + ".LOCALE", new Locale(DEFAULT_LOCALE));
chain.doFilter(request, response);
}
}
...
}
public class FilterLocaleResolver implements LocaleResolver
{
private Locale DEFAULT_LOCALE = new Locale("en");
@Override
public Locale resolveLocale(HttpServletRequest request)
{
Locale locale = (Locale) request.getAttribute(LocaleFilter.class.getName() + ".LOCALE");
return (locale != null ? locale : DEFAULT_LOCALE);
}
@Override
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale)
{
request.setAttribute(LocaleFilter.class.getName() + ".LOCALE", locale);
}
}
Таким образом, нет никакой потребности отобразить локаль в каждом действии в контроллерах. Следующий пример будет хорошо работать:
@Controller
@RequestMapping("/test")
public class TestController
{
@RequestMapping("action")
public ModelAndView action(HttpServletRequest request, HttpServletResponse response)
{
ModelAndView mav = new ModelAndView("test/action");
...
return mav;
}
}
В Spring 3.0 вы можете указать своим контроллерам искать переменные пути. Например,
@RequestMapping("/{locale}/action")
public void action(@PathVariable String locale) {
...
}