This article is currently in the process of being translated into Persian (~99% done).
Application Culture / UICulture
اگر کمی با اعداد و تاریخ ها در برنامه wpf خود کار کرده باشید، برای مثال در یکی از مقالات این آموزش شاید نکته جالبی را دیده باشید، اعداد و تاریخ ها به صورت خودکار به فرمتی که کامپیوتر شما از آن استفاده می کند نمایش داده میشود. اگر شما در یک کشور انگلیسی زبان زندگی میکنید شاید نکته بزرگی به نظر نرسد اما اگر در یکی از کشور هایی زندگی کنید که تاریخ و اعداد به روش دیگر نمایش داده میشوند این نکته جالبی است.
اگر با خود فکر میکنید که " تفاوت بین فرمت اعداد و تاریخ در کشور های مختلف نمیتواند اینقدر زیاد باشد"،پیشنهاد میکنم برنامه ساده زیر را بررسی کنید که من اعداد و تاریخ های یکسان را مطابق با فرمتی که در کشور های آمریکا، آلمان و سوئد استفاده میشود نوشته ام:
همانطور که میبینید، تفاوت های جزئی بسیاری در نحوه نمایش اعداد و تاریخ ها وجود دارد. خبر خوب این است که فریمورک .NET می تواند به شما کمک زیادی کند - در واقع ، این کار از قبل انجام شده است: به صورت پیشفرض، تاریخ ها و شماره ها مطابق با تنظیمات کامپیوتری که برنامه شما در آن اجرا می شود ، قالب بندی می شوند. خبر بد این است که این رفتار ممکن است همیشه مطابق خواسته شما نباشد. اما نگران نباشید - به راحتی می توانید این مورد را تغییر دهید. همه اینها مربوط به استفاده از کلاس CultureInfo است که می توانید در این لینک بیشتر در مورد آن بخوانید C# Tutorial article on CultureInfo اما فعلا ، بیایید درباره نحوه استفاده از این تکنیک ها در برنامه WPF خود بحث کنیم.
قالب بندی مخصوص
اگر فقط نیاز به اعمال قالب بندی بر روی قسمت خاصی از اطلاعات داشته باشید، مثلا محتویات یک کنترل Label، میتوانید براحتی با ترکیب متد ToString() و کلاس CultureInfoاین کار را انجام دهید. برای نمونه، من در مثال بالا، قالب بندی بومی شده متفاوتی را اعمال کرده ام. به این صورت:
double largeNumber = 123456789.42;
CultureInfo usCulture = new CultureInfo("en-US");
CultureInfo deCulture = new CultureInfo("de-DE");
CultureInfo seCulture = new CultureInfo("sv-SE");
lblNumberUs.Content = largeNumber.ToString("N2", usCulture);
lblNumberDe.Content = largeNumber.ToString("N2", deCulture);
lblNumberSe.Content = largeNumber.ToString("N2", seCulture);
این کار ممکن است در بعضی جاها که به یک قالب بندی خاص در چند مکان مختلف احتیاج داریم، کافی باشد، اما در کل این شما هستید که باید تصمیم بگیرید که آیا برنامه شما از تنظیمات سیستم استفاده کند (بصورت پیش فرض) یا اینکه می خواهید این رفتار پیش فرض سیستم را برای برنامه تغییر دهید.
CurrentCulture و CurrentUICulture
اعمال کردن culture یا بومی سازی به برنامه WPF بسیار آسان است. شما با دو ویژگی که در CurrentThread از کلاس Thread پیدا میشود سروکار دارید: CurrentCulture و CurrentUICulture . اما تفاوت این دو در چیست؟
خصوصیت CurrentCulture ، همان چیزی است قالبندی اعداد، تاریخ ها و... را کنترل میکند و مقدار پیشفرض آن از سیستم عاملی که برنامه در آن اجرا میشود میآید. این مقدار بسته به زبانی که در سیستم عامل مورد استفاده قرار گرفته، تغییر میکند. این یک امر خیلی عادی است که مثلا فردی که در آلمان زندگی میکند سیستم عامل ویندوز خود را با رابط کاربری انگلیسی نصب کند، درحالیکه برای اعداد و تاریخ ها، شیوه آلمانی را اعمال کند. برای چنین موقعیتی، خصوصیت CurrentCulture بصورت پیشفرض آلمانی است.
خصوصیت CurrentUICulture زبانی مورد استفاده را مشخص میکند. این خصوصیت فقط بستگی به پشتیبانی برنامه از ویژگی چندزبانی، دارد؛ مثلا در مواقع استفاده از فایل های language-resource . تکرار میکنم، این خصوصیت در مواقع سروکله زدن با ورودی/خروجی های از نوع اعداد، تاریخ و... به شما امکان اعمال یک culture برای یک زبان (مثل انگلیسی) را درحالیکه زبان دیگری (مثل آلمانی) استفاده میکنید، میدهد.
تغییر Culture (بومی سازی) برنامه
بر اساس آنچه که یاد گرفتیم، شما باید تصمیم بگیرید که CurrentCulture و/یا CurrentUICulture را تغییر دهید. این تغییرات را هر زمان که بخواهید میتوانید انجام دهید، اما به نظر میرسد در هنگام شروع برنامه منطقی تر باشد -در غیراینصورت ممکن است قبل از تغییر Culture ، بعضی از خروجی ها با Culture پیش فرض تولید شوند. یکی از دلایلی که Culture و UICulture را در ابتدای اجرای برنامه در رویداد Application_Startup() از فایل App.xaml.cs برنامه WPF تغییر میدهیم، همین است:
private void Application_Startup(object sender, StartupEventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("de-DE");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("en-US");
}
از آنجا که ما از کلاس Thread و همچنین CultureInfo استفاده می کنیم، فراموش نکنید که namespace های مورد نیاز را به کد خود اضافه کنید (اگر از قبل موجود نباشند) :
using System.Threading;
using System.Globalization;
با این کار همه عددها و تاریخ ها براساس آنچه آلمانی ها (de-DE) ترجیح میدهند، قالب بندی میشوند. همانطور که گفتیم، درصورتیکه برنامه شما از ویژگی چندزبانی پشتیبانی نمیکند، میتوانید خطی را که UICulture مشخص میکند(خط آخر) حذف کنید.
تغییر Culture در هنگام شروع برنامه ( رویداد Application_Startup ) یا در ابتدای متد سازنده پنجره اصلی برنامه منطقی تر بنظر میرسد، چراکه با تغییر خصوصیت CurrentCulture مقادیری که فعلاً تولید شده اند خودبخود بروزرسانی نمیشوند. اگرچه این بدان معنا نیست که شما نمیتوانید آنها را تغییر دهید؛ مثال بعدی، چگونگی تاثیر گرفتن خروجی برنامه براساس خصوصیت CurrentCulture را بخوبی نشان داده است:
<Window x:Class="WpfTutorialSamples.WPF_Application.ApplicationCultureSwitchSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfTutorialSamples.WPF_Application"
mc:Ignorable="d"
Title="ApplicationCultureSwitchSample" Height="200" Width="320">
<StackPanel Margin="20">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Label>Number:</Label>
<Label Name="lblNumber" Grid.Column="1" />
<Label Grid.Row="1">Date:</Label>
<Label Name="lblDate" Grid.Row="1" Grid.Column="1" />
</Grid>
<StackPanel Orientation="Horizontal" HorizontalAlignment="Center" Margin="0,20">
<Button Tag="en-US" Click="CultureInfoSwitchButton_Click" HorizontalContentAlignment="Stretch">English (US)</Button>
<Button Tag="de-DE" Click="CultureInfoSwitchButton_Click" HorizontalContentAlignment="Stretch" Margin="10,0">German (DE)</Button>
<Button Tag="sv-SE" Click="CultureInfoSwitchButton_Click" HorizontalContentAlignment="Stretch">Swedish (SE)</Button>
</StackPanel>
</StackPanel>
</Window>
using System;
using System.Globalization;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
namespace WpfTutorialSamples.WPF_Application
{
public partial class ApplicationCultureSwitchSample : Window
{
public ApplicationCultureSwitchSample()
{
InitializeComponent();
}
private void CultureInfoSwitchButton_Click(object sender, RoutedEventArgs e)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo((sender as Button).Tag.ToString());
lblNumber.Content = (123456789.42d).ToString("N2");
lblDate.Content = DateTime.Now.ToString();
}
}
}
قسمت جذاب برنامه در رویداد CultureInfoSwitchButton_Click است، که در آنجا CurrentCulture را بر اساس اینکه کدام دکمه کلیک شده باشد، تنظیم میکنیم، سپس دو Label که حاوی عدد و تاریخ هستند را بروزرسانی میکنیم:
Culture و Thread ها: خصوصیت DefaultThreadCurrentCulture
اگر برنامه شما بیش از یک Thread دارد، باید به فکر استفاده از خصوصیت DefaultThreadCurrentCulture باشید. این خصوصیت را میتوانید در کلاس CultureInfo بیابید (از دات نت فریم ورک 4.5 به بعد). با این خصوصیت میتوانیم مطمئن باشیم که نه تنها Thread فعلی، بلکه همه Thread هایی که در آینده استفاده می کنیم هم از Culture یکسان استفاده خواهند کرد. می توانید از رویداد Application_Startup استفاده کنید.
CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("de-DE");
بنابراین ،آیا مجبورید هر دو ویژگی CurrentCulture و DefaultThreadCurrentCulture را تنظیم کنید؟ حقیقتا ، خیر -اگر شما همین الان ویژگی CurrentCulture رو تغییر ندادید، تنظیمات ویژگی DefaultThreadCurrentCulture برای CurrentCulture هم اعمال خواهد شد. به زبان دیگر،اگر قصد استفاده از چند نخی (multiple threads) را در برنامه خود دارید منطقی تر است از DefaultThreadCurrentCulture به جای CurrentCulture استفاده کنید - همه حالت ها رو برای شما پوشش خواهد داد.
خلاصه فصل
سر و کله زدن با Culture برنامه های WPF خیلی مهمه ، اما خوشبختانه، WPF خیلی از کار ها رو به صورت کامل و فوری برای شما انجام میده. اگر نیاز به تغییر در رفتار(behavior) پیشفرض داشته باشید ، می تونید به سادگی از ویژگی های CurrentCultureو CurrentUICultureاستفاده کنید، همانطور که در مثال های متعدد این مقاله نشان داده شد است.