Asp.NET MVC Çoklu Dil Fonksiyonları

Herkes  Yazar Herkes Yazar

12 Ocak 2017 Yazılım Dilleri (152) /Asp.Net MVC (110) (981)

Paylaşmak güzeldir. Lütfen sizde paylaşın...


Solution Explorer penceresinden projemize sağ tıklayıp, “Add” -> “Add ASP.NET Folder” -> “Add_GlobalResources” kombinasyonlarını takip edip, bu klasörü projemize eklemiş oluyoruz.

Oluşturduğumuz bu “Add_GlobalResources” isimdeki özel dosyanın içine, kelimelerimizin farklı dillerdeki karşılıklarını yazacağımız Resources dosayasını ekleyelim.
“Add_GlobalResources” klasörüne sağ tıklayıp, “Add” sekmesinden “New Item” seçeneğini seçelim.Çıkan pencereden “Resources File” dosyasına tıklayalım.Burada dikkat etmemiz gereken bir husus var.Bu Resource dosyasının adına ben şimdilik “lang” diyoruz
(*kullanacağımız sınıflar varsayılan olarak “lang” adında bir parametre kullanıyorlar.* varsayılan dil olarak “lang” ismindeki Resource dosyasını kullanacağız.Yani oluşturacağımız dilin standardına göre “lang.fr”(Fransızca) gibisinden isimlerde Resource dosyaları oluşturuacağız.Bu standartlar önemlidir.Mesela Türkçe’de “.tr”, İngilizce’de “en” gibi…)
“lang.resx” dosyamızı açarsak karşımıza aşağıdaki gibi bir pencere gelecektir.

Projemizde “CokluDilSiniflari” adli bir klasör açıyoruz

--- Localization.cs ---
  public class LocalizationAttribute : ActionFilterAttribute
       {
           public override void OnActionExecuting(ActionExecutingContext filterContext)
           {
               if (filterContext.RouteData.Values["lang"] != null &&
                   !string.IsNullOrWhiteSpace(filterContext.RouteData.Values["lang"].ToString()))
               {
                   // set the culture from the route data (url)
                   var lang = filterContext.RouteData.Values["lang"].ToString();
                   Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(lang);
               }
               else
               {
                   // load the culture info from the cookie
                   var cookie = filterContext.HttpContext.Request.Cookies["MvcLocalization.CurrentUICulture"];
                   var langHeader = string.Empty;
                   if (cookie != null)
                   {
                       // set the culture by the cookie content
                       langHeader = cookie.Value;
                       Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader);
                   }
                   else
                   {
                       // set the culture by the location if not speicified
                       langHeader = filterContext.HttpContext.Request.UserLanguages[0];
                       Thread.CurrentThread.CurrentUICulture = CultureInfo.CreateSpecificCulture(langHeader);
                   }
                   // set the lang value into route data
                   filterContext.RouteData.Values["lang"] = langHeader;
               }
               // save the location into cookie
               HttpCookie _cookie = new HttpCookie("MvcLocalization.CurrentUICulture", Thread.CurrentThread.CurrentUICulture.Name);
               _cookie.Expires = DateTime.Now.AddYears(1);
               filterContext.HttpContext.Response.SetCookie(_cookie);
               base.OnActionExecuting(filterContext);
           }
       }

“Localization” sınıfı “ActionFilterAttribute” sınıfından türediği için bir Attribute sınıfıdır.Bu Attribute’un yazıldığı Controller metodu çalıştığı anda, adres çubuğundan “filterContext.RouteData.Values[“lang”]” kodu ile, “lang” değişkenindeki değeri arayacaktır.

“lang” değişkenine gelen değere göre, sitemizde hangi dil dosyasının çalışacağını belirleyecektir.

Şimdide, “ResourceExtensions” isimdeki sınıfı inceleyelim.

--- ResourceExtensions.cs ---
    public static class ResourceExtensions
    {
        public static string Resource(this Controller controller, string expression, params object[] args)
        {
            ResourceExpressionFields fields = GetResourceFields(expression, "~/");
            return GetGlobalResource(fields, args);
        }
        public static string Resource(this HtmlHelper htmlHelper, string expression, params object[] args)
        {
            string path = (string)htmlHelper.ViewData[LocalizationWebFormView.ViewPathKey];
            if (string.IsNullOrEmpty(path))
                path = "~/";

            ResourceExpressionFields fields = GetResourceFields(expression, path);
            if (!string.IsNullOrEmpty(fields.ClassKey))
                return GetGlobalResource(fields, args);

            return GetLocalResource(path, fields, args);
        }
        public static string Language(this HtmlHelper htmlHelper, string controller, string key, params object[] args)
        {
            //Replace Language with a name of your choice, if you have lang.en.resx, you should change the value here to "lang"
            string expression ;
            if(controller!="")
                expression = "lang"+controller+"," + key;
            else
                expression = "lang," + key;
            return Resource(htmlHelper, expression, args);
        }
        static string GetLocalResource(string path, ResourceExpressionFields fields, object[] args)
        {
            try
            {
                return string.Format((string)HttpContext.GetLocalResourceObject(path, fields.ResourceKey, CultureInfo.CurrentUICulture), args);
            }
            catch { return (string)HttpContext.GetLocalResourceObject(path, fields.ResourceKey, CultureInfo.CurrentUICulture); }
        }
        static string GetGlobalResource(ResourceExpressionFields fields, object[] args)
        {
            try
            {
                return string.Format((string)HttpContext.GetGlobalResourceObject(fields.ClassKey, fields.ResourceKey, CultureInfo.CurrentUICulture), args);
            }
            catch { return (string)HttpContext.GetGlobalResourceObject(fields.ClassKey, fields.ResourceKey, CultureInfo.CurrentUICulture); }
        }
        static ResourceExpressionFields GetResourceFields(string expression, string virtualPath)
        {
            var context = new ExpressionBuilderContext(virtualPath);
            var builder = new ResourceExpressionBuilder();
            return (ResourceExpressionFields)builder.ParseExpression(expression, typeof(string), context);
        }
    }

Şimdide “LocalizationWebFormView” ismindeki sınıfımızı inceleyelim.

public class LocalizationWebFormView:WebFormView
{
    internal const string ViewPathKey = "~/App_GlobalResources/";
    public LocalizationWebFormView(string viewPath)
        : base(viewPath)
    {
    }
    public LocalizationWebFormView(string viewPath, string masterPath)
        : base(viewPath, masterPath)
    {
    }
    public override void Render(ViewContext viewContext, TextWriter writer)
    {
        // there seems to be a bug with RenderPartial tainting the page's view data
        // so we should capture the current view path, and revert back after rendering
        string originalViewPath = (string)viewContext.ViewData[ViewPathKey];
        viewContext.ViewData[ViewPathKey] = ViewPath;
        base.Render(viewContext, writer);
        viewContext.ViewData[ViewPathKey] = originalViewPath;
    }
}

Bu sınıf içinde önemli olan nokta, “ViewPathKey” ismindeki sabit değişken, Resource dosyalarımızın hangi klasör altında olduğunu belirtmektedir.
MVC projesi, hazır “Home(Controller)” adında bir Controller sınıfı bulundurmaktadır.Bu sınıfın içinde ActionResult tipinden “Index” adındaki metodun, View katmanındaki dosyasına aşağıdaki gibi yapı oluşturun.

<table width="60%">
    <tr>
        <td>
            İsim
        </td>
        <td>
            Soyisim
        </td>
        <td>
            Yaş
        </td>
        <td>
            Meslek
        </td>
    </tr>
</table>
<system.web>
...
    <pages>
      <namespaces>
        <add namespace="System.Web.Mvc" />
        <add namespace="System.Web.Mvc.Ajax" />
        <add namespace="System.Web.Mvc.Html" />
        <add namespace="System.Web.Routing" />
        <add namespace="MVCCokluDil.CokluDilSiniflari" />
      </namespaces>
    </pages>
...
  </system.web>

Şimdi “lang.resx” dosyasını varsayılan olarak kabul ettiğimden dolayı, projemizin varsayılan dil lügatını oluşturalım.

Şimdi “Index.aspx” sayfamızda varsayılan olsun olmasın, dil yapımıza göre verilerimiz gösterilir.

<table width="60%">
    <tr>
        <td>
            <%: Html.Language("","İsim") %>
        </td>
        <td>
            <%: Html.Language("","Soyisim") %>
        </td>
        <td>
            <%: Html.Language("","Yaş") %>
        </td>
        <td>
            <%: Html.Language("","Meslek") %>
        </td>
    </tr>
</table>

Ve son olarak “Home(Controller)” isimdeki Controller sınıfımızdaki ActionResult tipinden olan “Index” metoduna “Localization” Attribute’unu yazalım.

[Localization]
public ActionResult Index()
{
    return View();
}

Farklı dil eklemek için;
“Add_GlobalResources” klasörüne sağ tıklayıp, “Add” sekmesinden “New Item” seçeneğini seçelim.Çıkan pencereden “Resources File” dosyasına tıklayalım.Resource dosyamızın adına “lang.tr.resx” yazalım ve “Add” butonunu işaretliyelim.

Anımsarsanız, “Localization” ismindeki attribute sınıfımız içinde bulunan “OnActionExecuting” metodunda, “filterContext.RouteData.Values[“lang”]” koduyla adres çubuğundaki “lang” değişkeninin taşıdığı değeri alıyordu.Bu “lang” değişkenine bir değer göndermediğimiz zaman, “ResourceExtensions” isimdeki sınıfımız içinde bulunan “Language” metodumuz, uygulamamızda direkt “lang” ismindeki Resource dosyasını çalıştırıyordu.Eğer bu “lang” değişkenine “.tr” gibi bir değer gönderirsek, “lang.tr” ismindeki Resource dosyası çalıştırılacaktır ve uygulamamızın dile “.tr” olacaktır.

Ee haliyle biz uygulamamızın URL Routing sistemine, “lang” değerini tutan bir kalıp oluşturmalıyız.

Projemizin Global.asax dosyasına aşağıdaki gibi bir metod oluşturuyorun.

routes.MapRoute("CokluDil",
    "{lang}/{controller}/{action}/{id}",
    new { controller = "Home", action = "Index", id = UrlParameter.Optional }
    );

Bu işlemi yaptıktan sonra projemizi başlatıyoruz.”Home(Controller)” ismindeki Controller sınıfımızın “Index” metodu çalıştırılıyor.(Bir önceki yazımızda bu Action metodu Localization attribute u ile işaretlemiş bulunmaktayız)

Tarayıcımızın adres çubuğuna “http://localhost:****/tr/Home” benzer bir URL yapısı girersek eğer, uygulamamızın dil yapısının Türkçe olduğunu göreceksiniz.

Aynı şekilde, “lang.en.resx” dosyası oluşturup, anahtar değerler karşılığı olarak İngilizce terimleri girelim ve aynı işlemleri yapalım.

“http://localhost:****/en/Home” URL yapısını giresek eğer, uygulamımızın dili bu sefer İngilizce olacaktır.

 

Konu ile alakalı bu linkteki bir diğer makalemizi okumanız tavsiye olunur.

 


Paylaşmak güzeldir. Lütfen sizde paylaşın...



Herkesyazar Ara