{"id":38767,"date":"2026-02-07T09:40:47","date_gmt":"2026-02-07T06:40:47","guid":{"rendered":"https:\/\/fatihsoysal.com\/blog\/?p=38767"},"modified":"2026-02-07T09:40:47","modified_gmt":"2026-02-07T06:40:47","slug":"spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi","status":"publish","type":"post","link":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/","title":{"rendered":"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi"},"content":{"rendered":"<p><body><\/p>\n<h2>Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi<\/h2>\n<p>Spring Framework, modern web uygulamalar\u0131n\u0131n geli\u015ftirilmesinde en \u00e7ok tercih edilen ekosistemlerden biridir. G\u00fcn\u00fcm\u00fcz k\u00fcresel d\u00fcnyas\u0131nda, bir uygulaman\u0131n farkl\u0131 dilleri ve k\u00fclt\u00fcrel tercihleri desteklemesi, kullan\u0131c\u0131 deneyimi a\u00e7\u0131s\u0131ndan kritik bir \u00f6neme sahiptir. Bu makale, Spring MVC tabanl\u0131 uygulamalarda uluslararas\u0131la\u015ft\u0131rma (Internationalization &#8211; i18n) ve yerelle\u015ftirme (Localization &#8211; L10n) kavramlar\u0131n\u0131, bunlar\u0131n nas\u0131l uyguland\u0131\u011f\u0131n\u0131 ve ad\u0131m ad\u0131m bir \u00f6rnekle nas\u0131l hayata ge\u00e7irilece\u011fini detayl\u0131 bir \u015fekilde ele alacakt\u0131r.<\/p>\n<h3>Giri\u015f: K\u00fcreselle\u015fen D\u00fcnyada Uygulama Geli\u015ftirme<\/h3>\n<p>Uygulamalar\u0131m\u0131z\u0131 geli\u015ftirirken, genellikle hedef kitlemizin tek bir dil veya b\u00f6lge ile s\u0131n\u0131rl\u0131 olmad\u0131\u011f\u0131n\u0131 fark ederiz. Bir uygulaman\u0131n d\u00fcnya \u00e7ap\u0131nda ba\u015far\u0131l\u0131 olabilmesi i\u00e7in farkl\u0131 dilleri, para birimlerini, tarih formatlar\u0131n\u0131 ve k\u00fclt\u00fcrel normlar\u0131 desteklemesi gerekir. \u0130\u015fte tam bu noktada i18n ve L10n devreye girer.<\/p>\n<p>Uluslararas\u0131la\u015ft\u0131rma (i18n), bir uygulaman\u0131n farkl\u0131 diller ve b\u00f6lgeler i\u00e7in uyarlanabilir hale getirilmesi s\u00fcrecidir. Bu, uygulaman\u0131n kod taban\u0131nda dil veya b\u00f6lgeye \u00f6zel metinlerin, formatlar\u0131n veya di\u011fer k\u00fclt\u00fcrel unsurlar\u0131n sabit kodlanmamas\u0131 anlam\u0131na gelir. &#8220;i18n&#8221; terimi, &#8220;internationalization&#8221; kelimesindeki &#8216;i&#8217; ve &#8216;n&#8217; harfleri aras\u0131nda 18 harf bulunmas\u0131ndan gelir.<\/p>\n<p>Yerelle\u015ftirme (L10n) ise, uluslararas\u0131la\u015ft\u0131r\u0131lm\u0131\u015f bir uygulaman\u0131n belirli bir dil ve b\u00f6lgeye \u00f6zel hale getirilmesi s\u00fcrecidir. Bu s\u00fcre\u00e7, metinlerin \u00e7evrilmesini, tarih ve saat formatlar\u0131n\u0131n ayarlanmas\u0131n\u0131, para birimi sembollerinin ve bi\u00e7imlerinin d\u00fczenlenmesini, renklerin, g\u00f6rsellerin ve di\u011fer k\u00fclt\u00fcrel unsurlar\u0131n hedeflenen b\u00f6lgeye uygun hale getirilmesini i\u00e7erir. &#8220;L10n&#8221; terimi de &#8220;localization&#8221; kelimesindeki &#8216;L&#8217; ve &#8216;n&#8217; harfleri aras\u0131nda 10 harf bulunmas\u0131ndan t\u00fcretilmi\u015ftir.<\/p>\n<p>Spring Framework, bu karma\u015f\u0131k s\u00fcre\u00e7leri basitle\u015ftirmek ve geli\u015ftiricilere g\u00fc\u00e7l\u00fc ara\u00e7lar sunmak i\u00e7in tasarlanm\u0131\u015ft\u0131r. Spring MVC&#8217;nin i18n ve L10n deste\u011fi sayesinde, uygulamalar\u0131n\u0131z\u0131 kolayca \u00e7ok dilli ve \u00e7ok b\u00f6lgeli hale getirebilirsiniz.<\/p>\n<h3>Temel Kavramlar ve Spring Mekanizmalar\u0131<\/h3>\n<p>Spring MVC&#8217;de i18n ve L10n&#8217;yi anlamak i\u00e7in baz\u0131 temel kavramlar\u0131 ve Spring&#8217;in bu konudaki ana bile\u015fenlerini bilmek \u00f6nemlidir.<\/p>\n<h4>Locale (Yerel Ayarlar)<\/h4>\n<p><code>java.util.Locale<\/code> s\u0131n\u0131f\u0131, belirli bir co\u011frafi, politik veya k\u00fclt\u00fcrel b\u00f6lgeyi temsil eder. Bir <code>Locale<\/code>, genellikle bir dil kodu (\u00f6rn. <code>en<\/code> for English, <code>tr<\/code> for Turkish) ve iste\u011fe ba\u011fl\u0131 olarak bir \u00fclke kodu (\u00f6rn. <code>US<\/code> for United States, <code>TR<\/code> for Turkey) kombinasyonundan olu\u015fur. \u00d6rne\u011fin, <code>en_US<\/code> Amerika Birle\u015fik Devletleri \u0130ngilizcesi&#8217;ni, <code>tr_TR<\/code> T\u00fcrkiye T\u00fcrk\u00e7esi&#8217;ni temsil eder. Spring, kullan\u0131c\u0131n\u0131n tercih etti\u011fi <code>Locale<\/code>&#8216;i belirleyerek ve bu <code>Locale<\/code>&#8216;e g\u00f6re i\u00e7erik sunarak i18n&#8217;yi y\u00f6netir.<\/p>\n<h4>Resource Bundles (Kaynak Paketleri \/ Mesaj Paketleri)<\/h4>\n<p>Resource Bundles, farkl\u0131 dillerdeki metin mesajlar\u0131n\u0131, etiketleri ve di\u011fer yerelle\u015ftirilmi\u015f i\u00e7eri\u011fi depolamak i\u00e7in kullan\u0131lan dosyalard\u0131r. Spring&#8217;de bu genellikle <code>.properties<\/code> uzant\u0131l\u0131 dosyalard\u0131r. Her dil ve b\u00f6lge kombinasyonu i\u00e7in ayr\u0131 bir <code>.properties<\/code> dosyas\u0131 olu\u015fturulur.<\/p>\n<p>\u00d6rnek bir yap\u0131:<br \/>\n*   <code>messages.properties<\/code>: Varsay\u0131lan dil (genellikle \u0130ngilizce) i\u00e7in mesajlar.<br \/>\n*   <code>messages_en.properties<\/code>: \u0130ngilizce mesajlar (iste\u011fe ba\u011fl\u0131, varsay\u0131lan <code>messages.properties<\/code> ise gerekmez).<br \/>\n*   <code>messages_tr.properties<\/code>: T\u00fcrk\u00e7e mesajlar.<br \/>\n*   <code>messages_de.properties<\/code>: Almanca mesajlar.<\/p>\n<p>Bu dosyalar\u0131n i\u00e7inde anahtar-de\u011fer \u00e7iftleri bulunur:<\/p>\n<pre><code class=\"language-properties\"># messages.properties\nwelcome.message=Welcome to our application!\nbutton.submit=Submit<\/code><\/pre>\n<pre><code class=\"language-properties\"># messages_tr.properties\nwelcome.message=Uygulamam\u0131za Ho\u015f Geldiniz!\nbutton.submit=G\u00f6nder<\/code><\/pre>\n<h4>MessageSource<\/h4>\n<p><code>org.springframework.context.MessageSource<\/code> aray\u00fcz\u00fc, Spring&#8217;in mesaj paketlerinden mesajlar\u0131 \u00e7\u00f6z\u00fcmlemek i\u00e7in kulland\u0131\u011f\u0131 ana bile\u015fendir. Bir <code>MessageSource<\/code> bean&#8217;i tan\u0131mlayarak, uygulaman\u0131zdaki metinleri <code>Locale<\/code>&#8216;e g\u00f6re dinamik olarak y\u00fckleyebilirsiniz.<\/p>\n<p>Spring&#8217;in en yayg\u0131n <code>MessageSource<\/code> implementasyonlar\u0131 \u015funlard\u0131r:<br \/>\n*   <code>ResourceBundleMessageSource<\/code>: Sabit bir dizindeki <code>.properties<\/code> dosyalar\u0131ndan mesajlar\u0131 y\u00fckler. Uygulama ba\u015flat\u0131ld\u0131\u011f\u0131nda t\u00fcm mesajlar\u0131 y\u00fckler ve \u00f6nbelle\u011fe al\u0131r.<br \/>\n*   <code>ReloadableResourceBundleMessageSource<\/code>: Geli\u015ftirme ortam\u0131nda \u00e7ok kullan\u0131\u015fl\u0131d\u0131r, \u00e7\u00fcnk\u00fc <code>.properties<\/code> dosyalar\u0131ndaki de\u011fi\u015fiklikleri uygulama yeniden ba\u015flat\u0131lmadan alg\u0131layabilir ve mesajlar\u0131 yeniden y\u00fckleyebilir. \u00dcretim ortam\u0131nda performans nedenleriyle genellikle <code>ResourceBundleMessageSource<\/code> tercih edilir.<\/p>\n<h4>Locale Resolvers (Yerel Ayar \u00c7\u00f6z\u00fcmleyicileri)<\/h4>\n<p><code>org.springframework.web.servlet.LocaleResolver<\/code> aray\u00fcz\u00fc, gelen her istekle birlikte kullan\u0131c\u0131n\u0131n tercih etti\u011fi <code>Locale<\/code>&#8216;i belirlemekten sorumludur. Spring, \u00e7e\u015fitli <code>LocaleResolver<\/code> implementasyonlar\u0131 sunar:<\/p>\n<p>*   <code>AcceptHeaderLocaleResolver<\/code>: HTTP iste\u011finin <code>Accept-Language<\/code> ba\u015fl\u0131\u011f\u0131na bakar. Bu, taray\u0131c\u0131 ayarlar\u0131ndan gelen varsay\u0131lan dil tercihidir. Spring&#8217;in varsay\u0131lan \u00e7\u00f6z\u00fcmleyicisidir.<br \/>\n*   <code>SessionLocaleResolver<\/code>: Kullan\u0131c\u0131n\u0131n <code>Locale<\/code>&#8216;ini HTTP oturumunda (session) saklar. Kullan\u0131c\u0131 bir kez dil se\u00e7ti\u011finde, bu tercih oturum boyunca korunur.<br \/>\n*   <code>CookieLocaleResolver<\/code>: Kullan\u0131c\u0131n\u0131n <code>Locale<\/code>&#8216;ini bir HTTP \u00e7erezinde (cookie) saklar. Bu, kullan\u0131c\u0131n\u0131n tercihini oturumlar aras\u0131nda bile hat\u0131rlamak i\u00e7in idealdir.<br \/>\n*   <code>FixedLocaleResolver<\/code>: Her zaman sabit bir <code>Locale<\/code> d\u00f6nd\u00fcr\u00fcr. Genellikle test ama\u00e7l\u0131 veya tek dilli uygulamalar i\u00e7in kullan\u0131l\u0131r.<\/p>\n<h4>LocaleChangeInterceptor (Yerel Ayar De\u011fi\u015fim Yakalay\u0131c\u0131s\u0131)<\/h4>\n<p><code>org.springframework.web.servlet.i18n.LocaleChangeInterceptor<\/code>, kullan\u0131c\u0131n\u0131n URL parametresi (\u00f6rn. <code>?lang=tr<\/code>) veya ba\u015fka bir yolla <code>Locale<\/code>&#8216;ini de\u011fi\u015ftirmesine olanak tan\u0131r. Bu interceptor, belirli bir parametreyi (varsay\u0131lan olarak <code>lang<\/code>) dinler ve bu parametre mevcutsa, <code>LocaleResolver<\/code> arac\u0131l\u0131\u011f\u0131yla kullan\u0131c\u0131n\u0131n <code>Locale<\/code>&#8216;ini de\u011fi\u015ftirir.<\/p>\n<h3>Spring MVC&#8217;de i18n\/L10n Ad\u0131m Ad\u0131m Uygulama \u00d6rne\u011fi<\/h3>\n<p>\u015eimdi, Spring Boot kullanarak \u00e7ok dilli bir web uygulamas\u0131 olu\u015fturmak i\u00e7in ad\u0131m ad\u0131m bir \u00f6rnek \u00fczerinde \u00e7al\u0131\u015fal\u0131m. Bu \u00f6rnekte Thymeleaf \u015fablon motorunu kullanaca\u011f\u0131z, ancak JSP veya di\u011fer \u015fablon motorlar\u0131yla da benzer prensipler ge\u00e7erlidir.<\/p>\n<h4>1. Proje Olu\u015fturma ve Ba\u011f\u0131ml\u0131l\u0131klar\u0131 Ekleme<\/h4>\n<p>\u00d6ncelikle, Spring Initializr (start.spring.io) kullanarak yeni bir Spring Boot projesi olu\u015ftural\u0131m. Gerekli ba\u011f\u0131ml\u0131l\u0131klar:<br \/>\n*   Spring Web<br \/>\n*   Thymeleaf<br \/>\n*   Spring Boot DevTools (iste\u011fe ba\u011fl\u0131, geli\u015ftirme kolayl\u0131\u011f\u0131 i\u00e7in)<\/p>\n<p><code>pom.xml<\/code> dosyan\u0131z\u0131n <code>dependencies<\/code> b\u00f6l\u00fcm\u00fc a\u015fa\u011f\u0131daki gibi g\u00f6r\u00fcnecektir (s\u00fcr\u00fcm numaralar\u0131 farkl\u0131l\u0131k g\u00f6sterebilir):<\/p>\n<pre><code class=\"language-xml\"><?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http:\/\/maven.apache.org\/POM\/4.0.0\" xmlns:xsi=\"http:\/\/www.w3.org\/2001\/XMLSchema-instance\"\n         xsi:schemaLocation=\"http:\/\/maven.apache.org\/POM\/4.0.0 https:\/\/maven.apache.org\/xsd\/maven-4.0.0.xsd\">\n    <modelVersion>4.0.0<\/modelVersion>\n    <parent>\n        <groupId>org.springframework.boot<\/groupId>\n        <artifactId>spring-boot-starter-parent<\/artifactId>\n        <version>3.2.5<\/version>\n        <relativePath\/> <!-- lookup parent from repository -->\n    <\/parent>\n    <groupId>com.example<\/groupId>\n    <artifactId>i18n-example<\/artifactId>\n    <version>0.0.1-SNAPSHOT<\/version>\n    <name>i18n-example<\/name>\n    <description>Spring MVC i18n Example<\/description>\n    <properties>\n        <java.version>17<\/java.version>\n    <\/properties>\n    <dependencies>\n        <groupId>org.springframework.boot<\/groupId>\n            <artifactId>spring-boot-starter-web<\/artifactId>\n        <\/dependency>\n        <dependency>\n            <groupId>org.springframework.boot<\/groupId>\n            <artifactId>spring-boot-starter-thymeleaf<\/artifactId>\n        <\/dependency>\n        <dependency>\n            <groupId>org.springframework.boot<\/groupId>\n            <artifactId>spring-boot-devtools<\/artifactId>\n            <scope>runtime<\/scope>\n            <optional>true<\/optional>\n        <\/dependency>\n        <dependency>\n            <groupId>org.springframework.boot<\/groupId>\n            <artifactId>spring-boot-starter-test<\/artifactId>\n            <scope>test<\/scope>\n        <\/dependency>\n    <\/dependencies>\n\n    <build>\n        <plugins>\n            <plugin>\n                <groupId>org.springframework.boot<\/groupId>\n                <artifactId>spring-boot-maven-plugin<\/artifactId>\n            <\/plugin>\n        <\/plugins>\n    <\/build>\n\n<\/project><\/code><\/pre>\n<h4>2. Mesaj Paketleri Olu\u015fturma<\/h4>\n<p><code>src\/main\/resources<\/code> dizini alt\u0131nda mesaj paketleri dosyalar\u0131m\u0131z\u0131 olu\u015ftural\u0131m:<\/p>\n<p>*   <code>messages.properties<\/code> (varsay\u0131lan dil &#8211; \u0130ngilizce)<br \/>\n*   <code>messages_tr.properties<\/code> (T\u00fcrk\u00e7e)<br \/>\n*   <code>messages_de.properties<\/code> (Almanca)<\/p>\n<p><strong><code>src\/main\/resources\/messages.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\">app.title=My Internationalized Application\nwelcome.message=Welcome to our application!\nlanguage.select=Select Language:\nlang.en=English\nlang.tr=Turkish\nlang.de=German<\/code><\/pre>\n<p><strong><code>src\/main\/resources\/messages_tr.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\">app.title=Uluslararas\u0131la\u015ft\u0131r\u0131lm\u0131\u015f Uygulamam\nwelcome.message=Uygulamam\u0131za Ho\u015f Geldiniz!\nlanguage.select=Dil Se\u00e7in:\nlang.en=\u0130ngilizce\nlang.tr=T\u00fcrk\u00e7e\nlang.de=Almanca<\/code><\/pre>\n<p><strong><code>src\/main\/resources\/messages_de.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\">app.title=Meine Internationalisierte Anwendung\nwelcome.message=Willkommen in unserer Anwendung!\nlanguage.select=Sprache ausw\u00e4hlen:\nlang.en=Englisch\nlang.tr=T\u00fcrkisch\nlang.de=Deutsch<\/code><\/pre>\n<h4>3. Spring Konfig\u00fcrasyonu<\/h4>\n<p>Uygulama i\u00e7in i18n bile\u015fenlerini yap\u0131land\u0131rmam\u0131z gerekiyor. Bunun i\u00e7in bir <code>WebMvcConfigurer<\/code> implementasyonu kullanabiliriz.<\/p>\n<p><strong><code>src\/main\/java\/com\/example\/i18nexample\/config\/WebConfig.java<\/code>:<\/strong><\/p>\n<pre><code class=\"language-java\">package com.example.i18nexample.config;\n\nimport org.springframework.context.MessageSource;\nimport org.springframework.context.annotation.Bean;\nimport org.springframework.context.annotation.Configuration;\nimport org.springframework.context.support.ReloadableResourceBundleMessageSource;\nimport org.springframework.web.servlet.LocaleResolver;\nimport org.springframework.web.servlet.config.annotation.InterceptorRegistry;\nimport org.springframework.web.servlet.config.annotation.WebMvcConfigurer;\nimport org.springframework.web.servlet.i18n.CookieLocaleResolver;\nimport org.springframework.web.servlet.i18n.LocaleChangeInterceptor;\n\nimport java.util.Locale;\n\n@Configuration\npublic class WebConfig implements WebMvcConfigurer {\n\n    \/\/ 1. MessageSource Bean'i Tan\u0131mlama\n    @Bean\n    public MessageSource messageSource() {\n        ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();\n        messageSource.setBasenames(\"classpath:messages\"); \/\/ messages.properties, messages_tr.properties vb.\n        messageSource.setDefaultEncoding(\"UTF-8\"); \/\/ Karakter kodlamas\u0131n\u0131 UTF-8 olarak ayarla\n        messageSource.setCacheSeconds(3600); \/\/ Mesajlar\u0131 1 saat \u00f6nbellekte tut\n        return messageSource;\n    }\n\n    \/\/ 2. LocaleResolver Bean'i Tan\u0131mlama\n    @Bean\n    public LocaleResolver localeResolver() {\n        \/\/ CookieLocaleResolver kullanarak kullan\u0131c\u0131n\u0131n dil tercihini \u00e7erezde saklayal\u0131m.\n        \/\/ B\u00f6ylece taray\u0131c\u0131 kapat\u0131l\u0131p a\u00e7\u0131lsa bile tercih korunur.\n        CookieLocaleResolver localeResolver = new CookieLocaleResolver();\n        localeResolver.setDefaultLocale(Locale.ENGLISH); \/\/ Varsay\u0131lan dil \u0130ngilizce\n        localeResolver.setCookieName(\"language\"); \/\/ \u00c7erezin ad\u0131\n        localeResolver.setCookieMaxAge(3600 <em> 24 <\/em> 30); \/\/ \u00c7erezi 30 g\u00fcn boyunca sakla\n        return localeResolver;\n    }\n\n    \/\/ 3. LocaleChangeInterceptor Bean'i Tan\u0131mlama ve Kaydetme\n    @Bean\n    public LocaleChangeInterceptor localeChangeInterceptor() {\n        LocaleChangeInterceptor lci = new LocaleChangeInterceptor();\n        lci.setParamName(\"lang\"); \/\/ URL'deki dil parametresi (\u00f6rn. ?lang=tr)\n        return lci;\n    }\n\n    @Override\n    public void addInterceptors(InterceptorRegistry registry) {\n        registry.addInterceptor(localeChangeInterceptor());\n    }\n}<\/code><\/pre>\n<p><strong>A\u00e7\u0131klamalar:<\/strong><br \/>\n*   <code>MessageSource<\/code>: <code>ReloadableResourceBundleMessageSource<\/code> kulland\u0131k. Bu, geli\u015ftirme s\u0131ras\u0131nda <code>.properties<\/code> dosyalar\u0131nda yap\u0131lan de\u011fi\u015fikliklerin uygulama yeniden ba\u015flat\u0131lmadan alg\u0131lanmas\u0131n\u0131 sa\u011flar. <code>setBasenames(\"classpath:messages\")<\/code> ile <code>messages.properties<\/code> \u00f6nekli dosyalar\u0131 aramas\u0131n\u0131 s\u00f6yledik.<br \/>\n*   <code>LocaleResolver<\/code>: <code>CookieLocaleResolver<\/code> se\u00e7tik. Bu, kullan\u0131c\u0131n\u0131n dil tercihini bir \u00e7erezde saklayarak, taray\u0131c\u0131 kapansa bile bu tercihin hat\u0131rlanmas\u0131n\u0131 sa\u011flar. <code>setDefaultLocale(Locale.ENGLISH)<\/code> ile varsay\u0131lan dilin \u0130ngilizce oldu\u011funu belirledik.<br \/>\n*   <code>LocaleChangeInterceptor<\/code>: Bu interceptor, URL&#8217;deki <code>lang<\/code> parametresini dinler. \u00d6rne\u011fin, <code>http:\/\/localhost:8080\/?lang=tr<\/code> iste\u011fi geldi\u011finde, <code>LocaleChangeInterceptor<\/code> bu parametreyi yakalar ve <code>LocaleResolver<\/code> arac\u0131l\u0131\u011f\u0131yla kullan\u0131c\u0131n\u0131n dilini T\u00fcrk\u00e7e olarak ayarlar. Daha sonra, t\u00fcm sayfalardaki i\u00e7erik T\u00fcrk\u00e7e olarak g\u00f6sterilir.<\/p>\n<h4>4. Controller Olu\u015fturma<\/h4>\n<p>\u015eimdi ana sayfam\u0131z\u0131 g\u00f6sterecek basit bir controller olu\u015ftural\u0131m.<\/p>\n<p><strong><code>src\/main\/java\/com\/example\/i18nexample\/controller\/HomeController.java<\/code>:<\/strong><\/p>\n<pre><code class=\"language-java\">package com.example.i18nexample.controller;\n\nimport org.springframework.stereotype.Controller;\nimport org.springframework.web.bind.annotation.GetMapping;\n\n@Controller\npublic class HomeController {\n\n    @GetMapping(\"\/\")\n    public String home() {\n        return \"index\"; \/\/ index.html (Thymeleaf) \u015fablonunu d\u00f6nd\u00fcr\n    }\n}<\/code><\/pre>\n<h4>5. View Olu\u015fturma (Thymeleaf ile)<\/h4>\n<p><code>src\/main\/resources\/templates<\/code> dizini alt\u0131nda <code>index.html<\/code> dosyam\u0131z\u0131 olu\u015ftural\u0131m. Thymeleaf, i18n mesajlar\u0131n\u0131 kolayca entegre etmek i\u00e7in <code>#{...}<\/code> s\u00f6zdizimini kullan\u0131r.<\/p>\n<p><strong><code>src\/main\/resources\/templates\/index.html<\/code>:<\/strong><\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html xmlns:th=\"http:\/\/www.thymeleaf.org\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title th:text=\"#{app.title}\"><\/title>\n    <style>\n        body { font-family: Arial, sans-serif; margin: 20px; }\n        .language-selector a { margin-right: 10px; text-decoration: none; color: #007bff; }\n        .language-selector a:hover { text-decoration: underline; }\n        h1 { color: #333; }\n    <\/style>\n<\/head>\n<body>\n    \n\n    <div class=\"language-selector\">\n        <span th:text=\"#{language.select}\">Select Language:<\/span>\n        <a th:href=\"@{\/?lang=en}\" th:text=\"#{lang.en}\">English<\/a>\n        <a th:href=\"@{\/?lang=tr}\" th:text=\"#{lang.tr}\">Turkish<\/a>\n        <a th:href=\"@{\/?lang=de}\" th:text=\"#{lang.de}\">German<\/a>\n    <\/div>\n\n<\/body>\n<\/html><\/code><\/pre>\n<p><strong>A\u00e7\u0131klamalar:<\/strong><br \/>\n*   <code>th:text=\"#{app.title}\"<\/code>: Bu Thymeleaf ifadesi, <code>messageSource<\/code>&#8216;dan <code>app.title<\/code> anahtar\u0131n\u0131n de\u011ferini al\u0131r ve mevcut <code>Locale<\/code>&#8216;e g\u00f6re ekrana basar.<br \/>\n*   Dil de\u011fi\u015ftirme ba\u011flant\u0131lar\u0131: <code>th:href=\"@{\/?lang=en}\"<\/code> gibi ba\u011flant\u0131lar, <code>LocaleChangeInterceptor<\/code>&#8216;\u0131n dinledi\u011fi <code>lang<\/code> parametresini kullanarak dilin de\u011fi\u015ftirilmesini sa\u011flar. Kullan\u0131c\u0131 bir dile t\u0131klad\u0131\u011f\u0131nda, <code>LocaleChangeInterceptor<\/code> devreye girer, <code>LocaleResolver<\/code> arac\u0131l\u0131\u011f\u0131yla \u00e7erezdeki <code>Locale<\/code>&#8216;i g\u00fcnceller ve sayfa yeniden y\u00fcklenir.<\/p>\n<h4>6. Uygulamay\u0131 \u00c7al\u0131\u015ft\u0131rma ve Test Etme<\/h4>\n<p>Uygulamay\u0131 \u00e7al\u0131\u015ft\u0131rd\u0131ktan sonra (\u00f6rne\u011fin, IDE&#8217;nizden main metodu ile veya <code>mvn spring-boot:run<\/code> komutuyla):<br \/>\n1.  Taray\u0131c\u0131n\u0131zda <code>http:\/\/localhost:8080\/<\/code> adresine gidin. Varsay\u0131lan dil olan \u0130ngilizce i\u00e7eri\u011fi g\u00f6rmelisiniz.<br \/>\n2.  &#8220;Turkish&#8221; ba\u011flant\u0131s\u0131na t\u0131klay\u0131n. Sayfa yeniden y\u00fcklenecek ve t\u00fcm metinler T\u00fcrk\u00e7e&#8217;ye d\u00f6necektir.<br \/>\n3.  &#8220;German&#8221; ba\u011flant\u0131s\u0131na t\u0131klay\u0131n. Sayfa yeniden y\u00fcklenecek ve t\u00fcm metinler Almanca&#8217;ya d\u00f6necektir.<br \/>\n4.  Taray\u0131c\u0131n\u0131z\u0131 kapat\u0131p tekrar a\u00e7t\u0131\u011f\u0131n\u0131zda, <code>CookieLocaleResolver<\/code> sayesinde en son se\u00e7ti\u011finiz dilin hala aktif oldu\u011funu g\u00f6receksiniz.<\/p>\n<h4>7. Formlarda i18n ve Do\u011frulama Mesajlar\u0131<\/h4>\n<p>Spring MVC, formlarla \u00e7al\u0131\u015f\u0131rken de i18n deste\u011fi sunar. Thymeleaf&#8217;te form alanlar\u0131n\u0131n etiketlerini ve do\u011frulama (validation) mesajlar\u0131n\u0131 da mesaj paketlerinden alabilirsiniz.<\/p>\n<p>\u00d6rne\u011fin, bir kullan\u0131c\u0131 giri\u015f formu d\u00fc\u015f\u00fcnelim.<br \/>\n\u00d6nce form do\u011frulama mesajlar\u0131 i\u00e7in yeni bir mesaj paketi olu\u015ftural\u0131m:<br \/>\n<strong><code>src\/main\/resources\/ValidationMessages.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\">NotBlank.user.username=Username cannot be empty.\nSize.user.username=Username must be between {min} and {max} characters.<\/code><\/pre>\n<p><strong><code>src\/main\/resources\/ValidationMessages_tr.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\">NotBlank.user.username=Kullan\u0131c\u0131 ad\u0131 bo\u015f b\u0131rak\u0131lamaz.\nSize.user.username=Kullan\u0131c\u0131 ad\u0131 {min} ile {max} karakter aras\u0131nda olmal\u0131d\u0131r.<\/code><\/pre>\n<p><code>WebConfig<\/code> s\u0131n\u0131f\u0131m\u0131zda <code>MessageSource<\/code>&#8216;a bu yeni paketi ekleyelim:<\/p>\n<pre><code class=\"language-java\">\/\/ ...\n@Bean\npublic MessageSource messageSource() {\n    ReloadableResourceBundleMessageSource messageSource = new ReloadableResourceBundleMessageSource();\n    \/\/ Birden fazla basename belirtebiliriz\n    messageSource.setBasenames(\"classpath:messages\", \"classpath:ValidationMessages\"); \n    messageSource.setDefaultEncoding(\"UTF-8\");\n    messageSource.setCacheSeconds(3600);\n    return messageSource;\n}\n\/\/ ...<\/code><\/pre>\n<p>\u015eimdi bir model ve controller olu\u015ftural\u0131m:<br \/>\n<strong><code>src\/main\/java\/com\/example\/i18nexample\/model\/User.java<\/code>:<\/strong><\/p>\n<pre><code class=\"language-java\">package com.example.i18nexample.model;\n\nimport jakarta.validation.constraints.NotBlank;\nimport jakarta.validation.constraints.Size;\n\npublic class User {\n\n    @NotBlank\n    @Size(min = 3, max = 20)\n    private String username;\n\n    private String password; \/\/ Basitlik ad\u0131na validasyon eklemedik\n\n    \/\/ Getters and Setters\n    public String getUsername() {\n        return username;\n    }\n\n    public void setUsername(String username) {\n        this.username = username;\n    }\n\n    public String getPassword() {\n        return password;\n    }\n\n    public void setPassword(String password) {\n        this.password = password;\n    }\n}<\/code><\/pre>\n<p><strong><code>src\/main\/java\/com\/example\/i18nexample\/controller\/UserController.java<\/code>:<\/strong><\/p>\n<pre><code class=\"language-java\">package com.example.i18nexample.controller;\n\nimport com.example.i18nexample.model.User;\nimport jakarta.validation.Valid;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.validation.BindingResult;\nimport org.springframework.web.bind.annotation.GetMapping;\nimport org.springframework.web.bind.annotation.ModelAttribute;\nimport org.springframework.web.bind.annotation.PostMapping;\n\n@Controller\npublic class UserController {\n\n    @GetMapping(\"\/login\")\n    public String showLoginForm(Model model) {\n        model.addAttribute(\"user\", new User());\n        return \"login\";\n    }\n\n    @PostMapping(\"\/login\")\n    public String processLogin(@Valid @ModelAttribute(\"user\") User user, BindingResult bindingResult) {\n        if (bindingResult.hasErrors()) {\n            return \"login\"; \/\/ Hata varsa formu tekrar g\u00f6ster\n        }\n        \/\/ Giri\u015f ba\u015far\u0131l\u0131, ba\u015fka bir sayfaya y\u00f6nlendir\n        return \"redirect:\/success\";\n    }\n\n    @GetMapping(\"\/success\")\n    public String loginSuccess() {\n        return \"success\";\n    }\n}<\/code><\/pre>\n<p><strong><code>src\/main\/resources\/templates\/login.html<\/code>:<\/strong><\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html xmlns:th=\"http:\/\/www.thymeleaf.org\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title th:text=\"#{app.title} + ' - ' + #{login.form.title}\"><\/title>\n    <style>\n        body { font-family: Arial, sans-serif; margin: 20px; }\n        .language-selector a { margin-right: 10px; text-decoration: none; color: #007bff; }\n        .language-selector a:hover { text-decoration: underline; }\n        h1 { color: #333; }\n        .error { color: red; font-size: 0.9em; margin-top: 5px; }\n        label { display: block; margin-top: 10px; }\n        input[type=\"text\"], input[type=\"password\"] { padding: 8px; margin-top: 5px; width: 200px; }\n        button { padding: 10px 15px; margin-top: 15px; background-color: #28a745; color: white; border: none; cursor: pointer; }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"language-selector\">\n        <span th:text=\"#{language.select}\">Select Language:<\/span>\n        <a th:href=\"@{\/login?lang=en}\" th:text=\"#{lang.en}\">English<\/a>\n        <a th:href=\"@{\/login?lang=tr}\" th:text=\"#{lang.tr}\">Turkish<\/a>\n        <a th:href=\"@{\/login?lang=de}\" th:text=\"#{lang.de}\">German<\/a>\n    <\/div>\n\n    \n\n    <form th:action=\"@{\/login}\" th:object=\"${user}\" method=\"post\">\n        <div>\n            <label for=\"username\" th:text=\"#{login.form.username}\">Username:<\/label>\n            <input type=\"text\" id=\"username\" th:field=\"*{username}\" \/>\n            <span th:if=\"${#fields.hasErrors('username')}\" th:errors=\"*{username}\" class=\"error\">Username Error<\/span>\n        <\/div>\n        <div>\n            <label for=\"password\" th:text=\"#{login.form.password}\">Password:<\/label>\n            <input type=\"password\" id=\"password\" th:field=\"*{password}\" \/>\n        <\/div>\n        <div>\n            <button type=\"submit\" th:text=\"#{button.submit}\">Submit<\/button>\n        <\/div>\n    <\/form>\n<\/body>\n<\/html><\/code><\/pre>\n<p><strong><code>src\/main\/resources\/templates\/success.html<\/code>:<\/strong><\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html xmlns:th=\"http:\/\/www.thymeleaf.org\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title th:text=\"#{app.title} + ' - ' + #{login.success.title}\"><\/title>\n    <style>\n        body { font-family: Arial, sans-serif; margin: 20px; }\n        h1 { color: #333; }\n        p { font-size: 1.1em; }\n    <\/style>\n<\/head>\n<body>\n    \n    <p th:text=\"#{login.success.message}\">You have successfully logged in.<\/p>\n<\/body>\n<\/html><\/code><\/pre>\n<p><code>messages.properties<\/code> dosyalar\u0131na yeni anahtarlar ekleyelim:<br \/>\n<strong><code>messages.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\"># ... (\u00f6nceki anahtarlar)\nlogin.form.title=User Login\nlogin.form.username=Username:\nlogin.form.password=Password:\nlogin.success.title=Login Successful!\nlogin.success.message=You have successfully logged in.<\/code><\/pre>\n<p><strong><code>messages_tr.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\"># ... (\u00f6nceki anahtarlar)\nlogin.form.title=Kullan\u0131c\u0131 Giri\u015fi\nlogin.form.username=Kullan\u0131c\u0131 Ad\u0131:\nlogin.form.password=\u015eifre:\nlogin.success.title=Giri\u015f Ba\u015far\u0131l\u0131!\nlogin.success.message=Ba\u015far\u0131yla giri\u015f yapt\u0131n\u0131z.<\/code><\/pre>\n<p>Bu \u00f6rnekte, <code>th:errors=\"*{username}\"<\/code> Thymeleaf \u00f6zelli\u011fi sayesinde, <code>@NotBlank<\/code> ve <code>@Size<\/code> gibi validasyon anotasyonlar\u0131ndan gelen hata mesajlar\u0131 otomatik olarak <code>ValidationMessages.properties<\/code> dosyas\u0131ndan al\u0131n\u0131r ve mevcut <code>Locale<\/code>&#8216;e g\u00f6re ekranda g\u00f6sterilir.<\/p>\n<h4>8. Tarih ve Say\u0131 Bi\u00e7imlendirme (L10n)<\/h4>\n<p>i18n sadece metin \u00e7evirisi de\u011fil, ayn\u0131 zamanda <code>Locale<\/code>&#8216;e \u00f6zg\u00fc tarih, saat ve say\u0131 bi\u00e7imlendirmesini de i\u00e7erir. Spring, bu konuda da g\u00fc\u00e7l\u00fc destek sunar.<\/p>\n<p><code>@DateTimeFormat<\/code> ve <code>@NumberFormat<\/code> anotasyonlar\u0131, modeldeki alanlar\u0131n <code>Locale<\/code>&#8216;e g\u00f6re bi\u00e7imlendirilmesini sa\u011flar.<\/p>\n<p>\u00d6rne\u011fin, bir \u00fcr\u00fcn modelimiz olsun:<br \/>\n<strong><code>src\/main\/java\/com\/example\/i18nexample\/model\/Product.java<\/code>:<\/strong><\/p>\n<pre><code class=\"language-java\">package com.example.i18nexample.model;\n\nimport org.springframework.format.annotation.DateTimeFormat;\nimport org.springframework.format.annotation.NumberFormat;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\n\npublic class Product {\n    private String name;\n\n    @NumberFormat(style = NumberFormat.Style.CURRENCY) \/\/ Para birimi olarak formatla\n    private BigDecimal price;\n\n    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE) \/\/ ISO tarih format\u0131, Locale'e g\u00f6re g\u00f6sterilir\n    private LocalDate manufacturingDate;\n\n    \/\/ Constructors, Getters and Setters\n    public Product(String name, BigDecimal price, LocalDate manufacturingDate) {\n        this.name = name;\n        this.price = price;\n        this.manufacturingDate = manufacturingDate;\n    }\n\n    public String getName() { return name; }\n    public void setName(String name) { this.name = name; }\n    public BigDecimal getPrice() { return price; }\n    public void setPrice(BigDecimal price) { this.price = price; }\n    public LocalDate getManufacturingDate() { return manufacturingDate; }\n    public void setManufacturingDate(LocalDate manufacturingDate) { this.manufacturingDate = manufacturingDate; }\n}<\/code><\/pre>\n<p>Bir controller ve view ile bu veriyi g\u00f6sterelim:<br \/>\n<strong><code>src\/main\/java\/com\/example\/i18nexample\/controller\/ProductController.java<\/code>:<\/strong><\/p>\n<pre><code class=\"language-java\">package com.example.i18nexample.controller;\n\nimport com.example.i18nexample.model.Product;\nimport org.springframework.stereotype.Controller;\nimport org.springframework.ui.Model;\nimport org.springframework.web.bind.annotation.GetMapping;\n\nimport java.math.BigDecimal;\nimport java.time.LocalDate;\n\n@Controller\npublic class ProductController {\n\n    @GetMapping(\"\/product\")\n    public String showProduct(Model model) {\n        Product product = new Product(\"Laptop\", new BigDecimal(\"1234.56\"), LocalDate.of(2023, 10, 26));\n        model.addAttribute(\"product\", product);\n        return \"product\";\n    }\n}<\/code><\/pre>\n<p><strong><code>src\/main\/resources\/templates\/product.html<\/code>:<\/strong><\/p>\n<pre><code class=\"language-html\"><!DOCTYPE html>\n<html xmlns:th=\"http:\/\/www.thymeleaf.org\">\n<head>\n    <meta charset=\"UTF-8\">\n    <title th:text=\"#{app.title} + ' - ' + #{product.detail.title}\"><\/title>\n    <style>\n        body { font-family: Arial, sans-serif; margin: 20px; }\n        .language-selector a { margin-right: 10px; text-decoration: none; color: #007bff; }\n        .language-selector a:hover { text-decoration: underline; }\n        h1 { color: #333; }\n        p { margin-bottom: 5px; }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"language-selector\">\n        <span th:text=\"#{language.select}\">Select Language:<\/span>\n        <a th:href=\"@{\/product?lang=en}\" th:text=\"#{lang.en}\">English<\/a>\n        <a th:href=\"@{\/product?lang=tr}\" th:text=\"#{lang.tr}\">Turkish<\/a>\n        <a th:href=\"@{\/product?lang=de}\" th:text=\"#{lang.de}\">German<\/a>\n    <\/div>\n\n    \n\n    <p><strong th:text=\"#{product.name}\">Name:<\/strong> <span th:text=\"${product.name}\">Laptop<\/span><\/p>\n    <p><strong th:text=\"#{product.price}\">Price:<\/strong> <span th:text=\"${product.price}\">1234.56<\/span><\/p>\n    <p><strong th:text=\"#{product.manufacturing.date}\">Manufacturing Date:<\/strong> <span th:text=\"${product.manufacturingDate}\">2023-10-26<\/span><\/p>\n\n<\/body>\n<\/html><\/code><\/pre>\n<p><code>messages.properties<\/code> dosyalar\u0131na yeni anahtarlar ekleyelim:<br \/>\n<strong><code>messages.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\"># ...\nproduct.detail.title=Product Details\nproduct.name=Name:\nproduct.price=Price:\nproduct.manufacturing.date=Manufacturing Date:<\/code><\/pre>\n<p><strong><code>messages_tr.properties<\/code>:<\/strong><\/p>\n<pre><code class=\"language-properties\"># ...\nproduct.detail.title=\u00dcr\u00fcn Detaylar\u0131\nproduct.name=Ad\u0131:\nproduct.price=Fiyat\u0131:\nproduct.manufacturing.date=\u00dcretim Tarihi:<\/code><\/pre>\n<p><code>product.html<\/code> sayfas\u0131n\u0131 ziyaret etti\u011finizde ve dili de\u011fi\u015ftirdi\u011finizde, \u00fcr\u00fcn ad\u0131 gibi statik metinlerin yan\u0131 s\u0131ra, fiyat (<code>1.234,56 TL<\/code> vs. <code>$1,234.56<\/code>) ve \u00fcretim tarihi (<code>26.10.2023<\/code> vs. <code>Oct 26, 2023<\/code>) gibi alanlar\u0131n da <code>Locale<\/code>&#8216;e g\u00f6re otomatik olarak bi\u00e7imlendirildi\u011fini g\u00f6receksiniz. Spring&#8217;in formatlama deste\u011fi, bu t\u00fcr L10n ihtiya\u00e7lar\u0131n\u0131 otomatik olarak kar\u015f\u0131lar.<\/p>\n<h3>Geli\u015fmi\u015f Konular ve En \u0130yi Uygulamalar<\/h3>\n<h4>Mesaj Paketleri Y\u00f6netimi<\/h4>\n<p>B\u00fcy\u00fck uygulamalarda, t\u00fcm mesajlar\u0131 tek bir <code>messages.properties<\/code> dosyas\u0131na koymak y\u00f6netimi zorla\u015ft\u0131rabilir. Uygulaman\u0131n farkl\u0131 b\u00f6l\u00fcmleri i\u00e7in ayr\u0131 mesaj paketleri (\u00f6rn. <code>validation.properties<\/code>, <code>errors.properties<\/code>, <code>dashboard.properties<\/code>) olu\u015fturmak ve bunlar\u0131 <code>MessageSource<\/code>&#8216;a <code>setBasenames<\/code> metodunda virg\u00fclle ay\u0131rarak eklemek iyi bir uygulamad\u0131r.<\/p>\n<h4>Veritaban\u0131ndan Mesaj Y\u00fckleme<\/h4>\n<p>Baz\u0131 durumlarda, mesajlar\u0131 <code>.properties<\/code> dosyalar\u0131nda tutmak yerine bir veritaban\u0131nda depolamak isteyebilirsiniz. Bu, \u00e7evirilerin dinamik olarak g\u00fcncellenmesi veya CMS (\u0130\u00e7erik Y\u00f6netim Sistemi) entegrasyonu gibi senaryolarda faydal\u0131d\u0131r. Spring&#8217;in <code>MessageSource<\/code> aray\u00fcz\u00fcn\u00fc implemente ederek kendi \u00f6zel <code>DatabaseMessageSource<\/code>&#8216;unuzu olu\u015fturabilirsiniz.<\/p>\n<h4>Varsay\u0131lan Dil (Fallback Locale)<\/h4>\n<p>Bir <code>Locale<\/code> i\u00e7in belirli bir mesaj bulunamad\u0131\u011f\u0131nda, Spring varsay\u0131lan <code>Locale<\/code>&#8216;e (genellikle <code>messages.properties<\/code> taraf\u0131ndan temsil edilen <code>Locale<\/code>) geri d\u00f6ner. Bu davran\u0131\u015f, <code>MessageSource<\/code> yap\u0131land\u0131rmas\u0131nda <code>fallbackToSystemLocale<\/code> gibi \u00f6zelliklerle ayarlanabilir. Mesaj paketlerinizde her zaman bir varsay\u0131lan dil oldu\u011fundan emin olun.<\/p>\n<h4>SEO ve i18n<\/h4>\n<p>Uluslararas\u0131la\u015ft\u0131r\u0131lm\u0131\u015f web siteleri i\u00e7in arama motoru optimizasyonu (SEO) yaparken, farkl\u0131 dil ve b\u00f6lge varyantlar\u0131n\u0131 arama motorlar\u0131na bildirmek \u00f6nemlidir. Bunun i\u00e7in <code>hreflang<\/code> etiketleri kullan\u0131l\u0131r. \u00d6rne\u011fin:<\/p>\n<pre><code class=\"language-html\"><link rel=\"alternate\" href=\"http:\/\/example.com\/en-us\" hreflang=\"en-us\" \/>\n<link rel=\"alternate\" href=\"http:\/\/example.com\/tr-tr\" hreflang=\"tr-tr\" \/><\/code><\/pre>\n<p>Bu etiketler, arama motorlar\u0131na bir sayfan\u0131n farkl\u0131 dil veya b\u00f6lge versiyonlar\u0131n\u0131n nerede bulundu\u011funu s\u00f6yler.<\/p>\n<h4>Test Etme<\/h4>\n<p>i18n ve L10n \u00f6zelliklerini test ederken, farkl\u0131 <code>Locale<\/code>&#8216;leri sim\u00fcle etmek \u00f6nemlidir. Spring MockMvc ile testler yazarken, HTTP iste\u011fine <code>Accept-Language<\/code> ba\u015fl\u0131\u011f\u0131 ekleyerek veya <code>LocaleChangeInterceptor<\/code>&#8216;\u0131n parametresini (\u00f6rn. <code>?lang=tr<\/code>) kullanarak farkl\u0131 dillerdeki yan\u0131tlar\u0131 test edebilirsiniz.<\/p>\n<h4>Performans Konular\u0131<\/h4>\n<p><code>ResourceBundleMessageSource<\/code> ve <code>ReloadableResourceBundleMessageSource<\/code> mesajlar\u0131 \u00f6nbelle\u011fe al\u0131r. <code>ReloadableResourceBundleMessageSource<\/code>&#8216;un <code>setCacheSeconds<\/code> metodu ile \u00f6nbellek s\u00fcresini ayarlayabilirsiniz. \u00dcretim ortam\u0131nda, mesaj paketlerinin s\u0131k s\u0131k de\u011fi\u015fmedi\u011fi durumlarda <code>setCacheSeconds<\/code> de\u011ferini y\u00fcksek tutmak veya <code>ResourceBundleMessageSource<\/code> kullanmak performans\u0131 art\u0131rabilir.<\/p>\n<h3>Sonu\u00e7<\/h3>\n<p>Spring MVC, uygulamalar\u0131n\u0131z\u0131 uluslararas\u0131la\u015ft\u0131rmak ve yerelle\u015ftirmek i\u00e7in kapsaml\u0131 ve esnek bir \u00e7er\u00e7eve sunar. <code>MessageSource<\/code>, <code>LocaleResolver<\/code> ve <code>LocaleChangeInterceptor<\/code> gibi temel bile\u015fenler sayesinde, farkl\u0131 dilleri ve k\u00fclt\u00fcrel tercihleri destekleyen uygulamalar geli\u015ftirmek olduk\u00e7a basittir. Bu makalede sunulan ad\u0131m ad\u0131m \u00f6rnek ve a\u00e7\u0131klamalarla, kendi Spring MVC uygulaman\u0131zda i18n ve L10n&#8217;yi ba\u015far\u0131yla uygulayabilir ve k\u00fcresel bir kullan\u0131c\u0131 kitlesine hitap edebilirsiniz. K\u00fcreselle\u015fen d\u00fcnyada, kullan\u0131c\u0131 deneyimini zenginle\u015ftirmek ve pazar eri\u015fimini geni\u015fletmek i\u00e7in i18n ve L10n&#8217;nin \u00f6nemi yads\u0131namaz. Spring Framework, bu s\u00fcreci geli\u015ftiriciler i\u00e7in olabildi\u011fince sorunsuz hale getirerek, daha eri\u015filebilir ve kullan\u0131c\u0131 dostu uygulamalar olu\u015fturmam\u0131za olanak tan\u0131r.<\/body><\/p>\n","protected":false},"excerpt":{"rendered":"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi\nSpring Framework, modern web uygulamalar\u0131n\u0131n geli\u015ftirilmesinde en \u00e7ok terc","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"csco_page_header_type":"","csco_page_load_nextpost":"","csco_page_subscribe_form":"","csco_page_contact_form":"","footnotes":""},"categories":[1490],"tags":[],"class_list":{"0":"post-38767","1":"post","2":"type-post","3":"status-publish","4":"format-standard","6":"category-mvc","7":"cs-entry","8":"cs-video-wrap"},"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v20.5 (Yoast SEO v25.3.1) - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/\" \/>\n<meta property=\"og:locale\" content=\"tr_TR\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi\" \/>\n<meta property=\"og:description\" content=\"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi Spring Framework, modern web uygulamalar\u0131n\u0131n geli\u015ftirilmesinde en \u00e7ok terc\" \/>\n<meta property=\"og:url\" content=\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/\" \/>\n<meta property=\"og:site_name\" content=\"Kodlar\u0131n Gizemli D\u00fcnyas\u0131\" \/>\n<meta property=\"article:published_time\" content=\"2026-02-07T06:40:47+00:00\" \/>\n<meta name=\"author\" content=\"Fatih Soysal\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Yazan:\" \/>\n\t<meta name=\"twitter:data1\" content=\"Fatih Soysal\" \/>\n\t<meta name=\"twitter:label2\" content=\"Tahmini okuma s\u00fcresi\" \/>\n\t<meta name=\"twitter:data2\" content=\"16 dakika\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/\"},\"author\":{\"name\":\"Fatih Soysal\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"headline\":\"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi\",\"datePublished\":\"2026-02-07T06:40:47+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/\"},\"wordCount\":1960,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"articleSection\":[\"MVC\"],\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/#respond\"]}],\"copyrightYear\":\"2026\",\"copyrightHolder\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/\",\"name\":\"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131\",\"isPartOf\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\"},\"datePublished\":\"2026-02-07T06:40:47+00:00\",\"breadcrumb\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/#breadcrumb\"},\"inLanguage\":\"tr\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Anasayfa\",\"item\":\"https:\/\/fatihsoysal.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#website\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/\",\"name\":\"Fatihsoysal.com\",\"description\":\"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim\",\"publisher\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"tr\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1\",\"name\":\"Fatih Soysal\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"tr\",\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"contentUrl\":\"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png\",\"width\":512,\"height\":512,\"caption\":\"Fatih Soysal\"},\"logo\":{\"@id\":\"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/\"},\"description\":\"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.\",\"url\":\"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/","og_locale":"tr_TR","og_type":"article","og_title":"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi","og_description":"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi Spring Framework, modern web uygulamalar\u0131n\u0131n geli\u015ftirilmesinde en \u00e7ok terc","og_url":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/","og_site_name":"Kodlar\u0131n Gizemli D\u00fcnyas\u0131","article_published_time":"2026-02-07T06:40:47+00:00","author":"Fatih Soysal","twitter_card":"summary_large_image","twitter_misc":{"Yazan:":"Fatih Soysal","Tahmini okuma s\u00fcresi":"16 dakika"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/#article","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/"},"author":{"name":"Fatih Soysal","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"headline":"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi","datePublished":"2026-02-07T06:40:47+00:00","mainEntityOfPage":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/"},"wordCount":1960,"commentCount":0,"publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"articleSection":["MVC"],"inLanguage":"tr","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/#respond"]}],"copyrightYear":"2026","copyrightHolder":{"@id":"https:\/\/fatihsoysal.com\/blog\/#organization"}},{"@type":"WebPage","@id":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/","url":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/","name":"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi - Kodlar\u0131n Gizemli D\u00fcnyas\u0131","isPartOf":{"@id":"https:\/\/fatihsoysal.com\/blog\/#website"},"datePublished":"2026-02-07T06:40:47+00:00","breadcrumb":{"@id":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/#breadcrumb"},"inLanguage":"tr","potentialAction":[{"@type":"ReadAction","target":["https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/fatihsoysal.com\/blog\/spring-mvc-internationalization-i18n-ve-localization-l10n-ornegi\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Anasayfa","item":"https:\/\/fatihsoysal.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Spring MVC Internationalization (i18n) ve Localization (L10n) \u00d6rne\u011fi"}]},{"@type":"WebSite","@id":"https:\/\/fatihsoysal.com\/blog\/#website","url":"https:\/\/fatihsoysal.com\/blog\/","name":"Fatihsoysal.com","description":"Blog - Yaz\u0131l\u0131m D\u00fcnyas\u0131 Tecr\u00fcbelerim","publisher":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/fatihsoysal.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"tr"},{"@type":["Person","Organization"],"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/002a254750921dcfd568a99e48240dd1","name":"Fatih Soysal","image":{"@type":"ImageObject","inLanguage":"tr","@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/","url":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","contentUrl":"https:\/\/fatihsoysal.com\/blog\/wp-content\/uploads\/2024\/04\/cropped-replicate-prediction-3kgg1hgjn5rgp0cf0p5tr0jw7w-1.png","width":512,"height":512,"caption":"Fatih Soysal"},"logo":{"@id":"https:\/\/fatihsoysal.com\/blog\/#\/schema\/person\/image\/"},"description":"Kullan\u0131m ve kodlama m\u00fckemmeliyetini odak alan uygulamalar olu\u015fturma deneyimine sahip, profesyonel olarak 15+ y\u0131l \u00fczeri deneyime sahip bir yaz\u0131l\u0131m m\u00fchendisi.","url":"https:\/\/fatihsoysal.com\/blog\/author\/fatihsoysal\/"}]}},"yoast_meta":{"yoast_wpseo_title":"","yoast_wpseo_metadesc":"","yoast_wpseo_canonical":""},"amp_enabled":true,"_links":{"self":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38767","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/comments?post=38767"}],"version-history":[{"count":1,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38767\/revisions"}],"predecessor-version":[{"id":38768,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/posts\/38767\/revisions\/38768"}],"wp:attachment":[{"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/media?parent=38767"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/categories?post=38767"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/fatihsoysal.com\/blog\/wp-json\/wp\/v2\/tags?post=38767"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}