Java İle Spring Boot Üzerinde Çoklu Dil Desteği Nasıl Yapılır?

Java İle Spring Boot Üzerinde Çoklu Dil Desteği Nasıl Yapılır?
Java İle Spring Boot Üzerinde Çoklu Dil Desteği Nasıl Yapılır?

Gereksinimler ve Ön Hazırlık

Uygulamaya başlamadan önce sisteminizde Java 17 veya üzeri bir sürümün yüklü olduğundan emin olun. Spring Boot 3.x sürümleri ile tam uyumlu bir çalışma ortamı için aşağıdaki yapılandırmaları kontrol etmelisiniz.

  • JDK 17+: Modern dil özellikleri ve performans iyileştirmeleri için gereklidir.
  • Maven veya Gradle: Bağımlılık yönetimi için standart araçlar.
  • IDE: IntelliJ IDEA veya Eclipse gibi Spring desteği olan bir geliştirme ortamı.

Projenizde spring-boot-starter-web bağımlılığının tanımlı olması yeterlidir. Ekstra bir kütüphane kurulumuna gerek kalmadan Spring'in çekirdek özelliklerini kullanacağız.

Adım 1: Mesaj Kaynaklarını (Message Bundles) Oluşturma

Spring Boot, çoklu dil desteği için ResourceBundleMessageSource sınıfını kullanır. Bu sınıf, src/main/resources dizini altında bulunan messages_xx.properties dosyalarını otomatik olarak okur. "xx" kısmı dil kodunu (örneğin tr, en) temsil eder.

# messages.properties (Varsayılan dil - İngilizce)
welcome.message=Welcome to our application!
login.button=Login

# messages_tr.properties (Türkçe)
welcome.message=Uygulamamıza hoş geldiniz!
login.button=Giriş Yap

Bu dosyalar, anahtar-değer çiftlerinden oluşur. Spring, Locale nesnesine göre doğru dosyayı otomatik olarak seçecektir. Dosyaların UTF-8 kodlamasında kaydedildiğinden emin olun; aksi takdirde Türkçe karakter sorunları yaşayabilirsiniz.

Adım 2: LocaleResolver Yapılandırması

Uygulamanızın kullanıcının hangi dili tercih ettiğini anlaması için bir LocaleResolver bean'ine ihtiyacı vardır. Varsayılan olarak Spring, HTTP isteğindeki Accept-Language başlığını (header) kullanır. Ancak, kullanıcıya dil değiştirme butonu sunmak istiyorsanız SessionLocaleResolver veya CookieLocaleResolver kullanmanız önerilir.

@Configuration
public class LocaleConfig {

    @Bean
    public LocaleResolver localeResolver() {
        CookieLocaleResolver resolver = new CookieLocaleResolver();
        resolver.setDefaultLocale(Locale.ENGLISH);
        resolver.setCookieName("lang_cookie");
        return resolver;
    }
}

Bu konfigürasyon, kullanıcının dil tercihini bir çerezde (cookie) saklar. Böylece kullanıcı sayfayı yenilediğinde veya tekrar geldiğinde seçtiği dil korunur.

Adım 3: LocaleChangeInterceptor ile Dil Değişimi

Kullanıcının bir URL parametresi (örneğin ?lang=tr) üzerinden dil değiştirebilmesini sağlamak için LocaleChangeInterceptor sınıfını kullanırız. Bu interceptor, gelen isteği dinler ve parametreye göre dili günceller.

@Configuration
public class WebMvcConfig implements WebMvcConfigurer {

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        LocaleChangeInterceptor interceptor = new LocaleChangeInterceptor();
        interceptor.setParamName("lang");
        registry.addInterceptor(interceptor);
    }
}

Bu yapılandırma ile /home?lang=tr adresine gidildiğinde, sistem otomatik olarak Türkçe mesajları getirecektir.

Adım 4: Controller ve View Katmanında Kullanım

Mesajları Controller içerisinde veya Thymeleaf gibi bir şablon motorunda kullanmak oldukça basittir. Spring, MessageSource arayüzünü enjekte ederek mesajlara erişmemizi sağlar.

@Controller
public class HomeController {

    @Autowired
    private MessageSource messageSource;

    @GetMapping("/home")
    public String home(Model model, Locale locale) {
        String welcome = messageSource.getMessage("welcome.message", null, locale);
        model.addAttribute("message", welcome);
        return "index";
    }
}

Eğer Thymeleaf kullanıyorsanız, HTML içerisinde #{welcome.message} sözdizimi ile mesajları doğrudan çağırabilirsiniz. Bu, kodunuzu temiz ve yönetilebilir kılar.

Adım 5: Çoklu Dil Desteği Yöntemlerinin Karşılaştırılması

Yöntem Avantajı Dezavantajı
CookieLocaleResolver Kullanıcı oturumundan bağımsızdır. Çerezler silinirse tercih kaybolur.
SessionLocaleResolver Sunucu tarafında güvenli saklanır. Sunucu belleğini kullanır.
AcceptHeaderLocaleResolver Ek yapılandırma gerektirmez. Kullanıcı dilini değiştiremez.

Adım 6: Hata Yönetimi ve Güvenlik Uyarıları

Çoklu dil desteği eklerken, eksik anahtarlar (missing keys) uygulamanızın hata vermesine neden olabilir. Bu durumu yönetmek için MessageSource yapılandırmasında setUseCodeAsDefaultMessage(true) metodunu kullanabilirsiniz.

Kritik Güvenlik Uyarısı: Dil dosyalarınızı (properties) dışarıdan erişilebilir dizinlere koymayın. Ayrıca, kullanıcıdan gelen lang parametresini asla doğrudan veritabanı sorgularında veya dosya yolu oluşturmada kullanmayın; bu durum SQL Injection veya Path Traversal saldırılarına yol açabilir. Her zaman beklenen dil kodlarını (tr, en, de) bir liste ile valide edin.

Sıkça Sorulan Sorular

Dinamik içerikleri (veritabanından gelen) nasıl çevirebilirim?

Veritabanındaki içerikler için genellikle "Locale" tabanlı bir yapı kurmanız gerekir. Örneğin, bir ürünün adını product_name_tr ve product_name_en gibi sütunlarda tutabilir veya ayrı bir çeviri tablosu oluşturarak ilişkilendirebilirsiniz.

Neden Türkçe karakterler bozuk görünüyor?

Java'nın standart Properties sınıfı varsayılan olarak ISO-8859-1 kodlamasını kullanır. IDE ayarlarınızdan properties dosyalarının UTF-8 olarak kaydedildiğinden ve Spring Boot'un bunu tanıdığından emin olun.

Uygulama çalışırken dil dosyalarını güncelleyebilir miyim?

Evet, MessageSource bean'i üzerinde setCacheSeconds(int) metodunu kullanarak dosyaların ne sıklıkla tekrar okunacağını belirleyebilirsiniz. 0 değeri, her istekte dosyaların tekrar okunmasını sağlar (geliştirme aşaması için uygundur).

Mobil uygulamalar için farklı bir yöntem mi izlemeliyim?

Mobil uygulamalar (REST API) için AcceptHeaderLocaleResolver en yaygın tercihtir. Mobil istemci, isteğin header kısmına dil bilgisini ekler ve API buna göre JSON yanıtını yerelleştirir.

Çeviri dosyalarım çok büyürse ne yapmalıyım?

Dosyaları messages_tr.properties yerine messages/auth_tr.properties, messages/product_tr.properties gibi modüllere ayırabilir ve Basenames listesine ekleyebilirsiniz.

Çoklu Dil Desteğinde Performans Optimizasyonu ve Önbellekleme

Spring Boot uygulamalarında MessageSource kullanımı, her istekte dosya sistemine erişim sağlayabilir. Küçük projelerde bu bir sorun teşkil etmese de, yüksek trafikli uygulamalarda disk I/O operasyonlarını minimize etmek hayati önem taşır. Spring, varsayılan olarak mesajları önbelleğe alır, ancak bu süreyi projenizin ihtiyaçlarına göre optimize edebilirsiniz.

application.properties dosyanızda aşağıdaki ayarları yaparak önbellek davranışını kontrol edebilirsiniz:

# Mesajların önbellekte tutulma süresi (saniye cinsinden)
# -1 değeri, mesajların uygulama kapanana kadar önbellekte kalacağını belirtir.
spring.messages.cache-duration=3600

# Mesajların her zaman yeniden yüklenmesini sağlar (Geliştirme ortamı için önerilir)
spring.messages.always-use-message-format=true

Eğer çok sayıda dil dosyası ve mesaj anahtarı ile çalışıyorsanız, ReloadableResourceBundleMessageSource sınıfını manuel olarak yapılandırarak bellek kullanımını yönetebilirsiniz:

@Bean
public MessageSource messageSource() {
    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();
    messageSource.setBasename("classpath:messages");
    messageSource.setDefaultEncoding("UTF-8");
    // Önbellek süresini 1 saat olarak ayarla
    messageSource.setCacheSeconds(3600);
    return messageSource;
}

Çoklu Dil Desteği İçin Birim Testleri (Unit Testing)

Uygulamanızın farklı dillerde doğru mesajları döndürdüğünden emin olmak için MessageSource bileşenini test etmek kritik bir adımdır. JUnit ve MockMvc kullanarak, belirli bir Locale için beklenen çıktının doğruluğunu şu şekilde test edebilirsiniz:

@SpringBootTest
class LocalizationTests {

    @Autowired
    private MessageSource messageSource;

    @Test
    void testTurkishGreeting() {
        String message = messageSource.getMessage("welcome.message", null, new Locale("tr", "TR"));
        assertEquals("Hoş geldiniz!", message);
    }

    @Test
    void testEnglishGreeting() {
        String message = messageSource.getMessage("welcome.message", null, Locale.ENGLISH);
        assertEquals("Welcome!", message);
    }
}

Bu testler, dil dosyalarınızda bir anahtar eksik olduğunda veya yanlış bir çeviri yapıldığında CI/CD süreçlerinizin hata vermesini sağlayarak, üretim ortamında oluşabilecek "kırık metin" sorunlarını engeller.

İleri Seviye: Dinamik Parametre ve Çoğul Eki Yönetimi

Mesajlarınızda sadece statik metinler değil, dinamik veriler ve çoğul ekleri (pluralization) de kullanmanız gerekebilir. Spring, MessageFormat kütüphanesini temel aldığı için mesaj dosyalarınızda şu yapıyı kullanabilirsiniz:

# messages_tr.properties
items.count=Sepetinizde {0} adet ürün bulunmaktadır.
items.plural=Sepetinizde {0, choice, 0#hiç ürün yok|1#bir ürün var|1


Sonuç

Java ile Spring Boot üzerinde çoklu dil desteği yapmak, projenizin profesyonellik seviyesini artıran ve kullanıcı deneyimini iyileştiren temel bir yetenektir. Bu rehberde öğrendiğiniz LocaleResolver ve MessageSource yapıları, ölçeklenebilir ve sürdürülebilir bir sistem kurmanız için yeterlidir.

Bir sonraki adım olarak, çeviri süreçlerini otomatize etmek için veritabanı tabanlı bir MessageSource implementasyonu yazmayı deneyebilir veya profesyonel çeviri platformları (Crowdin, Lokalise gibi) ile entegrasyon sağlayabilirsiniz. Kod güvenliği konusunda her zaman kullanıcı girdilerini filtrelemeyi ve güncel kütüphaneleri takip etmeyi unutmayın.

Sorumluluk Reddi: Bu makalede paylaşılan kod örnekleri eğitim amaçlıdır. Üretim ortamına almadan önce güvenlik testlerinden geçirilmesi ve projenizin özel ihtiyaçlarına göre konfigüre edilmesi geliştiricinin sorumluluğundadır.
Bu yazıya tepkinizi paylaşın:
Zeynep Kaya

Ev ekonomisi ve kişisel organizasyon üzerine birçok yayın yönettim. Okuyucuların günlük yaşam kalitesini artıracak uygulanabilir çözümler üretmeyi hedefliyorum.

Yorumlar (0)

Yorum Yaz