Tigraine

Daniel Hoelbling-Inzko talks about programming

View localization with dynamics in MVC3

Posted by Daniel Hölbling on March 31, 2011

I ended up doing a good bit of Javascript and Ruby development lately and whenever I go back doing .NET afterwards I feel like things are getting in my way..

For instance the way localization is handled by .NET is a major pain point in all things I’ve been doing lately. WPF is probably the shining example of how not to do it (LocBaml? Serious?), but MVC3 also throws stones your way.

Problem is, that Views are not compiled – so you don’t get access to the static Resources.XXX properties from your Views. This is unfortunate and there are ways around that like using Helpers etc.

But I really grew fond of dynamic in C# for so I decided to simply use that to wrap the usage of my resources so I can write code like this in my Views:

@App.L10n.Product.Name

This is done by hanging my custom dynamic ResourceWrapper onto the dynamic ApplicationContext in Global.asax.

protected void Application_Start() { Application.Add("L10n", new MultiResourceWrapper()); … }

And my MultiResourceWrapper is simply wrapping all Resources existing in the MVC application on startup, and allows access to them through their name:

public class MultiResourceWrapper : DynamicObject { private readonly Dictionary<string, object> resources = new Dictionary<string, object>(); public MultiResourceWrapper() { var assemblyNamespace = this.GetType().Assembly.GetManifestResourceNames(); foreach (var s in assemblyNamespace) { var manager = new ResourceManager(ExtractResourceFullName(s), GetType().Assembly); var name = ExtractResourceName(s); resources.Add(name, new ResourceWrapper(manager)); } }

string ExtractResourceFullName(string s) { var regex = new Regex(@"(.*).resources$"); return regex.Match(s).Groups1.Value; }

string ExtractResourceName(string s) { var regex = new Regex(@"([a|A-z|Z]*).resources$"); return regex.Match(s).Groups1.Value; }

public override bool TryGetMember(GetMemberBinder binder, out object result) { result = resources[binder.Name]; return true; }

public class ResourceWrapper : DynamicObject { readonly ResourceManager manager; public ResourceWrapper(ResourceManager manager) { this.manager = manager; }

public override bool TryGetMember(GetMemberBinder binder, out object result) { result = manager.GetString(binder.Name); return true; } } }

As you can see all I need to do now to have localized strings for something is to add a Resource somewhere in my MVC application and then access it through it’s name from within the View.

One important thing though: I intentionally omitted any error handling code for the case where you mistype something. Nothing is more annoying than WPF bindings that simply don’t work because of typos, so having the app blow up with a YSOD is to me preferrable to a silent failure you have to spot later in deployment. But feel free to expand this to your liking.

The code is also available as a Gist from GitHub: MultiResourceWrapper.cs

Filed under net, programmierung
comments powered by Disqus

My Photography business

Projects

dynamic css for .NET

Archives

more