![]() |
|
Spaces home Silverlight and Internat...PhotosProfileFriendsMore ![]() | ![]() |
Silverlight and International ThoughtsXAML on Safari!
11/16/2008 LocWebService: Only download resources per UserControl
1. Introduction In this sample I will show how bind text elements that load localization resources from the server side resx file via a WCF service in silverlight 2.0. Advantages:
Disadvantages:
2. UserControl local resources configuration I first created two helper class's to assist in design time binding called LocItem and LocCollection LocItem implements the INotifyPropertyChanged class and contains two properties ItemName and ItemValue. This will enable us to dynamically update a localizable string at runtime. We then need to a LocItem for every localizable string we add it to our UserControl Resources per control or page. LocCollection is another helper class based from Silverlight Control Toolkit ObjectCollection This is a enumerable collection of our loc strings on a page, that get over the limitation that ResourceDictionary does not implement iEnumerable. Both these are instantiated in markup and then bound to your localizable element. <UserControl.Resources>
</UserControl.Resources> ...
3. WCF Service When the control initializes we make a WCF request to get all translations in our LocCollection. On the server side we lookup our server side resx file for each requested string and wrap it in a XDocument of LocString . Once the WCF loaded event fires we then update the ItemValue our individual LocItems to display the localizable strings.
4. Code This is a pretty crude sample but you could wrap this functionality in asp.net style base page to make it scale cleaner. Download: LocWebService.zip 10/26/2008 SL 2.0 localization on-demand sample updatedOverview Updated To fix bugs on english code to check for culture installed and to fallback to english if culture not available This is a more advanced sample showing concepts I showed beta 2 samples and integrated into Silverlight 2.0 RTW project. Im not going over each part as this has already been detailed in earlier posts.
Requirements Visual Studio professional or greater plus the Silverlight Tools for Visual Studio 2008 SP1 and the excellent Dmytro Kryvko’s Extended Strongly Typed Resource Generator 2.3 at http://dmytro.kryvko.googlepages.com/ installer is at http://dmytro.kryvko.googlepages.com/ResXFileCodeGeneratorEx23.zip Code: http://cid-2b248d261d0e0035.skydrive.live.com/self.aspx/Public/LocOndemand.zip 10/17/2008 Creating a localizable Silverlight 2.0 RTW ApplicationAbout The sample below shows how you can bind language resources (resx) using only markup. The final version of Silverlight makes localization alot cleaner. Requirements Visual Studio professional or greater plus the Silverlight Tools for Visual Studio 2008 SP1 and the excellent Dmytro Kryvko’s Extended Strongly Typed Resource Generator 2.3 at http://dmytro.kryvko.googlepages.com/ installer is at http://dmytro.kryvko.googlepages.com/ResXFileCodeGeneratorEx23.zip Instructions 1. Open Visual Studio
28. In Project Explorer right click on Strings.resx and copy and paste it into the resources folder <param name="culture" value="de" /> <param name="uiculture" value="de" /> 42. Click Save, press F5 Code: http://cid-2b248d261d0e0035.skydrive.live.com/self.aspx/Public/SL2%7C_RTM%7C_Loc.zip
Further Reading http://msdn.microsoft.com/en-us/library/cc189057(VS.95).aspx 9/7/2008 Silverlight Localization Methods: User Controls Vs. ApplicationIn this article I'm going to review usercontrol and two types of localization methods around them
1. User Control Overview "UserControls are the basic unit of reusable Xaml and the code that goes with it." User Controls are sometimes called custom controls. Most Silverlight applications will use and create many usercontrols in an application to simplify the application design in a more object orientated structure. A usercontrol can be used for UI elements (eg: dropdownlist, styled buttons, image viewer etc..) or computational (eg: prime number control etc...) or data retrieval (eg: load xml etc...). Once you have created something worth re-using, you can instantiated directly in XAML as a custom type user control. eg: <CoolButtonUCNamespace:coolButton x:Name="button1" ButtonText="Click Here" />. Some samples of user controls but note most controls wont have many UI strings to localize eg:
2. Localization per custom controls On the Silverlight forums people occasionally ask how to do localization on a per control basis? eg: coolButton.xaml with coolButtonResource.de.resx where each control has its own set of resource files. This will mean you need to manage, localize & build many seperate files. To me this method gives some advantages and disadvantages Advantages:
Disadvantages:
Unless your a usercontrol vendor, this method would not be my first choice. 3. Localization on application only The excellent Jordan Hammond created a novel way and wrote sample application by registering custom dependency properties and having all controls in generic.xaml. But if you to have seperate controls, downloadable on demand, but I'll try to explain the logic and basics. First review the good example of creating a reusable user control http://community.devexpress.com/blogs/theonewith/archive/2008/08/06/custom-silverlight-controls-creating-a-reusable-messagebox-dialog-part-i.aspx Note a custom type user control can register custom dependency properties where you can set all localisable resources in its declaration and bind xaml at runtime eg: <CoolButtonUCNamespace:coolButton x:Name="button1" ButtonText="Click Here" /> as <CoolButtonUCNamespace:coolButton x:Name="button1" ButtonText="{Binding LocButtonText, Source={StaticResource LocStrings}}" /> using the resx xaml binding as shown in the previous article. Using this method you can expose all UI string properties in each of your user controls. This allows you to override the default strings and use a single application resx file per application rather than a rex per control. Advantages:
Disadvantages:
4. Conclusion Thanks Jordan to pointing me to this method. I believe the localization per application is better due to the cleaner content and code separation which makes life far easier for the translator. Please share your thoughts below. 7/12/2008 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" ) 4. Source Code
As always there is sample available but i cant upload it to Silverlight Streaming as i cant figure out how to upload an application with multiple xaps.
Update : I figured out how to add the ondemand to silverlight Streaming
Note: I tried using the culture=auto object parameter as to automatically detect and load the users culture based on the browser settings, Im sure got this to work at some point before but i cant get it to work now. :-(
Update : I figured out how to get culture=auto to work and updated the code sample on skydrive. 7/5/2008 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
6/27/2008 Silverlight Marketization (Market Customization)In this article I’ll explain how to use maketization (short for market customization) in Silverlight to reduce your loc costs and to enhance your application for particular market. 1. What is marketization? 2. What should be marketised? 3. Silverlight Example 4. Expandable UI 5. Sample and source code 1. What is Marketization? Marketization is under the Internationalization tree, it the ability to target a website or application to a particular market rather than simply a language. A language (eg: En = english) can shared in many countries and some countries speak more than one language each having a particalar market or culture (eg: fr-ca = french canada). Of those familiar with developing sites for international markets, most are familiar with localization (translation of product UI) , but few use the implement the globalization process in full. If you do, you can greatly reduce your external translation costs and provide a more targeted user experience to all your users.
If you are not familiar with the .net localization process I strongly recommend you review .NET Internationalization and Developing International Software, both excellent books on the subject who explain the rest of these subjects better than I ever can. It reduces loc costs by normalizing your international resources, strings, urls and settings so you only need to translate at the language level rather than down the many market level. Translations dont need to targeted at a paticalar market but they may have some small spelling differences (eg: colour & color) so the text should be translated in formal way and avoid local phares and terms. In .net we have a culture parent language fallback system to enable this eg:
2. What should be marketized? Website and product UI text translations and strings should all be in one localization strings resx file while the market resx file should contain a) Market Links/URLs b) Enabling market specific features settings c) Tracking and advertizing codes d) Branding Generally the market resx will have a small fraction (1/10 - 1/3) of the elements that are in the strings file and it helps to be quite ruthless in the setting that are in your marketiztion settings resource file as it needs to configure for many more markets .
3. Silverlight Example In this example below we can display national sports of many countries and languages. You need to create 2 resource files and make them bind the UI text to strings resource file and market resx file to control the visibility of elements of the application per country. I wrapped the text in expandable grids that gracefully fit to meet the size of a translation. A market picker ListBox is binded to the market list to dynamically refresh both the UI language and the culture of the application.
4. Expandable UI
Please remember translation string lengths differ greatly per language and you don’t want to have fixed widths or the text can be clipped or overlapping other UI. It is always recommended for any international user controls to use stackpanels, wrappanels and autosizing grids for international text, as some languages are up 40% longer on average. Long text should allowed wrap (TextWrapping="Wrap") , and add scroll bars (ScrollViewer) as necessary. If UI absolutely cant be expanded then ellipses (...) converter function could be used to restrict the text size but this should be avoided if possible.
Live Sample: http://silverlight.services.live.com/invoke/6655/Marketization/iframe.html Source code: http://cid-2b248d261d0e0035.skydrive.live.com/self.aspx/Public/marketization.zip
|
|||||||||
|
|