2015-06-15 4 views
10

Ich versuche, meine erste Spring MVC 4 App mit i18n Unterstützung zu bauen und dachte darüber nach, wie ich ein Standard/Fallback Gebietsschema verwenden kann, wenn der Benutzer die Sprache URI manipuliert Parameter auf einen nicht vorhandenen oder unterstützt locale zum Beispiel http://localhost.de?lang=abcSpring MVC: Fallback für unbekannten Sprachcode in uri Parameter Wert

im mit dem Code

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

, die in der Regel funktioniert, wenn ich die uRL das erste Mal öffnen, aber es scheint nicht für den Fall zu arbeiten Ich habe es beschrieben. Ich weiß, dass es einen Mechanismus gibt, der die Eigenschaftendatei für Standardnachrichten verwenden würde, aber ich möchte für diesen Fall ein Standard/Fallback-Gebietsschema festlegen. Muss ich vielleicht einen benutzerdefinierten Filter implementieren?

+0

Hat niemand eine Idee? War viel auf der Suche, konnte aber noch keine Lösung oder Idee finden .... – StephanM

+0

Was passiert, wenn Sie zu http://localhost.de?lang=abc navigieren? Welches Gebietsschema wird in diesem Fall verwendet? –

+0

kann ich dir nicht mehr sagen, da ich bereits einen Filter gebaut habe, der den Sprachcode überprüft. Wenn meine App diese Sprache nicht unterstützt, setze ich sie manuell auf meine Standardsprache. In deinem Fall wäre es also "de"/deutsch ... – StephanM

Antwort

5

Wahrscheinlich weit davon entfernt, perfekt zu sein, aber das ist, was ich gebaut ...

Ich muss auch sagen, dass ich die Standardsprache Auswahlmechanismus ein bisschen wegen SEO muss geändert und ich beschlossen, die Sprache zu ändern nicht durch Verwenden Sie einen get-Parameter, aber verwenden Sie stattdessen den ersten Teil meines uri-Pfades für die ausgewählte Sprache. Zum Beispiel: http://myurl.com/en/test.html statt http://myurl.com/test.html?lang=de

In meiner Anmerkung basierte Konfiguration:

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

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

} 

Der Filter, der für einen gültigen Sprachcode in der uri prüft .. .

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

} 

}

Frontend-Pfad ist "Ressourcen" in meinem Fall, wo alle statischen Dateien wie js, CSS, Schriftarten usw. liegen. localizationService.getSupportedLocaleLanguageIsoCodes() ist ein Set, das derzeit drei Sprachcodes enthält (en, ru, de). Also im Falle eines falschen Sprachcodes wie abc mache ich einen Forward mit meiner Standardsprache "de". Für mich war/war es eine akzeptable Lösung, weil ein falscher Sprachcode in der uri bedeutet, dass die uri vom Benutzer manipuliert wurde ...

Wie ich schon sagte, ist es vielleicht nicht die "Lösung"; zum Beispiel bin ich nicht sicher, wie und wenn es mit Cookies funktioniert und/oder "sich an mich erinnert" -Authentifizierungen (unter Verwendung von Federsicherheit) ... hatte gerade keine Zeit, es zu testen ...

7

Mein Vorschlag wäre es, die Unterklasse SessionLocaleResolver und überschreibt die getLocale Methode:

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

Dies gilt nicht den Spring classes in jeder größeren Art und Weise ändern und wird wahrscheinlich in absehbarer Zukunft ohne Probleme zur Arbeit zu gehen.

Verwandte Themen