Sitecore Dictionary Redux

March 15, 2015

Sitecore DictionaryI always knew Sitecore provided Dictionary support for a long time but I also knew there were, shall we say, scalability problems. Like, let's say, general user access (it was located under the system node) and the inability to create individual dictionaries for individual sites. Because of that, I, and apparently others, have been inanely custom rolling dictionaries. That is, until I came upon Scott Mulligan's article highlighting the latest changes in Sitecore 6.6 (yesss, it's been a while, I know [sighs, rolls eyes]) that convinced me to finally stop reinventing the wheel and adopt the Sitecore provided solution. 

There are resources out there to help get started like John Wests' seemingly canonical post. There's also a super handy article by "sitecorecode" (I couldn't find the author's actual name but I guess you know who you are). And my long time friend M3, as he's known colloquially, breaks it down like a legend.

 

That being said, there's no cookbook so any real depth on the topic is up to us/me/we/you/them/it to decompile and sift through the debris [duh-briss], then craft clearer guides from zero to working. 

1. Setting up a dictionary

First thing you'll need to do, assuming you have a Sitecore instance running and you're logged into it (because without that you're basically reading the wrong site), is insert a "Dictionary Domain" [dik-shun-air-ee doh-main] object from the template: "/sitecore/templates/System/Dictionary/Dictionary Domain". There are no icons for the dictionary items so you'll just have to deal. However, since the larger structure is unlikely to change without a developer, you could probably get by with changing the icons on the instance and be ok. In case you're wondering, the red book is in the "People" [peep-pull] icon section. Second row, all the way to the right. It would however be a lot better if someone at Sitecore (wink, nudge, cough......) were to add the icons to the system itself. Fabulous even.

Dictionary Domains

Moving right along. Once you've got a "Dictionary Domain" (not scare quotes) created, you'll need to specify which dictionary your site is going to use. The way to do this is to add an attribute to the site node in your config file: dictionaryDomain="NameOfDictionaryDomainItem". 

Dictionary Site Attribute

If you're wondering how this helps Sitecore find the dictionary in the tree, I'm assuming (perhaps incorrectly) that the underlying code is using a "Lucene" [lou-seen] index to get all the dictionary domain items and pull the correct one by name. Probably.

Fallbacks

There's a fallback concept with dictionaries that should be explained. On the Dictionary Domain node you created is a "Fallback Domain" [fall-bak doh-main] field. If you were to have local (to the site) dictionary and a global (to mulitple sites) dictionary, then this would make sense to have a fallback. Maybe you want to have most of your content global but then a few overrides locally. The field seemingly also pulls results from Lucene allowing you to place your dictionaries wherever you need them.

Dictionary Fallback Field 

2. Adding entries

Once you've got the basic structure in place, you'll want to populate some values. You have two insert options: a folder and an entry. 

Dictionary Insert Options

Foldering

I like to separate into groups by function such as form labels, global labels, navigation etc. I'm going to create a single folder called global and a single entry called copyright. This is pretty common for a site so that should be easy to follow.

Dictionary Domain Tree

The Keys to the Car

When you create your entries, the name should be short and common sense. It's only going to be used by content editors to logically find content. On each item you have two values to populate: the key and the phrase. 

The key is what will be used to call this entry from code. It's a shared field so you won't have to set it on each language you translate to, thankfully. For the key value, I think it makes sense to use the format folder.subfolder.entryname. If we included the site name we'd hobble ourselves when it looks for fallback values. So in this instance it would be "global.copyright" [glow-bull dot kop-ee-rite] (since I didn't create any level of subfolders). I also recommend using lowercase since that introduces less room for error.

Dictionary Entry Key and Phrase

The phrase is the text value that shows up. This is not a shared field so it's value is unique to all languages used. Translate away!

3. Accessing the entries

Now the last step is how to access it where it's needed. You're going to be using the Sitecore.Globalization.Translate namespace. There's a list of methods available but mostly you're only going to care about a few. And they are: 

Sitecore.Globalization.Translate.Text(

string key,
params object[] parameters

)

This is the most basic query and it will look at your context site and try to find the "dictionaryDomain" attribute to find the set of keys to use. If you didn't set it on your site node it will default to the global dictionary (in Sitecore) and if it doesn't find the key there (which is likely), it will return you the key itself. If you think that's a bad user experience and don't want the keys to show up as a default, Mikey "Interfaces" [he-see-them] has a nice write-up on how to fix that. 

There's one thing you should wonder about and that is what do the object[] parameters do? Good question, I'm glad you were paying so close attention. This is a hidden gem that allows you to pass in parameters for the entrie's phrase field which is fed through the string formatter. In the previous step, for example, I'm passing in the year and having it replace {0}. Here's the honey:

Dictionary Entry Format

Sitecore.Globalization.Translate.TextByDomain(

string domain, 
Sitecore.Globalization.TranslateOptions options, 
string key, params object[] parameters

)

This method assumes you haven't added any attribute to your site, or want to reach into a different dictionary than the context is set to. You specify the "domain" which is the Dictionary Domain instance item name. 

The TranslateOptions allows you to specify the Database, FallbackDomains, SuppressDefaultFallback and SuppressFallback. I can see this being useful for several types of edge cases. Sitecore modules come to mind since you might need your content to be in the core database or you might want to prevent fallback to dictionaries outside of your control. 

Also supports parameter goodness.

Sitecore.Globalization.Translate.TextByLanguage(

string key, 
Sitecore.Globalization.TranslateOptions options,
 
Sitecore.Globalization.Language language,
string key, params object[] parameters

)

This builds further by allowing you to specify a language to get the content by. I would imagine that if you have a translated site but always wanted to keep, perhaps, your business name pulled from one language, you could. 

In Summation

The process is a little jarring at first and without icons, can be slightly less visually appealing but it's now (as in a while ago) possible to create a dictionary, specific to a site, populate unique keys that are translatable and control how to display them. Better late than never amirite? I meant me using it, not Sitecore changing it. Well, I guess that too, but also me. Anyways [that's-all-folks].