#6 Spring Boot – internacjonalizacja czyli locale w akcji

Dzięki wykorzystaniu internacjonalizacji tworzenie aplikacji w różnych językach (nie programowania 😉 ) stało się bardzo proste. Możemy przygotować jeden plik wzorcowy, a następnie przekazać go do odpowiednich tłumaczy, którzy przygotują nam przetłumaczone teksty w narzuconym przez nas formacie. Skrótem używanym naprzemiennie z internacjonalizacją jest i18n. Jest to ilość znaków pomiędzy “i” oraz “n” w słowie “internationalization“.

Autokonfiguracja

Aby skorzystać z internacjonalizacji w Spring Boot’cie mamy do tego utworzoną odpowiednią auto-konfigurację MessageSourceAutoConfiguration. Dzięki temu nie musimy tworzyć ekstra beanów konfiguracyjnych tylko możemy wykorzystać plik application.properties:

# INTERNATIONALIZATION (MessageSourceAutoConfiguration)

# Comma-separated list of basenames, each following the ResourceBundle convention.
spring.messages.basename=messages

# Loaded resource bundle files cache expiration, in seconds. When set to -1, bundles are cached forever. 
spring.messages.cache-seconds=-1

# Message bundles encoding.
spring.messages.encoding=UTF-8

# Set whether to fall back to the system Locale if no files for a specific Locale have been found.
spring.messages.fallback-to-system-locale=true

Messages

Pliki z językami mają odpowiednie nazwy. Głównym plikiem domyślnym jest:

messages.properties

Jeśli chcemy utworzyć specyfikowany plik, dodajemy do niego postfix oznaczający język:

messages_pl.properties # polski
messages_de.properties # niemiecki

resourcesMessages

Pliki domyślnie są wyszukiwane na classpath’ie:

Static resources can be moved to /public (or /static or /resources or /META-INF/resources)
in the classpath root. Same for messages.properties (Spring Boot detects this automatically 
in the root of the classpath).

Jeśli natomiast chcemy zmienić lokalizację plików messages, należy wykorzystać plik application.properties:

spring.messages.basename=locale/messages

Gdy dodaliśmy już interesujące nas pliki, możemy sprawdzić działanie w Tymianku (Thymleafie, ale ostatnio przeczytałem tłumaczenie i zostało mi w głowie ;)). W momencie wywołania sprawdzana jest lokalizacja. Jeśli nie ma żadnego pliku messages.properties, zostanie załadowana wartość domyślna, czyli “Default“.

Korzystamy

Dodajmy sobie teraz kod:

<h1 th:text="#{CompanyName}">CodeCouple</h1>

A w plikach messages, messages_pl, messages_de dodajmy wartość z odpowiednimi końcówkami:

CompanyName=CodeCouple.tutaj_koncowka

Aby przetestować poprawność działania, wystarczy ustawić w przeglądarce domyślny język.

  • ZIq Shh

    Pół dnia się z tym męczyłem. Temat prosty i przyjemny ale czasem jak utkniesz.. dzięki!

    • CodeCouple.pl

      Mamy nadzieję, że nasz wpis pomógł 😉

  • Paweł Szymański

    brakuje mi np zmiany języka z selecta

    plus js

    $(document).ready(function() {

    $("#locales").change(function () {

    var selectedOption = $('#locales').val();

    if (selectedOption != ''){

    window.location.replace('?lang=' + selectedOption);

    }

    });

    });

    i niestety do tego potrzeba beanów

    package pl.ccy.b2b.config;

    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.LocaleResolver;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;
    import org.springframework.web.servlet.i18n.SessionLocaleResolver;

    import java.util.Locale;

    @Configuration
    public class LocaleConfiguration implements WebMvcConfigurer {

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

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

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
    registry.addInterceptor(localeChangeInterceptor());
    }

    }