Fixing Internationalization in ASP.NET

I've been building websites with ASP.NET for a little over 10 years now, and I have a dirty little secret to confess: I've never Internationalized a single one of them.

It's not from lack of trying, I can tell you. I've got a good dozen false starts under my belt, and plenty of hours spent studying the code from other people's sites that implement Internationalization (abbreviated as i18n for us lazy typists) the way that Microsoft wants you to do it. And my conclusion is that it's just plain not worth the effort.

I18n is hopelessly broken in ASP.NET. Let's look at this nice snippet of sample code to see why:

<!-- STEP ONE, in MyPage.aspx: Create Runat="Server" Literal Control: --> <asp:Literal ID="lblPages" runat="server" meta:resourcekey="lblPagesResource1" Text="Pages"/> <!-- STEP TWO, in MyPage.es-ES.resx: Create Message Key/Value: --> <data name="lblPagesResource1.Text" xml:space="preserve"> <value>Browse</value> </data> ...and that's for EVERY piece of text in your whole site!

Notice that you need to make every single piece of localized text into a runat="server" control. And that you then need to add this crazy long attribute (that Intellisense doesn't know about, so you have to type out in full) to each one of those controls so that ASP.NET can find them in one of the Resource files that you need to generate by hand for every text fragment in your entire website.

If it sounds like a ridiculous amount of work for your developers, you're probably being charitable. In practice, it's so much extra work that nobody actually does it. That, my friends, is the reason you hardly ever see any multi-language websites written with ASP.NET.

Recently, however, my hand was truly forced. We're getting pretty close to launching FairTutor to the public, and since it has target audiences in both the United States and Latin America it pretty much needs to work in Spanish as well as English. This is the part where I start wistfully looking back to a couple Django projects we did not too long ago, and the absolute breeze it was localizing those sites. If only the rest of Django wasn't so crap, we could just port this project across and… Hang on a sec. Port. Yeah, how about we simply port that amazing Django i18n stuff over to ASP.NET instead.

That was a week ago.

Today, I'm releasing some code that I hope will single-handedly fix i18n in ASP.NET. It's based on the way that everybody else does it. Let's pause a minute to let that sink in, since many of my fellow .NET devs might not have been aware of this fact: There's another way of doing i18n, and it's so simple and straightforward that every other web framework uses it in some form or another to do multi-language websites.

In Django, PHP, Java, Rails, and pretty much everything else out there, you simply call a function called gettext() to localize text. Usually, you alias that function to _(), so you're looking at like 5 keystrokes (including quotes) to mark a piece of text for internationalization. That's simple enough that even lazy developers like me can be convinced to do it.

Better still, frameworks that use this gettext() library (it's actually a chunk of open source code from the GNU folks), also tend to come with a program that will sift through your source and automagically generate translation files for you (in .PO format, which is basic enough to be edited in notepad by non-tech-savvy translators, but is popular enough that there are several existing editors built just for it), containing every text fragment that was marked for i18n.

The whole process is so simple and straightforward that you're left to wonder why Microsoft felt compelled to spend so much time and effort reinventing it all to be worse.

Introducing FairlyLocal

I really want ASP.NET to stop forcing people to monkey with XML files and jump through hoops just to show web pages in Spanish, so I'm going to package up all this code and release it as Open Source:

FairlyLocal - Gettext Internationalization for ASP.NET

At the moment, there's not a whole lot to it. It'll find where you're using the FairlyLocal.GetText() (or its _() alias) and generate .PO files for you. And it'll suck in various language versions of those files and translate text on your website. Not much there, eh? But then that's the whole point: i18n is supposed to be simple and straightforward. Hopefully, FairlyLocal will make that an actuality for the ASP.NET community.

I look forward to hearing your feedback.

FairTutor is our latest project here at Expat. It's a website that connects Spanish teachers in South America with students in the US and lets them hold live online Spanish lessons.

We'll be starting Beta classes soon, so if you want to score some free Spanish lessons, you might want to go sign up for the waiting list!


Jason Kester
@jasonkester

I run a little company called Expat Software. Right now, the most interesting things we're doing are related to Cloud Storage Analytics, Online Classrooms, and Customer Lifecycle Metrics for SaaS Businesses. I'll leave it to you to figure out how those things tie together.


Subscribe in a reader


Copyright © 2018 Expat Software