2015-06-15 14 views
10

Im đang cố gắng xây dựng ứng dụng Spring MVC 4 đầu tiên của tôi với hỗ trợ i18n và nghĩ cách sử dụng ngôn ngữ mặc định/dự phòng trong trường hợp người dùng đang thao tác với ngôn ngữ uri tham số để một tổ chức phi hiện tại hoặc hỗ trợ locale Ví dụ http://localhost.de?lang=abcSpring MVC: Dự trữ mã ngôn ngữ không xác định trong giá trị tham số uri

Im sử dụng mã

@Bean 
public LocaleResolver localeResolver() { 
    SessionLocaleResolver sessionLocaleResolver = new SessionLocaleResolver(); 
    sessionLocaleResolver.setDefaultLocale(Locale.GERMAN); 
    return sessionLocaleResolver; 
} 

mà hoạt động nói chung nếu tôi mở url lần đầu tiên nhưng có vẻ như không làm việc đối với trường hợp tôi đã mô tả. Tôi biết có một cơ chế sẽ sử dụng tệp thuộc tính thư mặc định nhưng tôi muốn đặt ngôn ngữ mặc định/dự phòng cho trường hợp này. Tôi có cần triển khai bộ lọc tùy chỉnh không?

+0

Không ai có ý tưởng? Đã tìm kiếm rất nhiều nhưng không thể tìm được giải pháp hay ý tưởng nào ... – StephanM

+0

Điều gì sẽ xảy ra khi bạn điều hướng đến http://localhost.de?lang=abc? Ngôn ngữ nào được sử dụng trong trường hợp này? –

+0

Tôi không thể nói cho bạn biết nữa vì tôi đã xây dựng bộ lọc kiểm tra mã ngôn ngữ. Nếu ứng dụng của tôi không hỗ trợ ngôn ngữ này, hãy cài đặt nó theo cách thủ công sang ngôn ngữ mặc định của tôi. Vì vậy, trong trường hợp của bạn nó sẽ được thiết lập để "de"/german ... – StephanM

Trả lời

5

Có lẽ còn lâu mới được hoàn hảo nhưng đây là những gì tôi xây dựng ...

Tôi cũng cần phải nói rằng tôi đã thay đổi cơ chế chọn ngôn ngữ mặc định một chút vì SEO cần và tôi đã quyết định thay đổi ngôn ngữ không phải do bằng cách sử dụng tham số get nhưng thay vào đó hãy sử dụng phần đầu tiên của đường dẫn uri của tôi cho ngôn ngữ đã chọn. Ví dụ: http://myurl.com/en/test.html thay vì http://myurl.com/test.html?lang=de

Trong cấu hình dựa chú thích của tôi:

@Bean 
public LocaleResolver localeResolver() { 
    UriLocaleResolver uriLocaleResolver = new UriLocaleResolver(); 
    return uriLocaleResolver; 
} 

Nơi đặt resolver

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; 
    } 

} 

Bộ lọc mà kiểm tra cho một mã ngôn ngữ hợp lệ trong 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; 
    } 

} 

}

Đường dẫn lối vào là "tài nguyên" trong trường hợp của tôi, nơi tất cả các tệp tĩnh như js, css, phông chữ, v.v. localizationService.getSupportedLocaleLanguageIsoCodes() là Tập hợp chứa ba mã ngôn ngữ (en, ru, de). Vì vậy, trong trường hợp một mã ngôn ngữ sai như abc im làm một chuyển tiếp với ngôn ngữ mặc định của tôi "de". Đối với tôi nó là/là giải pháp chấp nhận được vì có một mã ngôn ngữ sai trong uri có nghĩa là uri đã bị người dùng thao tác ...

Giống như tôi đã nói nó có thể không phải là giải pháp; ví dụ im không chắc chắn như thế nào và nếu nó hoạt động với cookie và/hoặc "nhớ tôi" xác thực (sử dụng bảo mật mùa xuân) ... chỉ cần không có thời gian để kiểm tra nó ...

7

Đề xuất của tôi sẽ là phân lớp SessionLocaleResolver và ghi đè lên các phương pháp getLocale:

@SpringBootApplication 
public class DemoApplication { 

    public static void main(String[] args) { 
     SpringApplication.run(DemoApplication.class, args); 
    } 

    private static Set<Locale> allowedLocales; 

    static { 
     HashSet<Locale> allowed = new HashSet<>(); 
     allowed.add(Locale.GERMAN); 
     allowed.add(Locale.CANADA); 
     allowedLocales = Collections.unmodifiableSet(allowed); 

    } 

    @Bean 
    LocaleResolver localeResolver() { 
     return new LimitedSessionLocaleResolver(); 
    } 

    class LimitedSessionLocaleResolver extends SessionLocaleResolver { 
     @Override 
     public Locale resolveLocale(HttpServletRequest request) { 
      Locale locale = super.resolveLocale(request); 
      if (!allowedLocales.contains(locale)) { 
       return determineDefaultLocale(request); 
      } 
      return locale; 
     } 
    } 
} 

này không sửa đổi các lớp học mùa xuân trong bất kỳ cách nào và có lẽ sẽ làm việc mà không vấn đề trong tương lai gần.

Các vấn đề liên quan