Tutorials  /  JavaScript

Spring MVC Internationalization and Localization - Beispiel

Ccentron Redaktion · Januar 2024 ·6 Min. Lesezeit ·JavaScript, Tutorial

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
VM

Passende Infrastruktur bei centron

Node-Anwendungen wollen deployt werden: ccloud³ VMs mit vollem Root-Zugriff ab 3,12 € im Monat – oder gleich als Managed Server, wenn der Betrieb nicht bei Ihnen liegen soll. Cloud Server mieten →

Spring i18n Maven-Konfiguration

Unsere Spring MVC pom.xml sieht wie folgt aus.

Code
<?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>
        <!-- Spring -->
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context</artifactId>
            <version>${org.springframework-version}</version>
            <exclusions>
                <!-- Exclude Commons Logging in favor of SLF4j -->
                <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>
                
        <!-- AspectJ -->
        <dependency>
            <groupId>org.aspectj</groupId>
            <artifactId>aspectjrt</artifactId>
            <version>${org.aspectj-version}</version>
        </dependency>    
        
        <!-- Logging -->
        <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>

        <!-- @Inject -->
        <dependency>
            <groupId>javax.inject</groupId>
            <artifactId>javax.inject</artifactId>
            <version>1</version>
        </dependency>
                
        <!-- Servlet -->
        <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>
    
        <!-- Test -->
        <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:

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

messages_fr.properties-Code:

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.

Go
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.

Code
<%@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.

Code
<?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
       >
        <beans:property name="prefix" value="/WEB-INF/views/" />
        <beans:property name="suffix" value=".jsp" />
    </beans:bean>

    <beans:bean
       >
        <beans:property name="basename" value="classpath:messages" />
        <beans:property name="defaultEncoding" value="UTF-8" />
    </beans:bean>

    <beans:bean
       >
        <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
           >
            <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:

Code
<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):

Spring localization example en

Übergeben der Lokalisierung als Parameter (fr Lokalisierung):

Spring localization example fr

Weitere Anfragen ohne Lokalisierung:

Spring localization example fr cookie

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.

Spring i18n example cookie

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:

Code
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.

Jetzt 200 € Guthaben sichern

Testen Sie Ihr Setup auf ccloud³

Registrieren Sie sich in der ccloud³ und erhalten Sie 200 € Startguthaben für Ihr Projekt – z. B. für eine PostgreSQL-VM mit automatischen Backups.

centron Redaktion Technische Redaktion

Das Redaktionsteam von centron schreibt Anleitungen aus dem Betriebsalltag: getestet auf unserer eigenen Plattform, betrieben im Rechenzentrum in Hallstadt bei Bamberg.

Kategorie JavaScript
Teilen
Noch offene Fragen?

Unser Team hilft Ihnen bei Ihrem konkreten Setup weiter – von Menschen, die die Plattform selbst betreiben.

War dieses Tutorial hilfreich?

Ihre Antwort wird anonym gespeichert und hilft uns, die Tutorials zu verbessern.

Kommentare

Noch keine Kommentare – stellen Sie die erste Frage zu diesem Tutorial.

Zum Kommentieren anmelden

Kommentare stehen centron-Kunden offen. Melden Sie sich in Ihrem Konto an, um eine Frage zu diesem Tutorial zu stellen.

Weiterlesen

Das könnte Sie auch interessieren

Jetzt kostenlos anfangen

Melden Sie sich an und erhalten Sie in den ersten 60 Tagen ein Guthaben von 200 € bei centron.

Dieses Werbeangebot gilt nur für neue Konten. Angebot ausschließlich für Gewerbetreibende.

Jetzt loslegen Sales kontaktieren