افزودن قابلیت چندزبانه و internationalization به ASP.net Core

به نام خدا. در این آموزش قصد دارم نحوه افزودن قابلیت پشتیبانی از چندین زبان (چندزبانه) و internationalization در ASP.net Core را خدمتتان آموزش دهم.

کدهای این آموزش را می توانید از لینک زیر دانلود و استفاده کنید:

کدهای این آموزش در آدرس زیر قابل مشاهده و دانلود است
https://github.com/MohammadMoeinFazeli/ASP.netCore_Internationalization

internationalization چیست و قابلیت چندزبانه چه سودی دارد؟

internationalization یا به اختصار i18n که به فارسی بین المللی کردن ترجمه می شود، به هماهنگی سایت یا نرم افزار با منطقه جغرافیای کاربر اشاره دارد. این هماهنگی عموما از نظر زبانی است. یعنی زبان متون یک سایت متناسب با زبان کاربر تغییر کند. این قابلیت چند زبانه می تواند امکان استفاده از سایت یا نرم افزار شما را توسط کاربران مختلف با زبان های گوناگون فراهم کند.

برای پیاده سازی کامل قابلیت چندزبانه در یک سایت، توسعه دهنده باید این قابلیت را هم به سمت UI و هم سمت Backend اضافه کند. در این آموزش به نحوه ی افزودن این قابلیت به کدهای سمت سرور (BackEnd) با ASP.net Core خواهیم پرداخت.

پیاده سازی یک پروژه ی WebAPI پایه با ASP.net Core

برای ایجاد قابلیت های چند زبانه و internationalization در سمت سرور ابتدا یک پروژه ASP.net Core جدید ایجاد کنید. اگر نیاز به راهنمایی دارید از آموزش های زیر استفاده کنید:

– آموزش ویدئویی ASP.net Core WebAPI

– ایجاد اولین پروژه Web API در ASP.net Core با Visual Studio 2019

ایجاد یک Controller چند زبانه

برای پیاده سازی قابلیت چند زبانه در یک کنترلر باید از سرویس StringLocalizer با کمک اینترفیس IStringLocalizer استفاده کنید. برای این کار کنترلری با نام SampleController در کدهای زیر ایجاد کردیم و در تابع Get مقدار عبارت برگشت داده شده را متناسب با زبان مدنظر کاربر ترجمه و خروجی مناسب را برگرداندیم: (سایر جزییات و تنظیمات در ادامه ی آموزش آمده است… لطفا شکیبا باشید!!!)

public class SampleController : ControllerBase
    {
        private readonly IStringLocalizer<SampleController> _localizer;

        public SampleController(IStringLocalizer<SampleController> localizer)
        {
            _localizer = localizer;
        }

        [HttpGet]
        public string Get()
        {
            return _localizer["Hello World"];
        }
}

افزودن فایل ترجمه به پروژه

برای این که فایل ترجمه برای هرزبان را به پروژه ی خود اضافه کنید، ابتدا یک پوشه با نام Resources ایجاد کنید. روی این پوشه کلیک راست کرده و روی گزینه ی add new folder کلیک کنید و پوشه ای با نام Controllers درون آن ایجاد کنید. آنگاه روی این پوشه کلیک راست کرده و سپس روی add new item کلیک کنید و یک item از نوع resource با نام SampleController.fa.resx ایجاد کنید. سپس همین کار را تکرار کنید و یک item دیگر با نام SampleController.en.resx ایجاد کنید. این فایل ها برای ترجمه متون درون کنترلر SampleController به زبان های مختلف (در اینجا فارسی و انگلیسی) هستند.

همانطور که از نحوه ی ایجاد پوشه ها و نام فایل ها مشخص است، برای ایجاد فایل های ترجمه باید از قانون نامگذاری در ASP.net Core پیروی کنید. یعنی:

1- باید فایل های ترجمه ی Controllerها را درون پوشه ی Resources/Controllers قرار دهید و نام فایل مطابق با قانون ControllerName.lang.resx باشد.

2- برای ایجاد فایل ترجمه ی سایر کلاس ها نیز باید پوشه متناسب با namespace آن ها، پوشه ی مناسب را ایجاد کرده و فایل ترجمه را مطابق با قانون ClassName.lang.resx اضافه کنید. مثلا اگر کلاسی با نام UserService درون پوشه ی Services دارید که namespace آن ProjectName.Services است باید یک پوشه با نام Services درون Resources ایجاد کرده و فایل ترجمه ی UserService.fa.resx را برای ترجمه به فارسی به آن اضافه کنید.

اکنون که فایل های ترجمه را اضافه کردید می توانید ترجمه های خود را به صورت کلید-مقدار به آن ها اضافه کنید مثلا به فایل SampleController.fa.resx کلید Hello World و مقدار “سلام دنیا” را اضافه کنید.

افزودن سرویس و میان افزار Localization به پروژه

برای استفاده از قابلیت چند زبانه باید سرویس و میان افزار مربوطه را به پروژه ی خود اضافه کنید. برای این کار از کدهای زیر در کلاس Startup استفاده کنید:

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {

        services.AddLocalization(options => options.ResourcesPath = "Resources");

        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var supportedCultures = new[]
        {
            new CultureInfo("en"),
            new CultureInfo("fa"),
        };

        app.UseRequestLocalization(new RequestLocalizationOptions
        {
            DefaultRequestCulture = new RequestCulture("en"),
            // Formatting numbers, dates, etc.
            SupportedCultures = supportedCultures,
            // UI strings that we have localized.
            SupportedUICultures = supportedCultures
        });

        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        app.UseMvc();
    }
}

در قسمت تعریف میان افزار UseRequestLocalization، همانطور که در کد بالا مشخص است، زبان پیش فرض را می تواند تعیین کرد. در اینجا زبان پیش فرض en یا انگلیسی تعیین شده است. آرایه ی supportedCultures نیز لیست زبان های این پروژه است.

ارسال درخواست و فراخوانی APIها با تعیین زبان مورد نظر

در هنگام ارسال درخواست به سرور و فراخوانی APIها می توان زبان مورد نظر را به سرور ارسال و پاسخ با ترجمه مناسب را از سرور دریافت کرد. بدین منظور می توان از یکی از سه روش زیر استفاده کرد:

1- QueryString: ارسال مخفف زبان مدنظر را در درخواست ها به صورت Query String. مثال: http://localhost:53371/api/Sample?culture=en

2- هدر Accept-Language: تعیین مقدار زبان مورد نظر در فیلد Accept-Language در header درخواست ارسال شده به سرور.

3- استفاده از Cookieها. من دو روش بالا را ترجیح می دهم… مخصوصا روش دوم یعنی تنظیم هدر Accept-Language. به همین خاطر روش سوم را بیشتر توضیح نمی دهم.

استفاده از فایل اشتراکی برای ترجمه

شما می توانید یک یا چند فایل ترجمه ی اشتراکی نیز در پروژه ی خود داشته باشید و از آن در تمام کلاس های خود برای ترجمه ی متون استفاده کنید. بدین منظور باید ابتدا یک کلاس fake (الکی) ایجاد کنید. من نام این کلاس را SharedTranslate می گذارم و بدنه ی آن نیز به صورت زیر خالی است:

namespace i18nASPnetCore.SharedResources
{
    public class SharedTranslate
    {
    }
}

با توجه به namespace و نام این کلاس و براساس قانون نامگذاری فایل های ترجمه، ابتدا یک پوشه به نام SharedResources درون پوشه ی Resources ایجاد کرده و فایل های ترجمه ی اشتراکی (مثلا فایل SharedTranslate.fa.resx برای زبان فارسی) را درون آن قرار می دهم.

حال برای استفاده از این فایل ترجه اشتراکی در controller خود با استفاده از قابلیت Dependency Injection از کدهای زیر استفاده می کنیم:

[Route("api/[controller]")]
[ApiController]
public class SampleController : ControllerBase
{
    private readonly IStringLocalizer<SampleController> _localizer;
    private readonly IStringLocalizer<SharedTranslate> _sharedLocalizer;

    public SampleController(IStringLocalizer<SampleController> localizer,
        IStringLocalizer<SharedTranslate> sharedLocalizer)
    {
        _localizer = localizer;
        _sharedLocalizer = sharedLocalizer;
    }

    [HttpGet]
    public string Get()
    {
        return _localizer["Hello World"];
    }

    [HttpGet("shared")]
    public string GetShared()
    {
        return _sharedLocalizer["Welcome"];
    }
}

ترجمه ی پیام های Validation یا مدل ها (DataAnnotations)

فرض کنید مدلی به صورت زیر داریم:

public class SampleViewModel
{
    [Required(ErrorMessage = "The Email field is required.")]
    [EmailAddress(ErrorMessage = "The Email field is not a valid email address.")]
    [Display(Name = "Email")]
    public string Email { get; set; }
}

برای ترجمه ی پیام های خطای نشان داده شده توسط این مدل می توانیم همانند روش به اشتراک گذاری ترجمه ها، یک کلاس fake (الکی) مثلا با نام DataAnnotationTranslate ایجاد کنیم، سپس فایل های ترجمه را نیز همانند روش اشتراکی در مکان مناسب ایجاد کرده و ترجمه ها را درون آن قرار دهیم. مثلا ترجمه ی فارسی با کلید “The Email field is required” برابر “فیلد ایمیل الزامی است” می باشد.

اکنون برای فعالسازی قابلیت ترجمه ی مدل ها باید تنظیمات زیر را در تابع ConfigureServices کلاس startup.cs اعمال کنیم:

public void ConfigureServices(IServiceCollection services)
{
    services.AddLocalization(options => options.ResourcesPath = "Resources");

    services.AddMvc().AddDataAnnotationsLocalization(options => {
        options.DataAnnotationLocalizerProvider = (type, factory) =>
            factory.Create(typeof(DataAnnotationTranslate));
    });
}

البته برای هرمدل نیز می توانید فایل های ترجمه ی جدا داشته باشید ولی این کار خیلی مورد پسند بنده نیست زیرا بسیاری از پیام های خطا در مدلهای مختلف یکسان هستند.

نکته اضافه: قرار دادن فایل های ترجمه در یک پروژه ی جداگانه

برای قرار دادن فایل های ترجمه در یک پروژه ی جداگانه، ابتدا یک پروژه ی Class Library ایجاد کنید. اکنون همانند روش اشتراکی یک کلاس (برای مثال با نام SharedTranslate.cs) درون این پروژه ایجاد کنید. آن گاه فایل های ترجمه را هم نام با این فایل کلاس اشتراکی (مثلا SharedTranslate.fa.resx) و در کنار آن (نه درون پوشه ای جداگانه) ایجاد نمایید و ترجمه های خود را درون آن ها قرار دهید.

تغییر بعدی که باید ایجاد شود در کلاس startup در فایل startup.cs است که باید سرویس Localization بدون پارمتر مسیر Resource همانند کد زیر مورد استفاده قرار گیرد:

services.AddLocalization();

بسیار عالی. امیدوارم این آموزش برای شما مفید باشد. با پیوستن به کانال تلگرامی ما به آدرس https://t.me/angular_netcore از آخرین آموزش ها و اخبار مطلع شوید.

اگر سوالی داشتید لطفا آن را در بخش دیدگاه های همین پست مطرح بفرمایید. مجددا اعلام می کنم که کدهای این پروژه از این آدرس به صورت رایگان قابل دانلود و استفاده است.

موفق باشید. التماس دعا

3 دیدگاه برای “افزودن قابلیت چندزبانه و internationalization به ASP.net Core

  1. سلام.ممنون از آموزشتون. من یک پروژه چند لایه با .net core 3 ایجاد کردم. و فایل های resource و در لایه جداگانه قرار دادم . وقتی برنامرو اجرا میکنم در layout، کلید localizer و نشون میده بهم و مقداری که در فایل Resource قراردادم و نشون نمیده. اما وقتی فولدر resource و در خود پروژه اصلی قرار میدم کار میکنه. توی startup هم resourcepath و نزاشتم. ممنون میشم بگین مشکل از کجاست؟

    1. سلام وقتی فایل های مربوط به ترجمه را در پروژه ی جداگانه ای قرار می دهید باید یک کلاس خالی با نام همان فایل ترجمه در پروژه ی جدید ایجاد کنید مثلا اگر اسم فایل ترجمه شما SharedTranslate.fa.resx است باید یک فایل SharedTranslate.cs که درون آن یک کلاس public و خالی با نام SharedTranslate است ایجاد کنید….

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *