| sly 的个人资料Silverlight and Internat...照片日志列表 | 帮助 |
|
2008/7/12 Silverlight : on demand culture downloaderIn this article, im going to explain how to create a localized silverlight application that only downloads the culture resources as required and in the process breifly i'll explain
1. On Demand Assembly deployment and the onDemandLoc class
2. ObservableCollection & INotifyCollectionChanged
3. Build xaps in batch file
4. Source Code
1. On Demand Assembly deployment and the onDemandLoc class
On Demand Assembly deployment is useful to increase startup performance of a RIA sites and allows the developer to only load the parts of application a user need in an "on demand" basis. This is of course especially useful when we need to use our culture resource files as well. Imagine 1000 words to download for 20 languages, when all you require in application in one culture. It is a waste of bandwidth and the user patience.
Below is a small class that allows you to download a class based on the current culture in use.
It use the webclient to download a xap of the cultures name it extract the culture dll of your namespace and then loads the assemably into memory.
public class onDemandLoc
{ private static ICollection<string> LoadedLang; private string CurrentLCID; static onDemandLoc() {
LoadedLang = App.getlang(); } internal void LoadLocDll() {
CurrentLCID = System.Threading.Thread.CurrentThread.CurrentCulture.TwoLetterISOLanguageName;
System.Net.WebClient wc = new System.Net.WebClient(); wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OpenXAP); wc.OpenReadAsync(new Uri(CurrentLCID + ".xap", UriKind.Relative)); } internal void OpenXAP(object sender, OpenReadCompletedEventArgs e) { if ((e.Error == null) && (e.Cancelled == false)) { Assembly a = LoadAssemblyFromXap(App.Current.GetType().Namespace + "." + CurrentLCID + ".resources.dll", e.Result); LoadedLang.Add(CurrentLCID); } } internal Assembly LoadAssemblyFromXap(string relativeUriString, Stream xapPackageStream) { Uri uri = new Uri(relativeUriString, UriKind.Relative); StreamResourceInfo xapPackageSri = new StreamResourceInfo(xapPackageStream, null); StreamResourceInfo assemblySri = Application.GetResourceStream(xapPackageSri, uri); AssemblyPart assemblyPart = new AssemblyPart(); Assembly a = assemblyPart.Load(assemblySri.Stream); return a; } } 2. ObservableCollection & INotifyCollectionChanged
Once the assembly is loaded into memory it can be used, but i also add the culture to our list of loaded cultures to avoid re-downloading the same culture twice. I used an ObservableCollection<T> class and used the INotifyCollectionChanged event to trigger the event that the culture is downloaded and ready for use and thus we can safely refresh our page content using the new culture strings. Im not sure this is the best method, but i wanted to make it as re-useable as possible. I would love to hear suggestions of how others do it.
private static ObservableCollection<string> LoadedLang;
public App() { this.Startup += this.Application_Startup; this.Exit += this.Application_Exit; this.UnhandledException += this.Application_UnhandledException; InitializeComponent(); LoadedLang = GetNewCollection(); INotifyCollectionChanged collection = LoadedLang as INotifyCollectionChanged; collection.CollectionChanged += new NotifyCollectionChangedEventHandler(LocCollectionChangedEvt); } void LocCollectionChangedEvt(object sender, NotifyCollectionChangedEventArgs e) { Page page1 = new Page(); ((Page)this.RootVisual).LayoutRoot.Children.Clear(); ((Page)this.RootVisual).LayoutRoot.Children.Add(page1); }
public static ObservableCollection<string> GetNewCollection() { return new ObservableCollection<string>(); }
public static ICollection<string> getlang() { return LoadedLang; } 3. Build xaps in batch file
Lastly we need to build out language xaps using the Visual Studio post build event and a small batch file so the user can download, remember if the user culture does not exist it fall back to english. I use some helper vbs file to help create and to zip files. Some people said in the past they had issues with the vbs zip functions i updated them a little and hopefully they are more intl friendly
for %%i in (da de fr ja nl) do (
if exist "$(TargetDir)%%i\%%i.zip" del "$(TargetDir)%%i\%%i.zip" cscript /nologo "$(SolutionDir)$(ProjectName)\createzip.vbs" "$(TargetDir)%%i\%%i.zip" echo ^<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" ^>^<Deployment.Parts^>^<AssemblyPart Source="$(ProjectName).%%i.resources.dll" /^>^</Deployment.Parts^>^</Deployment^> > "$(TargetDir)%%i\appmanifest.xaml" cscript /nologo "$(SolutionDir)$(ProjectName)\addfiletozip.vbs" "$(TargetDir)%%i\%%i.zip" "$(TargetDir)%%i\appmanifest.xaml" if exist "$(TargetDir)%%i\$(ProjectName).%%i.resources.dll" del "$(TargetDir)%%i\$(ProjectName).%%i.resources.dll" move /Y "$(TargetDir)%%i\$(ProjectName).resources.dll" "$(TargetDir)%%i\$(ProjectName).%%i.resources.dll" cscript /nologo "$(SolutionDir)$(ProjectName)\addfiletozip.vbs" "$(TargetDir)%%i\%%i.zip" "$(TargetDir)%%i\$(ProjectName).%%i.resources.dll" move /Y "$(TargetDir)%%i\%%i.zip" "$(SolutionDir)$(ProjectName)Web\ClientBin\%%i.xap" del "$(TargetDir)%%i\appmanifest.xaml" del "$(TargetDir)%%i\$(ProjectName).%%i.resources.dll" ) I added code to allow culture=auto to work and updated the code sample on skydrive. 4. Source Code
Update : I figured out how to add the ondemand to silverlight Streaming
Updated: Code Sample for SL 2.0 RTW. http://wpf-e.spaces.live.com/Blog/cns!2B248D261D0E0035!407.entry 2008/7/5 Silverlight Localizability and Pseudo-LocalizationIn this sample I’ll try to give you an overview of localizability and some tools that can help assist you in the process, particularity pseudo-localization. 1. What is Localizability? 2. Enter Pseudo-Localization 3. No Custom Cultures yet 4. Code and sample 5. Other news: Bidi 1. What is Localizability? Localizability is the process to ensure that all UI strings in an application can be translated eg: no hard coded text or text on images. This is under the World-Readiness node of internationalization tree.
We need to do localizability testing on a product to minimize the number of times we need to get our strings translated. We always aim to do one localization or translation cycle to reduce localization costs. I cant give the subject justice but please review .NET Internationalization and Developing International Software for further information. A common example of a localizability issues · Hard coded strings · Text in images · Fixed text lengths · Wrong encoding (eg: ansi rather than utf-8) For each issue there is an easy workaround 1. Hard code string: Move the hardcoded strings to the global application strings.resx file and reference these resx strings in the UI see http://wpf-e.spaces.live.com/Blog/cns!2B248D261D0E0035!203.entry 2. Text in images: Remove the string from the image and place in the resx file and make the image a grid that expands to the size of the string see http://wpf-e.spaces.live.com/Blog/cns!2B248D261D0E0035!232.entry 3. Fixed text lengths: See expandable UI section in http://wpf-e.spaces.live.com/Blog/cns!2B248D261D0E0035!232.entry 4. Wrong Encoding: This is more a globalization issue rather than a localizability issue but you need to ensure all xaml and resx files are saved at in Unicode (default in visual studio) or UTF8 What is not a localizability issue is, user content stored or external resources. Eg: An international imputed content is designed to differ per user and any text they enter should be stored in their language, so this would be user error if the user inputted English text in a German UI. Also if user german user subscribed to English RSS feed this probably what they wanted. 2. Enter Pseudo-Localization Pseudo Localization is a test process designed to make to easy to find hard coded strings, fixed width UI or improper encoding. It does this by converting the English UI elements to a extreme internationalized version of the UI Eg: “Hello {0}” becomes “[Ħęľľő {0}! !!! !!!]” In the above example the string is 1. The text is wrapped in the square brackets to show easily if a string is clipped 2. Each character or glyph is replaced with an international version of the character, to show if any encoding issues are present 3. The string length is in increased by 40% to show that any width restrictions There is a excellent tool, Pseudoizer.exe part of the John Robbins MSDN article .NET Internationalization Utilities to convert resx files to this format.
3. No Custom cultures yet In .net there is the concept of custom cultures and Pseudo Cultures which allow the developer to create non-standard cultures eg: – ES-US or “Spanish – United States” to better target your users. But the object CultureAndRegionInfoBuilder doesn’t exist yet in Silverlight globalization class so instead we can use some obscure culture to display our pseudo culture eg: en-029 or English – Caribbean 4. Code and sample
Sample: http://silverlight.services.live.com/invoke/6655/Pseudo/iframe.html Code: http://cid-2b248d261d0e0035.skydrive.live.com/self.aspx/Public/Pseudo.zip 5. Other news: BiDi/RTL Mark Rideout has stated there is no out-of-box support in 2.0 for Bidirectional or Right to Left text eg: Hebrew and Arabic . But there are some free 3rd party dlls using nBiDi to provide this functionality http://www.santeon.com/silverlight/ and http://www.codeplex.com/SilverlightRTL
|
|
|