DEV Community

Anuj Ashok Potdar
Anuj Ashok Potdar

Posted on

2 2

Spring PetClinic Goes Global: Enhancing Accessibility with Multi-Language Support

Introduction

The Spring PetClinic application is a flagship example of Spring Boot best practices, used by developers worldwide to learn enterprise patterns. Recently, my pull request (#0c88f9) was merged, introducing a critical feature: full internationalization (i18n) support using URL-based language switching. This update not only makes the application accessible to non-English speakers but also modernizes its architecture for scalability. Let’s explore why this matters.


The Problem: Limited Language Support

Before this change, Spring PetClinic lacked robust support for multiple languages. While it included basic message properties, it didn’t fully leverage Spring’s i18n capabilities, making it difficult to:

  1. Switch Languages Dynamically: Users couldn’t change languages via the URL, a common requirement for global applications.
  2. Maintain Consistency: Hardcoded text in HTML files made translations error-prone and fragmented.
  3. Scale to New Languages: Adding a new language required manual updates across HTML templates, violating the DRY (Don’t Repeat Yourself) principle.

For a reference application like PetClinic, this was a missed opportunity to demonstrate scalable i18n practices.


The Solution: URL-Based Localization and Decoupled Text

The commit introduces three key improvements:

1. Dynamic Language Switching via URL Parameters

A new WebConfiguration class configures Spring’s LocaleResolver to read the lang parameter from URLs (e.g., ?lang=es). This allows users to bookmark or share language-specific links, aligning with RESTful principles.

@Configuration  
public class WebConfiguration implements WebMvcConfigurer {  
    @Bean  
    public LocaleResolver localeResolver() {  
        SessionLocaleResolver slr = new SessionLocaleResolver();  
        slr.setDefaultLocale(Locale.ENGLISH);  
        return slr;  
    }  

    @Bean  
    public LocaleChangeInterceptor localeChangeInterceptor() {  
        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();  
        lci.setParamName("lang");  
        return lci;  
    }  

    @Override  
    public void addInterceptors(InterceptorRegistry registry) {  
        registry.addInterceptor(localeChangeInterceptor());  
    }  
}  
Enter fullscreen mode Exit fullscreen mode

2. Centralized Message Properties

All UI text was moved to messages.properties files (e.g., messages_es.properties, messages_fr.properties), decoupling content from presentation. This ensures translations are maintained in a single location.

Example (messages_es.properties):

welcome=¡Bienvenido a PetClinic!  
owners=Propietarios  
find_owners=Buscar Propietarios  
Enter fullscreen mode Exit fullscreen mode

3. HTML Template Cleanup

Hardcoded text in Thymeleaf templates was replaced with Spring’s #{...} expressions, enabling dynamic resolution based on the user’s locale:

<!-- Before -->  
<h2>Find Owners</h2>  

<!-- After -->  
<h2 th:text="#{find_owners}">Find Owners</h2>  
Enter fullscreen mode Exit fullscreen mode

Architectural Impact: Why This Matters

1. Scalability for Global Audiences

By supporting URL-driven language switching, PetClinic now serves as a blueprint for building globally accessible applications. Developers can easily add new languages by creating a messages_xx.properties file—no code changes required.

2. Separation of Concerns

Decoupling text from HTML templates follows the MVC pattern rigorously. Content editors can now manage translations without touching Java code or Thymeleaf markup.

3. Improved Maintainability

Centralized message properties reduce duplication and make it easier to spot missing translations. For example, adding support for Japanese (messages_ja.properties) becomes a trivial task.

4. Enhanced User Experience

Users can now share language-specific URLs (e.g., https://petclinic.com?lang=de), making the app more inclusive and user-friendly.


Lessons for Developers

  1. Design for Global Audiences Early: Baking i18n into your architecture from day one avoids costly refactors later.
  2. Leverage Framework Features: Spring’s LocaleResolver and Thymeleaf’s i18n integration simplify what could otherwise be a complex task.
  3. Prioritize Clean Templates: Keep text out of HTML/CSS/JS—it belongs in resource files.

Community Impact

This commit closes issue #1854, addressing a long-standing request from contributors. By merging this, PetClinic:

  • Encourages participation from non-English speakers.
  • Demonstrates Spring’s i18n capabilities as a learning tool.
  • Sets a precedent for other open-source projects to prioritize accessibility.

Conclusion

Internationalization isn’t just about translating text—it’s about architecting applications to embrace diversity. This update ensures Spring PetClinic remains a modern, inclusive example for developers worldwide.

Check out the full commit here and consider contributing your own translations!

AWS Q Developer image

Build your favorite retro game with Amazon Q Developer CLI in the Challenge & win a T-shirt!

Feeling nostalgic? Build Games Challenge is your chance to recreate your favorite retro arcade style game using Amazon Q Developer’s agentic coding experience in the command line interface, Q Developer CLI.

Participate Now

Top comments (2)

Collapse
 
nevodavid profile image
Nevo David

this is actually super helpful - real talk, the amount of times ive seen apps ignore language stuff is insane. you think more teams should bake in i18n from the start or fix it after they launch?

Collapse
 
anizmo profile image
Anuj Ashok Potdar

Hey Nevo, thanks for sharing your thoughts. My honest take is, starting early definitely helps save a lot of time especially in an enterprise application where you expect to have many contributors work on it.
It becomes an exhausting task to change text from string literals to tokens once the project is big but if you start it off as a process to begin with, as and when your app gets bigger you can always enforce it and build it up piece by piece.

I have followed this practice for real world applications that have been deployed for 20-30 countries and I have always felt I should have started sooner. :)

DevCycle image

Ship Faster, Stay Flexible.

DevCycle is the first feature flag platform with OpenFeature built-in to every open source SDK, designed to help developers ship faster while avoiding vendor-lock in.

Start shipping

👋 Kindness is contagious

Explore this practical breakdown on DEV’s open platform, where developers from every background come together to push boundaries. No matter your experience, your viewpoint enriches the conversation.

Dropping a simple “thank you” or question in the comments goes a long way in supporting authors—your feedback helps ideas evolve.

At DEV, shared discovery drives progress and builds lasting bonds. If this post resonated, a quick nod of appreciation can make all the difference.

Okay