Skip to main content

Spring Boot i18n: nemzetköziesítési beállítási oktatóanyag

Állítsa be a MessageSource elemet, hozzon létre területspecifikus properties fájlokat, oldja fel a területeket és rendereljen többnyelvű Thymeleaf-sablonokat — majd automatizálja a fordítást mesterséges intelligenciával.

1

Függőségek hozzáadása

A Spring Boot Starter Web alapból tartalmazza a MessageSource automatikus beállítását. Szerveroldalon renderelt i18n-sablonokhoz adja hozzá a Thymeleafet, lokalizált hibaüzenetekhez pedig a validation startert.

A Spring Boot automatikusan beállít egy MessageSource beant, amely az osztályútvonal messages.properties fájljából olvas. Kifejezett konfigurációra csak az alapnév, kódolás vagy gyorsítótárazási viselkedés testreszabásakor van szükség.
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

A MessageSource és LocaleResolver beállítása

A Spring MessageSource az alapnév-konvenció szerint tölti be a fordításokat .properties fájlokból: messages.properties (alapértelmezett), messages_de.properties (német), messages_ja.properties (japán). Állítson be LocaleResolver elemet a kérésenként használandó terület meghatározásához.

Fordításfájlok

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 beállítása

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;
    }
}
Ha a fordítások a lefordított szöveg helyett a kulcsnevet adják vissza, a leggyakoribb ok a hibás alapnév. Az alapértelmezett „messages”, amely az osztályútvonal messages.properties fájljára mutat. Ha a fájlok neve eltérő, vagy alkönyvtárban vannak, kifejezetten állítsa be a spring.messages.basename értéket.

Terület feloldása

Állítsa be, hogyan határozza meg a Spring az egyes kérések aktív területét. A CookieLocaleResolver munkamenetek között is megőrzi a felhasználó választását. A LocaleChangeInterceptor lehetővé teszi a terület váltását például ?lang=de lekérdezési paraméterrel.

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

Fordítások használata a kódban

A lefordított üzeneteket vezérlőkben MessageSource-befecskendezéssel, Thymeleaf-sablonokban a #{...} szintaxissal, REST API-kban pedig az automatikusan feloldott Locale paraméterrel érheti el.

Vezérlő MessageSource használatával

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";
    }
}

Thymeleaf-sablonok

A Thymeleaf #{...} kifejezése automatikusan feloldja az üzenetkulcsokat a .properties fájlokból. Paramétereket a #{key(arg0, arg1)} szintaxissal adjon át. A sablon a LocaleResolver által feloldott területet használja.

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>
Az olyan Thymeleaf-kifejezések, mint a #{greeting('World')}, argumentumokat adnak át a MessageFormatnak. A HTML-címkéken belüli statikus szöveg tartalékként szolgál, amikor a sablont Spring nélkül tekintik meg — ez közvetlenül a sablonokon dolgozó tervezőknek hasznos.

REST API lokalizációja

REST API-knál a Spring automatikusan feloldja a Locale értéket az Accept-Language fejlécből. Fecskendezze be metódusparaméterként, és adja át a MessageSource elemnek. Az ügyfelek eltérő Accept-Language fejlécekkel váltanak nyelvet.

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!"}
}
A REST API-k általában fejlécalapú AcceptHeaderLocaleResolver, a webalkalmazások pedig cookie-alapú CookieLocaleResolver elemet használnak. Ha mindkettőt ugyanabból az alkalmazásból szolgálja ki, fontolja meg egy egyéni LocaleResolver használatát, amely előbb a cookie-kat ellenőrzi, majd az Accept-Language fejlécre vált.

Bean-ellenőrzési üzenetek

A Spring automatikusan feloldja az ellenőrzési korlátozások üzeneteit a MessageSource elemből. A korlátozásannotációkban használjon kapcsos zárójeles helyőrzőket, például {validation.name.required} értéket, és határozza meg a fordításokat a .properties fájlokban.

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öbbes számok és változók kezelése

A Spring java.text.MessageFormat formátumot használ interpolációhoz és többes számokhoz. A ChoiceFormat minta kezeli az alapvető többesszám-szabályokat, a teljes ICU-támogatáshoz (az arab 6, az orosz 3 alakjához) azonban adja hozzá az ICU4J könyvtárat.

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}
A ChoiceFormat nem azonos az ICU többesszám-szabályaival. CLDR-kategóriák (zero, one, two, few, many, other) helyett számtartományokat (0#, 1#, 1<) használ. Összetett többesszám-szabályú nyelvekhez, például arabhoz, lengyelhez vagy oroszhoz a ChoiceFormat nem elegendő — használja helyette az ICU4J MessageFormat elemét.

Fordítások automatizálása

A kész i18n-beállítással fordítsa le .properties fájljait mesterséges intelligenciával. Kérje meg az IDE MI-alapú segédét a forrásfájl lefordítására, vagy használja az i18n Agent parancssori eszközét a CI/CD-folyamatban.

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
Fordítson fokozatosan — amikor új kulcsokat ad a messages.properties fájlhoz, csak az új kulcsokat fordítsa le az összes területifájl újragenerálása helyett. Így megmaradnak a meglévő fájlok ember által ellenőrzött fordításai.

A fordítási minőség automatizálása

Az i18n-validate segítségével még kiadás előtt találja meg a hiányzó kulcsokat és hibás helyőrzőket. Az i18n-pseudo használatával valódi fordítások beérkezése előtt tesztelje a felületet pszeudofordításokkal.

Nulla beállítás spring-locale-chain használatával

A spring-locale-chain egy nyílt forráskódú Spring Boot starter, amely egyetlen függőségből automatikusan beállítja a LocaleResolver, LocaleChangeInterceptor és támogatottterület-ellenőrzést. Határozza meg a támogatott területeket az application.yml fájlban, a többit a könyvtár kezeli.

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>

Ajánlott fájlszerkezet

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

Gyakori buktatók

A nem ASCII-karakterek hibásan jelennek meg

A Java .properties fájljai alapértelmezés szerint ISO-8859-1, nem UTF-8 kódolásúak. Az ékezetes (ü) vagy CJK-karakterek hibásan jelennek meg. Megoldás: állítsa be a spring.messages.encoding=UTF-8 értéket az application.yml fájlban, vagy használjon Unicode escape-szekvenciákat, például \u00FC értéket a .properties fájlokban. A Spring Boot ReloadableResourceBundleMessageSource alapértelmezése UTF-8, a ResourceBundleMessageSource elemé nem.

A ChoiceFormat hibás nem angol többes számoknál

A Java ChoiceFormat eleme ({0,choice,0#|1#|1<}) csak számtartományokat támogat — nem képes olyan CLDR többesszám-kategóriák kifejezésére, mint a 'few' vagy 'many'. Az arab (6 alak), lengyel (3 alak) és orosz (3 alak) helyes többes számához ICU4J szükséges. Ne feltételezze, hogy a ChoiceFormat minden nyelvet kezel.

A fordítási változások nem jelennek meg

A ResourceBundleMessageSource alapértelmezés szerint korlátlan ideig gyorsítótárazza a csomagokat. Fejlesztéskor használjon ReloadableResourceBundleMessageSource elemet cacheSeconds=0 értékkel, hogy újraindítás nélkül lássa a változásokat. Éles környezetben állítson be észszerű gyorsítótár-időtartamot (például 3600 másodpercet) a teljesítmény és a frissítési sebesség egyensúlyához.

Váratlan tartalék a JVM területére

Alapértelmezés szerint a Spring a JVM alapértelmezett területére (Locale.getDefault()), nem a messages.properties fájlra vált. Az alapértelmezett csomag következetes használatához állítsa be a spring.messages.fallback-to-system-locale=false értéket az application.yml fájlban. Enélkül egy „fr” JVM-területű szerver francia szöveget mutat angol helyett, ha a kért területről hiányzik egy kulcs.

Try i18n Agent Now

Drop your translation file here

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

or click to browse

Target languages

No signup requiredInstant estimate

Területi tartalék spring-locale-chain használatával

Ha egy fordítási kulcs hiányzik egy regionális területi beállításból, például a pt-BR változatból, a Spring Boot a pt szülőterület ellenőrzése helyett közvetlenül az alapértelmezett területre vált.

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

A támogatott keretrendszerek és a 75 beépített lánc teljes listájáért tekintse meg Területi tartalék útmutatónkat. Learn more →

Gyakran Ismételt Kérdések