Spring Boot i18n: Uluslararasılaştırma kurulumu eğitimi
MessageSource'u yapılandırın, yerel ayara özgü properties dosyaları oluşturun, yerel ayarları çözümleyin ve çok dilli Thymeleaf şablonları oluşturun — ardından çevirileri yapay zeka ile otomatikleştirin.
Bağımlılıkları ekleyin
Spring Boot Starter Web, MessageSource otomatik yapılandırmasını hazır olarak içerir. Sunucu tarafında oluşturulan i18n şablonları için Thymeleaf'i ve yerelleştirilmiş hata iletileri için doğrulama starter'ını ekleyin.
<!-- 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>MessageSource ve LocaleResolver'ı yapılandırın
Spring'in MessageSource bileşeni, çevirileri temel ad kuralını kullanarak .properties dosyalarından yükler: messages.properties (varsayılan), messages_de.properties (Almanca), messages_ja.properties (Japonca). Her istek için hangi yerel ayarın kullanılacağını belirlemek üzere bir LocaleResolver yapılandırın.
Çeviri dosyaları
# 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 yapılandırması
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;
}
}Yerel ayar çözümlemesi
Spring'in her istek için etkin yerel ayarı nasıl belirleyeceğini yapılandırın. CookieLocaleResolver kullanıcının seçimini oturumlar arasında korur. LocaleChangeInterceptor, kullanıcıların ?lang=de gibi bir sorgu parametresi aracılığıyla yerel ayar değiştirmesini sağlar.
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());
}
}Çevirileri kodda kullanın
Çevrilmiş iletilere denetleyicilerde MessageSource ekleme yoluyla, Thymeleaf şablonlarında #{...} söz dizimiyle ve REST API'lerinde otomatik çözümlenen Locale parametresini kullanarak erişin.
MessageSource kullanan denetleyici
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 şablonları
Thymeleaf'in #{...} ifadesi, ileti anahtarlarını .properties dosyalarınızdan otomatik olarak çözümler. Parametreleri #{key(arg0, arg1)} söz dizimiyle aktarın. Şablon, LocaleResolver'ınız tarafından çözümlenen yerel ayarı kullanır.
<!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 yerelleştirmesi
Spring, REST API'lerinde Locale değerini Accept-Language üstbilgisinden otomatik olarak çözümler. Bunu bir yöntem parametresi olarak ekleyin ve MessageSource'a aktarın. İstemciler farklı Accept-Language üstbilgileri göndererek dil değiştirir.
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 doğrulama iletileri
Spring, doğrulama kısıtı iletilerini MessageSource'unuzdan otomatik olarak çözümler. Kısıt ek açıklamalarınızda {validation.name.required} gibi kaşlı ayraçlı yer tutucular kullanın ve çevirileri .properties dosyalarınızda tanımlayın.
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Çoğulları ve değişkenleri yönetin
Spring, ekleme ve çoğullar için java.text.MessageFormat kullanır. ChoiceFormat kalıbı temel çoğul kurallarını yönetir ancak tam ICU çoğul desteği (Arapçanın 6 biçimi, Rusçanın 3 biçimi) için ICU4J kitaplığını ekleyin.
# 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}Çevirileri otomatikleştirin
i18n kurulumunuz tamamlandığında .properties dosyalarınızı yapay zeka kullanarak çevirin. IDE'nizde yapay zeka yardımcınızdan kaynak dosyanızı çevirmesini isteyin veya CI/CD işlem hattınızda i18n Agent CLI'ı kullanın.
# 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Çeviri kalitesini otomatikleştirin
spring-locale-chain ile sıfır yapılandırma
spring-locale-chain; LocaleResolver'ı, LocaleChangeInterceptor'ı ve desteklenen yerel ayar doğrulamasını tek bir bağımlılıkla otomatik olarak yapılandıran açık kaynaklı bir Spring Boot starter'ıdır. Desteklediğiniz yerel ayarları application.yml içinde tanımlayın, geri kalanını kitaplık yönetir.
<!-- 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>Önerilen dosya yapısı
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.gradleYaygın hatalar
ASCII dışı karakterlerin bozuk görünmesi
ChoiceFormat'ın İngilizce dışındaki çoğullarda bozulması
Çeviri değişikliklerinin yansımaması
Beklenmedik biçimde JVM yerel ayarına dönülmesi
i18n Agent'ı şimdi deneyin
Çeviri dosyanızı buraya bırakın
JSON, YAML, PO, XML, CSV, Markdown, Properties
veya göz atmak için tıklayın
Hedef diller
spring-locale-chain ile yerel ayar geri dönüşü
pt-BR gibi bölgesel bir yerel ayarda çeviri anahtarı eksik olduğunda Spring Boot, önce üst yerel ayar pt'yi denetlemek yerine doğrudan varsayılan yerel ayara geçer.
<!-- 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
- enDesteklenen çerçevelerin tam listesi ve 75 yerleşik zincir için Yerel Ayar Geri Dönüşü Rehberimize bakın. Learn more →