Dmytro Duk
May 11, 2011
  6144
(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 world.episerver.com.

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" ?> 
  <languages>
    <language name="Svenska" id="sv">
      ...
    </language>
</languages>

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:

<datepickerformat>yy-mm-dd</datepickerformat>

Norwegian short date string 25.05.2011 corresponds to jQuery pattern dd.mm.yy and so on. Refer to jQuery documentation: http://docs.jquery.com/UI/Datepicker/formatDate

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,

Scripts

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:

c.datepicker("option","duration",0);

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.

Download

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 ;)

Feedback

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

May 11, 2011

Comments

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. 2.0.0.10) 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
Opti ID overview

Opti ID allows you to log in once and switch between Optimizely products using Okta, Entra ID, or a local account. You can also manage all your use...

K Khan | Jul 26, 2024

Getting Started with Optimizely SaaS using Next.js Starter App - Extend a component - Part 3

This is the final part of our Optimizely SaaS CMS proof-of-concept (POC) blog series. In this post, we'll dive into extending a component within th...

Raghavendra Murthy | Jul 23, 2024 | Syndicated blog

Optimizely Graph – Faceting with Geta Categories

Overview As Optimizely Graph (and Content Cloud SaaS) makes its global debut, it is known that there are going to be some bugs and quirks. One of t...

Eric Markson | Jul 22, 2024 | Syndicated blog

Integration Bynder (DAM) with Optimizely

Bynder is a comprehensive digital asset management (DAM) platform that enables businesses to efficiently manage, store, organize, and share their...

Sanjay Kumar | Jul 22, 2024

Frontend Hosting for SaaS CMS Solutions

Introduction Now that CMS SaaS Core has gone into general availability, it is a good time to start discussing where to host the head. SaaS Core is...

Minesh Shah (Netcel) | Jul 20, 2024

Optimizely London Dev Meetup 11th July 2024

On 11th July 2024 in London Niteco and Netcel along with Optimizely ran the London Developer meetup. There was an great agenda of talks that we put...

Scott Reed | Jul 19, 2024