Showing posts with label Roundedcube. Show all posts
Showing posts with label Roundedcube. Show all posts

Monday, November 01, 2010

The Roundedcube Blog is now on www.roundedcube.com

We have launched a new http://www.roundedcube.com/ where you can find all future blog posts and all of the published content from this site as well.


Please take a quick moment to adjust your favorites to direct you to http://blog.roundedcube.com/ to read more from the team at Roundedcube.

Thursday, August 12, 2010

Tackling Fallback Fields and Values in Sitecore

I recently had the opportunity to fight with …. Err … learn about globalization within Sitecore. If you don’t know what Globalization is within Sitecore, then you are reading the right article, because your knowledge on the subject is the same as mine was when I first started working with it. I almost viewed it as the scary monster under my bed, about to tear my feet off the moment the light goes out. But, trudging forward and facing my fears, I pressed on and the outcome was quite surprising. I actually had a lot of fun once I got around some of the major obstacles in my way, the largest and most pronounced being my very own lack of knowledge on this specific subject. So, after beating my head against the wall, sweating profusely for days at a time, and finally consulting an oracle (he looked kind of like a homeless person to me, but I took his word for it) here is what I have found out about Globalization within Sitecore.

Before I begin, let me preface this with the following statement: this post is not an end-all be-all for globalization, just information I happen to remember and care to relate from my experiences. It also only deals with globalization within the context of Sitecore. Good, now that we got that out of the way, we can continue….

As you may or may not know, globalization is just a fancy pants way to say multi-lingual, which is an even more fancy way to say multiple languages. So, if you want multiple languages to display on your site, then you are going to have to use some form of globalization. For the purposes of this post, let us assume that we are dealing with English as your main language and Bangladeshi (just because I like the way it sounds….. Bangladeshi  ) as your secondary language.

In order to create a user-friendly website that caters to both of your demographic groups, we need some form of language switching on the site. Putting a dropdown at the top of your site is easy enough. In this example, we are setting our language embedding to “always”, so the URL of the current page also defines the language context being used. We do this with the following line in the web.config:

<linkManager defaultProvider="sitecore">
<providers>
<clear />
<add name="sitecore" type="Sitecore.Links.LinkProvider, Sitecore.Kernel" addAspxExtension="true" alwaysIncludeServerUrl="false" encodeNames="true" languageEmbedding="always" languageLocation="filePath" shortenUrls="true" useDisplayName="false" />
</providers>
</linkManager>

Now when you navigate to a page within Sitecore, you should see something like this: http://www.yoursite.com/en/ItemName.aspx for the English version or http://www.yoursite.com/bgd/ItemName.aspx for the Bangladeshi version.

Create a Bangladeshi versions of “ItemName”, fill it with content, publish, and BLAMO, Bangladeshi content for all to see. Easy enough, right? Yay for out of the box functionality! And for most websites this is all that will ever be required. But let’s get our knees dirty and dig in a bit deeper.

Say we want to fall back to the English version of the page if the Bangladeshi version doesn’t exist. All we do is write a custom pipeline process that will determine if the item exists in the current language, and if it doesn’t, send the user to the /en/ version of the page. This is pretty basic stuff. Here is a quick overview on how to do that if you are interested:

Update web.config with your custom pipeline process. Make sure it’s in the correct location…

<processor type="Sitecore.Pipelines.HttpRequest.ItemResolver, Sitecore.Kernel" />
<processor type="YourAssemblyHere.Pipelines.HttpRequest.FallbackLanguageProcessor, YourAssemblyHere " />
<processor type="Sitecore.Pipelines.HttpRequest.LayoutResolver, Sitecore.Kernel" />

And add the corresponding class to your project…

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace YourAssemblyHere.Pipelines.HttpRequest
{
public class FallbackLanguageProcessor
{
public void Process(Sitecore.Pipelines.HttpRequest.HttpRequestArgs args)
{
Sitecore.Data.Items.Item contextItem = Sitecore.Context.Item;
if (contextItem == null || contextItem.Versions.Count > 0)
return;


Sitecore.Globalization.Language language = Sitecore.Context.Language;
if (Sitecore.Context.Language.Name != "en")
language = Sitecore.Globalization.Language.Parse("en");
Sitecore.Data.Database contextDatabase = Sitecore.Context.Database;
Sitecore.Context.Item = contextDatabase.GetItem(Sitecore.Context.Item.ID, language);
}
}
}

As you can see, all this does is determine if the current item does NOT have a version (so you are trying to view a Bangladeshi page but it doesn’t exist), get the English version of this page, reset the context, and you are on your merry way. Weeeeeeeeee, isn’t this fun!?!

By this time in the project, I was feeling pretty good about my accomplishments and up to this point wasn’t getting tripped up too much. But alas, a new requirement came down from above: let’s make each FIELD fall back to English if there is no value within the Bangladeshi version. This means that if I go to the About Us page, and I’m in the Bangladeshi context, and there is no About Us page within Sitecore for the Bangladeshi item then I need to display the English version of that page without changing the context of the site! I know, I get a migraine just thinking about it.

Before I continue, I must give you fellow Globalization newbie’s a bit of advice… If you can help it, NEVER display multiple languages to the user on the same page. Not only does this create confusion for the user, it is rather pointless. If the user doesn’t understand English, then why would they ever care to see it on your website? Once you start mixing and matching languages on the same page the context of the site gets confusing for the user. They see content that is in their native language, but the navigation links (some or all of them) are in some foreign language (English in this case). But what the heck right? Let’s see just how extensible Sitecore really is (I love trying to break stuff!).

The process is similar to what we did earlier. We need to add a process to the “renderField” pipeline section of the web.config like this…

<processor type="Sitecore.Pipelines.RenderField.GetDateFieldValue, Sitecore.Kernel" />
<processor type="YourAssemblyHere.Pipelines.FieldRender.FallbackLanguageProcessor, YourAssemblyHere" />

<processor type="Sitecore.Pipelines.RenderField.AddBeforeAndAfterValues, Sitecore.Kernel" />

And add another class that handles this process like so…

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Sitecore.Pipelines.RenderField;


namespace YourAssemblyHere.Pipelines.FieldRender
{
public class FallbackLanguageProcessor
{
public void Process(RenderFieldArgs args)
{
//only perform this logic if this is not the default language
if (Sitecore.Context.Language.Name != "en")
{
if (args.Item != null)
{
//Get the current Item passed in by the arguments
Sitecore.Data.Items.Item currentItem = args.Item;
if (currentItem != null)
{
if (currentItem.Fields[args.FieldName] != null)
{
//if the current item has no valid value
if (currentItem.Fields[args.FieldName].Value.Equals("$name") ||
(currentItem.Fields[args.FieldName].Value.Equals(string.Empty)))
{
//Determine the fallback language for this item. in this case, we are forcing english.
Sitecore.Globalization.Language language = Sitecore.Globalization.Language.Parse("en");
//get the item in the default language
Sitecore.Data.Items.Item newItem = Sitecore.Context.Database.GetItem(currentItem.ID, language);


if (newItem != null)
{
//only make the update if the english field has a value
if (newItem.Fields[args.FieldName] != null)
if (!string.IsNullOrEmpty(newItem.Fields[args.FieldName].Value))
args.Result.FirstPart = newItem.Fields[args.FieldName].Value;
//disable web edit for this field, since it’s a fallback field editors should not be able to edit
args.DisableWebEditContentEditing = true;
}
}
}
}
}
}
}
}
}

Seems easy enough! Now, like before, our process will tick off and check to see if the FIELD that is trying to be displayed exist in Bangladeshi, and if not, go get the English value for that field and display that instead. Quick note: if you are accustomed to using sc:fld(‘Title’,.) in your xslt renderings, then those values don’t go through the fieldRender pipeline. You must use sc:field(‘Title’,.) in order for our custom process to have any effect. This specific issue causes grey hair apparently, so take heed! Just make sure your outputting your xslt value-of’s with sc:field. If you are using <sc:text, etc, then it should work fine.

Now, we have our FIELDS displaying English if the Bangladeshi field doesn’t have a value (this is mostly due to lazy or “too-busy-to-get-to-it” content editors ). So, here is where we currently are at. We are on the Bangladeshi site, looking at the About Us page. The top navigation is displaying either English or Bangladeshi links, depending on if that value exists in Sitecore, and all is good in the world.

“What about non-“fieldRender” pipeline values that are grabbed programmatically?” you say. Alright, let’s explore that. One example of why it is important to be able to get a fallback for a specific field programmatically is when you are setting the text property of a label to a field of an item.

So, pretend that on the Page_Load method we set a <asp: Label’s “Text” property to the Title field of the current item. We have to check to see if the item exists in Bangladeshi first, and if it doesn’t, then get the English version of the item and then display the title. Here is how to do that.

public static bool HasContextLanguage(Item item)
{
Item latestVersion = item.Versions.GetLatestVersion();
return ((latestVersion != null) && (latestVersion.Versions.Count > 0));
}

As you can see, pass it the item you want to check and it will return a “true” if the item exist within Bangladeshi (assuming you are within the Bangladeshi context), and “false” if it does not. You will use this method to see if you need to perform some additional logic, like grabbing an English version of the item and displaying the Title. Your Page_Load method might look a little something like this….

protected void Page_Load(object sender, EventArgs e)
{
if (!Page.IsPostBack)
{
Item currentItem = Sitecore.Context.CurrentItem;
if (!HasContextLanguage(currentItem))
currentItem = currentItem.Versions.GetLatestVersion(Sitecore.Globalization.Language.Parse("en"));
lblTitle.Text = currentItem.Fields["Title"].Value;
}
}

The last thing I want to go over is quite a bit more complex that what has been covered so far, so I apologize in advance for the mass confusion you are about to read and my general lack of ability to convey something in a more precise manner. It has to do with a fallback field on a fallback item that is a referenced target item of the current item. All that alludes to is how we handle globalization on referenced items within Sitecore (lookup fields, reference fields, multi-select fields, etc).

For example, imagine you have a “Page” Template with a lookup field called “Contact”. This “Contact” field will reference an item based on a “Contact” template that has the following fields: Name, Title, Company, Phone Number, and Address. Assume that the page and the contact are already created within Sitecore, but only in English. Along comes the Bangladeshi content editor and they add a Bangladeshi version to the page. While entering in content for the page, they select the English-only contact (we will call him “Bob” for now) and publish the item. We have to take a few things into consideration when trying to output Bob’s information.

When someone goes to the page and is in the Bangladeshi context, how do we display Bob correctly? Normally you get the TargetItem of the Contact field and display the name. In this case, it’s not so simple. You have to remember that Bob doesn’t exist within the Bangladeshi context. So first we have to get the Target item, and then do our check to see if it (Bob) exists in the current context and if not, get the English version of Bob to display. Here is how we would go about that:

Sitecore.Data.Fields.LookupField lookupField = item.Fields["Contact"];
if (lookupField != null && lookupField.TargetItem != null)
{
Item targetItem = lookupField.TargetItem;
if (!HasContextLanguage(targetItem))
targetItem = targetItem.Versions.GetLatestVersion(Sitecore.Globalization.Language.Parse("en"));
//Do Stuff with Bob here....
}

This logic is getting the “Contact” lookup field, getting its “TargetItem”(Bob), checking to see if the TargetItem exist within the current context, and if not, re-getting the target item as the English version, and then displaying the information as necessary.

I hope this all makes sense, I know I babble on and on and on and on a ….err, heh. Oh, and even after typing it 18,976 times, I still like the word “Bangladeshi”. Congratulations, you are at the end of my ranting and can go on with your lives. I hope you have learned something of value. Happy globalization!

Thanks – Caleb Miller.

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com/WhatsNew/Blog/tackling-fallback-fields-and-values-in-sitecore

Tuesday, August 03, 2010

What does Sitecore v6.3 Really Mean?

So it used to be called the TwinPeaks release if you follow the Sitecore Roadmap but exactly what does it bring to the table? There are some blogs already out regarding the release. Alex Shyba showed how easy it is to cluster the CMS client (in fact he did 6 virtual servers in less than hour – follow him on Twitter to get more updates). Oh yes, that’s what v6.3 really allows you to do (plus some other stuff that you should read on the release notes). But as a business person, you might ask, so what?

Well, we know that enterprises (that’s the keyword) always need performance as one of the top requirements to be fast and efficient. The Sitecore delivery engine (i.e. content delivery – CD servers) had always been keen to being clustered and allows you to load-balance them to achieve a pretty good performance. And that’s important because Sitecore itself may use up to 30% of CPU utilization (that’s what I’ve heard a while back in v5). So making sure that the site visitors are experiencing beautiful user interactions while delivering them promptly can be a tough achievement if you don’t load-balance your delivery servers. Almost all implementations nowadays have this requirement and should now be something that you should be aware of.

Sitecore v6.3 brings a new level performance except it’s not on the delivery side of things but more on the authoring side. With v6.3, IT can now load-balance the CMS client allowing for better responsiveness. It introduces the Event Queue which Adam Conn of Sitecore blogged about (it even has a nice video). Essentially, it is like a recipe whereby if you want to replicate your mom’s cooking again and again, you follow the recipe. In a way, v6.3 CMS client servers look at the queue to see what else need to be done and thus become “in synch” with the other servers.

As a business person, should I care about this? I say yes because now there’s more freedom on how Sitecore is deployed geographically. For international companies, this makes maintaining Web site more effective. Also, this becomes an ammunition to having a more globalized management of Web sites. Sitecore had been an eye-candy for managing globalized content because of translations, languages, publishing capabilities; but, there’s always that feeling that it’s really hard to distribute authorship because of geographical distances. With v6.3, this fear or concern is minimized because performance (and reliability) becomes less of an issue.

I’m hoping that corporations will now feel comfortable bringing in your international sites into one platform, that is Sitecore. The only thing that I think that you need to be cautious is how those other systems going to integrate with your Web site and allow them to be “load-balanceable” as well. I’ll leave you with this but one hint is to consider Sitecore not just a CMS but also as a foundational technical platform for other capabilities.

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com/WhatsNew/Blog/what-does-sitecore-v63-really-mean

Thursday, July 01, 2010

The Return of One of the Original Five

It's funny how your life can go full circle at times. After a four year career detour, I'm happy to return to Roundedcube as the new programmer on the block. As one of the Original Five employees at Roundedcube, it's good to be back and to work with friends from the start of my programming career. The company has grown a lot while I was gone. We're up to 16 employees now with many new clients while still maintaining relationships with many of the clients I have worked with in the past.

I think the coolest change I've seen (besides the new building of course) is that all of our teams consist of more than one person now! There are dedicated project managers, designers, sales-ers (?), and a large programmer pool. It's nice to be able to know what your team is working on and have a defined role in the process and definitely improves performance and the final product.

As a developer, the opportunities to learn new technologies and business practices are great. Much of the business now is directed towards Content Management Systems, specifically Sitecore. While I'm sure there's a learning curve to CMS development, the solutions we can provide to our clients make for interesting projects so I'm looking forward to working on my first CMS-based project.

One of the challenges in returning to a place you've worked before is figuring out what you need to remember from your previous time there and what you have to forget. In many ways it's harder than starting at a new company because you find yourself slipping into familiar habits of the ways things used to be done instead of thinking about how to do them now. I think it's better to do something, even if it's wrong, then to sit around and wait for someone to hold your hand. Well, that's assuming that it doesn't take too long to clean it up later.

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com/WhatsNew/Blog/the-return-of-one-of-the-original-five

Monday, April 26, 2010

Quick Dreamcore Shout Out

I’d like to quickly thank everyone from Sitecore for putting up a great inaugural annual event, Dreamcore. You can ask Sitecore and they’ll tell you that I’ve been waiting for this. Even though it was only a couple of days, it was enough to get excited again about the prospect of Sitecore and the world of CMS.

Besides learning about the new stuff that Sitecore has in the pipeline, it was great to know where Michael, Bjarne and the rest of Sitecore gang think the market will be, the so-called “Digital Intimacy.” I don’t think we’ll be competing against match.com or eharmony.com anytime soon, but the idea of committing to your audience’s needs is key to engaging them. You can see this commitment from Sitecore initially with their release of OMS. Analytics nowadays seems to be just a buzzword, but in Sitecore world, it’s more than just giving you reports but it’s about tying things together from the multi-variant test results to actual contextual content delivery that matters to the visitor. It’s basically like eharmony’s “form of a thousand personality questions” and match you with "the right” person…sort of.

I’m amazed at the products presented in the conference. One would think that since this is a Sitecore show, it would just be about the CMS. Besides the improvements in the CMS (such as the OMS and other modules), there are renewed commitments to the Intranet and Foundry. There’s also the Ecommerce module that allows for simple online shopping; also, the Email Campaign Manager seemingly replaces the Newsletter module for more robust online campaigns. I think these are great products on top of Sitecore because they are turnkey solutions that would allow us to penetrate other markets.

Again, thanks Sitecore for the great show. I can’t wait for next years. By the way, thanks for the interview as well. You truly value your partners (we’ve been doing it for 5 years now) and customers.

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com/WhatsNew/Blog/quick-dreamcore-shout-out

Friday, February 19, 2010

Where's the bathroom?

How many of you have ever wandered into the back of a strange, new restaurant or brew house, stood in front of those doors with crossed legs and said to yourself, “I have no idea which one’s for me.” Not knowing for sure but with time not on your side you take your shot – enter – then find out you’ve made the wrong choice.

This is a bit how I felt walking into Roundedcube on February 1st. Not knowing who was who, what was what or even where the bathroom was located I wondered if I had made the right decision. Was leaving my last job the right thing to do? Fortunately, now almost three weeks into this, I’ve got a pretty good feeling about the whole thing. I’m starting to get the hang of it around here and even know how to make it to work without using my GPS.

When I decided to make the move to St. Louis (originally hailing from the Cornhuskers state) I knew there was going to be some uncertainty, discomfort and change. In fact a friend of mine told me that the reason you feel like the stupidest person at your new job is likely because you are the stupidest person at your new job. For a good couple days that was undoubtedly the case and now I’m regretting the name calling he endured.

In my previous position it was my responsibility to invent the vocabulary, the definitions, the processes, and the templates. Now, even though I’m in the exact same business, a lot of those things have changed. Development…implementation; scope of work…statement of work; tomato…tomato. The map is still the same, we’re all heading in the same direction but the legend is just a little different.

The more I thought about these differences the more I was reminded of Patrick Lencioni’s book, “The Five Dysfunctions of a Team: A Leadership Fable.” One of my main take-aways from the book was that constructive conflict is a good and necessary thing. If used and managed correctly it keeps us from trudging down the road of “artificial harmony” because, in the end, the real magic, the stuff that separates good from great, really comes from our differences not our similarities.

Now, to be totally fair some things didn’t really change at all. Prior to coming to Roundedcube I spent the last 10 years in the IT/Web world so this definitely wasn’t my first rodeo. That being said here are a few things that made me feel right at home:
  • By 10:00 AM more than half the staff is hopped up on coffee, Mountain Dew or some other high glucose or caffeine rich substance
  • An almost diabolical sense of competition whether that be in web strategy or ping-pong
  • One-half out of their mind in search of an iPad – the other half snickering at the first half because they’ve yet to receive their much anticipated, gold embossed invitation to the “Cult of Mac”
  • 50% in favor of the waterfall method, 50% in favor of agile and 0% of customers who really care as long as their projects get done on time and under budget
  • Four words…scope creep, change request!
  • But most importantly; an amazingly talented group of people that spend their days pouring their creativity into strategy, work items, code and comps then leaving the office to make time with their family, playing music or cheating death on a high speed crotch-rocket
In the end, figuring out that my definition of the word “creative” was different than Roundedcube’s really didn’t amount to a hill of beans. What is most impressive and important is that no matter what words we were using we were still talking about the right process, the right projects and making sure we’re delivering the right solution to each and every one of our clients.

As the new Manager of Client Engagements for Roundedcube I’m really looking forward to meeting with all of you…that is existing and future clients, vendors and partners. My long-time philosophy for every project is that we should be able to (A) decrease costs or (B) increase revenue. If we can’t do either then we’re not doing our job but if we can do both then you’ll want to work with us again in the future. Please let me know if there’s anything I can do to help your business. You can e-mail me at shane.freeman@roundedcube.com or give me a call at (866) 692-2823 x 102. I look forward to hearing from you!

*EDIT October 28, 2010. We have moved our blog to http://blog.roundedcube.com and you can now comment on this specific post at http://www.roundedcube.com//WhatsNew/Blog/wheres-the-bathroom