allBlogsList

Tokenizing Sitecores Dictionary

Prior to the great CMS tools we have today, like Sitecore, the more common CMS-like approach in development usually revolved around a token of some sort.  You would have an html file with special tokens using certain patterns that your code would read against, pick up on the tokens and replace with some content or functionality. With Sitecore and a proper development approach, the need for token based solutions has been limited.  However scenarios do come up.  Imagine your content authors want to place a copyright year or proper company name in several places but want to keep them centralized.  Imagine if you have a need to support functional content which you would prefer to only change once via a shared field but want the labels to be in several languages.  When scenarios like this arise you need to start thinking out of the box a bit. The solution for this is to create a class that used along with the FieldRenderer.  It attaches to the renderField pipeline, and essentially looks through your content for a token, searches the dictionary for a term key of the same name and returns the phrase. Lets take a look at the code:

public class DictionaryReplacer
    {
        private static string tokenPattern = "%%([a-zA-Z]+)%%";
        private static char[] trimChar = { '%' };

        public void Process(RenderFieldArgs args)
        {
            // if in page editing mode then ignore this processor
			if (Sitecore.Context.PageMode.IsPageEditorEditing)
			{
				return;
			}

			Assert.ArgumentNotNull(args, "args");

            if (!string.IsNullOrEmpty(args.Result.FirstPart))
            {
                args.Result.FirstPart = ProcessLines(args.Result.FirstPart);
            }

            if (!string.IsNullOrEmpty(args.Result.LastPart))
            {
                args.Result.LastPart = ProcessLines(args.Result.LastPart);
            }
        }

        protected string ProcessLines(string text)
        {
            if (string.IsNullOrEmpty(text))
            {
                return text;
            }

            Regex rgx = new Regex(tokenPattern);

            // search for tokens and return dictionary value
            foreach (Match match in rgx.Matches(text))
            {
                string matchValue = match.Value;
                string definitionValue = Translate.Text(matchValue.Trim(trimChar));
                text = text.Replace(matchValue, definitionValue);
            }

            return text;
        }
    }

In this class our token pattern is %%key%%.  So for example, if a content author entered %%copyrightyear%% into a rich text field, our code would pick up on this and search the dictionary for "copyrightyear".  Assuming our phrase for this key was "2013", then that would be returned as the value.   Also notice that we have chosen to return from our process if we are in page editor mode.  This guarantees tokens are displayed in page editor mode versus their end value. Now in order for this to work you need to attach it to the renderField pipeline.  I have attached it right after the GetFieldValue process is run.  Also remember to use best practice and add your pipeline as a patch and not directly to the web.config.  The xml for Pipelines.config looks as follows:

<configuration xmlns:patch="http://www.sitecore.net/xmlconfig/">
  <sitecore>
    <pipelines>
      <renderField>
        <processor patch:after="*[@type='Sitecore.Pipelines.RenderField.GetFieldValue, Sitecore.Kernel']" type="Dev.Extensions.Pipelines.DictionaryReplacer, Dev.Extensions" />
      </renderField>
    </pipelines>
  </sitecore>
</configuration>

As far as what can go into dictionary definitions it seems fairly open.  But here are a couple considerations when creating your dictionary:

  1. Create a folder structure.  Your list will grow over time.  The most common is to simple create a folder for each letter in the alphabet and place keys based on their first letter.
  2. Update the definition template - key field with the standard value of "$name".  Considering that your item name and key field value will probably be the same, if you have many definitions to create this will save you a ton of time.
  3. If your phrases are more than one word, don't be afraid to create long names.  This gives their placement in the field prior to render a lot more meaning.  For example if you have a phrase of "Please contact us at 1-888-555-5555", your token name could be "%%pleasecontactusat%%".
  4. All though you can put large amounts of text and even html into the phrase of a definition item, if you find yourself in this scenario consider not using a token solution.  If the approach is a shared field with labels in multiple language, look to see if that part of the content can be moved to an unshared field.
  5. If using this approach for globalization, remember to tokenize for sentences or paragraphs.  Different languages will present different sentence structures and piecing together several tokens to make a sentence will leave different language viewers wondering why you did such a poor job translating.

Overall using token replacement with Sitecore's dictionary can give your content authors a lot more control over handling centralized content.  Make sure to go over with your authors proper usage of tokens.  Get on the same page with their goals and map out scenarios where they are used well and scenarios where to many tokens could be over board and cause content management problems down the road.