Close

Spring MVC - Themes with Internationalization

[Last Updated: Sep 9, 2026]

The following example shows how to use the internationalization capabilities that come with Spring MVC's theme functionality. By default, ResourceBundleThemeSource (which implements ThemeSource) is used to load theme properties via a ResourceBundle. That means we can also add i18n-based, multiple theme properties files. One of them will be picked depending on the client's locale (based on the 'Accept-Language' header value). Check out our MVC i18n tutorial as well.

Note: Spring MVC's theme support (ThemeResolver, ThemeSource, ResourceBundleThemeSource, and the related implementations shown below) was deprecated as of Spring Framework 6.0 in favor of using CSS directly, and was removed entirely in Spring Framework 7.0. The example on this page will not compile against Spring Framework 7.0 or later, and against Spring Boot 4 and later, since those classes no longer exist. It remains useful for understanding how theming worked in earlier Spring MVC versions.

Example

Java Config Class

In this example, we are using the default FixedThemeResolver.

In addition to multiple theme.properties files, we are also going to add some i18n-based message files. For that, we have to configure our own ResourceBundleMessageSource bean:

package com.logicbig.example;

import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ResourceBundleMessageSource;
import org.springframework.web.servlet.config.annotation.*;

@EnableWebMvc
@Configuration
@ComponentScan
public class MyWebConfig implements WebMvcConfigurer {

    @Bean
    public MessageSource messageSource() {
        //this is only needed for text messages and not needed for theme internationalization
        ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
        messageSource.setBasenames("texts/msg");
        return messageSource;
    }

    @Override
    public void addViewControllers(ViewControllerRegistry registry) {
        //mapping '/' to index view name without a controller
        ViewControllerRegistration r = registry.addViewController("/");
        r.setViewName("index");
    }

    @Override
    public void configureViewResolvers(ViewResolverRegistry registry) {
        registry.jsp();//default prefix=/WEB-INF/", suffix=".jsp"
    }
}

Theme Properties Files

src/main/resources/theme.properties

background=beige
content-style=width:500px;border:solid 2px blue;margin:auto;padding:30px;

src/main/resources/theme_fr.properties

background=darkBlue 
content-style=width:500px;border:solid 2px white;color:white;margin:auto;padding:30px;

Also note that, by default, the theme's ResourceBundleThemeSource uses an empty base name prefix, so we don't need to use a prefix with the theme properties file names. In the next example, we will learn how to use a custom prefix base name.

Message Properties Files

src/main/resources/texts/msg.properties

app.msg = hi there

src/main/resources/texts/msg_fr.properties

app.msg = salut

JSP View

/src/main/webapp/WEB-INF/index.jsp

<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<html>
<body style="background-color:<spring:theme code='background'/>;">
<div style="<spring:theme code='content-style'/>">
    <spring:message code="app.msg"/>
</div>
</body>
</html>

To try examples, run embedded Jetty (configured in pom.xml of example project below):

mvn jetty:run

Output

From a browser with the default locale of 'en-US':

Using curl:

$ curl -s "http://localhost:8080/"

<html>
<body style="background-color:beige;">
<div style="width:500px;border:solid 2px blue;margin:auto;padding:30px;">
hi there
</div>
</body>
</html>

Using curl with an explicit 'Accept-Language' header value of 'fr-FR':

$ curl -s "http://localhost:8080/" -H "Accept-Language: fr-FR"

<html>
<body style="background-color:darkBlue ;">
<div style="width:500px;border:solid 2px white;color:white;margin:auto;padding:30px;">
salut
</div>
</body>
</html>

Example Project

Dependencies and Technologies Used:

  • spring-webmvc 6.0.0 (Spring Web MVC)
     Version Compatibility: 4.1.0.RELEASE - 6.2.19Version List
    ×

    Version compatibilities of spring-webmvc with this example:

      javax.servlet-api:3.x
    • 4.1.0.RELEASE
    • 4.1.1.RELEASE
    • 4.1.2.RELEASE
    • 4.1.3.RELEASE
    • 4.1.4.RELEASE
    • 4.1.5.RELEASE
    • 4.1.6.RELEASE
    • 4.1.7.RELEASE
    • 4.1.8.RELEASE
    • 4.1.9.RELEASE
    • 4.2.0.RELEASE
    • 4.2.1.RELEASE
    • 4.2.2.RELEASE
    • 4.2.3.RELEASE
    • 4.2.4.RELEASE
    • 4.2.5.RELEASE
    • 4.2.6.RELEASE
    • 4.2.7.RELEASE
    • 4.2.8.RELEASE
    • 4.2.9.RELEASE
    • 4.3.0.RELEASE
    • 4.3.1.RELEASE
    • 4.3.2.RELEASE
    • 4.3.3.RELEASE
    • 4.3.4.RELEASE
    • 4.3.5.RELEASE
    • 4.3.6.RELEASE
    • 4.3.7.RELEASE
    • 4.3.8.RELEASE
    • 4.3.9.RELEASE
    • 4.3.10.RELEASE
    • 4.3.11.RELEASE
    • 4.3.12.RELEASE
    • 4.3.13.RELEASE
    • 4.3.14.RELEASE
    • 4.3.15.RELEASE
    • 4.3.16.RELEASE
    • 4.3.17.RELEASE
    • 4.3.18.RELEASE
    • 4.3.19.RELEASE
    • 4.3.20.RELEASE
    • 4.3.21.RELEASE
    • 4.3.22.RELEASE
    • 4.3.23.RELEASE
    • 4.3.24.RELEASE
    • 4.3.25.RELEASE
    • 4.3.26.RELEASE
    • 4.3.27.RELEASE
    • 4.3.28.RELEASE
    • 4.3.29.RELEASE
    • 4.3.30.RELEASE
    • 5.0.0.RELEASE
    • 5.0.1.RELEASE
    • 5.0.2.RELEASE
    • 5.0.3.RELEASE
    • 5.0.4.RELEASE
    • 5.0.5.RELEASE
    • 5.0.6.RELEASE
    • 5.0.7.RELEASE
    • 5.0.8.RELEASE
    • 5.0.9.RELEASE
    • 5.0.10.RELEASE
    • 5.0.11.RELEASE
    • 5.0.12.RELEASE
    • 5.0.13.RELEASE
    • 5.0.14.RELEASE
    • 5.0.15.RELEASE
    • 5.0.16.RELEASE
    • 5.0.17.RELEASE
    • 5.0.18.RELEASE
    • 5.0.19.RELEASE
    • 5.0.20.RELEASE
    • 5.1.0.RELEASE
    • 5.1.1.RELEASE
    • 5.1.2.RELEASE
    • 5.1.3.RELEASE
    • 5.1.4.RELEASE
    • 5.1.5.RELEASE
    • 5.1.6.RELEASE
    • 5.1.7.RELEASE
    • 5.1.8.RELEASE
    • 5.1.9.RELEASE
    • 5.1.10.RELEASE
    • 5.1.11.RELEASE
    • 5.1.12.RELEASE
    • 5.1.13.RELEASE
    • 5.1.14.RELEASE
    • 5.1.15.RELEASE
    • 5.1.16.RELEASE
    • 5.1.17.RELEASE
    • 5.1.18.RELEASE
    • 5.1.19.RELEASE
    • 5.1.20.RELEASE
    • 5.2.0.RELEASE
    • 5.2.1.RELEASE
    • 5.2.2.RELEASE
    • 5.2.3.RELEASE
    • 5.2.4.RELEASE
    • 5.2.5.RELEASE
    • 5.2.6.RELEASE
    • 5.2.7.RELEASE
    • 5.2.8.RELEASE
    • 5.2.9.RELEASE
    • 5.2.10.RELEASE
    • 5.2.11.RELEASE
    • 5.2.12.RELEASE
    • 5.2.13.RELEASE
    • 5.2.14.RELEASE
    • 5.2.15.RELEASE
    • 5.2.16.RELEASE
    • 5.2.17.RELEASE
    • 5.2.18.RELEASE
    • 5.2.19.RELEASE
    • 5.2.20.RELEASE
    • 5.2.21.RELEASE
    • 5.2.22.RELEASE
    • 5.2.23.RELEASE
    • 5.2.24.RELEASE
    • 5.2.25.RELEASE
    • 5.3.0
    • 5.3.1
    • 5.3.2
    • 5.3.3
    • 5.3.4
    • javax.servlet-api:4.x
    • 5.3.5
    • 5.3.6
    • 5.3.7
    • 5.3.8
    • 5.3.9
    • 5.3.10
    • 5.3.11
    • 5.3.12
    • 5.3.13
    • 5.3.14
    • 5.3.15
    • 5.3.16
    • 5.3.17
    • 5.3.18
    • 5.3.19
    • 5.3.20
    • 5.3.21
    • 5.3.22
    • 5.3.23
    • 5.3.24
    • 5.3.25
    • 5.3.26
    • 5.3.27
    • 5.3.28
    • 5.3.29
    • 5.3.30
    • 5.3.31
    • 5.3.32
    • 5.3.33
    • 5.3.34
    • 5.3.35
    • 5.3.36
    • 5.3.37
    • 5.3.38
    • 5.3.39
    • javax.* -> jakarta.*
      jakarta.servlet-api:6.x
      Java 17 min
    • 6.0.0
    • 6.0.1
    • 6.0.2
    • 6.0.3
    • 6.0.4
    • 6.0.5
    • 6.0.6
    • 6.0.7
    • 6.0.8
    • 6.0.9
    • 6.0.10
    • 6.0.11
    • 6.0.12
    • 6.0.13
    • 6.0.14
    • 6.0.15
    • 6.0.16
    • 6.0.17
    • 6.0.18
    • 6.0.19
    • 6.0.20
    • 6.0.21
    • 6.0.22
    • 6.0.23
    • 6.1.0
    • 6.1.1
    • 6.1.2
    • 6.1.3
    • 6.1.4
    • 6.1.5
    • 6.1.6
    • 6.1.7
    • 6.1.8
    • 6.1.9
    • 6.1.10
    • 6.1.11
    • 6.1.12
    • 6.1.13
    • 6.1.14
    • 6.1.15
    • 6.1.16
    • 6.1.17
    • 6.1.18
    • 6.1.19
    • 6.1.20
    • 6.1.21
    • 6.2.0
    • 6.2.1
    • 6.2.2
    • 6.2.3
    • 6.2.4
    • 6.2.5
    • 6.2.6
    • 6.2.7
    • 6.2.8
    • 6.2.9
    • 6.2.10
    • 6.2.11
    • 6.2.12
    • 6.2.13
    • 6.2.14
    • 6.2.15
    • 6.2.16
    • 6.2.17
    • 6.2.18
    • 6.2.19

    Versions in green have been tested.

  • jakarta.servlet-api 6.0.0 (Jakarta Servlet API documentation)
  • JDK 17
  • Maven 3.9.11

Spring MVC Themes with Internationalization Example Select All Download
  • spring-mvc-theme-and-i18n
    • src
      • main
        • java
          • com
            • logicbig
              • example
                • MyWebConfig.java
          • resources
            • texts
          • webapp
            • WEB-INF

    See Also

    Join