ILearnable .Net

May 22, 2011

Introducing EPiLang

Filed under: Uncategorized — andreakn @ 18:28

A while back I wrote about how to get strongly typed globalization handling for EPiServer CMS.

In the time since I have been playing around with ways to empower administrators of EPiServer sites to change the globalization texts themselves without having to involve developers directly. I don’t have know how many times the customer has come to me and requested that this string should be that and required me to circumvent our standard deployment routine so that “we can get the new string out immediately”

What I have come up with is basically a framework that allows each text used to be persistently overridden in runtime by an administrator. Combined with the T4-goodness from my previous post I believe I have made something that could turn out to be useful for some other sites. I Have decided to call it EPiLang (yes, I am inspired by the awesome EPiImage framework)

Under normal conditions you can access globalized strings in three different ways in EPiServer:

  1. <%= LanguageManager.Instance.Translate(“/xpath/to/string”) %>
  2. <EPiServer:Translate runat=”server”  Text=”/xpath/to/string” />
  3. <%$ Resources: EPiServer,>
Each of these methods require you to spell the path to the text correctly and also requires a fair bit of looking up the xml file(s) going “where did I put that string….” .
With EPiLang you can access strings this way
  • <%= LanguageService.Translate(“/xpath/to/string”) %>
  • <EPiLang:Translate runat=”server”  Text=”/xpath/to/string” />
  • <%$ Resources: EPiServer,>
  • <%= %>
The first three are as you can see remarkably like the originals, but the last one is the one you’ll find yourself using over and over again since it is strongly typed and gives you compiler support and intellisense.
No matter which of these you use, after adding the webcontrol <EPiLang:Editor runat=”server” /> to the very end of your master page, any administrator surfing the site will get a new item on his/her EPiServer context menu:
When they click that item a list of all overrideable texts used for that page rendering will be shown in the lower right hand corner of the page:
If the administrator clicks on one of the texts then an editor is shown in a lightbox:
Now the administrator may input a new string into the textbox and click save
on refreshing the page the globalized text will now be changed:
What happened here was that every time EPiLang is asked to fetch a string, it registers it on the HttpContext.Current.Request.Items array, so that when the editor is rendered it can produce a list of all the relevant strings.  The mechanism used for localizing this string here (this is taken from the AlloyTech sample provided by EPiServer) is like this:
EPiServer has defined its own resourcefactory which enables this syntax, however EPiLang substitutes this factory with  its own during installation and so is able to override which string is actually displayed.
There is a way to enable administrators to just click on the text inline instead of finding it in the list on the lower right hand side, we can exchange the code above with a strongly typed editable string:
which in turn light up the string when an admin enables editing of globalized strings through the context menu
The editable text is in fact a <span> tag with some attributes set which enables the editing
Overridden strings are not saved back to the xml file, as the next deploy would probably undo what the admin just did. Instead they are saved into EPiServers Dynamic Data store, along with the original string. That way if the string in the xml file changes for any reason then that value is used (until it is overridden at a later stage). Using this setup ensures that the latest write wins.
If you want to play around with EPiLang you are more than welcome to do so. It is CMS6 only and you will find it on nuget under the name Forse.EPiLang
When you install it it modifies your web.config slightly, it:
  • Adds Forse.EPiLang to pages/namespaces
  • Adds Forse.EPiLang.Controls to pages/controls
  • Adds a httphandler to handle the overriding commands (from the lightbox)
  • Exchanges the resourceProviderFactoryType with a new one.
on uninstall all these changes are reverted.
You will also get a readme file under the App_Readme folder. It contains the instructions on what to do to get up and running.
If this is useful for anyone I’ll put it up on EPiCode. Any feedback is much appreciated


  1. Thanks Andreas, I’m trying to use EPiLang in my project, but met several probems: 1. nuget package has updated my project and config, but it refers to Forse.EPiLang assembly, and when I changed config to use my assembly instead, it doesn’t work because of missed resources. So I built Forse.EPiLang from epicode sources, resources are embedded there, but I still have a coulpe issues: 1) it works only in view mode (not in preview) 2) it doesn’t work in me IE9 3) When I click “Save” button in “Override Globalized text” window, it saves entered value in the database, but don’t show this nice “saved ok” message and adds an error to the console log: Error: Syntax error, unrecognized expression: span.epilanguage[data-ident=no_/Spekter/ContentTypes/Statistics]

    Comment by Vladimir Levchuk — October 9, 2012 @ 14:49 | Reply

    • Hmm, It’s been a while since I last had an EPiServer project on my hands, so the EPiLang project has sort of stranded for me,
      I’m guessing that
      1) preview-mode interferes with jQuery (check the js-console in chrome (press F12 to enable)), if so: you can substitute all the ‘$’s in the js code with ‘jQuery’ in order to reach jQuery even if there is another js-framework “hogging” the $
      2) IE9 didn’t exist when I wrote EPiLang, so I never tested on it… probably an upgrade of jquery to the latest version will fix this, otherwise check the js-console in IE (again, press F12)
      3) it seems that the quotes around the ident is missing, so it tries to fetch the clickable span with the data-ident attribute set to no_/Spekter/ContentTypes/Statistics (in order to update its content) but it fails, this stops the further processing and displaying the “saved ok” message, instead of
      $(‘[data-ident=SOMEIDENT/WITH/SLASHES]’) it ought to be $(‘[data-ident=”SOMEIDENT/WITH/SLASHES”]’) (the trick is the double quotes within the single quotes)

      Comment by andreakn — October 10, 2012 @ 20:25 | Reply

      • Thank you for the reply ( and for the good idea implemented in EPiLang 🙂 ). I found 1 more bug, in back-end this time: Forse.EPiLang.LanguageService contains a static reference to DynamicDataStore which breaks application. It should be replaced with “per request” data store:

        private static DynamicDataStore DynamicDataStore
        var result = DynamicDataStoreFactory.Instance.GetStore(“EPiLang_Overrides”) ?? DynamicDataStoreFactory.Instance.CreateStore(“EPiLang_Overrides”, typeof(LanguageString));
        return result;

        Comment by Vladimir Levchuk — November 13, 2012 @ 14:15

  2. 1) Preview mode does not interfere with jQuery (EPiServer, it seems, has “rebranded” the version of jQuery it uses so that “$” and “jQuery” are free).
    2) IE9 wasn’t the problem, even though it is a problem with sites using doctype html (IE9 forces the child page to the same DOCTYPE as the parent page. No matter what.)
    3) Correct! Adding double quotes fixes the problem, but gives you another one (see 4)
    4) Upgrade SimpleModal to SimpleModal >= 1.4.3, as the supplied version (1.4.1) has a bug in it.

    Comment by Pelle Bjerkestrand — October 22, 2012 @ 12:18 | Reply

    • Hey, Pelle! Long sea, no thyme! Considering you and Vladimir both work at Creuna I’ll just assume that you guys figure it out between you. Feel free to submit a patch to the EPiLang project on EPiCode! I haven’t touched EPiServer since last time we worked together so I’m getting steadily more rusty 😉

      Comment by andreakn — October 22, 2012 @ 22:04 | Reply

      • Come work here again, Andreas!

        Vladimir and I are on the same project, so we are talking together, I just thought it could help others if I posted here:)

        Comment by Pelle — October 26, 2012 @ 12:47

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Blog at

%d bloggers like this: