eray aydoğdu

jQuery and ASP.NET MVC fanatic.

Asp.Net MVC Çoklu Dil Desteği

İki dil site yapımı ya da çoklu dil desteği olan bir site yapımı için session veya cache yöntemi de kullanılabilir fakat profesyonel bir uygulamada bu en iyi çözüm yolu değil. Bunun en güçlü ve pratik yolu dil değişkenini asp.net mvc nin url routing mekanizmasını kullanarak saklamaktır.

Amaç url nin şu şekilde gözükmesini sağlamak : /{culture}/{Controller}/{Action} yani /tr/Home/About

Öncelikle MvcRouteHandler class ını extend etmemiz gerekiyor. Culture parametresi için MultiCultureMvcRouteHandler ve culture parametresi kullanmayacağımız SingleCultureMvcRouteHandler class larımızı oluşturalım.

Custom Route Handlers oluşturalım

public class MultiCultureMvcRouteHandler : MvcRouteHandler
{
    protected override IHttpHandler GetHttpHandler(RequestContext requestContext)
    {
        var culture = requestContext.RouteData.Values["culture"].ToString();
        var ci = new CultureInfo(culture);
        Thread.CurrentThread.CurrentUICulture = ci;
        Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
        return base.GetHttpHandler(requestContext);
    }
}

Base implementation ını çağırmadan önce GetHttpHandler override ederken RouteData collection ından culture parametresini alıyoruz, CultureInfo objesi yaratıp current culture ve current thread özelliklerini ayarladık.

public class SingleCultureMvcRouteHandler : MvcRouteHandler {}

Bu class ı culture yani dil ayarı yapmamızı gerektirmeyen sayfaları için kullanacağız.

Registering Routes (Route larımızı tanımlayalım)

Global.asax dosyasındaki RegisterRoute() methodumuzu açalım. Default route tanımlamasının altına aşağıda ki foreach blogunu ekleyelim.

public static void RegisterRoutes(RouteCollection routes)
{
    routes.IgnoreRoute("{resource}.axd/{*pathInfo}");

    routes.MapRoute(
         "Default", // Route name
         "{controller}/{action}/{id}", // URL with parameters
         new { controller = "Home", action = "Index", id = UrlParameter.Optional } // Parameter defaults
    );

    foreach (Route r in routes)
    {
        if (!(r.RouteHandler is SingleCultureMvcRouteHandler))
        {
            r.RouteHandler = new MultiCultureMvcRouteHandler();
            r.Url = "{culture}/" + r.Url;

           if (r.Defaults == null)
           {
               r.Defaults = new RouteValueDictionary();
           }
           r.Defaults.Add("culture", Culture.tr.ToString());

           if (r.Constraints == null)
           {
               r.Constraints = new RouteValueDictionary();
           }
           r.Constraints.Add("culture", new CultureConstraint(Culture.en.ToString(),
Culture.tr.ToString()));
        }
   }

}

Culture enum ve CultureConstraint class larımızıda oluşturalım.

public class CultureConstraint : IRouteConstraint
{
    private string[] _values;
    public CultureConstraint(params string[] values)
    {
        this._values = values;
    }

    public bool Match(HttpContextBase httpContext,Route route,string parameterName,
                        RouteValueDictionary values, RouteDirection routeDirection)
    {

        string value = values[parameterName].ToString();
        return _values.Contains(value);

    }

}
    public enum Culture
    {
        tr = 1,
        en = 2
    }

Dil değiştirme İşlemi

Dil değişikliği yapmak için aşağıdaki gibi basit bir Action ımız var. AccountController mıza koyabiliriz. İstersiniz HomeController a da koyabilirsiniz.

public ActionResult ChangeCulture(Culture lang, string returnUrl)
{
     if (returnUrl.Length >= 3)
     {
         returnUrl = returnUrl.Substring(3);
     }
     return Redirect("/" + lang.ToString() + returnUrl);
}

İkinci dil e geçmek için CultureSwitchControl.ascx adında bir partial view oluşturdum. Bununda kodu aşağıda ki gibi:

<%@ Control Language="C#" Inherits="System.Web.Mvc.ViewUserControl" %>

<%= Html.ActionLink("eng", "ChangeCulture", "Account",
    new { lang = (int)MvcLocalization.Helpers.Culture.en, returnUrl =
    this.Request.RawUrl }, new { @class = "culture-link" })%>

<%= Html.ActionLink("tr", "ChangeCulture", "Account",
    new { lang = (int)MvcLocalization.Helpers.Culture.tr, returnUrl =
    this.Request.RawUrl }, new { @class = "culture-link" })%>

Tek Dil

Eğer tek dile ihtiyaç duyacağımız sayfalar olursa onuda RouteHandler ını SingleCultureMvcRouteHandler olarak Global.asax ta tanımlamamız gerekecek.

routes.MapRoute(
          "AboutRoute",
          "About",
          new { controller = "Home", action = "About"}
   ).RouteHandler = new SingleCultureMvcRouteHandler();

Localization işlemi bu kadar.

Çok dilli web uygulaması yaparken karşınıza iki sorun daha çıkacak. Telaşlanmayın işin zor kısmını zaten hallettiniz. Geriye sayfa içinde ki sabit yazılar (örn. “Son Yazılar”,”Son Yorumlar”) ve dile göre değişecek resimler bannerler. Bu sorunu Resources Files kullanarak çok basit atlatabilirsiniz. Ancak resimler için tavsiyem 2 ayrı klasör oluşturup (tr ve en) adında dillere ait dosyalarınızı bu klasörlere atmanız ve sayfa içinde kullanacağınız zaman url deki parametreyle aynı olan dosya adınıza yol vermenizdir örneğin;

../../Content/tr/logo.jpg ve ../../Content/en/logo.jpg şeklinde url deki parametreyi sayfa içine taşırsanız(ister class yapın ister ViewData[“dil”] ile taşıyın farketmez) bu sorunu halledebilirsiniz.

Sabit yazılar içinse yine aynı yöntemi kullabilirsiniz fakat çok uzun sürebilir o yüzden tavsiyem Resources Files kullanmanızdır. bu konuda ufak bir araştırma ile çok sayıda dökümana ulaşabilirsiniz, üstelik kullanımı çok kolay

11 Responses to “Asp.Net MVC Çoklu Dil Desteği”

  1. Yazınızı okudum uyguladım ama takıldığım bi kaç nokta var.
    3 ncü veya 4 ncü dil koymak istediğimde nasıl yapıyoruz. CultureSwitchControl.ascx dosyasında hata aldım…
    Resource files dosyası nasıl bu sisteme entegre edilip çalıştırılır.
    birde linklere tıklandığında yazıların dilleri değişmedi nasıl değişecek bunları çözemedim.

    Yorum by Hilmi SARI — 15 Ağustos 2011 @ 13:54

  2. 1-)başka bir dil daha eklemek istiyorsan “culture enum” tanımlayabilirsin.
    2-)CultureSwitchControl.ascx dosyasında nasıl bir hata aldın yazarsan yardımcı olmaya çalışayım.
    3-)Public Resource file ekleyip sonuna istediğin dilin culture parametresini eklemen yeterli. Nasıl ekleneceğini kısa bir araştırma ile resimli halinde bulabilirsin.
    4-)Dil değiştirme linkine tıkladıktan sonra resource file’dan aldığı stringlerin ilişkili dile ait olanları gelmesi gerekiyor. Tahminim resource files ların namespace leriyle ilgili bir karışıklık yaşamış olduğunu düşünüyorum.

    Yorum by Eray Aydoğdu — 19 Ağustos 2011 @ 07:52

  3. merhaba,
    paylaşımınız için teşekkürler.türkçe kaynaklar arasında bulduğum en iyi örnek diyebilirim.
    bir de örnek bir proje koysaydınız daha iyi olabilirdi :) iyi çalışmalar!

    Yorum by altuğ — 04 Eylül 2011 @ 19:14

  4. Hilmi SARI
    Culture Switch view a @Html.ActionLink(“fr”, “ChangeCulture”, “Default”,
    new { lang = (int)MvcMultiDil.Models.Culture.fr, returnUrl =
    this.Request.RawUrl }, new { @class = “culture-link” })
    Culture Enum olan yeri

    public enum Culture
    {
    tr = 1,
    en = 2,
    fr = 3
    }

    Global.asax daki kodu
    r.Constraints.Add(“culture”, new CultureConstraint(Culture.en.ToString(),Culture.tr.ToString(),Culture.fr.ToString()));

    bu şekilde değiştirin fransızca için.

    Yorum by Serkan — 07 Haziran 2012 @ 15:11

  5. admin çok zordurumdayım bunu mutlaka yapmak zorundayım açıkcası bunu pek anlamadım kaynak dosyaların lütfen göndere bilirmisiniz çok zor durumdayım bunu yapmamı istediler kripto_tuna@hotmail.com

    Yorum by mustafa — 03 Temmuz 2012 @ 06:43

  6. mustafa, kaynak kodlarını zaten paylaştım makalede yapman gereken yeni bir mvc projesi oluşturman ve buradaki kodları boş projeye geçirmen..

    Yorum by Eray Aydoğdu — 04 Temmuz 2012 @ 08:14

  7. Merhabalar;
    Her şeyi sizin gibi yaptım daha sonra lang.resx ve lang.en.resx dosyaları ekledim içersine ver girdim daha sonra bir class yazdım bunun içeresine

    [Display(ResourceType = typeof(lang), Name = “Menu_AnaSayfa”)]
    public string AnaSayfa { get; set; }
    Kod blogunu yazdım

    ANCAK projeyi çalıştırdığımda

    public static string Menu_AnaSayfa {
    get {
    return ResourceManager.GetString(“Menu_AnaSayfa”, resourceCulture);
    } buradaki resourceCulture null geliyor buda hata vermesine sebeb oluyor. Acaba sizden sonra yaptıklarım da bir hatamı var ?

    Yorum by Vehbi — 24 Haziran 2013 @ 11:56

  8. @Html.ActionLink(“en”, “ChangeCulture”, “Home”,
    new { lang = (int)MvcLocalization.Helpers.Culture.en, returnUrl =
    this.Request.RawUrl }, new { @class = “culture-link” })

    MvcLocalization yazdığımda hata alıyorum sebebi ne olabilir.

    Yorum by Mert — 03 Nisan 2014 @ 11:59

  9. Ne hatası alıyorsun bilemedim ancak tahminim, Helper ‘ının namespace ini bir kontrol et sanırım ondan kaynaklı olabilir.

    Yorum by Eray Aydoğdu — 03 Nisan 2014 @ 12:17

  10. sanırım MvcLocalization adında bir model oluşturmam gerekli değil mi

    Yorum by Mert — 03 Nisan 2014 @ 12:26

  11. Eğer benim gibi buradaki mvc2 anlatımı ile mcv3 te bu olayı yapmak isterseniz CultureSwitchControl partialView’iniz Şu şekilde olmalıdır.

    @Html.ActionLink(“Türkçe”, “ChangeCulture”, “Home”, new { lang = “tr”, returnUrl = this.Request.RawUrl }, null)
    |@Html.ActionLink(“English”, “ChangeCulture”, “Home”, new { lang = “en”, returnUrl = this.Request.RawUrl }, null)
    |@Html.ActionLink(“Almanca”, “ChangeCulture”, “Home”, new { lang = “de”, returnUrl = this.Request.RawUrl }, null)
    |@Html.ActionLink(“Rusça”, “ChangeCulture”, “Home”, new { lang = “ru”, returnUrl = this.Request.RawUrl }, null)

    Kolaygelsin.

    Yorum by Mert — 03 Nisan 2014 @ 15:34

Bu yazıya yapılan yorumlar için RSS beslemeleri. TrackBack URL

Leave a Response