Localization/Globalization strategy for MEF

Jun 29, 2009 at 8:54 AM

I have developed my UI as MEF export and each UI is a dll for me. What about localization/Globalization strategy for my MEF UI's now ? Has anyone done this before or thought about this ?

 

Regards,

Bhupesh.

Jul 2, 2009 at 6:35 PM

Hi Bhupesh

Is the question has anyone thought of using MEF for providing loc/glob versions of content to controls?

Glenn

Jul 24, 2010 at 11:00 PM
Edited Jul 24, 2010 at 11:01 PM

Hi Bhupesh,

I found a solution that is working very well (at least for my needs)!

I took the localization solution from http://www.wintellect.com/CS/blogs/jprosise/archive/2010/06/21/dynamic-localization-in-silverlight.aspx and transformed it to use MEF! Now I can import the ILocalizationManager to all UserControls that need translation and just use it like this:

<Button Content="{Binding LocalizationManager.Dictionary.Greeting}" />

ILocalizationManager.cs (LocalizationContracts project)

public interface ILocalizationManager
{
   object Dictionary { get; }
   void ChangeCulture(CultureInfo culture);
}
LocalizationManager.cs (LocalizationManager project)
[Export(typeof(ILocalizationManager))]
public class LocalizationAgent : ILocalizationManager, INotifyPropertyChanged
{
	public event PropertyChangedEventHandler PropertyChanged;

	private Resources _resources;
	private static bool _downloaded = false;

	public LocalizationAgent()
	{
	   this._resources = new Resources();
	}

	private void OnPropertyChanged(string propertyName)
	{
	   if (this.PropertyChanged != null)
  	   this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
	}

	public object Dictionary
	{
	   get
	   {
	       return this._resources;
	   }
	}

	public void update(CultureInfo culture)
	{
		Thread.CurrentThread.CurrentCulture = Thread.CurrentThread.CurrentUICulture = culture;
		this.OnPropertyChanged("Dictionary");
	}

	public void ChangeCulture(CultureInfo culture)
       	{
           	   string name = culture.Name.ToLower();

	   if (name.StartsWith("de") || name.StartsWith("es"))
           	   {
                	if (!_downloaded)
                	{
                 	   WebClient wc = new WebClient();
                	    wc.OpenReadCompleted += new OpenReadCompletedEventHandler(OnOpenReadCompleted);
		wc.OpenReadAsync(new Uri("ResourcesDe.xap", UriKind.Relative), culture);
                  	  return;
                }
            }

	this.update(culture);
        }

	void OnOpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
	{
		CultureInfo culture = (CultureInfo)e.UserState;

		if (e.Error == null)
		{
			_downloaded = true;

			StreamResourceInfo sri = new StreamResourceInfo(e.Result, null);
			XmlReader reader = XmlReader.Create(Application.GetResourceStream(sri, new Uri("AppManifest.xaml", UriKind.Relative)).Stream);
				AssemblyPartCollection parts = new AssemblyPartCollection();

			if (reader.Read())
				{
					reader.ReadStartElement();
					if (reader.ReadToNextSibling("Deployment.Parts"))
					{
						while (reader.ReadToFollowing("AssemblyPart"))
						{
							parts.Add(new AssemblyPart() { Source = reader.GetAttribute("Source") });
						}
					}
				}

				foreach (AssemblyPart part in parts)
			{
					if (part.Source.ToLower().Contains("resources"))
				{
						Stream assembly = Application.GetResourceStream(sri, new Uri(part.Source, UriKind.Relative)).Stream;
						part.Load(assembly);
				}
			}

			this.update(culture);
		}
	}
}
In the LocalizationManager project you have to add a resource file, for example "Resources.resx" as used in the Jeff Prosise's Blog.
One can now create multiple projects for all the languages or put them all in one project, how Jeff Prosise did it.
Ah, one last thing, the import:
[Import(AllowDefault = true, AllowRecomposition = true)]
public ILocalizationManager LocalizationManager { get; set; }
To switch the language at runtime just call
this.LocalizationManager.ChangeCulture(ci);
Hope I could help you a little bit!
And thanks to Jeff Prosise!
Tim.
Jul 14, 2011 at 9:00 AM

Hi Timtos,

i try your solution but there is something i could not understand. When i read from Resources directly i find my resources variables, when i do with _resources i didn't. I can't understand why. Could you help?