Hiding properties in EPiServer edit mode based on the language branch

Intro

Building a multi-language website is always challenging. Among other things, we need to think about date formats, language analyzers, and full-text search. However, we must also not forget the site editors and provide them the best possible editing experience.

Recently, I was working on a multi-language website, and in this blog post, I will describe the challenges we had with multiple languages, and how we customized the editing interface to solve some of those challenges.

Language Code

When working on a multi-language website, we need to make sure that HTML lang attribute is not hard-coded and that we're using the correct language code. Most of the time, we can simply enable multiple languages in admin mode, and set the HTML lang attribute to CurrentPage.Language.TwoLetterISOLanguageName, but that's not always the case.

Our client is a Norwegian company in a public sector that wanted a new multi-language website in Norwegian and in English.

The Norwegian language has two distinct written varieties: Bokmål ("Book Language") and Nynorsk ("New Norwegian"). Some statistics say that Nynorsk is used in writing by roughly 10% of the population in Norway, while Bokmål is dominant and is used by close to 90%.

Most Norwegian companies, in the public sector, have a "Nynorsk quota.", i.e., a certain percentage on Norwegian content (at least 10%) should be written in Nynorsk.

If we know that every EPiServer page is written in English, Bokmål, and Nynorsk, we can simply enable those three languages in admin mode and set their language codes (en, nb, and nn) in the HTML lang attribute. However, what if only 10% of the Norwegian content is written in Nynorsk?

We could enable English and Bokmål and create a string property in a base class that allows site editors to override the language code.

But having a free text field is very error-prone; editors can type whatever they want.

Having a checkbox would be much better. If it's checked, we simply set the HTML lang attribute to nn, and if not, we use the CurrentPage.Language.TwoLetterISOLanguageName.

But, this checkbox should only be visible in the Norwegian branch.

How do we solve this?

We solve this with a custom attribute.

Custom Attribute

The idea was to create a bool property in a base page, and decorate it with a custom attribute like this:

[Display(GroupName = SystemTabNames.PageHeader)]
[CultureSpecific]
[VisibleInBranch("nb")]
public virtual bool IsNynorsk { get; set; }

By default, the property should be hidden in all branches, except for those specified in the VisibleInBranch attribute.

Code:

[AttributeUsage(AttributeTargets.Property)]
public class VisibleInBranchAttribute : Attribute
{
    public VisibleInBranchAttribute(params string[] languageBrances)
    {
        LanguageBranches = languageBrances ?? throw new ArgumentNullException(nameof(languageBrances));
    }

    public string[] LanguageBranches { get; }
}
public class MetaDataExtender : IMetadataExtender
{
    public void ModifyMetadata(ExtendedMetadata metadata, IEnumerable<Attribute> attributes)
    {
        var model = metadata.Model as ILocalizable;

        foreach (var modelMetadata in metadata.Properties)
        {
            var property = (ExtendedMetadata)modelMetadata;
            var attribute = property.Attributes.OfType<VisibleInBranchAttribute>().FirstOrDefault();
            if (attribute == null)
            {
                continue;
            }

            property.ShowForEdit = model != null &&
                                    attribute.LanguageBranches.Contains(model.Language.TwoLetterISOLanguageName);
        }
    }
}
[InitializableModule]
[ModuleDependency(typeof(InitializableModule))]
public class InitModule : IInitializableModule
{
    public void Initialize(InitializationEngine context)
    {
        if (context.HostType != HostType.WebApplication)
        {
            return;
        }

        var registry = context.Locate.Advanced.GetInstance<MetadataHandlerRegistry>();
        registry.RegisterMetadataHandler(typeof(ContentData), new MetaDataExtender());
    }

    public void Uninitialize(InitializationEngine context)
    {
    }
}

Note: The code has been tested with EPiServer 11.3

This is how the editing interface looks in the English branch:

episerver edit mode - english branch 

And, this is how it looks in the Norwegian branch:

episerver edit mode - norwegian branch

AI

The custom checkbox and the VisibleInBranch attribute solved the problem, but editors still have to remember to check the box. One way to improve this would be to use Microsoft Cognitive Service and Text Analytics API to recognize the language and warn the site editor if the checkbox is not selected.

https://azure.microsoft.com/en-us/services/cognitive-services/text-analytics/

comments powered by Disqus