Cloud-Lösungen der Zukunft - Testen!

Revolutionäre Cloud-Technologie, ganz ohne versteckte Kosten. Profitieren Sie von unserer Testphase und entdecken Sie umfassende Funktionen. Der Anmeldeprozess ist transparent und unkompliziert. Starten Sie jetzt Ihre Reise in die Cloud - Kostenfrei!

Spring MVC Internationalization und Localization – Beispiel

Willkommen zum Spring Internationalization (i18n) Tutorial. Bei jeder Webanwendung mit Nutzern aus aller Welt ist Internationalization (i18n) oder Localization (L10n) sehr wichtig für eine bessere Benutzerinteraktion. Die meisten Webanwendungs-Frameworks bieten einfache Möglichkeiten, die Anwendung basierend auf den lokalen Einstellungen der Nutzer zu lokalisieren. Spring folgt ebenfalls diesem Muster und bietet umfangreiche Unterstützung für Internationalization (i18n) durch den Einsatz von Spring-Interzeptoren, Locale Resolvers und Resource Bundles für verschiedene Sprachen.

Spring Internationalization i18n

Lassen Sie uns ein einfaches Spring MVC-Projekt erstellen, in dem wir den Request-Parameter verwenden, um die Nutzerlokalität zu erhalten und darauf basierend die Label-Werte der Antwortseite aus den lokal spezifischen Resource Bundles setzen. Erstellen Sie ein Spring MVC-Projekt im Spring Tool Suite, um den Basiscode für unsere Anwendung zu haben.

Spring i18n Beispielprojekt

Spring i18n Maven-Konfiguration

Unsere Spring MVC pom.xml sieht wie folgt aus.

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="https://maven.apache.org/POM/4.0.0" xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="https://maven.apache.org/POM/4.0.0 https://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.journaldev</groupId>
    <artifactId>spring</artifactId>
    <name>Springi18nExample</name>
    <packaging>war</packaging>
    <version>1.0.0-BUILD-SNAPSHOT</version>
    <properties>
        <java-version>1.6</java-version>
        <org.springframework-version>4.0.2.RELEASE</org.springframework-version>
        <org.aspectj-version>1.7.4</org.aspectj-version>
        <org.slf4j-version>1.7.5</org.slf4j-version>
    </properties>
    <dependencies>
        
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
            <exclusions>
                
                <exclusion>
                    <groupId>commons-logging</groupId>
                    <artifactId>commons-logging</artifactId>
                 </exclusion>
            </exclusions>
        </dependency>
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-webmvc</artifactId>
            <version>${org.springframework-version}</version>
        </dependency>
                
        
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>    
        
        
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>${org.slf4j-version}</version>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>${org.slf4j-version}</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.15</version>
            <exclusions>
                <exclusion>
                    <groupId>javax.mail</groupId>
                    <artifactId>mail</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>javax.jms</groupId>
                    <artifactId>jms</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jdmk</groupId>
                    <artifactId>jmxtools</artifactId>
                </exclusion>
                <exclusion>
                    <groupId>com.sun.jmx</groupId>
                    <artifactId>jmxri</artifactId>
                </exclusion>
            </exclusions>
            <scope>runtime</scope>
        </dependency>

        
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
                
        
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>servlet-api</artifactId>
            <version>2.5</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet.jsp</groupId>
            <artifactId>jsp-api</artifactId>
            <version>2.1</version>
            <scope>provided</scope>
        </dependency>
        <dependency>
            <groupId>javax.servlet</groupId>
            <artifactId>jstl</artifactId>
            <version>1.2</version>
        </dependency>
    
        
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.7</version>
            <scope>test</scope>
        </dependency>        
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-eclipse-plugin</artifactId>
                <version>2.9</version>
                <configuration>
                    <additionalProjectnatures>
                        <projectnature>org.springframework.ide.eclipse.core.springnature</projectnature>
                    </additionalProjectnatures>
                    <additionalBuildcommands>
                        <buildcommand>org.springframework.ide.eclipse.core.springbuilder</buildcommand>
                    </additionalBuildcommands>
                    <downloadSources>true</downloadSources>
                    <downloadJavadocs>true</downloadJavadocs>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.6</source>
                    <target>1.6</target>
                    <compilerArgument>-Xlint:all</compilerArgument>
                    <showWarnings>true</showWarnings>
                    <showDeprecation>true</showDeprecation>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.2.1</version>
                <configuration>
                    <mainClass>org.test.int1.Main</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

Spring Resource Bundle

Der Einfachheit halber nehmen wir an, dass unsere Anwendung nur zwei Lokalisierungen unterstützt – en und fr. Wenn keine Benutzerlokalisierung angegeben ist, verwenden wir Englisch als Standardlokalisierung. Lassen wir Spring Resource Bundles für beide diese Lokalisierungen erstellen, die auf der JSP-Seite verwendet werden.

messages_en.properties-Code:

label.title=Login-Seite
label.firstName=Vorname
label.lastName=Nachname
label.submit=Login

messages_fr.properties-Code:

label.title=Connectez-vous page
label.firstName=Pr\u00E9nom
label.lastName=Nom
label.submit=Connexion

Beachten Sie, dass ich Unicode für Sonderzeichen in den französischen Lokalisierungs-Ressourcenbündeln verwende, damit sie in der an die Clientanfragen gesendeten Antwort-HTML richtig interpretiert werden. Ein weiterer wichtiger Punkt ist, dass beide Ressourcenbündel sich im Klassenpfad der Anwendung befinden und ihr Name dem Muster „messages_{locale}.properties“ folgt. Wir werden später sehen, warum diese Punkte wichtig sind.

Spring MVC Internationalization i18n – Controller-Klasse

Unsere Controller-Klasse ist sehr einfach, sie protokolliert lediglich die Nutzerlokalisierung und gibt die home.jsp-Seite als Antwort zurück.

package com.journaldev.spring;

import java.util.Locale;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

/**
 * Handles requests for the application home page.
 */
@Controller
public class HomeController {
    
    private static final Logger logger = LoggerFactory.getLogger(HomeController.class);
    
    /**
     * Simply selects the home view to render by returning its name.
     */
    @RequestMapping(value = "/", method = RequestMethod.GET)
    public String home(Locale locale, Model model) {
        logger.info("Welcome home! The client locale is {}.", locale);
    
        return "home";
    }
    
}

Spring MVC Internationalization i18n JSP-Seite

Unser home.jsp-Seitencode sieht wie folgt aus.

<%@taglib uri="https://www.springframework.org/tags" prefix="spring"%>
<%@ page session="false"%>
<html>
<head>
<title><spring:message code="label.title" /></title>
</head>
<body>
    <form method="post" action="login">
        <table>
            <tr>
                <td><label> <strong><spring:message
                                code="label.firstName" /></strong>
                </label></td>
                <td><input name="firstName" /></td>
            </tr>
            <tr>
                <td><label> <strong><spring:message
                                code="label.lastName" /></strong>
                </label></td>
                <td><input name="lastName" /></td>
            </tr>
            <tr>
                <spring:message code="label.submit" var="labelSubmit"></spring:message>
                <td colspan="2"><input type="submit" value="${labelSubmit}" /></td>
            </tr>
        </table>
    </form>
</body>
</html>

Der einzige erwähnenswerte Teil ist die Verwendung von spring:message, um die Nachricht mit dem gegebenen Code abzurufen. Stellen Sie sicher, dass die Spring-Tag-Bibliotheken mit der taglib jsp-Direktive konfiguriert sind. Spring kümmert sich um das Laden der entsprechenden Resource-Bundle-Nachrichten und stellt sie für die Verwendung auf den JSP-Seiten bereit.

Spring MVC Internationalization i18n – Bean-Konfigurationsdatei

Die Spring Bean-Konfigurationsdatei ist der Ort, an dem die Magie passiert. Das ist die Schönheit des Spring Frameworks, da es uns hilft, uns mehr auf die Geschäftslogik zu konzentrieren, statt auf das Kodieren von trivialen Aufgaben. Lassen Sie uns sehen, wie unsere Spring Bean-Konfigurationsdatei aussieht und wir werden uns jede der Beans einzeln ansehen.

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="https://www.springframework.org/schema/mvc"
    xmlns:xsi="https://www.w3.org/2001/XMLSchema-instance" xmlns:beans="https://www.springframework.org/schema/beans"
    xmlns:context="https://www.springframework.org/schema/context"
    xsi:schemaLocation="https://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
        https://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
        https://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

    <!-- DispatcherServlet Context: defines this servlet's request-processing 
        infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving 
        up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Resolves views selected for rendering by @Controllers to .jsp resources 
        in the /WEB-INF/views directory -->
    <beans:bean
        class="org.springframework.web.servlet.view.InternalResourceViewResolver">
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <beans:bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <beans:property name="basename" value="classpath:messages" />
        <beans:property name="defaultEncoding" value="UTF-8" />
    </beans:bean>

    <beans:bean id="localeResolver"
        class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
        <beans:property name="defaultLocale" value="en" />
        <beans:property name="cookieName" value="myAppLocaleCookie"></beans:property>
        <beans:property name="cookieMaxAge" value="3600"></beans:property>
    </beans:bean>

    <interceptors>
        <beans:bean
            class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
            <beans:property name="paramName" value="locale" />
        </beans:bean>
    </interceptors>

    <context:component-scan base-package="com.journaldev.spring" />

</beans:beans>

Das annotation-driven-Tag ermöglicht das Controller-Programmiermodell. Das context:component-scan gibt das Paket an, in dem Spring nach annotierten Komponenten sucht. Der messageSource-Bean ist für i18n konfiguriert, wobei die Eigenschaft basename den Standort der Ressourcenbündel angibt. Der localeResolver-Bean setzt ein Cookie zur Erkennung der Benutzerlokalisierung und der org.springframework.web.servlet.i18n.LocaleChangeInterceptor-Interceptor wird zur Identifizierung der Benutzerlokalisierung verwendet. Der Standard-lokaleResolver ist AcceptHeaderLocaleResolver, der den accept-language-Header in der HTTP-Anfrage des Clients verwendet.

Spring MVC Internationalization – Framework-Konfiguration

Wenn Sie sich über die Konfiguration wundern, die dem Spring Framework mitteilt, unsere Kontextkonfigurationen zu laden, befindet sie sich im Deployment-Deskriptor unserer MVC-Anwendung.

Servlet-Konfiguration:

<servlet>
    <servlet-name>appServlet</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>
        
<servlet-mapping>
    <servlet-name>appServlet</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping>

Wir können den Ort oder den Namen der Kontextdatei ändern, indem wir die Konfiguration der web.xml ändern. Unsere Spring i18n-Anwendung ist bereit, sie kann in jedem Servlet-Container bereitgestellt werden. Normalerweise exportiere ich sie als WAR-Datei in das webapps-Verzeichnis eines eigenständigen Tomcat-Web-Servers. Hier sind die Screenshots unserer Anwendungs-Startseite mit verschiedenen Lokalisierungen. Standard-Startseite (en Lokalisierung):

Übergeben der Lokalisierung als Parameter (fr Lokalisierung):

Weitere Anfragen ohne Lokalisierung:

Wie Sie auf dem obigen Bild sehen können, übergeben wir keine Lokalisierungsinformationen in der Clientanfrage, aber unsere Anwendung erkennt trotzdem die Benutzerlokalisierung. Sie haben jetzt wahrscheinlich erraten, dass es aufgrund des CookieLocaleResolver-Beans ist, den wir in unserer Spring Bean-Konfigurationsdatei konfiguriert haben. Sie können jedoch Ihre Browser-Cookies überprüfen, um dies zu bestätigen. Ich verwende Chrome und das folgende Bild zeigt die von der Anwendung gespeicherten Cookie-Daten.

Beachten Sie, dass die Cookie-Ablaufzeit eine Stunde beträgt, also 3600 Sekunden, wie durch die cookieMaxAge-Eigenschaft konfiguriert. Wenn Sie die Serverprotokolle überprüfen, können Sie sehen, dass die Lokalisierung protokolliert wird.

Beispiele für Serverprotokolle:

INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is en.
INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is fr.
INFO : com.journaldev.spring.HomeController - Welcome home! The client locale is fr.

Das ist alles für die Spring i18n-Beispielanwendung.

Starten Sie Ihre kostenlose Testversion: Entfalten Sie das volle Potenzial von Spring MVC Internationalization und Localization mit unseren Cloud-Lösungen

Sind Sie bereit, Ihre Spring MVC-Projekte auf ein neues Niveau zu heben? Erleben Sie die mühelose Internationalisierung und Lokalisierung mit unserer Cloud-Plattform.

Try for free!