Spring Boot i18n: internacionalizācijas iestatīšanas pamācība
Konfigurējiet MessageSource, izveidojiet lokalizācijām specifiskus properties failus, atrisiniet lokalizācijas un atveidojiet daudzvalodu Thymeleaf veidnes, pēc tam automatizējiet tulkošanu ar MI.
Pievienot atkarības
Spring Boot Starter Web uzreiz ietver MessageSource automātisko konfigurāciju. Pievienojiet Thymeleaf serverī atveidotām i18n veidnēm un validācijas sākuma pakotni lokalizētiem kļūdu ziņojumiem.
<!-- 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>Konfigurēt MessageSource un LocaleResolver
Spring MessageSource ielādē tulkojumus no .properties failiem pēc bāzes nosaukuma nosacījuma: messages.properties (noklusējums), messages_de.properties (vācu), messages_ja.properties (japāņu). Konfigurējiet LocaleResolver, lai noteiktu katram pieprasījumam izmantojamo lokalizāciju.
Tulkošanas faili
# 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 konfigurācija
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;
}
}Lokalizācijas atrisināšana
Konfigurējiet, kā Spring nosaka aktīvo lokalizāciju katram pieprasījumam. CookieLocaleResolver saglabā lietotāja izvēli starp sesijām. LocaleChangeInterceptor ļauj lietotājiem pārslēgt lokalizācijas ar pieprasījuma parametru, piemēram, ?lang=de.
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());
}
}Izmantot tulkojumus kodā
Kontrolleros piekļūstiet tulkotiem ziņojumiem ar MessageSource injicēšanu, Thymeleaf veidnēs — ar #{...} sintaksi, bet REST API — izmantojot automātiski atrisināto Locale parametru.
Kontrolleris ar MessageSource
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 veidnes
Thymeleaf izteiksme #{...} automātiski atrisina ziņojumu atslēgas no .properties failiem. Nododiet parametrus ar sintaksi #{key(arg0, arg1)}. Veidne izmanto LocaleResolver atrisināto lokalizāciju.
<!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>REST API lokalizācija
REST API gadījumā Spring automātiski atrisina Locale no galvenes Accept-Language. Injicējiet to kā metodes parametru un nododiet MessageSource. Klienti pārslēdz valodu, sūtot dažādas Accept-Language galvenes.
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!"}
}Bean validācijas ziņojumi
Spring automātiski atrisina validācijas ierobežojumu ziņojumus no MessageSource. Ierobežojumu anotācijās izmantojiet figūriekavu vietturus, piemēram, {validation.name.required}, un definējiet tulkojumus .properties failos.
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 einApstrādāt daudzskaitli un mainīgos
Spring interpolācijai un daudzskaitlim izmanto java.text.MessageFormat. ChoiceFormat modelis apstrādā daudzskaitļa pamatkārtulas, taču pilnam ICU daudzskaitļa atbalstam (6 arābu formām, 3 krievu formām) pievienojiet ICU4J bibliotēku.
# 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}Automatizēt tulkošanu
Kad i18n iestatīšana ir pabeigta, tulkojiet .properties failus ar MI. IDE lūdziet MI asistentam iztulkot avota failu vai izmantojiet i18n Agent CLI CI/CD konveijerā.
# 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,esAutomatizēt tulkojumu kvalitāti
Bez konfigurēšanas ar spring-locale-chain
spring-locale-chain ir atvērtā pirmkoda Spring Boot sākuma pakotne, kas ar vienu atkarību automātiski konfigurē LocaleResolver, LocaleChangeInterceptor un atbalstīto lokalizāciju validāciju. Definējiet atbalstītās lokalizācijas application.yml, un bibliotēka paveiks pārējo.
<!-- 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>Ieteicamā failu struktūra
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.gradleBiežākās kļūdas
Rakstzīmes ārpus ASCII tiek rādītas nesalasāmi
ChoiceFormat nedarbojas daudzskaitlim ārpus angļu valodas
Tulkojumu izmaiņas neparādās
Negaidīta atkāpšanās uz JVM lokalizāciju
Izmēģiniet i18n Agent tūlīt
Nometiet tulkošanas failu šeit
JSON, YAML, PO, XML, CSV, Markdown, Properties
vai noklikšķiniet, lai izvēlētos
Mērķa valodas
Lokalizācijas atkāpšanās ar spring-locale-chain
Ja reģionālajā lokalizācijā, piemēram, pt-BR, trūkst tulkojuma atslēgas, Spring Boot uzreiz pāriet uz noklusējuma lokalizāciju, nevis vispirms pārbauda vecāklokalizāciju pt.
<!-- Maven -->
<dependency>
<groupId>ai.i18nagent</groupId>
<artifactId>spring-locale-chain</artifactId>
</dependency># application.yml
locale-chain:
fallbacks:
pt-BR:
- pt
- en
zh-Hant-HK:
- zh-Hant
- zh
- enPilnu atbalstīto sistēmu sarakstu un 75 iebūvētās ķēdes skatiet mūsu lokalizāciju atkāpšanās ceļvedī. Learn more →