It’s day #1 on a new project demanding my favorite requirement: localization yay! The yay emphasize is mine because localization presents some thorny technical challenges that often pull along a trailer load of complexity. Framework tools make many of the localization tasks a breeze but there’s always that one piece just beyond .NET’s reach: storing localized text in a database. Since I’ve spent far too many hours (days?) wrestling with lookup table and lookup tables for lookup table solutions it’s time to start this project off with a simple and elegant solution – one that plays nice with Entity Framework and maybe even brings its own UI to the party.
My requirements are simple: I’m using EF code first and will need to store entities having multilanguage properties… and I want to work with a super-simple, elegant, unobtrusive API that reads like poetry. Spoiler alert — we’re bringing JSON to the party along with my new favorite NuGet package (ok dislaimer I wrote it).
Let’s jump in — this tutorial will ditch the too-popular generic lookup table approach and store localized text for entities as key/value serialized JSON. Our JSON is simple, readable, and searchable. We’ll then use some simple extension methods from the NuGet package OrangeJetpack.Localization to make getting and setting our localized text a breeze.
To peak ahead just a bit we’ll be using a regular EF POCO model and code-first migrations. We’ll work with an entity Planet having a PlanetId and a Name property that will eventually be localized to English, Russian, and Japanese. Ultimately it will look like this in our database:
To start things off new-up a fresh ASP.NET MVC web application. You can play along at home or download a working demo at: https://github.com/andy-mehalick/OrangeJetpack.LocalizationDemo. Next we’ll add our simple EF POCO and DbContext classes:
We’ll then let code first migrations create our local db with some Powershell in Package Manager Console:
PM> Add-Migrations AddPlanet
Finally, let’s add a HomeController with Index() and scaffold a list view.
Snap your fingers to add some sample data and you should see:
Eesh, close but let’s now show the localized content only.
NuGet and OrangeJetpack.Localization.Mvc
PM> Install-Package OrangeJetpack.Localization.Mvc
This package will add a LocalizationLanguages property to app settings, let’s add the language codes for English, Russian, and Japanese:
Finally, let’s update Planet to indicate it is localizable and that Planet.Name is localized – we can do this by implementing ILocalizable and decorating Name with LocalizedAttribute:
This now generously grants us access to an IEnumerable
Back to HomeController.Index(), add an optional langCode input parameter and change _db.Planets.ToList() to _db.Planets.Localize(langCode, I => i.Name):
Of course we could get language code from the user’s web browser or a profile setting but let’s keep it simple for now. If we omit a language code or use an unsupported one it will default to the first language in our app settings, “en” by default. Let’s run it again passing in the language code for Russian:
Here’s what it would look like with no language, Japanese, or an unknown language:
Multiple Localized Properties
Finally, one bonus of our extension method Localize() is its support for multiple properties; if Planet had additional localized properties we could pass them in as a params list:
That’s it for now, in Part 2 we’ll look at adding and updating our localizable entities with the included editor template for MVC and eventually we’ll dig deeper in OrangeJetpack.Localization implementation. If you want to jump ahead you can find the project at https://github.com/andy-mehalick/OrangeJetpack.Localization.