Try our conversational search powered by Generative AI!

Dmytro Duk
May 11, 2011
(1 votes)

Localization workaround for EPiServer CMO 2.0

Globalization support is improved in CMO next version for EPiServer CMS 6 R2. Current users of CMO 2.0 can use the following workaround to solve localization issues in campaign and LPO test settings (see details here and here). After these changes you should be able to operate dates and numbers in your current culture format. This solution doesn’t require code recompilation. It is applicable to CMO 2.0 release version published on

Let’s consider the simple scenario, when Swedish language is set as default on your site,  for example in culture and uiCulture properties of globalization section in your web.config file.

Language files

You probably will see “[Missing text...]” warnings if language file is missing for your current culture, in our case Swedish.
CMO_EN.xml file contains all CMO string resources in English and can be found in lang directory of your site. Make a copy of this file, rename corresponding to your language. In our case it is Swedish, so rename new language file to CMO_SV.xml, open file and update name and id properties of language node:

<?xml version="1.0" encoding="utf-8" standalone="yes" ?> 
    <language name="Svenska" id="sv">

Now you should get English texts instead of [Missed text …] warnings. Optionally texts in language file can be translated to get CMO UI in required language.

The one change is required in node /cmo/lpo/settings/datepickerformat. Please define jQuery date format that corresponds to .NET short date format for your culture. Yes, tricky one :)
Example: Swedish short date string is something like 2011-05-25. Corresponding jQuery date format for Swedish culture is yy-mm-dd:


Norwegian short date string 25.05.2011 corresponds to jQuery pattern and so on. Refer to jQuery documentation:

It is important to have language files both for current culture and current UI culture on your site, if they are different.

CMO UI controls

Go to directory where CMO UI is installed. Typically it is somewhere like this: C:\Program Files (x86)\EPiServer\CMS\6.0.530.0\Install\Modules\CMO2.0.0.0\CMO\

Need to update settings controls for LPO tests and campaigns to make sure that date picker is initialized with required date format.

LPO Test settings

Update arguments in Cmo.SetupDatePicker method calls inside $(document).ready function in LpoTestSettings.aspx file:

// On document load finished
$(document).ready(function () {
// … omitted code … 
    Cmo.SetupDatePicker($(Cmo.dateFrom), '<%= TranslateForScript("/cmo/lpo/settings/datecountryformat") %>', '<%= LanguageManager.Instance.TranslateForScript("/cmo/lpo/settings/datepickerformat", System.Threading.Thread.CurrentThread.CurrentCulture.IetfLanguageTag.Substring(0, 2)) %>', '-1d');
    Cmo.SetupDatePicker($(Cmo.dateTo), '<%= TranslateForScript("/cmo/lpo/settings/datecountryformat") %>', '<%= LanguageManager.Instance.TranslateForScript("/cmo/lpo/settings/datepickerformat", System.Threading.Thread.CurrentThread.CurrentCulture.IetfLanguageTag.Substring(0, 2)) %>', '-1d');

Campaign settings

Open file Units\CampaignGeneralSettings.ascx, update arguments in Cmo.SetupDatePicker method calls inside $(document).ready function:

// On document load finished
$(document).ready(function() {
    Cmo.SetupDatePicker($(Cmo.dateFrom), '<%= TranslateForScript("/cmo/lpo/settings/datecountryformat") %>', '<%= LanguageManager.Instance.TranslateForScript("/cmo/lpo/settings/datepickerformat", System.Threading.Thread.CurrentThread.CurrentCulture.IetfLanguageTag.Substring(0, 2)) %>', '0d');
    Cmo.SetupDatePicker($(Cmo.dateTo), '<%= TranslateForScript("/cmo/lpo/settings/datecountryformadt") %>', '<%= LanguageManager.Instance.TranslateForScript("/cmo/lpo/settings/datepickerformat", System.Threading.Thread.CurrentThread.CurrentCulture.IetfLanguageTag.Substring(0, 2)) %>', '0d');

KPI settings

Update \Units\Kpi\KpiSettingsEditor.ascx to make sure that decimal KPI values are processed correctly in the current culture format. Add CultureInvariantValues="true" option for KPI values validators:

<asp:CompareValidator runat="server" ValidationGroup="<%# ValidationGroupName %>" ID="CompareValidatorValue" Display="Dynamic" 
    ErrorMessage="<%$ Resources: EPiServer, cmo.campaignMonitor.settings.kpi.valueerrorcompare %>" Text="*" 
    Type="Double" ControlToValidate="TextBoxValue" ValueToCompare="0.01" Operator="GreaterThanEqual" CssClass="kpiEditorValidator"
    CultureInvariantValues="true" />
<asp:CompareValidator runat="server" ValidationGroup="<%# ValidationGroupName %>" ID="CompareValidatorExpectedValue" Display="Dynamic" 
    ErrorMessage="<%$ Resources: EPiServer, cmo.campaignMonitor.settings.kpi.expectedvalueerrorcompare %>" Text="*" 
    Type="Double" ControlToValidate="TextBoxExpectedValue" ControlToCompare="TextBoxValue" Operator="GreaterThanEqual" CssClass="kpiEditorValidator" 
    CultureInvariantValues="true" />

JavaScript code in this control must be updated to fix decimal separators in KPI data for current culture. Add following code just in the beginning of initializeKpiEditor function:

$(function () {
    var initializeKpiEditor = function ()
        var kpiData = eval($("#<%= KpiData.ClientID %>").val());
        var defaultDecimalSeparator = ".";
        var currentDecimalSeparator = "<%= System.Globalization.NumberFormatInfo.CurrentInfo.NumberDecimalSeparator %>";
        $.each(kpiData, function(index, kpi) { 
            kpi.value = kpi.value.toString().replace(defaultDecimalSeparator, currentDecimalSeparator);
            kpi.expectedValue = kpi.expectedValue.toString().replace(defaultDecimalSeparator, currentDecimalSeparator);
        // … omitted code … 
    // … omitted code …

Then find the following line below in initializeKpiEditor function:

kpiList: eval($("#<%= KpiData.ClientID %>").val()),

and change it to:

kpiList: kpiData,


Go to Scripts directory inside CMO UI folder. It should be somewhere like: C:\Program Files (x86)\EPiServer\CMS\6.0.530.0\Install\Modules\CMO2.0.0.0\CMO\Scripts\
Open cmo.min.js file. This is compressed script, so be careful when updating it. Find string:


and after this string insert following code:

if(b) c.datepicker('option',"dateFormat",b);

As a result updated Cmo.SetupDatePicker function in cmo.min.js must looks like this:

Cmo.SetupDatePicker=function(c,d,b,e){var a=c.val();c.datepicker({showOtherMonths:true,showOn:"button",buttonImageOnly:false});c.datepicker("option",$.extend({showMonthAfterYear:false},$.datepicker.regional[d]));c.datepicker("option","minDate",e);c.datepicker("option","duration",0);if(b) c.datepicker('option',"dateFormat",b);c.focus(function(){if(c.val()==""){c.datepicker("show")}});c.change(function(){EPi.PageLeaveCheck.SetPageChanged(true)});c.val(a);if(c.val()!=""){c.val(Cmo.getDateInSpecifiedFormat(c.val(),b))}if(c.attr("disabled")){c.datepicker("disable")}};

Open CmoScripts.js in the same folder Scripts and define date format option for datepicker inside Cmo.SetupDatePicker function, just after the line element.datepicker('option', 'duration', 0);

Cmo.SetupDatePicker = function (element, locale, format, mindate) {
// … omitted code …
    element.datepicker('option', 'duration', 0);
    if (format) {
        element.datepicker('option', "dateFormat", format);
// … omitted code …

Clear cache

Since changes where made in JavaScript and control markup, previous versions of scripts and compiled controls can be cached by browser, proxy, IIS or in Temporary ASP.NET Files folder. Decide how to clear that caches depending on your environment.


Replace your existing files or use it to compare and make changes manually, it’s up to you. Don’t forget to backup your files before update ;)


Please let me know if this workaround doesn’t work for you, I will try to find the solution.

May 11, 2011


May 12, 2011 06:02 AM

Great work Dmytro!
Have tested the fix, worked like a charm!

May 12, 2011 02:50 PM

well its nice to have this workaround.thanks

May 15, 2011 08:47 PM

When can we expect an official patch or a new CMO version which fixes this?

Eivind Hodneland
Eivind Hodneland May 16, 2011 10:39 AM

Thanks. This worked well. However, I also had to apply an updated EpiServer.Cmo.Ui.Dll (v. to not have the dates in LPO test and campaign listings display garbage.

May 16, 2011 02:54 PM

I've tried to limit changes and make sure that user is able to enter values in required culture format.
We are working on CMO next version and hopefully it will be available soon.

Please login to comment.
Latest blogs
Introducing Image Transformer - AI Assistant for Optimizely

We've got something super cool to share with you, and it's all about giving your images a fresh spin. Image Transformer, the latest feature from ou...

Luc Gosso (MVP) | Feb 26, 2024 | Syndicated blog

Welcome 2024 Winter OMVPs

Hello, Optimizely community! We are thrilled to announce and welcome the newest members to the Optimizely Most Valuable Professionals (OMVP) progra...

Patrick Lam | Feb 26, 2024

Optimizely Opal... what it does actually do?

At Opticon 2023, Optimizely announced its first AI product Opal. AI is definitely the new tech buzzword in 2024 and with promises that AI will be...

Jon Jones | Feb 25, 2024 | Syndicated blog

How to add more Content Area Context Menu Item in Optimizely CMS 12

Hey folks, today I will share something related to Context Menu customization in the Content Area of Optimizely CMS. As you know, the content area ...

Binh Nguyen | Feb 25, 2024