November Happy Hour will be moved to Thursday December 5th.

Sanjay Kumar
Feb 1, 2021
  2070
(6 votes)

Multilingual cart validation message

The purpose of this blog to display the cart validation messages market's language specific and make it user-friendly to the customer for the better understanding. 

About the Market in Episerver Commerce?
Market is a central of Episerver Commerce. A single site can have multiple markets, each with its own product catalog, language, currency, and promotions. Classes in this topic are available in the Mediachase.Commerce or Mediachase.Commerce.Markets namespaces.

Problem:
In one of my site, I have implemented multi-market functionality and managed the content accordingly but there is no feature to display the cart validation message in readable format to the customer for market language specific.

e.g.

  • United State (en) : Display the cart validation message in English language.
  • France (fr) : Display the cart validation message in French language.

Solution:

Episerver provides a class method OrderValidationService.ValidateOrder(cart) to validate your cart before to save, using IOrderRepository.Save(cart) method. With the help of this method we make sure the cart has enough quantity, prices are correct and up-to-date, and any promotions are applied correctly.

The ValidateOrder(cart) method returns IDictionary<ILineItem, IList<ValidationIssue>> validation issue per ILineItem but  ValidationIssue is an enum type that returns validation message in below formats which are not user-friendly and market language specific.

  • CannotProcessDueToMissingOrderStatus
  • RemovedDueToCodeMissing
  • RemovedDueToNotAvailableInMarket
  • RemovedDueToUnavailableCatalog
  • ...

So let’s make cart validation message user-friendly in the simple way.

Step 1: Create an XML file language specific and place the all possible cart validation message like below and placed into the lang folder under the site root.

<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<languages>
  <language name="English" id="en">
    <cart>
      <validation>
        <CannotProcessDueToMissingOrderStatus>Cannot process due to missing order status.</CannotProcessDueToMissingOrderStatus>
        <RemovedDueToCodeMissing>The catalog entry code that maps to the line item has been removed or changed.</RemovedDueToCodeMissing>
        <RemovedDueToNotAvailableInMarket>Item has been removed from the cart because it is not available in your market.</RemovedDueToNotAvailableInMarket>
        <RemovedDueToUnavailableCatalog>Item has been removed from the cart because the catalog of this entry is not available.</RemovedDueToUnavailableCatalog>
        <RemovedDueToUnavailableItem>Item has been removed from the cart because it is not available at this time.</RemovedDueToUnavailableItem>
        <RemovedDueToInsufficientQuantityInInventory>Item has been removed from the cart because there is not enough available quantity.</RemovedDueToInsufficientQuantityInInventory>
        <RemovedDueToInactiveWarehouse>Item has been removed from the cart because the selected warehouse is inactive.</RemovedDueToInactiveWarehouse>
        <RemovedDueToMissingInventoryInformation>Item has been removed due to missing inventory information.</RemovedDueToMissingInventoryInformation>
        <RemovedDueToInvalidPrice>Item has been removed due to an invalid price.</RemovedDueToInvalidPrice>
        <RemovedDueToInvalidMaxQuantitySetting>Item has been removed due to an invalid setting for maximum quantity.</RemovedDueToInvalidMaxQuantitySetting>
        <AdjustedQuantityByMinQuantity>Item quantity has been adjusted due to the minimum quantity threshold.</AdjustedQuantityByMinQuantity>
        <AdjustedQuantityByMaxQuantity>Item quantity has been adjusted due to the maximum quantity threshold.</AdjustedQuantityByMaxQuantity>
        <AdjustedQuantityByBackorderQuantity>Item quantity has been adjusted due to backorder quantity threshold.</AdjustedQuantityByBackorderQuantity>
        <AdjustedQuantityByPreorderQuantity>Item quantity has been adjusted due to the preorder quantity threshold.</AdjustedQuantityByPreorderQuantity>
        <AdjustedQuantityByAvailableQuantity>Item quantity has been adjusted due to the available quantity threshold.</AdjustedQuantityByAvailableQuantity>
        <PlacedPricedChanged>This item's price has changed since it was added to your cart.</PlacedPricedChanged>
        <RemovedGiftDueToInsufficientQuantityInInventory>Gift item has been removed from the cart because there is not enough available quantity.</RemovedGiftDueToInsufficientQuantityInInventory>
        <RejectedInventoryRequestDueToInsufficientQuantity>The inventory request for item has been rejected because there is not enough available quantity.</RejectedInventoryRequestDueToInsufficientQuantity>
      </validation>
    </cart>
  </language>
  <language name="French" id="fr">
    <cart>
      <validation>
        <CannotProcessDueToMissingOrderStatus>Il ne peut pas être traité en raison d'un statut de commande manquant.</CannotProcessDueToMissingOrderStatus>
        <RemovedDueToCodeMissing>Le code d'entrée de catalogue qui correspond à l'élément de campagne a été supprimé ou modifié.</RemovedDueToCodeMissing>
        <RemovedDueToNotAvailableInMarket>L'article a été retiré du panier car il n'est pas disponible sur votre marché.</RemovedDueToNotAvailableInMarket>
        <RemovedDueToUnavailableCatalog>L'article a été retiré du panier car le catalogue de cette entrée n'est pas disponible.</RemovedDueToUnavailableCatalog>
        <RemovedDueToUnavailableItem>L'article a été retiré du panier car il n'est pas disponible pour le moment.</RemovedDueToUnavailableItem>
        <RemovedDueToInsufficientQuantityInInventory>L'article a été retiré du panier car la quantité disponible est insuffisante.</RemovedDueToInsufficientQuantityInInventory>
        <RemovedDueToInactiveWarehouse>L'article a été retiré du panier car l'entrepôt sélectionné est inactif.</RemovedDueToInactiveWarehouse>
        <RemovedDueToMissingInventoryInformation>L'article a été supprimé en raison d'informations d'inventaire manquantes.</RemovedDueToMissingInventoryInformation>
        <RemovedDueToInvalidPrice>L'article a été supprimé en raison d'un prix non valide.</RemovedDueToInvalidPrice>
        <RemovedDueToInvalidMaxQuantitySetting>L'article a été supprimé en raison d'un paramètre non valide pour la quantité maximale.</RemovedDueToInvalidMaxQuantitySetting>
        <AdjustedQuantityByMinQuantity>La quantité d'articles a été ajustée en raison du seuil de quantité minimale.</AdjustedQuantityByMinQuantity>
        <AdjustedQuantityByMaxQuantity>La quantité d'articles a été ajustée en raison du seuil de quantité maximale.</AdjustedQuantityByMaxQuantity>
        <AdjustedQuantityByBackorderQuantity>La quantité d'articles a été ajustée en raison du seuil de quantité de commandes en souffrance.</AdjustedQuantityByBackorderQuantity>
        <AdjustedQuantityByPreorderQuantity>La quantité d'articles a été ajustée en raison du seuil de quantité de précommande.</AdjustedQuantityByPreorderQuantity>
        <AdjustedQuantityByAvailableQuantity>La quantité d'articles a été ajustée en raison du seuil de quantité disponible.</AdjustedQuantityByAvailableQuantity>
        <PlacedPricedChanged>Le prix de cet article a changé depuis qu'il a été ajouté à vos favoris.</PlacedPricedChanged>
        <RemovedGiftDueToInsufficientQuantityInInventory>L'article cadeau a été retiré du panier car la quantité disponible est insuffisante.</RemovedGiftDueToInsufficientQuantityInInventory>
        <RejectedInventoryRequestDueToInsufficientQuantity>La demande d'inventaire pour l'article a été rejetée car la quantité disponible n'est pas suffisante.</RejectedInventoryRequestDueToInsufficientQuantity>
      </validation>
    </cart>
  </language>
</languages>

Step 2: Create a model class that will hold the error message and variant code.

public class CartValidationIssue
{
        public string Message { get; set; }
 
        public string Code{ get; set; }

        public bool IsBlank => string.IsNullOrWhiteSpace(this.Message);
       
        public static CartValidationIssue Make(string message, string code)
        {
            return new CartValidationIssue
            {
                Message = message,
                Code = code,
            };
        }
 }

Step 3: Create described methods where you are validating your cart and returns the validation messages in the list format after reading from XML file and show on the cart page or mini-cart area.

  1. Use ICurrentMarket interface and get the current market culture
  2. Make sure you have selected correct default language for the current market in commerce manager for e.g. France choose default language francais

 

public List<CartValidationIssue> ValidateCart(ICart cart)
{

            var validationResult = _orderValidationService.ValidateOrder(cart);

            var errors =
                validationResult
                    ?.Select(lineItemIssueEntry => new
                    {
                        LineItemIssues =
                            lineItemIssueEntry.Value
                                .Select(validationIssue => new
                                {
                                    ValidationIssueMessage = this.GetCartValidationMessage(validationIssue),
                                    LineItemCode = lineItemIssueEntry.Key.Code,
                                })
                                .ToList(),
                    })
                    .SelectMany(lineItemIssueGroup => lineItemIssueGroup.LineItemIssues)
                    .Select(x => CartValidationIssue.Make(x.ValidationIssueMessage, x.LineItemCode))
                    .Where(x => !x.IsBlank)
                    .ToList() ?? new List<CartValidationIssue>();

            return errors;
 }
 private string GetCartValidationMessage(ValidationIssue issue)
 {
            var market = _currentMarket.GetCurrentMarket();
            var cultureInfo = market.DefaultLanguage;

            switch (issue)
            {
                default:
                case ValidationIssue.None:
                    return null;

                case ValidationIssue.CannotProcessDueToMissingOrderStatus:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/CannotProcessDueToMissingOrderStatus", "It cannot process due to missing order status.", cultureInfo);

                case ValidationIssue.RemovedDueToCodeMissing:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToCodeMissing", "The catalog entry code that maps to the line item has been removed or changed.", cultureInfo);

                case ValidationIssue.RemovedDueToNotAvailableInMarket:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToNotAvailableInMarket", "The catalog entry code that maps to the line item has been removed or changed.", cultureInfo);

                case ValidationIssue.RemovedDueToUnavailableCatalog:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToUnavailableCatalog", "The catalog entry code that maps to the line item has been removed or changed.", cultureInfo);

                case ValidationIssue.RemovedDueToUnavailableItem:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToUnavailableItem", "Item has been removed from the cart because it is not available at this time.", cultureInfo);

                case ValidationIssue.RemovedDueToInsufficientQuantityInInventory:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToInsufficientQuantityInInventory", "Item has been removed from the cart because there is not enough available quantity.", cultureInfo);

                case ValidationIssue.RemovedDueToInactiveWarehouse:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToInactiveWarehouse", "Item has been removed from the cart because the selected warehouse is inactive.", cultureInfo);

                case ValidationIssue.RemovedDueToMissingInventoryInformation:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToMissingInventoryInformation", "Item has been removed due to missing inventory information.", cultureInfo);

                case ValidationIssue.RemovedDueToInvalidPrice:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToInvalidPrice", "Item has been removed due to an invalid price.", cultureInfo);

                case ValidationIssue.RemovedDueToInvalidMaxQuantitySetting:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedDueToInvalidMaxQuantitySetting", "Item has been removed due to an invalid setting for maximum quantity.", cultureInfo);

                case ValidationIssue.AdjustedQuantityByMinQuantity:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/AdjustedQuantityByMinQuantity", "Item quantity has been adjusted due to the minimum quantity threshold", cultureInfo);

                case ValidationIssue.AdjustedQuantityByMaxQuantity:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/AdjustedQuantityByMaxQuantity", "Item quantity has been adjusted due to the maximum quantity threshold.", cultureInfo);

                case ValidationIssue.AdjustedQuantityByBackorderQuantity:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/AdjustedQuantityByBackorderQuantity", "Item quantity has been adjusted due to backorder quantity threshold.", cultureInfo);

                case ValidationIssue.AdjustedQuantityByPreorderQuantity:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/AdjustedQuantityByPreorderQuantity", "Item quantity has been adjusted due to the preorder quantity threshold.", cultureInfo);

                case ValidationIssue.AdjustedQuantityByAvailableQuantity:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/AdjustedQuantityByAvailableQuantity", "Item quantity has been adjusted due to the available quantity threshold.", cultureInfo);

                case ValidationIssue.PlacedPricedChanged:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/PlacedPricedChanged", "This item's price has changed since it was added to your favorites.", cultureInfo);

                case ValidationIssue.RemovedGiftDueToInsufficientQuantityInInventory:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RemovedGiftDueToInsufficientQuantityInInventory", "Gift item has been removed from the cart because there is not enough available quantity.", cultureInfo);

                case ValidationIssue.RejectedInventoryRequestDueToInsufficientQuantity:
                    return LocalizationService.Current.GetStringByCulture("/cart/validation/RejectedInventoryRequestDueToInsufficientQuantity", "The inventory request for item has been rejected because there is not enough available quantity.", cultureInfo);
            }
 }

Result:

e.g. The validation message display for France(fr) market in the French language.

Enjoy the coding and share your thoughts 😊

Thanks for your visit!

Feb 01, 2021

Comments

Please login to comment.
Latest blogs
Optimizely SaaS CMS + Coveo Search Page

Short on time but need a listing feature with filters, pagination, and sorting? Create a fully functional Coveo-powered search page driven by data...

Damian Smutek | Nov 21, 2024 | Syndicated blog

Optimizely SaaS CMS DAM Picker (Interim)

Simplify your Optimizely SaaS CMS workflow with the Interim DAM Picker Chrome extension. Seamlessly integrate your DAM system, streamlining asset...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Optimizely CMS Roadmap

Explore Optimizely CMS's latest roadmap, packed with developer-focused updates. From SaaS speed to Visual Builder enhancements, developer tooling...

Andy Blyth | Nov 21, 2024 | Syndicated blog

Set Default Culture in Optimizely CMS 12

Take control over culture-specific operations like date and time formatting.

Tomas Hensrud Gulla | Nov 15, 2024 | Syndicated blog