public class FaLanguageActionFilterAttribute : ActionFilterAttribute { public override void OnActionExecuting(ActionExecutingContext context) { CultureInfo.CurrentCulture = new CultureInfo("fa-IR"); CultureInfo.CurrentUICulture = new CultureInfo("fa-IR"); base.OnActionExecuting(context); } }
+ برای تنظیم اطلاعات تکراری Viewها میتوان کلاس پایه آنها را نیز سفارشی سازی کرد:
public abstract class MyCustomBaseView<TModel> : RazorPage<TModel> { protected MyCustomBaseView() { CultureInfo.CurrentCulture = new CultureInfo("fa-IR"); CultureInfo.CurrentUICulture = new CultureInfo("fa-IR"); }
برای آزمایش آن، سعی کنید چنین برنامهای را در ویندوز 8 اجرا کنید:
using System; namespace CultureAndNumbers { class Program { static void Main(string[] args) { var number = Convert.ToDecimal("12.32"); Console.WriteLine(number); } } }
خروجی آن به نحو ذیل است:
بله! چون در فرهنگ جاری سیستم، علامت ممیز دیگر . نیست، رشتهی 12.32 نیز بیمعنا است و قابل تبدیل به یک عدد دسیمال نخواهد بود.
همچنین باید دقت داشت تاثیر فرهنگ جاری سیستم بر روی متدهای Convert.ToDecimal و decimal.Parse یکسان است.
روشی برای آزمایش موقت فرهنگهای مختلف
برای اینکه بتوان فرهنگهای مختلف را به سادگی مورد آزمایش قرار داد، نیاز است خاصیت CurrentCulture ترد جاری برنامه را تغییر داد و پس از پایان کار، مجددا این ترد را به فرهنگ پیش از آزمایش تنظیم کرد. برای این منظور میتوان از پیاده سازی الگوی IDisposable کمک گرفت:
public class CultureScope : IDisposable { private readonly CultureInfo _originalCulture; public CultureScope(string culture) { _originalCulture = Thread.CurrentThread.CurrentCulture; Thread.CurrentThread.CurrentCulture = new CultureInfo(culture); } public void Dispose() { Thread.CurrentThread.CurrentCulture = _originalCulture; } }
using (var cultureScope = new CultureScope("fa-IR")) { Console.WriteLine(Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator); var number = decimal.Parse("12.32"); Console.WriteLine(number); }
تعیین صریح فرهنگ مورد استفاده
یک راه حل برای رفع این مشکل، قید صریح فرهنگ مورد استفاده است. برای مثال اگر اعداد در بانک اطلاعاتی به صورت 12.32 ثبت شدهاند، میتوان نوشت:
using (var cultureScope = new CultureScope("fa-IR")) { Console.WriteLine(Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator); var number = decimal.Parse("12.32", new CultureInfo("en")); Console.WriteLine(number); }
اما این روش هم قابل اطمینان نیست. زیرا کاربر میتواند در کنترل پنل سیستم، به سادگی علامت ممیز را مثلا به # تغییر دهد و در این حالت باز هم برنامه کرش خواهد کرد. راه حلی که برای این مساله در دات نت وجود دارد، فرهنگی است به نام Invariant که یک کپی فقط خواندنی از فرهنگ انگلیسی را به همراه دارد و در این حالت تنظیمات اختصاصی کاربر در کنترل پنل، ندید گرفته خواهند شد:
using (var cultureScope = new CultureScope("fa-IR")) { Console.WriteLine(Thread.CurrentThread.CurrentCulture.NumberFormat.NumberDecimalSeparator); var number = decimal.Parse("12.32", CultureInfo.InvariantCulture); Console.WriteLine(number); }
Extension Methods
با تشکر
ضمن اینکه یک مطلب را هم مد نظر داشته باشید. اینجا هدف بیشتر ذکر یک سری نکته است به همین جهت اسم سایت tips دارد (نکات ریز).
اسم سایت encyclopedia نیست که برای هر مطلبی قرار باشد کتاب نوشته شود. اگر نوشته شد، چقدر خوب؛ اگر نه ... یک نکته ریز جدید یاد گرفتید. این هم خوب.
همچنین هدف از این سایت خواننده عام با سطح مطالعه و اطلاعات صفر نیست و نبوده. از روز اولش اینطور نبوده و نخواهد بود.
یک مطالب رو هم فراموش نکنید. به قول مولوی: «گر تو بهتر میزنی بستان بزن»
در طی یک ماهی که این سایت در حالت تعلیق بود ... من هر چقدر سایتهای فارسی زبان فنی برنامه نویسی رو گشتم که دوتا مطلب به درد بخور پیدا کنم ... چیزی نیافتم. هیچی! واقعا دریغ از یک مطلب فنی به درد بخور که منتشر شده باشد. حالا همین عده منتظرند سریع بریزند سر یک نفر شروع کنند به داد و قال.
باز تکرار میکنم: «گر تو بهتر میزنی بستان بزن»
انتقال خودکار Data Annotations از مدلها به ViewModelهای ASP.NET MVC به کمک AutoMapper
- طراحی دیتابیس یا بانک اطلاعاتی بر پایه چند زبانه بودن و بررسی سناریوهای مختلف.
- نکاتی که باید در ساخت سایتهای چند زبانه به آنها دقت کرد.
- شیوهی تشخیص و تغییر زبان سایت
- معرفی چند کامپوننت وب، برای مباحث چند زبانه
طراحی مدل دیتابیس
اولین کار برای داشتن یک سایت چند زبانه، این است که یک مدل صحیح و مناسب را برای دیتابیس خود انتخاب کنید. یکی از اولین روشهایی که به ذهن هر فردی میرسد این است که برای هر ستون متنی که قرار است چند زبانه باشد، به تعداد زبانها برایش یک ستون در نظر بگیریم. یعنی برای جدول مقالات که قرار است در سه زبان فارسی و انگلیسی و عربی باشد، سه ستون برای عنوان مقاله و سه ستون نیز برای متن آن داشته باشیم. تصویر زیر نمونهای از این مدل را نشان میدهد.
مزایا:
- پیاده سازی آسان
معایب:
- در این روش با زیاد شدن هر زبان، تعداد ستونها افزایش مییابد که باعث میشود طراحی مناسبی نداشته باشد.
- در ضمن این مورد باید توسط برنامه نویس مرتبا اضافه گردد یا اینکه برنامه نویس این امکان را در سیستم قرار دهد که مدیر سایت بتواند در پشت صحنه کوئری افزودن ستون را ایجاد کند که باید جدول مرتبا مورد alter گرفتن قرار بگیرد.
- ممکن است همیشه برای هر زبانی مطلبی قرار نگیرد و این مورد باعث میشود بی جهت فضایی برای آن در نظر گرفته شود.
پی نوشت: با اینکه امروزه بحث فیلدهای sparse Column وجود دارد ولی این فیلدها در هر شرایطی مورد استفاده قرار نمیگیرند وبیشتر متعلق به زمانی است که میدانیم آن فیلد به شدت کم مورد استفاده قرار میگیرد.
پی نوشت دوم : در صورتی که فیلد شما مانند متن مقاله که عموما از نوع داده (varchar(max است استفاده میکنید و در صورتی که زبان مورد استفاده قرار نگیرد در خیلی از اوقات بی جهت فیلدهای Blob ساخته اید که بهینه سازی آن را نیز باید در نظر بگیرید.
ID | کد |
Language | زبان |
ISO | کد دو رقمی آن زبان |
Flag | پرچم آن کشور |
مزایا:
- پیاده سازی آسان
معایب:
- ایجاد رکوردهای تکراری، هر مقاله برای بعضی از اطلاعاتش که چند زبانه نیستند دادههای تکراری خواهد داشت.
- هر مقاله یک مقالهی جدا شناخته میشود و ارتباطی میان آنان نخواهد بود. بدین ترتیب توانایی ایجاد گزارشهایی چون هر گروه از مقاله و دسته بندی آنها از بین خواهد رفت. در ضمن مدیر عموما در یک سیستم مدیریتی میخواهد تنها یک لینک را به یک مقاله بدهد و سایت بنا به تشخیص در زبان مزبور، یکی از این مقالات را به کاربر نمایش دهد؛ نه اینکه مرتبا مدیر برای هر زبان، لینکی را مهیا کند و در این حالت چنین چیزی ممکن نخواهد بود.
- در یک سیستم فروشگاهی همانند تصویر بالا کار هم سختتر میشود و هر رکورد، یک محصول جدا شناخته میشود و ویرایشها هم برای هر کدام باید جداگانه صورت بگیرد که در عمل این طرح را رد میکند.
سومین راه حل این است که سه جدول ایجاد کنیم:
یک. جدول زبانها (که بالاتر ایجاد شده بود)
دو . جدول نام مقاله به همراه اطلاعات پایه و فیلدها بی نیاز به چند زبانه بودن
سه : یک جدول که هر دو ستون آن کدهای کلید دو جدول بالا را دارند و فیلدهای چند زبانه در آن وجود دارند.
جدول پایه
ID | کد |
Name | نام مقاله |
CreationDate | تاریخ ایجاد |
Writer | نویسنده |
Visibilty | وضعیت نمایش |
LanguageCode | کد زبان |
ArticleID | کد مقاله |
CreationDate | تاریخ ایجاد |
Visibility | وضعیت نمایش مقاله |
Title | عنوان مقاله |
ContentText | متن مقاله |
در جدول پایه یک مقاله ایجاد میشود که اطلاعات عمومی همه مقالات را دارد و حتی خصوصیت وضعیت نمایش آن، روی همهی مقالات با هر زبانی تاثیر میگذارد. در جدول دو، هر مقاله یک رکورد دارد که کد زبان و کد مقاله برای آن یک کلید ترکیبی به حساب میآیند. پس، از هر مقاله یک یا چند زبان خواهیم داشت. همچنین دارای فیلدهایی با وضعیت مخصوص به خود هم هستند؛ مثل فیلد وضعیت نمایش مقاله که فقط برای این مقاله با این زبان کاربرد دارد.
مزایا:
- گزارش گیری آسان برای هر دسته مقاله با زبانهای مختلف و ارتباط و یکپارچگی
- آسان در افزودن زبان.
معایب:
- ایجاد کوئریهای پیچیدهتر و جوین دار که به نسبت روشهای قبلی کوئریها پیچیدهتر شده اند.
- کدنویسی زیادتر.
استفاده از ساختارهای XML یا JSON برای ذخیره سازی اطلاعات چند زبانه مانند ساختارهای زیر:
XML<Articles> <Article> this is english text </Article> <Article> این یک متن فارسی است </Article> </Articles> یا <Articles> <en-us> this is english text </en-us> <fa-ir> این یک متن فارسی است </fa-ir> </Articles>
"Articles":["en-us':{"title":"this is english text","content":" english content"},"fa-ir":{"title":"متن فارسی","content":"محتوای فارسی"}]
از مزایای این روش ذخیرهی همه دادهها در یک ستون و یک جدول است و نیازی به ستونهای اضافه یا جداول اضافه نیست ولی معایب این روش استفاده از کوئریهای پیچیدهتر جهت ارتباط و خواندن است.
استفاده از بانکهای اطلاعاتی NO SQL
در این بانکها دیگر درگیر تعداد ستونها و جنس آنها نیستیم و میتوانیم برای هر مقاله یا محصول، هر تعداد زبان و یا فیلد را که میخواهیم، در نظر بگیریم و اضافه کنیم. برای آشنایی بیشتر با این نوع بانکها و انواع آن، مقالات مربوط به nosql را در سایت دنبال کنید.
نکاتی که در یک سایت چند زبانه باید به آنها توجه کرد.
یک . زبان آن صفحه را معرفی کنید: این کار هم به موتورهای جست و جو برای ثبت سایت شما کمک میکند و هم برای معلولین که از ابزارهای صفحه خوان استفاده میکنند، کمک بزرگی است. در این روش، صفحه خوانها و دستگاههای خط بریل که زبان صفحه را تشخیص نمیدهند با خواندن کد زبان میتوانند زبان صفحه را تشخیص دهند. با استفاده از خط زیر میتوانید زبان اصلی صفحهی خود را تنظیم نمایید:
<html lang="en">
اگر از XHTML استفاده میکنید خاصیت زیر را فراموش نکنید. دریافت W3C Validation بدون آن امکان پذیر نخواهد بود.
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<blockquote lang=”fr”> <p>Le plus grand faible des hommes, c'est l'amour qu'ils ont de la vie.</p> </blockquote>
سه. لینک ها : اگر دارید در صفحهای لینک به جایی میدهید که متفاوت از زبان شماست، حتما باید زبان صفحه یا سایت مقصد را مشخص کنید. مثلا لینک زیر برای صفحهای است که از یک زبان غیر فرانسوی به یک صفحهی با زبان فرانسوی هدایت میشود:
<a href="" hreflang="fr">French</a>
همچنین اگر متن لینک شما هم به زبان فرانسوی باشد خیلی خوب میشود که آن را هم بیان کنید و از خاصیت lang و هم hreflang همزمان استفاده کنید:
<a href="" hreflang="fr">Francais</a>
پنج. انکودینگ صفحه را مشخص کنید: برای اینکه نحوهی رمزگذاری و رمزگشایی حروف و نمادها مشخص گردد، باید انکودینگ تنظیم شود و حتی برای بعضی از موتورهای جست و جو که ممکن است با وب سایت شما به مشکل بر بخورند. امروزه بیشتر از صفحات یونیکد استفاده میشود که سطح وسیعی از کاراکترها را پشتیبانی میکند.
<meta http-equiv="Content-Type" content="text/html;charset=UTF-8">
HTML5
<meta charset="UTF-8">
شش. اندازهی فونت: موقعی که یک سایت چند زبانه را طراحی میکنید این نکته خیلی مهم هست که بدانید اندازه فونتهای زبان پیش فرض، برای باقی زبانها مناسب نیستند. به عنوان مثال ممکن است اندازه فونتی برای زبانهای انگلیسی، فرانسوی و آلمانی مناسب باشد ولی برای زبانهای فارسی و عربی و چینی و ... مناسب نباشد و خواندن آن سخت شود. به همین جهت یکی از راههای حل این مشکل استفاده از قالب css است که وابسته به خصوصیت lang ای است که شما برای صفحه و هر المان یا تگی که از این خصوصیت استفاده میکند، تعیین کردهاید.
:lang(en) { font-size: 85%; font-family: arial, verdana, sans-serif; } :lang(zh) { font-size: 125%; font-family: helvetica, verdana, sans-serif; }
خط زیر تعیین میکند که از استایل اول استفاده شود:
<html lang="en">
<html lang="zh">
<body class="english"> or <body class="chinese">
و استایل:
.english { font-size: 85%; font-family: arial, verdana, sans-serif; } .chinese { font-size: 125%; font-family: helvetica, verdana, sans-serif; }
هشت : زمان را نیز تغییر دهید: یکی از مواردی که در کمتر سایت چند زبانهای به چشم میخورد و به نظر بنده میتواند بسیار مهم باشد این است که time zone منطقهی هر زبان را بدانید. به عنوان مثال برای مقالهی خود، تاریخ ایجاد را به صورت UTC ذخیره کنید و سپس نمایش را بر اساس زبان یا حتی بهتر و دقیقتر از طریق IP کشور مربوطه به دست آورید. برای کاربران ثبت نام شده این تاریخ میتواند دقیقتر باشد همانند انجمنهای وی بولتین.
شیوههای تشخیص زبان سایت
یکی از راههای تشخیص زبان این است که موقعی که برای اولین بار کاربری به سایت مراجعه میکند، زبان مورد نظرش را سوال کنید و این اطلاعات را در یک کوکی بدون تاریخ انقضاء ذخیره کنید تا در دفعات بعدی آن را بررسی نمایید.
دومین راه، استفاده از IP کاربر مراجعه کننده است تا بر اساس آن زبان مورد نظر را انتخاب کنید.
در سومین شیوه که اغلب استفاده میشود، زبان سایت به طور پیش فرض بر روی یک زبان خاص که بهتر است انگلیسی باشد تنظیم شده است و سپس کاربر از طریق یک منو یا ابزارهای موجود در سایت، زبان سایت را تغییر دهد.
پی نوشت: فراموش نگردد که امکان تغییر زبان همیشه برای کاربر مهیا باشد و طوری نباشد که کاربر در آینده نتواند زبان سایت را تغییر دهد؛ حتی اگر تشخیص خودکار سایت برای زبان فعال باشد.
پلاگینها و ابزارهای مدیریت زبانپی نوشت: در روشهای بالا بهتر است همان مرتبهی اول اطلاعات را در یک کوکی ذخیره کنید تا مراحل پیگیری راحتتر و آسانتر شود.
دومین ابزار که بیشتر برای انتخاب کشور میباشد و من خودم در بخش مدیریتی سیستمها از آن استفاده میکنم، ابزار CountrySelector است. این پلاگین قابلیت جست و جو زبان را همزمان با تایپ کاربر نیر داراست. اسامی کشورها به صورت انگلیسی شروع شده و به زبان آن کشور در داخل پرانتز خاتمه مییابند و پرچم هر کشور نیز در کنار آن قرار دارد. کار کردن با آن بسیار راحت بوده و مستنداتش به طور کامل کار با آن را توضیح میدهد.
پلاگین بعدی International Telephone Input است که پیاده سازی پلاگین بالا میباشد. برای مواردی مفید است که شما نیاز دارید کد تلفنی کشوری را انتخاب کنید.
در مقالههای زیر که در سایت جاری است در مورد Globalization و به خصوص استفاده از ریسورسها مطالب خوبی بیان شده است:
قسمت بیست و دوم آموزش MVC که مبحث Globalization را دنبال میکند.
قسمت اول از شش قسمت مباحث Globalization که دنبالهی آن را میتوانید در مقالهی خودش دنبال کنید.
نحوه کار با ftp - بخش اول
<?xml version="1.0" encoding="utf-8" ?> <configuration> <system.diagnostics> <trace autoflush="true" /> <sources> <source name="System.Net"> <listeners> <add name="MyTraceFile"/> </listeners> </source> </sources> <sharedListeners> <add name="MyTraceFile" type="System.Diagnostics.TextWriterTraceListener" initializeData="System.Net.trace.log" /> </sharedListeners> <switches> <add name="System.Net" value="Verbose" /> </switches> </system.diagnostics> </configuration>