Skip to main content

Spring Boot i18n: internatsionaliseerimise seadistusjuhend

Seadista MessageSource, loo lokaadipõhised properties-failid, lahenda lokaadid ja renderda mitmekeelsed Thymeleafi mallid — seejärel automatiseeri tõlked tehisintellektiga.

1

Lisa sõltuvused

Spring Boot Starter Web sisaldab kohe MessageSource'i automaatse seadistuse. Lisa Thymeleaf serveris renderdatavate i18n-mallide jaoks ja valideerimise starter lokaliseeritud veateadete jaoks.

Spring Boot seadistab automaatselt MessageSource'i beani, mis loeb classpath'ilt faili messages.properties. Selgesõnalist seadistust on vaja ainult siis, kui soovid kohandada baasnime, kodeeringut või puhverdamiskäitumist.
pom.xml
<!-- pom.xml — Spring Boot Starter Web includes MessageSource auto-config -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

<!-- Thymeleaf for server-side rendered templates with i18n -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>

<!-- Validation (for localized error messages) -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
2

Seadista MessageSource ja LocaleResolver

Springi MessageSource laadib tõlked .properties-failidest baasnime tava järgi: messages.properties (vaikimisi), messages_de.properties (saksa), messages_ja.properties (jaapani). Seadista LocaleResolver määrama iga päringu jaoks kasutatava lokaadi.

Tõlkefailid

messages.properties
# src/main/resources/messages.properties (default / English)
nav.home=Home
nav.about=About
nav.settings=Settings

greeting=Hello, {0}!
cart.itemCount={0,choice,0#No items|1#1 item|1<{0,number} items}

error.notFound=Page not found
error.serverError=Something went wrong. Please try again.

MessageSource'i seadistus

I18nConfig.java
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.support.ReloadableResourceBundleMessageSource;
import org.springframework.validation.beanvalidation.LocalValidatorFactoryBean;

@Configuration
public class I18nConfig {

    @Bean
    public MessageSource messageSource() {
        ReloadableResourceBundleMessageSource source =
            new ReloadableResourceBundleMessageSource();
        source.setBasename("classpath:messages");
        source.setDefaultEncoding("UTF-8");
        source.setCacheSeconds(3600); // reload interval in dev
        return source;
    }

    // Wire MessageSource into Bean Validation
    @Bean
    public LocalValidatorFactoryBean validator(MessageSource messageSource) {
        LocalValidatorFactoryBean bean = new LocalValidatorFactoryBean();
        bean.setValidationMessageSource(messageSource);
        return bean;
    }
}
Kui tõlked tagastavad tõlgitud teksti asemel võtme nime, on tavalisim põhjus vale baasnimi. Vaikimisi on see 'messages', mis vastab classpath'il olevale failile messages.properties. Kui failid on teise nimega või alamkataloogis, määra spring.messages.basename selgesõnaliselt.

Lokaadi lahendamine

Seadista, kuidas Spring määrab iga päringu aktiivse lokaadi. CookieLocaleResolver säilitab kasutaja valiku seansside vahel. LocaleChangeInterceptor võimaldab kasutajatel lokaati vahetada päringuparameetriga, näiteks ?lang=de.

LocaleConfig.java
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.CookieLocaleResolver;
import org.springframework.web.servlet.i18n.LocaleChangeInterceptor;

import java.util.Locale;

@Configuration
public class LocaleConfig implements WebMvcConfigurer {

    @Bean
    public LocaleResolver localeResolver() {
        CookieLocaleResolver resolver = new CookieLocaleResolver("lang");
        resolver.setDefaultLocale(Locale.ENGLISH);
        resolver.setCookieMaxAge(3600 * 24 * 365); // 1 year
        return resolver;
    }

    @Bean
    public LocaleChangeInterceptor localeChangeInterceptor() {
        LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
        interceptor.setParamName("lang"); // ?lang=de switches locale
        return interceptor;
    }

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

Kasuta tõlkeid koodis

Kasuta tõlgitud sõnumeid kontrollerites MessageSource'i injektsiooni kaudu, Thymeleafi mallides süntaksiga # {...} ja REST API-des automaatselt lahendatud Locale'i parameetriga.

Kontroller MessageSource'iga

HomeController.java
import org.springframework.context.MessageSource;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.Locale;

@Controller
public class HomeController {

    private final MessageSource messageSource;

    public HomeController(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @GetMapping("/")
    public String home(Model model, Locale locale) {
        // Spring injects the resolved Locale automatically
        String greeting = messageSource.getMessage(
            "greeting",
            new Object[]{"World"},
            locale
        );
        model.addAttribute("greeting", greeting);
        return "home";
    }
}

Thymeleafi mallid

Thymeleafi avaldis # {...} lahendab sõnumivõtmed .properties-failidest automaatselt. Edasta parameetrid süntaksiga # {key(arg0, arg1)}. Mall kasutab LocaleResolveri lahendatud lokaati.

home.html
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <title th:text="#{nav.home}">Home</title>
</head>
<body>
    <!-- Simple message lookup -->
    <h1 th:text="#{greeting('World')}">Hello, World!</h1>

    <!-- Navigation with i18n -->
    <nav>
        <a href="/" th:text="#{nav.home}">Home</a>
        <a href="/about" th:text="#{nav.about}">About</a>
        <a href="/settings" th:text="#{nav.settings}">Settings</a>
    </nav>

    <!-- Parameterized messages -->
    <p th:text="#{cart.itemCount(3)}">3 items</p>

    <!-- Language switcher -->
    <div>
        <a th:href="@{/(lang=en)}">English</a>
        <a th:href="@{/(lang=de)}">Deutsch</a>
        <a th:href="@{/(lang=ja)}">日本語</a>
    </div>

    <!-- Conditional text based on locale -->
    <p th:if="${#locale.language == 'ja'}"
       th:text="#{greeting('ユーザー')}">
        こんにちは、ユーザーさん!
    </p>
</body>
</html>
Thymeleafi avaldised, nagu # {greeting('World')}, edastavad argumendid MessageFormat'ile. HTML-märgendite sees olev staatiline tekst toimib varusisuna, kui malli vaadatakse ilma Springita — see on kasulik mallidega otse töötavatele disaineritele.

REST API lokaliseerimine

REST API-de puhul lahendab Spring Locale'i automaatselt Accept-Language'i päisest. Sisesta see meetodi parameetrina ja edasta MessageSource'ile. Kliendid vahetavad keelt, saates erinevaid Accept-Language'i päiseid.

ApiController.java
import org.springframework.context.MessageSource;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;

import java.util.Locale;
import java.util.Map;

@RestController
@RequestMapping("/api")
public class ApiController {

    private final MessageSource messageSource;

    public ApiController(MessageSource messageSource) {
        this.messageSource = messageSource;
    }

    @GetMapping("/greeting/{name}")
    public ResponseEntity<Map<String, String>> greeting(
            @PathVariable String name,
            Locale locale) {  // Resolved from Accept-Language header
        String msg = messageSource.getMessage(
            "greeting", new Object[]{name}, locale
        );
        return ResponseEntity.ok(Map.of("message", msg));
    }

    // curl -H "Accept-Language: de" localhost:8080/api/greeting/Max
    // → {"message": "Hallo, Max!"}
}
REST API-d kasutavad tavaliselt AcceptHeaderLocaleResolverit (päisepõhine), veebirakendused aga CookieLocaleResolverit (küpsisepõhine). Kui pakud mõlemat samast rakendusest, kaalu kohandatud LocaleResolverit, mis kontrollib esmalt küpsiseid ja taandub seejärel Accept-Language'i päisele.

Beani valideerimissõnumid

Spring lahendab valideerimispiirangute sõnumid automaatselt sinu MessageSource'ist. Kasuta piirangu annotatsioonides looksulgudega kohatäitjaid, nagu {validation.name.required}, ning määra tõlked .properties-failides.

Bean Validation i18n
import jakarta.validation.constraints.*;

public class CreateUserRequest {

    @NotBlank(message = "{validation.name.required}")
    @Size(min = 2, max = 50, message = "{validation.name.size}")
    private String name;

    @Email(message = "{validation.email.invalid}")
    private String email;
}

// In messages.properties:
// validation.name.required=Name is required
// validation.name.size=Name must be between {min} and {max} characters
// validation.email.invalid=Please enter a valid email address
//
// In messages_de.properties:
// validation.name.required=Name ist erforderlich
// validation.name.size=Name muss zwischen {min} und {max} Zeichen lang sein
// validation.email.invalid=Bitte geben Sie eine gültige E-Mail-Adresse ein
4

Töötle mitmusevorme ja muutujaid

Spring kasutab interpoleerimiseks ja mitmusevormide jaoks java.text.MessageFormat'it. ChoiceFormati muster käsitleb lihtsaid mitmusereegleid, kuid täieliku ICU mitmusetoetuse jaoks (araabia keele kuus vormi, vene keele kolm) lisa ICU4J teek.

MessageFormat Plurals
# MessageFormat plural syntax in messages.properties
# Uses java.text.ChoiceFormat — NOT ICU plural rules
cart.itemCount={0,choice,0#No items|1#1 item|1<{0,number} items}

# For more complex plurals, use ICU4J:
# 1. Add dependency: com.ibm.icu:icu4j
# 2. Use ICUMessageSource instead of ResourceBundleMessageSource
#
# Then you can write ICU-style plurals:
# cart.items={count, plural, one {# item} other {# items}}

# Variables with MessageFormat:
welcome.message=Welcome, {0}! You have {1,number} new {1,choice,1#notification|1<notifications}.
order.total=Order total: {0,number,currency}
event.date=Event date: {0,date,long}
ChoiceFormat pole sama mis ICU mitmusereeglid. See kasutab CLDR-i kategooriate (zero, one, two, few, many, other) asemel arvulisi vahemikke (0#, 1#, 1<). Keerukate mitmusereeglitega keelte, nagu araabia, poola või vene keel, jaoks ChoiceFormatist ei piisa — kasuta selle asemel ICU4J MessageFormat'it.

Automatiseeri tõlked

Kui i18n-i seadistus on valmis, tõlgi .properties-failid tehisintellektiga. Palu IDE-s oma tehisintellekti abilisel lähtefail tõlkida või kasuta CI/CD-konveieris i18n Agent'i CLI-d.

Terminal
# Translate your .properties files with AI
# In your IDE, ask your AI assistant:
> Translate src/main/resources/messages.properties to German, Japanese, and Spanish

✓ messages_de.properties created (1.2s)
✓ messages_ja.properties created (1.5s)
✓ messages_es.properties created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate src/main/resources/messages.properties --lang de,ja,es
Tõlgi järk-järgult — kui lisad faili messages.properties uusi võtmeid, tõlgi kõigi lokaadifailide uuesti loomise asemel ainult uued võtmed. Nii säilivad olemasolevate failide inimeste ülevaadatud tõlked.

Automatiseeri tõlkekvaliteet

Leia i18n-validate'i abil puuduvad võtmed ja katkised kohatäitjad enne avaldamist. Testi kasutajaliidest i18n-pseudo abil pseudotõlgetega enne päris tõlgete saabumist.

Seadistamiseta spring-locale-chain

spring-locale-chain on avatud lähtekoodiga Spring Boot'i starter, mis seadistab ühe sõltuvusega automaatselt LocaleResolveri, LocaleChangeInterceptori ja toetatud lokaatide valideerimise. Määra toetatud lokaadid failis application.yml ning teek teeb ülejäänu.

pom.xml
<!-- Add spring-locale-chain for zero-config locale resolution -->
<dependency>
    <groupId>io.github.i18n-agent</groupId>
    <artifactId>spring-locale-chain</artifactId>
    <version>1.0.0</version>
</dependency>

Soovituslik failistruktuur

Project Structure
my-spring-app/
├── src/main/
│   ├── java/com/example/
│   │   ├── config/
│   │   │   ├── I18nConfig.java          # MessageSource bean
│   │   │   └── LocaleConfig.java        # LocaleResolver + interceptor
│   │   ├── controller/
│   │   │   └── HomeController.java      # Uses MessageSource
│   │   └── MyApplication.java
│   └── resources/
│       ├── messages.properties          # Default (English)
│       ├── messages_de.properties       # German
│       ├── messages_ja.properties       # Japanese
│       ├── messages_es.properties       # Spanish
│       ├── application.yml              # Spring config
│       └── templates/
│           └── home.html                # Thymeleaf with #{...}
├── pom.xml
└── build.gradle

Levinud komistuskivid

Mitte-ASCII märgid kuvatakse sodina

Java .properties-failid kasutavad vaikimisi ISO-8859-1 kodeeringut, mitte UTF-8-t. Sellised märgid nagu umlaudid (ü) või CJK-märgid kuvatakse sodina. Parandus: määra failis application.yml spring.messages.encoding=UTF-8 või kasuta .properties-failides Unicode'i paojadasid, nagu \u00FC. Spring Boot'i ReloadableResourceBundleMessageSource kasutab vaikimisi UTF-8-t, kuid ResourceBundleMessageSource mitte.

ChoiceFormat läheb mitteinglise mitmusevormidega katki

Java ChoiceFormat ({0,choice,0#|1#|1<}) toetab ainult arvulisi vahemikke — see ei saa väljendada CLDR-i mitmusekategooriaid, nagu few või many. Sellised keeled nagu araabia (kuus vormi), poola (kolm vormi) ja vene keel (kolm vormi) vajavad õigeks mitmusekäsitluseks ICU4J-d. Ära eelda, et ChoiceFormat haldab kõiki keeli.

Tõlkemuutused ei kajastu

ResourceBundleMessageSource puhverdab kogumid vaikimisi määramata ajaks. Kasuta arenduses ReloadableResourceBundleMessageSource'i koos valikuga cacheSeconds=0, et näha muudatusi taaskäivitamata. Tootmiskeskkonnas määra jõudluse ja värskenduskiiruse tasakaalustamiseks mõistlik puhvri kestus, näiteks 3 600 sekundit.

Ootamatu taandumine JVM-i lokaadile

Vaikimisi taandub Spring faili messages.properties asemel JVM-i vaikelokaadile (Locale.getDefault()). Vaikekogumi alati kasutamiseks määra failis application.yml spring.messages.fallback-to-system-locale=false. Vastasel juhul kuvab JVM-i lokaadiga 'fr' server taotletud lokaadist puuduva võtme puhul inglise keele asemel prantsuse keelt.

Proovi i18n Agent'i kohe

Kukuta tõlkefail siia

JSON, YAML, PO, XML, CSV, Markdown, Properties

või klõpsa faili valimiseks

Sihtkeeled

Registreerumine pole vajalikKohene hinnang

Varulokaat spring-locale-chainiga

Kui piirkondlikust lokaadist, näiteks pt-BR-st, puudub tõlkevõti, liigub Spring Boot otse vaikelokaadile ega kontrolli esmalt põhilokaati pt.

Terminal
<!-- Maven -->
<dependency>
  <groupId>ai.i18nagent</groupId>
  <artifactId>spring-locale-chain</artifactId>
</dependency>
Configuration
# application.yml
locale-chain:
  fallbacks:
    pt-BR:
      - pt
      - en
    zh-Hant-HK:
      - zh-Hant
      - zh
      - en

Vaata meie varulokaadi juhendist kõigi toetatud raamistike ja 75 sisseehitatud ahela loendit. Learn more →

Korduma kippuvad küsimused