Optimized Language support in Episerver Commerce
Catalog authoring were with Episerver Commerce 7.5 aligned with the authoring experience known from Episerver CMS. It made the life of development and authoring easier and gave our clients a long list of benefits. There are still features that are not supported due to the underlying Commerce engine and the usage of Meta Data Plus. One of them is the powerful Fallback and Replacement Language features.
What would these features provide?
Fallback and Replacement Language in Episerver CMS allows Content Editors and Administrators to configure how a Language Branche will inherit or be replaced by a Master Language. It’s a CMS feature we tend to use on client projects when building a solution that covers multiple languages across multiple markets. Feature would, in a Commerce context, enable us to inherit characteristics of Nodes and Products across Language Branches in similar markets – e.g. having the same portfolio of Products in French speaking countries like France, Switzerland and Luxembourg. Reality is that this is not supported in Episerver Commerce. We’ve created an alternative way of achieving something similar – it allows your Catalog Managers to simply replicate a product across Language Branches without needing to copy paste.
Working with an alternate solution
The solution we’ve ended up with is not activating the same features as Fallback and Replacement Language in Episerver CMS. Instead, it eases the workflow of translating Products and Nodes drastically.
Goal was the help Catalog Managers with replicating their Master Language – e.g. French in France – across Markets where Product Characteristics were considered identical.
Catalog features has been implemented via a ContentProvider, who acts as a proxy between the concept of IContent and the underlying Meta Data Plus data-layer. It is relying on a few important implementations in order to manage the mapping between Meta Fields and the Content Model.
Loading of Meta Data values
ICatalogPropertyLoader is an important interface in our context. Its implementation is responsible of loading information into an instance of EntryContentBase based on Meta Data Plus DTOs. Our need of adjusting the behavior for localization required us to adjust the implementation to take a Master Language in to account when creating the IContent representation of a Product or Node for a given Language Branch.
Above is the entire snippet that can achieve this. Let me take you on a small tour through the Code and put some words on the details we’ve implemented.
Most importantly, you need to understand how the two overrides of LoadMetaDataContentProperties adds inherited MetaData values when Commerce requests us to map a piece of content. We only apply the “fallback” values in case the content is a draft and not already being the Master Language. Reason for this conditional logic is that Episerver Commerce automatically creates a draft when a new Language – e.g. fr-LU – is requested.
When these conditions are fulfilled we request AddInheritedMetaDataAttributePropertyValues that is responsible of doing the actual mapping to our CatalogContentBase.
We start out by getting the Field Values for both the Language Branch and its Master Language. These Hash-tables will be our supplier of the values we need in order to load information to our Catalog content. By iterating through fields on the MetaClass associated with our Content Type, we can ensure that we are not mapping any of the Reserved Fields such as Id and Published Date. All other fields are automatically assigned the inherited value through a MetaDataPropertyMapper, that knows how to interpret between PropertyData and MetaDataType.
We need to do something exceptional when a MetaField belongs to a to an in-line block on our Catalog Content. By convention, this can easily be identified and all the Properties of our in-line block will automatically be mapped one by one.
As I mentioned earlier, Episerver Commerce automatically creates an empty draft when an Catalog Manager clicks on a new Language Branch. In order to apply our implementation above, we need to adjust how a new version of Catalog Content is build based on a given Content Reference.
Applying fallback when constructing Content
Implementations of ICatalogContentBuilder are responsible of constructing instances of CatalogContentBase based on a collection of Content References. We need to replace existing NodeBuilder and EntryBuilder in order to override the logic of creating a new draft.
Above builders are basically doing the same for two different kinds of Catalog Content. They ensure that Meta Data values are loaded to properties when a new Content Version is created through the Catalog Content Provider.
This is basically what is needed in order to get a inheriting workflow for doing translations. Please ensure to register these new implementations in Structuremap in order to ensure that Episerver is aware of our changes*.
Let us hope that Episerver will add native support for something similar. Until that happens, this approach is a great alternative to support Catalog Mangers in replicating products across Language Branches.
* Be aware that we are ejecting the existing implementations. These would still be registered due to the use of Add