Now when the program loads, we can easily go on and add the one that I need to add for the current CultureInfo. I have introduced the same in an article :
Simplest Way to implement Multilingual Application
Later on in my article Pluggable Resource for WPF ResourceDictionary, I have introduced the way by which you could plug - in the Resources into external assemblies.
So to summarize, whenever I need to use a string, I will need to modify the string resource with an appropriate key in the resource file. We need to create new Resource files for each language and also need to map each key with appropriate data.
So instead of Text="My Custom text", I will write something like Text="{DynamicResource rKeyCustomText}" so that the rKeyCustomText will be replaced with the appropriate text during runtime of the project and thus we can maintain language based string resources. To do this, we need to create a schema like :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"> <system:String x:Key="rKeyCustomText" >This is my custom Text</system:String> </ResourceDictionary>
For french we need to recreate the same as :
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:system="clr-namespace:System;assembly=mscorlib"> <system:String x:Key="rKeyCustomText">C'est mon texte personnalisé</system:String> </ResourceDictionary>
So the problem is once we declare a resource key we need to instantly convert the string to all the resource files that we need to support for the application and write that. So the work seems to me very boring and laborious. So I thought to build a tool to help you in this regard. Lets talk about how you can use this tool to build your Resource files automatically.
To build this application the technologies that I have used are :
- .NET (of course)
- WPF for UI
- Bing Services for Translator
- Threads to handle bankground work
Step 1 : Create a file for resource exactly with the same schema that I specified. You can insert system:strings of any language.
Step 2: Open the Console and choose the File you have just created.
Step 3: Create a file using Destination button.
Step 4: Choose the appropriate Source and target Language.
Step 5 : Click on Convert to generate the file.
Thus you can see the file will be generated with same schema.
The Implementation
The implementation is very simple. I took the help of LINQ classes for XML to generate the output. Lets look into the code:
public void CreateResourceDictionary(string targetfile, string destinationfile, DoWorkEventArgs e) { DateTime startTime = DateTime.Now; e.Result = ""; XDocument document = XDocument.Load(targetfile); oWorker.ReportProgress(2, "Initializing..."); foreach (XElement elem in document.Descendants("{clr-namespace:System;assembly=mscorlib}String")) { XAttribute attribute = elem.Attribute("{http://schemas.microsoft.com/winfx/2006/xaml}Key"); elememnts.Add(attribute.Value, elem.Value); } oWorker.ReportProgress(4, "Target File Read Successfully."); XDocument targetDocument = null; XNamespace xaml = "http://schemas.microsoft.com/winfx/2006/xaml/presentation"; XNamespace x = "http://schemas.microsoft.com/winfx/2006/xaml"; XNamespace system = "clr-namespace:System;assembly=mscorlib"; XElement root = new XElement(xaml + "ResourceDictionary", new XAttribute("xmlns", "http://schemas.microsoft.com/winfx/2006/xaml/presentation"), new XAttribute(XNamespace.Xmlns + "x", "http://schemas.microsoft.com/winfx/2006/xaml"), new XAttribute(XNamespace.Xmlns + "system", "clr-namespace:System;assembly=mscorlib")); oWorker.ReportProgress(5, "Creating Target File."); int elements = elememnts.Count; int i = 1; foreach (string key in elememnts.Keys) { try { using (LiveSearchPortTypeClient client = new LiveSearchPortTypeClient()) { string sCode = this.Currentsource.Code; string tCode = this.CurrentTarget.Code; SearchResponse response = client.Search(BuildRequest(elememnts[key], sCode, tCode)); if (response.Translation.Results.Count() > 0) { string item = response.Translation.Results[0].TranslatedTerm; XElement element = new XElement(system + "String", item); element.Add(new XAttribute(x + "Key", key)); root.Add(element); int percentage = ((i * 90)/elements) + 5; oWorker.ReportProgress(percentage, string.Format("string {0} is converted as {1}", elememnts[key], item)); //Cancel the WORKER if (oWorker.CancellationPending) { e.Cancel = true; break; } } } } catch (Exception ex) { // An exception occurred while accessing the network. oWorker.ReportProgress(((i * 90) / elements) + 5, ex.Message); } i = i+1; } targetDocument = targetDocument ?? new XDocument(); targetDocument.Add(root); targetDocument.Save(destinationfile); oWorker.ReportProgress(100, "Target file created Successfully"); TimeSpan span = DateTime.Now - startTime; e.Result = string.Concat(span.TotalSeconds, " seconds"); } public static SearchRequest BuildRequest(string query, string sCode, string tCode) { SearchRequest request = new SearchRequest(); request.AppId = "3382CF24D27D0A095C7C4945EA17FDD8E2946C73"; request.Query = query; request.Sources = new SourceType[] { SourceType.Translation }; request.Translation = new TranslationRequest(); request.Translation.SourceLanguage = sCode; request.Translation.TargetLanguage = tCode; request.Version = "2.2"; return request; }You can see the BuildRequest actually creates a SearchRequest object, which is used to invoke Bing translator. The SourceLanguage and TargetLanguage will enable you to specify the cultures.
The Search Request will then be invoked using LiveSearchPortTypeClient object. The call client.Search(Request) takes the request object and returns the result. The probable results will be found on the collection response.Translation.Results.
You can see we made a logic around this using XDocument objects to generate the same output that we need for the Resource.
I hope this would be helpful to you.
To Download the source code of the tool just click on the link
Download the Source files
Thank you for reading.
Thanks for this great article.
ReplyDeleteThe source code file is damaged or not available, could you please reupload it?