Oversættelse vha Custom Data Annotations

Arbejder man med internationale web applikationer, er man nok stødt på problemstillingen om, hvordan man oversætter sine sider. Der findes mange metoder, men når nu man er lidt doven og gerne vil undgå for meget arbejde, gælder det jo om at finde den metode som involverer mindst arbejde. Desuden kan man jo lige så godt bruge de metoder som frameworket tilbyder.

I mit arbejde med ASP.NET MVC 3 er jeg stødt på denne metode, der muligvis kunne spare mig for noget kode og kompleksitet andre steder i mit system. Det drejer sig om nedarvning af DataAnnotationsModelMetaDataProvider-klassen, hvor metoden CreateMetadata overstyres, således DisplayName-egenskaben oversættes. Det kunne se nogenlunde således ud: 

public class CustomModelMetadataProvider 
                : DataAnnotationsModelMetadataProvider
{
    protected override ModelMetadata CreateMetadata(
        IEnumerable<Attribute> attributes, 
        Type containerType, 
        Func<object> modelAccessor, 
        Type modelType, 
        string propertyName)
    {
        var metaData =  base.CreateMetadata(
            attributes, 
            containerType, 
            modelAccessor, 
            modelType, 
            propertyName);

        metaData.DisplayName = 
            metaData.GetDisplayName().Translate();

        return metaData;
    }
}

Den nye provider skal aktiveres i Global.asax, således den bliver kaldt når dataannotations skal behandles. Dette gøres i Application_Start således:

protected void Application_Start()
{
    AreaRegistration.RegisterAllAreas();

    ModelMetadataProviders.Current = 
        new CustomModelMetadataProvider();

    RegisterStorageConfiguration();
    RegisterGlobalFilters(GlobalFilters.Filters);
    RegisterRoutes(RouteTable.Routes);

    // ... og hvad vi ellers har...
}

Med dette på plads, kan (view)model udstyres med en nøgle til oversættelsen. Det kunne se således ud:

public class Person
{
    [Display(Name="First name")]
    public string FirstName { get; set; }

    [Display(Name="Last name")]
    public string LastName { get; set; }

    public string Address { get; set; }
}

Bemærk at for egenskaber uden Display-annotation vil det være egenskabens navn er benyttes som nøgle til oversættelse. Nu vil Person-objektets data kunne vises i et view således med oversatte ledetekster:

@model Person
@{
    Layout = null;
}

@Html.DisplayForModel()

Selve oversættelsen sker i Translate-funktionen, der i mit tilfælde er en Extension på string-objektet og som slår op i et datalager, hvor hver tekst er oversat til det aktuelle sprog. Hvilket sprog der er tale om, hentes (af Translate extension funktionen) i den aktuelle tråds UI Culture.

Comment