Internationalization with Entity Framework Code First – Part I

Recently, I needed to include I18N contents on a web application that uses EF Code First. When deciding the data model to use I came across this post, which describes 4 possible approaches. We needed the model to easily support adding new languages, so the first option (having one column for each translation of a given property/column) was no good. The first attempt was to use a single common translation table. The entities would be something like this:

    class Entity
    {
        // ...
        public LocalizableString LocalizableProp { get; set; }
    }

    class LocalizableString
    {
        public long Id { get; set; }
        [Required]
        public virtual ICollection<LocalizableStringEntry> Entries { get; set; }
    }

    class Language
    {
        public int Id { get; set; }
        [StringLength(8)]
        public string Code { get; set; } // Unique
        public string Name { get; set; }
    }

    class LocalizableStringEntry
    {
        public long Id { get; set; }
        [Required]
        public string Value { get; set; }
        [Required]
        public virtual Language Language { get; set; }
    }

However, we dropped this approach for 3 main reasons: it’s not easy (tidy) to ensure that all the properties are translated for a given language; multiple delete cascade paths are not supported by SQL Server (which would be useful to have all the translations deleted automatically); and it’s not very straightforward to select a complete translation for a specific entity. In addition, it isn’t very natural to have translations as top-level entities; even if you have identical properties on different entities you won’t share the LocalizableString instances. Bottom line: we ended up switching to a translation-table-per-entity approach (the last option on the previously mentioned post).

The goal is to have something like:

    public class SomeEntity
    {
        // ...
        public string NonLocalizableProp { get; set; }
        [Required]
        public virtual ICollection<SomeEntityTranslation> Translations { get; set; }
    }

    public class SomeEntityTranslation
    {
        [Required]
        public virtual Language Language { get; set; }
        [Required]
        public string LocalizableProp1 { get; set; }
        [Required]
        public string LocalizableProp2 { get; set; }
    }

This is easy to query, keeps column names and makes it possible to easily validate the set of required translated properties. Since we’ll be needing translations on multiple entities it is appropriate to define some strategy that eases the implementation of a translatable entity. I came up with two different possibilities: one that needs fewer model configurations but is a bit ugly; another that is tidier but requires some explicit model configurations. I’ll present the two approaches on the next posts of this series.

Advertisements

3 thoughts on “Internationalization with Entity Framework Code First – Part I

  1. Pingback: I18N with EF Code First – Part II « Luís Gonçalves

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s