Localization یا بومی سازی برنامه های WPF با استفاده از فایلهای RESX
سه شنبه 1 دی 1394در این مقاله بومی سازی (تعیین زبان نمایشی برنامه) در برنامه های WPF را بررسی خواهیم کرد . برای بومی سازی روش های مختلفی وجود دارد که در اینجا قصد داریم فرمت RESX را معرفی کنیم که اجازه می دهد خواص یا ویژگیهای WPF را از منابع RESX تعبیه شده واکشی کرده و استفاده کنیم.
در این مقاله بومی سازی (تعیین زبان نمایشی برنامه با توجه به نیاز کاربر ) در برنامه های WPF را بررسی خواهیم کرد . برای بومی سازی روش های مختلفی وجود دارد که در اینجا قصد داریم فرمت RESX را معرفی کنیم که اجازه می دهد خواص یا ویژگیهای WPF را از منابع RESX تعبیه شده واکشی کرده و استفاده کنیم.
منابع با استفاده از فایل RESX تعبیه شده میتوانند بومی شوند. روش مشابه به بومی سازی Windows Form است و منابع مربوط به هر پنجره WPF یا کنترل در فایلهای RESX جداگانه ذخیره می شوند. در برنامه های بزرگ که تعداد زیادی پنجره وجود دارد ، مدیریت آن تعداد منبع در یک فایل مشکل می شود و بومی سازی در این پروژه ها بسیار اهمیت پیدا میکند.
هر خاصیت WPF می تواند با استفاده از فایل های RESX بومی سازی شود. می توان از آنها برای محلی کردن تصاویر ، مکان ها ، سایزها و ویژگی های دیگر Layout استفاده کرد. پشتیبانی Built-in تعریف آیکون برای پنجره ها ، منو ها و نوار ابزار را بسیار آسان کرده است .
افزونه های RESX به شما اجازه می دهند تا یک مقدار دوم یا مجددی برای خاصیت هایی که استفاده میکنید قرار دهید تا زمانی که اگر منابع نتوانستند بارگذاری شوند از آن مقادیر استفاده شود.
استفاده از افزونه RESX
برای استفاده از این افزونه باید منبع ان را به پروژه خود اضافه کنید (infralution.Localization.Wpf) . با این کار می توانید از ResxExtension در فایل XAML خود استفاده کنید. به شما اجازه تعریف مقادیر خواص XAML را می دهد. ResxExtention از کلاس MarkupExtention مشتق می شوند و خواص را با داده های بازیابی شده از منبع RESX تعبیه شده ارزیابی میکنند. برای مثال Markup زیر خاصیت Text از یک TextBlock را به MyText از منبع RESX تعبیه شده به نام MyApp.TestWindow تنظیم میکند:
<TextBlock Text="{Resx ResxName=MyApp.TestWindow, Key=MyText}"/>
اگر هنوز منبع را ایجاد نکرده باشید ، در WPF designer به صورت #MyText نشان داده می شود که # مشخص میکند که منبع مورد نظر هنوز تعریف نشده است. قدم بعدی ایجاد فایل RESX و تعریف منبع است. فرض کنید پروژه ای با نام MyApp دارید ،آنگاه می توانید به سادگی فایل RESX با نام TestWindow.resx ایجاد کنید و عمل ساخت آن را به Embedded Resouce تنظیم کنید .یک رشته منبع با نام MyText اضافه کرده و پروزه را مجدد کامپایل کنید. اگر TestWindow را بازکنید، رشته منبع را که در TextBlock نشان داده شده است خواهید دید.
برای اضافه کردن بومی سازی ، فایل RESX را کپی کرده و نام آن را تغییر دهید . برای مثال برای بومی سازی فارسی، فایل RESX را در TestWindow.fr.resx کپی کرده و آن را به عنوان یک منبع RESX تعبیه شده در پروژه استفاده کنید.
تنظیم کردن خاصیت ResxNameبرای عنصر Resx در یک پنجره منجر به تعداد زیادی از کپی XAML می شود. استفاده از خواص متصل بسیار XAML را مختصر میکند. و این اجازه را می دهد که خواص ResxExtention.DefaultResxName پیوست شده را در بسیاری از عناصر به صورت زیر تنظیم کنید.
<Window ResxExtension.ResxName="WpfApp.MainWindow" Language="{UICulture}>"
اکنون خاصیت ResxName می تواند از عناصر Resx حذف شود. اگر فقط بخواهید خاصیت Key را مشخص کنید ، می توانید نام پارامتر را حذف کنید تا اعلان مختصری داشته باشید.
<TextBlock Text="{Resx MyText}"/>
تنظیمات DefaultResxName با استفاده از ویژگی های ضمیمه شده کارمیکنند که با استفاده از عنصر Resx ویژگی FrameworkElement را فراهم میکنند. هرچند عنصر Resx در MarkupExtension دیگر کار نخواهد کرد. در این مورد نیاز است که ResxName تعریف شود.
تغییر Culture(فرهنگ) در زمان طراحی
پنجره TestWindow.xaml را باز کنید. باید توجه داشته باشید که در پنجره اصلی دو آیکون برای نمایش وجود خواهد داشت. که به شما امکان انتخاب Culture های استفاده شده در زمان طراحی را می دهد. بر روی Icon کلیک کرده و Other Culture را انتخاب و از لیست باز شده گزینه مورد نظر خود را انتخاب کنید. مترجم در designer نمایش داده می شود که به فایل Resx مربوط به آن تغییر خواهد کرد.
در Visual Studio 2012 , 2013 یک designer جدید با نام XDesProc معرفی شد. همانند روند طراحی خارجی توسط Expression Blend استفاده می شود. shadow XDesProc اسمبلی های شما را درون دایرکتوری خود کپی میکند اما اسمبلی منبع ماهواره آن را نمی تواند کپی کند .به این معنی است که انتخاب Culture زمان طراحی با شکست مواجه می شود. برای حل این مشکل راه حلی پیاده سازی کرده ایم که سازنده کلاس ResxExtension ، رویداد AssemblyResolve را گرفته و به دنبال آخرین اسمبلی منطبق می گردد. برای تعیین دایرکتوری ها برای جستجو ، آن را از طریق فرایند های در حال اجرا برای فرایند میزبانی ویژوال استودیو خواهد یافت. به این معناست که اگر از designer ویژوال استودیو استفاده میکنیدو گزینه Enable the Visual Studio hosting process را در Debug setting انتخاب کرده باشید ، سوئیچ کردن culture زمان طراحی به درستی کار خواهد کرد. اگر این گزینه غیرفعال باشد یا از Expression Blend استفاده کنید باید در ResxExtension جستجو برای اسمبلی ماهواره در زمان طراحی تعریف شود. برای انجام این کار یک مقدار string در محل زیر در رجیستری ایجاد کنید.
HKEY_CURRENT_USER\Software\ResxExtension\AssemblyPath
مقدار آن را لیست مشخصی از دایرکتوری ها برای جستجو تنظیم کنید.
تغییر Culture در زمان اجرا به صورت پویا
Culture برنامه شما به راحتی می تواند به صورت پویا در زمان اجرا با استفاده از ویژگی CultureManager.UICulture تغییر کند. این ویژگی ، CurrentThread.UICulture را تنظیم میکند و به صورت خودکار همه XAML های فعال را که از ResxExtension استفاده میکنند بروزرسانی میکند.
تصاویر و آیکون ها
ResxExtensionفقط برای کار با Text نیست . علاوه بر text می تواند برای تصاویر و آیکون ها نیز بکار رود . براحتی می توان از تصاویر و آیکون های فایل Resx در XAML استفاده کرد. برای تعریف یک آیکون برای یک پنجره ، یک منبع آیکون را به فایل Resx با نام Window.Iconاضافه کنید ، سپس نشانه گذاری آن را به صورت زیر تعریف کنید :
<Window Icon="{Resx Window.Icon}"/>
این کار بسیار راحت تر از تعریف آیکون در WPF است. از همین روش می توانید برای منوها و نوارابزار نیز استفاده کنید.
بومی سازی انواع ویژگی های دیگر
ResxExtension می تواند برای بومی سازی ویژگی ها از هر نوعی استفاده شود. برای نمونه خاصیت margin از یک textblock می تواند به صورت زیر تعریف شود.
<TextBlock Margin="{Resx Key=MyMargin, DefaultValue='18,0,0,71'}"/>
در این مثال توجه داشته باشید که یک صفت DefaultValue تعریف کردیم. اگر منبعی یافت و بارگذاری نشود از این مقدار استفاده می شود. اگر DefaultValue تعریف نکرده باشید ممکن است که XAML آن را در designer بارگذاری نکند. منبع می تواند به عنوان یک رشته ساده ("18,0,0,71") تعریف شود ، یا می توانید آن را در فایل Resx با یک مقدار کامل تعریف کنید :
<data name="MyMargin" type="System.Windows.Thickness, PresentationFramework"> <value>18, 0, 0, 71</value> </data>
فرمت اتصال داده ها
WPF عنصر Binding برای اتصال ویژگی ها به یک Datasourec را فراهم میکند . ویژگی Binding.StringFormat امکان فراهم کردن یک رشته برای استفاده در فرمت داده های نمایشی را ارائه می دهد:
<Binding StringFormat="Selected Item: {0}" ElementName="_fileListBox" Path="SelectedItem"/>
برای بومی سازی آن باید StringFormat خاصی را با استفاده از عنصر Resx تعریف کنیم. با استفاده از آن Culture زمان اجرا تغییر نمیکند. اگر culture را تغییر دهید با خطای InvalidOperation با پیام" اتصال نمی تواند بعد از استفاده شدن تغییر کند" مواجه خواهید شد. متاسفانه اتصال با بروزرسانی پویا از Culture طراحی نشده است . برای غلبه به این ، ResxExtension می تواند مانند یک اتصال عمل کند. براحتی می توانید ویژگی های اتصال را تنظیم کنید و مقدار منابع به عنوان format stribg استفاده شده است. برای مثال اتصال بالا را می توان به صورت زیر نوشت :
<Resx Key="MyFormatString" BindingElementName="_fileListBox" BindingPath="SelectedItem"/>
همچنین می توان یک منبع متفاوت را مشخص کرد که با استفاده از ویژگی BindingTargetNullKey ، هنگام Nullبودن Target از آن استفاده شود.
ResxExtension ، قالب داده را از منابع داده ای متعدد با استفاده از عناصر تو در تو Resx پشتیبانی میکند.
<Resx Key="MyMultiFormatString"> <Resx BindingElementName="_fileListBox" BindingPath="Name"/> <Resx BindingElementName="_fileListBox" BindingPath="SelectedItem"/> </Resx>
در این نمونه باید منبع MyMultiFormatString با Palaceholder برای هر دو آرگومان datasource تعریف شود : "Selected {0}: {1}"
گسترش UICulture
در این پروژه افزونه نشانه گذاری دیگری نیز با نام UICulture تعریف شده است . که برای تنظیم زبان های یک پنجره WPF تنظیم می شود برای تطبیق زبان با Culture مورد نظر در برنامه (CultureManager.UICulture). همانند ResxExtension، افزونه UICulture نیز در هنگام تغییر CultureManager.UICulture ، عناصر پیوست شده را به صورت خودکار بروزرسانی میکند.
برای تبدیل Enum ها ، کلاس ResourceEnumConverter به پروژه اضافه شده است. این کلاس یک مکانیزم آسان را برای بومی سازی متن های نمایشی که با Enum مرتبط هستند فراهم میکند .
پنهان کردن پنجره فایل های Resx در solutionexplorer
یکی از امکانات جالب Windows Forms Localization آن است که فایلهای Resx مرتبط با یک فرم یا کنترل به صورت اتوماتیک پنهان هستند. برای دیدن این فایلهای Resx بر روی دکمه گسترش فرم یا کنترل کلیک میکنید. به این معناست که اگر زبان های بیشتری به پروژه خود اضافه کنید ، Solution explorer بهم ریخته نمی شود. همچنین می توانید این کار را برای فایلهای Resx که با فایلهای XAML در ارتباط هستند با استفاده از DependentUpon انجام دهید .
<EmbeddedResource Include="TestWindow.resx"> <DependentUpon>TestWindow.xaml</DependentUpon> <SubType>Designer</SubType> </EmbeddedResource>
مدیریت طول عمر شیء
مدیریت طول عمر شیء یکی از مسائل اصلی در هنگام طراحی یک MarkupExtension است که XAML که از آن استفاده میکند به صورت خودکار بروزرسانی خواهد شد. ResxExtension نیاز دارد که یک منبع را برای عناصر XAML هدف نگهداری کند که از آن برای فعال کردن بروزرسانی عناصر هنگام تغییر CultureManager.UICulture استفاده کند. هرچند این منبع یک منبع قوی است ، عناصر WPF که از extension استفاده کرده اند هرگز جمع آوری نخواهند شد. برای جلوگیری از این وضعیت ، extension یک منبع ضعیف از عناصر هدف WPF را نگهداری میکند. که عناصر هدف را برای جمع آوری فعال میکند. تنها مشکل ، وجود منبع قوی برای گسترش اشیاء است. این موضوع توسط دوره فراخوانی یک تابع پاکسازی که Extension هایی را که اهداف فعالی ندارند برطرف می شود.
این مدیریت طول عمر در بعضی کلاس های پایه ای پیاده سازی شده است و برای هر MarkupExtension که آن رفتار را نیاز داشته باشد استفاده می شود. ManagedMarkupExtension یک کلاس پایه ای برای Extension ها فراهم میکند و یک منبع ضعیف برای اشیاء هدف WPF پیاده سازی میکند. کلاس MarkupExtensionManager مجموعه ای از اشیاء ManagedMarkupExtension ها را مدیریت میکند و مکانیزم آپدیت و پاکسازی را پیاده سازی میکند. ResxExtension و UICultureExtensionManager هر دو از ManagedMarkupExtension مشتق شده اند و از یک نمونه استاتیک کلاس MarkupExtensionManager برای رسیدگی به آپدیت اهداف WPF هنگام تغییر CultureManager.UICulture استفاده میکنند.
پشتیبانی اتصال داده
غلبه بر تغییر ناپذیری اتصال داده ها کاری سخت و خسته کننده است. راه حلی کاملا ظریف وجود دارد که امکان تنظیم کردن مستقیم ویژگی های اتصال بر روی عنصر Resx را به ما می دهد. ResxExtension این ویژگیها را به یک نمونه اتصال اساسی نسبت می دهد و Binding.StringFormat را با مقدار منبع تنظیم میکند. زمانی که Culture تغییر میکند ، ResxExtension یک کپی از اتصال ایجاد میکند و هدف را برای استفاده اتصال جدید آپدیت میکند.
پشتیبانی Globalizer.NET
ResxExtension برای پشتیبانی بومی سازی برنامه های WPF با استفاده از ابزار Globalizer.NET طراحی شد. کلاس ResxExtension شامل یک رویداد static GetResourceمی شود که امکان قرار دادن Globalizer.NET را درون مکانیزم ترجمه منابع به ما می دهد و به صورت پویا ترجمه را برای منابع فراهم میکند. این امکان Globalizer را قادر می سازد ترجمه پنجره ها و کنترل هایی که از ResxExtension بدون داشتن منابع ماهواره ای استفاده میکنند را نمایش دهد . Globalizer.NET شامل قابلیتی برای اسکن پروژه WPF موجود برای تعیین زبان و به طور خودکار تبدیل آنها به یکدیگر با استفاده از ResxExtension ها است.
- WPF
- 2k بازدید
- 1 تشکر