استخدام Globalization & Localization

-

في هذا الدرس بنحكي عن الاعدادت configuration المطلوبه لإعداد موقع متعدد اللغات باستخدام ميزة Localisation & Globalization  في ASP.NET Core. ستتعلم هنا كيفية إنشاء موقع متعدد اللغات يدعم لغتين: وهي الإنجليزية والعربية.واكيد طبعا بنفس الطريقة بتقدر تضيف لغات حسب الحاجه.

Globalization هي عملية تصميم المواقع التي تدعم الثقافات المختلفة. تضيف Globalization دعمًا للإدخال والعرض والإخراج لمجموعة محددة من نصوص اللغات المختلفة.

Localization هو عملية تكييف globalized site ، الذي قمنا بتطبيقه بالفعل بمعالجته من أجل localizability ، فيما يتعلق ب culture/locale.

Internationalization  ينطوي على دعم كل من Globalization and Localization.

من المهم عند تطبيق globalization في مواقع الويب هي القدرة على تحديد اللغة أو الثقافة المطلوبة. وهذا الامر يلزم وجود آلية لتحديد المحتوى بناءً على client’s culture. فيما يلي بنحكي عن التفاصيل المطلوبة حتي نطبق هذا الكلام.
تمام نبدأ بالمطلوب:

اولا : تجهيز الاعدادات Configuring ل Globalization & Localization في Startup class

يجب اضافة سطر الكود التالي في ()ConfigureServices 
public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc()
        .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);

}
واكيد حتي يتعرف هذا الكود صح لازم نضيف namespaces الضرورية وهي :
using System.Globalization;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Options;
using Microsoft.AspNetCore.Mvc.Razor;


ثانيا: بنحتاج إلى تحديد languages or cultures المطلوب تطبيقها في الموقع. لتفعيل هذه الاعدادات بنحتاج الى اضافة الكود:

 services.Configure<RequestLocalizationOptions>(options =>
            {
                var supportedCultures = new[]
                {
                new CultureInfo("en-US"),
                new CultureInfo("ar-jo")
                };
                options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
                options.SupportedCultures = supportedCultures;
                options.SupportedUICultures = supportedCultures;
            });
استخدمنا CultureInfo class الي بوفر معلومات خاصة ب culture، مثل اللغة واللغة الفرعية والبلد / المنطقة والتقويم ... الخ.
لاحظ ان في الكود السابق اضفنا اللغات الانجليزية والعربية الى supportedCultures  
وبعدها حددنا اللغة الافتراضية باستخدام الكود:
 options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");

ثالثا:تطبيق الكود التالي فيConfigure() method

// after app.UseRouting();
    var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
    app.UseRequestLocalization(locOptions.Value);
في هذا الكود يتم تعيين نوع culture الحالية المطلوبة بواسطة مستعرض العميل في localization Middleware.

ملاحظة :يجب عمل configured ل  localization middleware  للترجمة قبل أي middleware قد تتحقق من request culture (على سبيل المثال : ()app.UseMvcWithDefaultRoute).

تستفيد Localization Middleware من المكون المسمى RequestCultureProviders لتحديد culture للطلب الحالي الذي ارسل من العميل.

يوجد 3 اناع من RequestCultureProviders والي بتستخدم لتحديد request culture بنجاح. وهذه الاناع هي:

  • QueryStringRequestCultureProvider - يتم تمرير culture and ui-culture في query string.

CookieRequestCultureProvider - يتم تعيين culture في ASP.NET Core culture cookie.

AcceptLanguageHeaderRequestCultureProvider - والتي تحصل على culture من لغة المتصفح التي حددها المستخدم.


الخطوة التالية :  تطبيق Request Culture

تمام حتي نفهم الموضوع خلونا نعمل Controller باسم GlobalizationController والكود : 

using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace StudentsAcademy.Controllers
{
    public class GlobalizationController : Controller
    {
        public IActionResult Index()
        {
            return View();
        }
    }
}

وبعدها نعمل View بالنقر يمين فوق index action ونضيف الكود التالي : 

@{
    ViewData["Title"] = "Home Page";
}
<div class="text-center">
    <h1 class="display-4">Welcome</h1>
</div>
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Localization
@using Microsoft.Extensions.Options
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
    ViewBag.message = cultureItems;
}
<form id="cultureForm" asp-action="Index">
    <label>Language:</label>
    <select onchange="SetCulture(this.value)" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
    </select>
   
</form>
<table class="table culture-table">
    <tr>
        <td>Culture</td>
        <td>
            @requestCulture.RequestCulture.Culture.Name
        </td>
    </tr>
    <tr>
        <td>UICulture</td>
        <td>
            @requestCulture.RequestCulture.UICulture.Name
        </td>
    </tr>
    <tr>
        <td>Date</td>
        <td>
            @DateTime.Now.ToLongDateString()
        </td>
    </tr>
    <tr>
        <td>Currency</td>
        <td>
            @(1000.00.ToString("c"))
        </td>
    </tr>
    <tr>
        <td>Number</td>
        <td>
            @(145.88m.ToString("F2"))
        </td>
    </tr>
</table>
<script>
    function SetCulture(selectedValue) {
        var culture = "/?culture=" + selectedValue + "&ui-culture=" + selectedValue;
        document.getElementById("cultureForm").action = culture;
        document.getElementById("cultureForm").submit();
    }
</script>

تمام نفهم شو عملنا في الكود:

الهدف من هذا View هو عرض الصفحة حسب اللغة المختارة بحيث يتم تغيير بعض الحقول بناء على اللغة مثال : التاريخ، العملة ... الخ.

تمام نرجع للكود واكيد بتشوف في البداية استخدمنا مجموعه من namespaces وهي : 

@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Localization
@using Microsoft.Extensions.Options

بعد هيك اضفنا الكود: 

@inject IOptions<RequestLocalizationOptions> LocOptions

الهدف من هذا الكود هو الحصول على RequestLocalizationOptions الي استخدمناها في startup class وعرفنا فيها اللغات الي بنستخدمها في الموقع بغرض عرضها في View.
الكود التالي :
@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
    ViewBag.message = cultureItems;
}


استخدمنا الامر ()Context.Features.Get  بهدف الحصول على culture المطلوبة من العميل. وبعدها رجعنا كل culture الي تم تعريفها في startup وتم تخزينها في List بهدف عرضها في Dropdown List للاختيار بينهم. 

الكود التالي هو: 

<form id="cultureForm" asp-action="Index">
    <label>Language:</label>
    <select onchange="SetCulture(this.value)" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
    </select>
</form>

في هذا الكود عرفنا form باسم cultureForm بحيث يكون مربوط مع action المسمى index عند الاختيار ، وعرفنا javascript function لاجراء التغيير المطلوب onchange="SetCulture(this.value)" واستخدمنا الكود asp-items="cultureItems" لعرض القيم culture داخل Dropdown .

كود JavaScript هو :

<script>
    function SetCulture(selectedValue) {
        var culture = "/?culture=" + selectedValue + "&ui-culture=" + selectedValue;
        document.getElementById("cultureForm").action = culture;
        document.getElementById("cultureForm").submit();
    }
</script>

استقبلنا قيمة culture وبعثناها في query string بالاسماء culture & ui-culture وبعدها عملنا submitل Form

الكود المتبقي هو كود HTML عادي عرضنا فيها Culture باسخدام الامر :

 @requestCulture.RequestCulture.Culture.Name

و UICulture باستخدام الامر :

 @requestCulture.RequestCulture.UICulture.Name
والتاريخ والعملة والارقام. 

تمام نشغل الصفحة ونشوف النتيجة: 

اكيد بتكون النتيجة عرض اللغات المدعومه في الموقع ب Dropdown List جرب تغير القيم وشوف نتيجة التغيير في الصفحه.

  


تمام 


نفهم شو هي RequestCultureProvider

عندما يبدأ المستعرض بارسال طلب إلى Server. يجب أن تكون هناك طريقة لتحديد culture التي تم طلبها من العميل.وهذه اعملية تتم بواسطة RequestCultureProviders.يوجد 3 اناع من هذا RequestCultureProviders هي:

  • QueryStringRequestCultureProvider

CookieRequestCultureProvider

AcceptLanguageHeaderRequestCultureProvider


الطريقة الأولى QueryStringRequestCultureProvider
تعتمد هذا الطريقة على ارسال culture بواسطة query string ويتم استخدام query string keys المسماة culture & ui-culture لهذا الغرض. وهي نفس الطريقة الي طبقناها سابقا. 

مثال : 
https://localhost:44356/?culture=ar-JO&ui-culture=ar-JO
في هذا الكود نخبر Server ان culture المطلوبة هي ar-JO والتي تعني اللغة العربية - الاردن.

الطريقة الثانية CookieRequestCultureProvider
في هذا provider، يتم تعيين culture في ASP.NET Core culture cookie. اسم default cookie name هو AspNetCore.Culture.
تمام نطبق مثال عملي حتي نفهم الموضوع. 
نرجع الى GlobalizationController ونعمل action جديده باسم cookie وبكون الكود: 
 public IActionResult Cookie()
            {
                return View();
            }
[HttpPost]
public IActionResult Cookie(string culture)
{
  Response.Cookies.Append(
   CookieRequestCultureProvider.DefaultCookieName,
   CookieRequestCultureProvider.MakeCookieValue(new RequestCulture(culture)),
   new CookieOptions { Expires = DateTimeOffset.UtcNow.AddMonths(1) }
   );
  return RedirectToAction("Cookie");
}

اكيد لاحظت ان في هاذي الطريقة استخدمنا Parameter من نوع String مع action . وهذا Parameter هو قيمة culture المرسلة من المستخدم في المتصفح.ثم استخدمنا MakeCookieValue action لإنشاء cookie هذا.
الكود CookieRequestCultureProvider.DefaultCookieName يرجع اسم default cookie المستخدم لتتبع معلومات culture المفضلة للمستخدم.

تمام الان خلونا نعمل View لهاذ action وبكون الكود : 

@{
    ViewData["Title"] = "Cookie Page";
}
<div class="text-center">
    <h1 class="display-4">Welcome</h1>
</div>
@using Microsoft.AspNetCore.Builder
@using Microsoft.AspNetCore.Localization
@using Microsoft.Extensions.Options
@inject IOptions<RequestLocalizationOptions> LocOptions
@{
    var requestCulture = Context.Features.Get<IRequestCultureFeature>();
    var cultureItems = LocOptions.Value.SupportedUICultures
        .Select(c => new SelectListItem { Value = c.Name, Text = c.DisplayName })
        .ToList();
}
<form asp-action="Cookie" method="post">
    <label>Language:</label>
    <select name="culture" onchange="this.form.submit()" asp-for="@requestCulture.RequestCulture.UICulture.Name" asp-items="cultureItems">
    </select>
</form>
<table class="table culture-table">
    <tr>
        <td>Culture</td>
        <td>
            @requestCulture.RequestCulture.Culture.Name
        </td>
    </tr>
    <tr>
        <td>UICulture</td>
        <td>
            @requestCulture.RequestCulture.UICulture.Name
        </td>
    </tr>
    <tr>
        <td>Date</td>
        <td>
            @DateTime.Now.ToLongDateString()
        </td>
    </tr>
    <tr>
        <td>Currency</td>
        <td>
            @(1000.00.ToString("c"))
        </td>
    </tr>
    <tr>
        <td>Number</td>
        <td>
            @(145.88m.ToString("F2"))
        </td>
    </tr>
</table>

اكيد لاحظت ان الكود هو نفس الكود السابق باستثناء  form block التي تشير إلى "asp-action="Cookie عند الإرسال. بالاضافة الى تغيير onchange event الخاص بكود Javascript 

شغل الصحفة بادخال الرابط :

https://localhost:44356/Globalization/Cookie

واكيد بتكوت النتيجة كالتالي(جرب تغير باللغة وشوف النتيجة)




افتح الآن " Developer Tools" في متصفحك وانتقل إلى علامة ‘Application’ tab. يمكنك العثور على cookie هذا في قسم " Cookies ".




الطريقة الثالثة AcceptLanguageHeaderRequestCultureProvider

يقوم مبدأ عمل AcceptLanguageHeaderRequestCultureProvider في استخدام culture المستخدم من إعدادات لغة المتصفح. في Chrome ،وحتي نفهم الموضوع خلونا نعمل اضافة للغة جديده الى Chrome  يمكنك إضافة لغة جديدة عن طريق فتح عنوان
chrome://settings/languages

خلونا نجرب نضيف لغة الاوردو Urdu مثلا الى Chrome ونعملها اول لغة في المتصفح

ننتقل الى GlobalizationController ونضيف action باسم Browser والكود الخاص به هو :

 public IActionResult Browser()
            {
                return View();
            }

تمام الان دور نعمل إنشاء View باسم Browser  وفيها قم بإنشاء جدول html يعرض فقط التاريخ الحالي والعملة والرقم:
الكود الخاص بهذا View :
@{
    ViewData["Title"] = "Browser Page";
}
<div class="text-center">
    <h1 class="display-4">Welcome</h1>
</div>
<table class="table culture-table">
    <tr>
        <td>Date</td>
        <td>
            @DateTime.Now.ToLongDateString()
        </td>
    </tr>
    <tr>
        <td>Currency</td>
        <td>
            @(1000.00.ToString("c"))
        </td>
    </tr>
    <tr>
        <td>Number</td>
        <td>
            @(145.88m.ToString("F2"))
        </td>
    </tr>
</table>
تمام نجرب الصفحة ولكن قبل عرض هذه الصفحة ، تأكد من حذف ملف AspNetCore.Culture cookie من علامة التبويب Network  الخاصة بـ " Developer tools’" في متصفح Chrome. وإلا سيتم تعيين culture  على أساس culture المخزنة فيها.

الآن قم بتشغيل التطبيق الخاص بك وافتح عنوان url الخاص بأسلوب إجراء "Browser" والذي في حالتي هو
 https://localhost:44356/Home/Browser