Internationalizing an enum in C#, while storing a non-localized value to the database

One problem I’ve run into several times, and never found a good solution to, is storing an enum value in a database column. It’s kind of ugly to store a string for something that isn’t really a string.

In a recent project, I had an additional problem – I needed to internationalize this program. The value in the database needed to always be one language (Spanish, in this case). However, the value to display in the browser needed to be in the user’s current language.

Here’s how I handled it.

Preparing to create a localized enum

Choose your (data)base language

I decided to always store the value in the database in the application’s base language – in this case, we’ll use English, although it could be any language you want.

The base language should be the one that the programmers and DBAs understand, since that will make it easier to understand if they ever have to debug or change something.

The example

For this sample, the “enum” we’ll use will be to handle status. The three statuses will be “Open”, “OnHold”, and “Closed”.

Create the resource file(s)

For this example, I’m using a resource file named “Literals”, in a directory named “Resources”. Here are our three values to save in the database, with their corresponding display values:

Literals.resx

Literals.resx

And here’s the version for the Spanish text:

Literals.es.resx

Literals.es.resx

Remember to set the access modifier to Public for your resource files.

Extension method

To do the translation, I use an extension method.

InCurrentLanguage() takes any string and displays the value from the resource file for the current language, if it finds a match. If it doesn’t find a match, it will display whatever value was passed to it.

A nice thing about this method is that you can use it on any string in your application.

If you already have a class for your extension methods, you can add the InCurrentLanguage() method to it, instead of adding this new class.

ExtensionMethods.cs

Base LocalizedEnum class

Now we need the base class to use for the localized enum values.

This class accepts the value to store in the database as a parameter of the constructor.

When reading from, or writing to, the database, use the ValueForDB() method. To display the translated value, call either ToString() or ValueForUI().

LocalizableEnumValue.cs

Defining the localized enum

Now we can define our localized enum.

Here’s the code for ProjectState.cs.

The constructor takes the database value (passing it to the base class, and storing it there). There are also overrides for equality checks. You probably don’t need all of them, especially since you’ll only be instantiating the objects once, but I added them in case you do something different in your code.

ProjectState.cs

Creating the localized enum

Here’s where the localized enum gets created and populated.

Ignore the two constants for now. The rest of the code is what needs to be done to create a localized enum.

In the static constructor, the list of values gets populated. I’m using a constant for these, so I don’t have to worry about mistyping the value. Notice that the values of the constants exactly match the values used for the resource names in Literals.resx. This lets the InCurrentLanguage() method does its work.

There is also the private static class ProjectStates.

This class, along with the public static properties for each value, makes the localized enum appear like a normal enum when you use IntelliSense. ToList() lets you get the values for binding to controls (such as a combobox). And, finally, ForDBValue() returns the appropriate localized enum value when you pass it the value you’d store in the database.

LocalizedEnums.cs

Using the localized enum

Everything is in place, so let’s actually use this.

Here’s how I load the enum values into a combobox for a Windows Form.

The data source is the list, and I use the constants to bind the value and display members. Again, I like to use constants so I don’t lose type by accidentally mistyping a string value.

Form1.cs

You can also use the localized enum as the datatype for a property.

Here’s a class that has a ProjectState property, along with a constructor that you could use when populating it from the value you’d read from the database (where you would have previously stored the ValueForDB while inserting or updating the record).

Project.cs

Summary

There is a bit of work to create these localizable enums. However, I’m a big believer in preparing your applications for internationalization. If you build something good, it’s a fairly simple way to expand your market.

Leave a Reply

Your email address will not be published. Required fields are marked *